From 393551e9898136513007b1e88a25bd4dcdb0d759 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Fri, 1 Feb 2013 02:09:03 -0800 Subject: gfs2: Remove improper checks in gfs2_set_dqblk. In set_dqblk it is an error to look at fdq->d_id or fdq->d_flags. Userspace quota applications do not set these fields when calling quotactl(Q_XSETQLIM,...), and the kernel does not set those fields when quota_setquota calls set_dqblk. gfs2 never looks at fdq->d_id or fdq->d_flags after checking to see if they match the id and type supplied to set_dqblk. No other linux filesystem in set_dqblk looks at either fdq->d_id or fdq->d_flags. Therefore remove these bogus checks from gfs2 and allow normal quota setting applications to work. Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/quota.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index ae55e248c3b7..e4f6ccf3da64 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -1543,13 +1543,9 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, switch(qid.type) { case USRQUOTA: type = QUOTA_USER; - if (fdq->d_flags != FS_USER_QUOTA) - return -EINVAL; break; case GRPQUOTA: type = QUOTA_GROUP; - if (fdq->d_flags != FS_GROUP_QUOTA) - return -EINVAL; break; default: return -EINVAL; @@ -1557,8 +1553,6 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, if (fdq->d_fieldmask & ~GFS2_FIELDMASK) return -EINVAL; - if (fdq->d_id != from_kqid(&init_user_ns, qid)) - return -EINVAL; error = qd_get(sdp, type, from_kqid(&init_user_ns, qid), &qd); if (error) -- cgit v1.2.3 From f4108a607f75b073423eed229ee4f95e5fc10631 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jan 2013 17:49:26 -0800 Subject: gfs2: Split NO_QUOTA_CHANGE inot NO_UID_QUTOA_CHANGE and NO_GID_QUTOA_CHANGE Split NO_QUOTA_CHANGE into NO_UID_QUTOA_CHANGE and NO_GID_QUTOA_CHANGE so the constants may be well typed. Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/bmap.c | 2 +- fs/gfs2/dir.c | 2 +- fs/gfs2/inode.c | 10 +++++----- fs/gfs2/quota.c | 4 ++-- fs/gfs2/quota.h | 5 +++-- fs/gfs2/super.c | 2 +- fs/gfs2/xattr.c | 4 ++-- 7 files changed, 15 insertions(+), 14 deletions(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index a68e91bcef3d..10c54e3c2e72 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1098,7 +1098,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 size) if (error) return error; - error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + error = gfs2_quota_hold(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE); if (error) return error; diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 9a35670fdc38..6d3e3e2cabf8 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -1849,7 +1849,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, if (!ht) return -ENOMEM; - error = gfs2_quota_hold(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + error = gfs2_quota_hold(dip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE); if (error) goto out; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 2b6f5698ef18..aa1050287f3c 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -548,7 +548,7 @@ static int link_dinode(struct gfs2_inode *dip, const struct qstr *name, if (error) return error; - error = gfs2_quota_lock(dip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + error = gfs2_quota_lock(dip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE); if (error) goto fail; @@ -1589,15 +1589,15 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) ngid = attr->ia_gid; if (!(attr->ia_valid & ATTR_UID) || ouid == nuid) - ouid = nuid = NO_QUOTA_CHANGE; + ouid = nuid = NO_UID_QUOTA_CHANGE; if (!(attr->ia_valid & ATTR_GID) || ogid == ngid) - ogid = ngid = NO_QUOTA_CHANGE; + ogid = ngid = NO_GID_QUOTA_CHANGE; error = gfs2_quota_lock(ip, nuid, ngid); if (error) return error; - if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { + if (ouid != NO_UID_QUOTA_CHANGE || ogid != NO_GID_QUOTA_CHANGE) { error = gfs2_quota_check(ip, nuid, ngid); if (error) goto out_gunlock_q; @@ -1611,7 +1611,7 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) if (error) goto out_end_trans; - if (ouid != NO_QUOTA_CHANGE || ogid != NO_QUOTA_CHANGE) { + if (ouid != NO_UID_QUOTA_CHANGE || ogid != NO_GID_QUOTA_CHANGE) { u64 blocks = gfs2_get_inode_blocks(&ip->i_inode); gfs2_quota_change(ip, -blocks, ouid, ogid); gfs2_quota_change(ip, blocks, nuid, ngid); diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index e4f6ccf3da64..dbfacaa8b6fb 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -524,7 +524,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) ip->i_res->rs_qa_qd_num++; qd++; - if (uid != NO_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { + if (uid != NO_UID_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { error = qdsb_get(sdp, QUOTA_USER, uid, qd); if (error) goto out; @@ -532,7 +532,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) qd++; } - if (gid != NO_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { + if (gid != NO_GID_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { error = qdsb_get(sdp, QUOTA_GROUP, gid, qd); if (error) goto out; diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h index f25d98b87904..7f67323a6a72 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h @@ -14,7 +14,8 @@ struct gfs2_inode; struct gfs2_sbd; struct shrink_control; -#define NO_QUOTA_CHANGE ((u32)-1) +#define NO_UID_QUOTA_CHANGE INVALID_UID +#define NO_GID_QUOTA_CHANGE INVALID_GID extern int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid); extern void gfs2_quota_unhold(struct gfs2_inode *ip); @@ -41,7 +42,7 @@ static inline int gfs2_quota_lock_check(struct gfs2_inode *ip) int ret; if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) return 0; - ret = gfs2_quota_lock(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + ret = gfs2_quota_lock(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE); if (ret) return ret; if (sdp->sd_args.ar_quota != GFS2_QUOTA_ON) diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index d6488674d916..7cc5a6054547 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1429,7 +1429,7 @@ static int gfs2_dinode_dealloc(struct gfs2_inode *ip) if (error) return error; - error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + error = gfs2_quota_hold(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE); if (error) return error; diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index 76c144b3c9bb..80c25ae79048 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c @@ -331,7 +331,7 @@ static int ea_remove_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, if (error) return error; - error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + error = gfs2_quota_hold(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE); if (error) goto out_alloc; @@ -1461,7 +1461,7 @@ int gfs2_ea_dealloc(struct gfs2_inode *ip) if (error) return error; - error = gfs2_quota_hold(ip, NO_QUOTA_CHANGE, NO_QUOTA_CHANGE); + error = gfs2_quota_hold(ip, NO_UID_QUOTA_CHANGE, NO_GID_QUOTA_CHANGE); if (error) return error; -- cgit v1.2.3 From 558e85289fca3d3397882442d1a695936c4f2662 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jan 2013 18:15:33 -0800 Subject: gfs2: Report quotas in the caller's user namespace. When a quota is queried return the uid or the gid in the mapped into the caller's user namespace. In addition perform the munged version of the mapping so that instead of -1 a value that does not map is reported as the overflowuid or the overflowgid. Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/quota.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index dbfacaa8b6fb..f8279eed56e1 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -1509,7 +1509,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr; fdq->d_version = FS_DQUOT_VERSION; fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA; - fdq->d_id = from_kqid(&init_user_ns, qid); + fdq->d_id = from_kqid_munged(current_user_ns(), qid); fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift; fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift; fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift; -- cgit v1.2.3 From 2f6c9896f71e6b6c1c565ea76dd9f5e89579c120 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jan 2013 18:33:38 -0800 Subject: gfs2: Introduce qd2index Both qd_alloc and qd2offset perform the exact same computation to get an index from a gfs2_quota_data. Make life a little simpler and factor out this index computation. Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/quota.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index f8279eed56e1..0e7c982377a1 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -120,11 +120,17 @@ out: return (atomic_read(&qd_lru_count) * sysctl_vfs_cache_pressure) / 100; } +static u64 qd2index(struct gfs2_quota_data *qd) +{ + return (2 * (u64)qd->qd_id) + + test_bit(QDF_USER, &qd->qd_flags) ? 0 : 1; +} + static u64 qd2offset(struct gfs2_quota_data *qd) { u64 offset; - offset = 2 * (u64)qd->qd_id + !test_bit(QDF_USER, &qd->qd_flags); + offset = qd2index(qd); offset *= sizeof(struct gfs2_quota); return offset; @@ -147,7 +153,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, qd->qd_slot = -1; INIT_LIST_HEAD(&qd->qd_reclaim); - error = gfs2_glock_get(sdp, 2 * (u64)id + !user, + error = gfs2_glock_get(sdp, qd2index(qd), &gfs2_quota_glops, CREATE, &qd->qd_gl); if (error) goto fail; -- cgit v1.2.3 From e08d8d7f201dc1e64f5d9d5aa2cd4f37aecaaab4 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jan 2013 19:25:50 -0800 Subject: gfs2: Modify struct gfs2_quota_change_host to use struct kqid Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/quota.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 0e7c982377a1..02913e95491c 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -71,7 +71,7 @@ struct gfs2_quota_change_host { u64 qc_change; u32 qc_flags; /* GFS2_QCF_... */ - u32 qc_id; + struct kqid qc_id; }; static LIST_HEAD(qd_lru_list); @@ -1200,7 +1200,9 @@ static void gfs2_quota_change_in(struct gfs2_quota_change_host *qc, const void * qc->qc_change = be64_to_cpu(str->qc_change); qc->qc_flags = be32_to_cpu(str->qc_flags); - qc->qc_id = be32_to_cpu(str->qc_id); + qc->qc_id = make_kqid(&init_user_ns, + (qc->qc_flags & GFS2_QCF_USER)?USRQUOTA:GRPQUOTA, + be32_to_cpu(str->qc_id)); } int gfs2_quota_init(struct gfs2_sbd *sdp) @@ -1264,7 +1266,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) continue; error = qd_alloc(sdp, (qc.qc_flags & GFS2_QCF_USER), - qc.qc_id, &qd); + from_kqid(&init_user_ns, qc.qc_id), &qd); if (error) { brelse(bh); goto fail; -- cgit v1.2.3 From b59c8b6f9d1b1220e5ed72152f42a658bf739d90 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jan 2013 19:35:56 -0800 Subject: gfs2: Modify qdsb_get to take a struct kqid Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/quota.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 02913e95491c..20762ae2a9c4 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -464,12 +464,13 @@ static void qd_unlock(struct gfs2_quota_data *qd) qd_put(qd); } -static int qdsb_get(struct gfs2_sbd *sdp, int user, u32 id, +static int qdsb_get(struct gfs2_sbd *sdp, struct kqid qid, struct gfs2_quota_data **qdp) { int error; - error = qd_get(sdp, user, id, qdp); + error = qd_get(sdp, qid.type == USRQUOTA ? QUOTA_USER : QUOTA_GROUP, + from_kqid(&init_user_ns, qid), qdp); if (error) return error; @@ -518,20 +519,20 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) return 0; - error = qdsb_get(sdp, QUOTA_USER, ip->i_inode.i_uid, qd); + error = qdsb_get(sdp, make_kqid_uid(ip->i_inode.i_uid), qd); if (error) goto out; ip->i_res->rs_qa_qd_num++; qd++; - error = qdsb_get(sdp, QUOTA_GROUP, ip->i_inode.i_gid, qd); + error = qdsb_get(sdp, make_kqid_gid(ip->i_inode.i_gid), qd); if (error) goto out; ip->i_res->rs_qa_qd_num++; qd++; if (uid != NO_UID_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { - error = qdsb_get(sdp, QUOTA_USER, uid, qd); + error = qdsb_get(sdp, make_kqid_uid(uid), qd); if (error) goto out; ip->i_res->rs_qa_qd_num++; @@ -539,7 +540,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) } if (gid != NO_GID_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { - error = qdsb_get(sdp, QUOTA_GROUP, gid, qd); + error = qdsb_get(sdp, make_kqid_gid(gid), qd); if (error) goto out; ip->i_res->rs_qa_qd_num++; -- cgit v1.2.3 From ed87dabcc3fc0a5040f95dd3f7206cffebca5c79 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jan 2013 19:42:40 -0800 Subject: gfs2: Convert gfs2_quota_refresh to take a kqid - In quota_refresh_user_store convert the user supplied uid into a kqid and pass it to gfs2_quota_refresh. - In quota_refresh_group_store convert the user supplied gid into a kqid and pass it to gfs2_quota_refresh. Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/quota.c | 5 +++-- fs/gfs2/quota.h | 2 +- fs/gfs2/sys.c | 14 ++++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 20762ae2a9c4..47315c091a09 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -1177,13 +1177,14 @@ static int gfs2_quota_sync_timeo(struct super_block *sb, int type) return gfs2_quota_sync(sb, type); } -int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id) +int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid) { struct gfs2_quota_data *qd; struct gfs2_holder q_gh; int error; - error = qd_get(sdp, user, id, &qd); + error = qd_get(sdp, qid.type == USRQUOTA ? QUOTA_USER : QUOTA_GROUP, + from_kqid(&init_user_ns, qid), &qd); if (error) return error; diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h index 7f67323a6a72..bef805de8491 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h @@ -28,7 +28,7 @@ extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change, u32 uid, u32 gid); extern int gfs2_quota_sync(struct super_block *sb, int type); -extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id); +extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid); extern int gfs2_quota_init(struct gfs2_sbd *sdp); extern void gfs2_quota_cleanup(struct gfs2_sbd *sdp); diff --git a/fs/gfs2/sys.c b/fs/gfs2/sys.c index 8056b7b7238e..e6d8d482422f 100644 --- a/fs/gfs2/sys.c +++ b/fs/gfs2/sys.c @@ -175,6 +175,7 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf, static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf, size_t len) { + struct kqid qid; int error; u32 id; @@ -183,13 +184,18 @@ static ssize_t quota_refresh_user_store(struct gfs2_sbd *sdp, const char *buf, id = simple_strtoul(buf, NULL, 0); - error = gfs2_quota_refresh(sdp, 1, id); + qid = make_kqid(current_user_ns(), USRQUOTA, id); + if (!qid_valid(qid)) + return -EINVAL; + + error = gfs2_quota_refresh(sdp, qid); return error ? error : len; } static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, size_t len) { + struct kqid qid; int error; u32 id; @@ -198,7 +204,11 @@ static ssize_t quota_refresh_group_store(struct gfs2_sbd *sdp, const char *buf, id = simple_strtoul(buf, NULL, 0); - error = gfs2_quota_refresh(sdp, 0, id); + qid = make_kqid(current_user_ns(), GRPQUOTA, id); + if (!qid_valid(qid)) + return -EINVAL; + + error = gfs2_quota_refresh(sdp, qid); return error ? error : len; } -- cgit v1.2.3 From 05e0a60d8025e280e56b3fa36ea8facc7c1c65c2 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jan 2013 19:52:08 -0800 Subject: gfs2: Store qd_id in struct gfs2_quota_data as a struct kqid - Change qd_id in struct gfs2_qutoa_data to struct kqid. - Remove the now unnecessary QDF_USER bit field in qd_flags. - Propopoage this change through the code generally making things simpler along the way. Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/incore.h | 3 +-- fs/gfs2/quota.c | 69 ++++++++++++++++++++------------------------------------ 2 files changed, 26 insertions(+), 46 deletions(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index c373a24fedd9..5b298bdab90c 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -391,7 +391,6 @@ struct gfs2_revoke_replay { }; enum { - QDF_USER = 0, QDF_CHANGE = 1, QDF_LOCKED = 2, QDF_REFRESH = 3, @@ -403,7 +402,7 @@ struct gfs2_quota_data { atomic_t qd_count; - u32 qd_id; + struct kqid qd_id; unsigned long qd_flags; /* QDF_... */ s64 qd_change; diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 47315c091a09..8cb4d10cb16a 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -122,8 +122,9 @@ out: static u64 qd2index(struct gfs2_quota_data *qd) { - return (2 * (u64)qd->qd_id) + - test_bit(QDF_USER, &qd->qd_flags) ? 0 : 1; + struct kqid qid = qd->qd_id; + return (2 * (u64)from_kqid(&init_user_ns, qid)) + + (qid.type == USRQUOTA) ? 0 : 1; } static u64 qd2offset(struct gfs2_quota_data *qd) @@ -136,7 +137,7 @@ static u64 qd2offset(struct gfs2_quota_data *qd) return offset; } -static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, +static int qd_alloc(struct gfs2_sbd *sdp, struct kqid qid, struct gfs2_quota_data **qdp) { struct gfs2_quota_data *qd; @@ -147,9 +148,7 @@ static int qd_alloc(struct gfs2_sbd *sdp, int user, u32 id, return -ENOMEM; atomic_set(&qd->qd_count, 1); - qd->qd_id = id; - if (user) - set_bit(QDF_USER, &qd->qd_flags); + qd->qd_id = qid; qd->qd_slot = -1; INIT_LIST_HEAD(&qd->qd_reclaim); @@ -167,7 +166,7 @@ fail: return error; } -static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, +static int qd_get(struct gfs2_sbd *sdp, struct kqid qid, struct gfs2_quota_data **qdp) { struct gfs2_quota_data *qd = NULL, *new_qd = NULL; @@ -179,8 +178,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, found = 0; spin_lock(&qd_lru_lock); list_for_each_entry(qd, &sdp->sd_quota_list, qd_list) { - if (qd->qd_id == id && - !test_bit(QDF_USER, &qd->qd_flags) == !user) { + if (qid_eq(qd->qd_id, qid)) { if (!atomic_read(&qd->qd_count) && !list_empty(&qd->qd_reclaim)) { /* Remove it from reclaim list */ @@ -214,7 +212,7 @@ static int qd_get(struct gfs2_sbd *sdp, int user, u32 id, return 0; } - error = qd_alloc(sdp, user, id, &new_qd); + error = qd_alloc(sdp, qid, &new_qd); if (error) return error; } @@ -469,8 +467,7 @@ static int qdsb_get(struct gfs2_sbd *sdp, struct kqid qid, { int error; - error = qd_get(sdp, qid.type == USRQUOTA ? QUOTA_USER : QUOTA_GROUP, - from_kqid(&init_user_ns, qid), qdp); + error = qd_get(sdp, qid, qdp); if (error) return error; @@ -574,18 +571,10 @@ static int sort_qd(const void *a, const void *b) const struct gfs2_quota_data *qd_a = *(const struct gfs2_quota_data **)a; const struct gfs2_quota_data *qd_b = *(const struct gfs2_quota_data **)b; - if (!test_bit(QDF_USER, &qd_a->qd_flags) != - !test_bit(QDF_USER, &qd_b->qd_flags)) { - if (test_bit(QDF_USER, &qd_a->qd_flags)) - return -1; - else - return 1; - } - if (qd_a->qd_id < qd_b->qd_id) + if (qid_lt(qd_a->qd_id, qd_b->qd_id)) return -1; - if (qd_a->qd_id > qd_b->qd_id) + if (qid_lt(qd_b->qd_id, qd_a->qd_id)) return 1; - return 0; } @@ -602,9 +591,9 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change) if (!test_bit(QDF_CHANGE, &qd->qd_flags)) { qc->qc_change = 0; qc->qc_flags = 0; - if (test_bit(QDF_USER, &qd->qd_flags)) + if (qd->qd_id.type == USRQUOTA) qc->qc_flags = cpu_to_be32(GFS2_QCF_USER); - qc->qc_id = cpu_to_be32(qd->qd_id); + qc->qc_id = cpu_to_be32(from_kqid(&init_user_ns, qd->qd_id)); } x = be64_to_cpu(qc->qc_change) + change; @@ -1047,8 +1036,8 @@ static int print_message(struct gfs2_quota_data *qd, char *type) printk(KERN_INFO "GFS2: fsid=%s: quota %s for %s %u\n", sdp->sd_fsname, type, - (test_bit(QDF_USER, &qd->qd_flags)) ? "user" : "group", - qd->qd_id); + (qd->qd_id.type == USRQUOTA) ? "user" : "group", + from_kqid(&init_user_ns, qd->qd_id)); return 0; } @@ -1070,8 +1059,8 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { qd = ip->i_res->rs_qa_qd[x]; - if (!((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) || - (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags)))) + if (!(qid_eq(qd->qd_id, make_kqid_uid(uid)) || + qid_eq(qd->qd_id, make_kqid_gid(gid)))) continue; value = (s64)be64_to_cpu(qd->qd_qb.qb_value); @@ -1081,10 +1070,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) if (be64_to_cpu(qd->qd_qb.qb_limit) && (s64)be64_to_cpu(qd->qd_qb.qb_limit) < value) { print_message(qd, "exceeded"); - quota_send_warning(make_kqid(&init_user_ns, - test_bit(QDF_USER, &qd->qd_flags) ? - USRQUOTA : GRPQUOTA, - qd->qd_id), + quota_send_warning(qd->qd_id, sdp->sd_vfs->s_dev, QUOTA_NL_BHARDWARN); error = -EDQUOT; @@ -1094,10 +1080,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) time_after_eq(jiffies, qd->qd_last_warn + gfs2_tune_get(sdp, gt_quota_warn_period) * HZ)) { - quota_send_warning(make_kqid(&init_user_ns, - test_bit(QDF_USER, &qd->qd_flags) ? - USRQUOTA : GRPQUOTA, - qd->qd_id), + quota_send_warning(qd->qd_id, sdp->sd_vfs->s_dev, QUOTA_NL_BSOFTWARN); error = print_message(qd, "warning"); qd->qd_last_warn = jiffies; @@ -1121,8 +1104,8 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change, for (x = 0; x < ip->i_res->rs_qa_qd_num; x++) { qd = ip->i_res->rs_qa_qd[x]; - if ((qd->qd_id == uid && test_bit(QDF_USER, &qd->qd_flags)) || - (qd->qd_id == gid && !test_bit(QDF_USER, &qd->qd_flags))) { + if (qid_eq(qd->qd_id, make_kqid_uid(uid)) || + qid_eq(qd->qd_id, make_kqid_gid(gid))) { do_qc(qd, change); } } @@ -1183,8 +1166,7 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid) struct gfs2_holder q_gh; int error; - error = qd_get(sdp, qid.type == USRQUOTA ? QUOTA_USER : QUOTA_GROUP, - from_kqid(&init_user_ns, qid), &qd); + error = qd_get(sdp, qid, &qd); if (error) return error; @@ -1267,8 +1249,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) if (!qc.qc_change) continue; - error = qd_alloc(sdp, (qc.qc_flags & GFS2_QCF_USER), - from_kqid(&init_user_ns, qc.qc_id), &qd); + error = qd_alloc(sdp, qc.qc_id, &qd); if (error) { brelse(bh); goto fail; @@ -1509,7 +1490,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, else return -EINVAL; - error = qd_get(sdp, type, from_kqid(&init_user_ns, qid), &qd); + error = qd_get(sdp, qid, &qd); if (error) return error; error = do_glock(qd, FORCE, &q_gh); @@ -1564,7 +1545,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, if (fdq->d_fieldmask & ~GFS2_FIELDMASK) return -EINVAL; - error = qd_get(sdp, type, from_kqid(&init_user_ns, qid), &qd); + error = qd_get(sdp, qid, &qd); if (error) return error; -- cgit v1.2.3 From 236c64e4b79b78059ec3e17362d8f02f6dc06f26 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jan 2013 20:09:30 -0800 Subject: gfs2: Remove the QUOTA_USER and QUOTA_GROUP defines Remove the QUOTA_USER and QUOTA_GRUP defines. Remove the last vestigal users of QUOTA_USER and QUOTA_GROUP. Now that struct kqid is used throughout the gfs2 quota code the need there is to use QUOTA_USER and QUOTA_GROUP and the defines are just extraneous and confusing. Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/quota.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 8cb4d10cb16a..0bbb0407fd96 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -65,9 +65,6 @@ #include "inode.h" #include "util.h" -#define QUOTA_USER 1 -#define QUOTA_GROUP 0 - struct gfs2_quota_change_host { u64 qc_change; u32 qc_flags; /* GFS2_QCF_... */ @@ -1476,18 +1473,14 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, struct gfs2_quota_data *qd; struct gfs2_holder q_gh; int error; - int type; memset(fdq, 0, sizeof(struct fs_disk_quota)); if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) return -ESRCH; /* Crazy XFS error code */ - if (qid.type == USRQUOTA) - type = QUOTA_USER; - else if (qid.type == GRPQUOTA) - type = QUOTA_GROUP; - else + if ((qid.type != USRQUOTA) && + (qid.type != GRPQUOTA)) return -EINVAL; error = qd_get(sdp, qid, &qd); @@ -1499,7 +1492,7 @@ static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid, qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lksb.sb_lvbptr; fdq->d_version = FS_DQUOT_VERSION; - fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA; + fdq->d_flags = (qid.type == USRQUOTA) ? FS_USER_QUOTA : FS_GROUP_QUOTA; fdq->d_id = from_kqid_munged(current_user_ns(), qid); fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift; fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift; @@ -1526,21 +1519,13 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, int alloc_required; loff_t offset; int error; - int type; if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) return -ESRCH; /* Crazy XFS error code */ - switch(qid.type) { - case USRQUOTA: - type = QUOTA_USER; - break; - case GRPQUOTA: - type = QUOTA_GROUP; - break; - default: + if ((qid.type != USRQUOTA) && + (qid.type != GRPQUOTA)) return -EINVAL; - } if (fdq->d_fieldmask & ~GFS2_FIELDMASK) return -EINVAL; -- cgit v1.2.3 From 7c06b5d67225dc99ca81a33db3e055e08da857c3 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jan 2013 20:27:54 -0800 Subject: gfs2: Use kuid_t and kgid_t types where appropriate. Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/inode.c | 3 ++- fs/gfs2/quota.c | 8 ++++---- fs/gfs2/quota.h | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index aa1050287f3c..ce07ce4734f4 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1580,7 +1580,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) { struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); - u32 ouid, ogid, nuid, ngid; + kuid_t ouid, nuid; + kgid_t ogid, ngid; int error; ouid = inode->i_uid; diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 0bbb0407fd96..87f274039c4b 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -492,7 +492,7 @@ static void qdsb_put(struct gfs2_quota_data *qd) qd_put(qd); } -int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid) +int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_quota_data **qd; @@ -918,7 +918,7 @@ fail: return error; } -int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid) +int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_quota_data *qd; @@ -1039,7 +1039,7 @@ static int print_message(struct gfs2_quota_data *qd, char *type) return 0; } -int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) +int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) { struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_quota_data *qd; @@ -1088,7 +1088,7 @@ int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid) } void gfs2_quota_change(struct gfs2_inode *ip, s64 change, - u32 uid, u32 gid) + kuid_t uid, kgid_t gid) { struct gfs2_quota_data *qd; unsigned int x; diff --git a/fs/gfs2/quota.h b/fs/gfs2/quota.h index bef805de8491..4f5e6e44ed83 100644 --- a/fs/gfs2/quota.h +++ b/fs/gfs2/quota.h @@ -17,15 +17,15 @@ struct shrink_control; #define NO_UID_QUOTA_CHANGE INVALID_UID #define NO_GID_QUOTA_CHANGE INVALID_GID -extern int gfs2_quota_hold(struct gfs2_inode *ip, u32 uid, u32 gid); +extern int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid); extern void gfs2_quota_unhold(struct gfs2_inode *ip); -extern int gfs2_quota_lock(struct gfs2_inode *ip, u32 uid, u32 gid); +extern int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid); extern void gfs2_quota_unlock(struct gfs2_inode *ip); -extern int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid); +extern int gfs2_quota_check(struct gfs2_inode *ip, kuid_t uid, kgid_t gid); extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change, - u32 uid, u32 gid); + kuid_t uid, kgid_t gid); extern int gfs2_quota_sync(struct super_block *sb, int type); extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid); -- cgit v1.2.3 From 6b24c0d279eacfb499854d09ea7f2b69d1721a29 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 31 Jan 2013 21:56:13 -0800 Subject: gfs2: Use uid_eq and gid_eq where appropriate Where kuid_t values are compared use uid_eq and where kgid_t values are compared use gid_eq. This is unfortunately necessary because of the type safety that keeps someone from accidentally mixing kuids and kgids with other types. Cc: Steven Whitehouse Signed-off-by: "Eric W. Biederman" --- fs/gfs2/acl.c | 2 +- fs/gfs2/inode.c | 19 +++++++++++-------- fs/gfs2/quota.c | 6 ++++-- 3 files changed, 16 insertions(+), 11 deletions(-) (limited to 'fs/gfs2/quota.c') diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index f850020ad906..f69ac0af5496 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -237,7 +237,7 @@ static int gfs2_xattr_system_set(struct dentry *dentry, const char *name, return -EINVAL; if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) return value ? -EACCES : 0; - if ((current_fsuid() != inode->i_uid) && !capable(CAP_FOWNER)) + if (!uid_eq(current_fsuid(), inode->i_uid) && !capable(CAP_FOWNER)) return -EPERM; if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index ce07ce4734f4..bb7c754f46a2 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -368,10 +368,11 @@ static void munge_mode_uid_gid(const struct gfs2_inode *dip, struct inode *inode) { if (GFS2_SB(&dip->i_inode)->sd_args.ar_suiddir && - (dip->i_inode.i_mode & S_ISUID) && dip->i_inode.i_uid) { + (dip->i_inode.i_mode & S_ISUID) && + !uid_eq(dip->i_inode.i_uid, GLOBAL_ROOT_UID)) { if (S_ISDIR(inode->i_mode)) inode->i_mode |= S_ISUID; - else if (dip->i_inode.i_uid != current_fsuid()) + else if (!uid_eq(dip->i_inode.i_uid, current_fsuid())) inode->i_mode &= ~07111; inode->i_uid = dip->i_inode.i_uid; } else @@ -978,8 +979,8 @@ static int gfs2_unlink_ok(struct gfs2_inode *dip, const struct qstr *name, return -EPERM; if ((dip->i_inode.i_mode & S_ISVTX) && - dip->i_inode.i_uid != current_fsuid() && - ip->i_inode.i_uid != current_fsuid() && !capable(CAP_FOWNER)) + !uid_eq(dip->i_inode.i_uid, current_fsuid()) && + !uid_eq(ip->i_inode.i_uid, current_fsuid()) && !capable(CAP_FOWNER)) return -EPERM; if (IS_APPEND(&dip->i_inode)) @@ -1589,16 +1590,17 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) nuid = attr->ia_uid; ngid = attr->ia_gid; - if (!(attr->ia_valid & ATTR_UID) || ouid == nuid) + if (!(attr->ia_valid & ATTR_UID) || uid_eq(ouid, nuid)) ouid = nuid = NO_UID_QUOTA_CHANGE; - if (!(attr->ia_valid & ATTR_GID) || ogid == ngid) + if (!(attr->ia_valid & ATTR_GID) || gid_eq(ogid, ngid)) ogid = ngid = NO_GID_QUOTA_CHANGE; error = gfs2_quota_lock(ip, nuid, ngid); if (error) return error; - if (ouid != NO_UID_QUOTA_CHANGE || ogid != NO_GID_QUOTA_CHANGE) { + if (!uid_eq(ouid, NO_UID_QUOTA_CHANGE) || + !gid_eq(ogid, NO_GID_QUOTA_CHANGE)) { error = gfs2_quota_check(ip, nuid, ngid); if (error) goto out_gunlock_q; @@ -1612,7 +1614,8 @@ static int setattr_chown(struct inode *inode, struct iattr *attr) if (error) goto out_end_trans; - if (ouid != NO_UID_QUOTA_CHANGE || ogid != NO_GID_QUOTA_CHANGE) { + if (!uid_eq(ouid, NO_UID_QUOTA_CHANGE) || + !gid_eq(ogid, NO_GID_QUOTA_CHANGE)) { u64 blocks = gfs2_get_inode_blocks(&ip->i_inode); gfs2_quota_change(ip, -blocks, ouid, ogid); gfs2_quota_change(ip, blocks, nuid, ngid); diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 87f274039c4b..afd2e5d38e5a 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -525,7 +525,8 @@ int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) ip->i_res->rs_qa_qd_num++; qd++; - if (uid != NO_UID_QUOTA_CHANGE && uid != ip->i_inode.i_uid) { + if (!uid_eq(uid, NO_UID_QUOTA_CHANGE) && + !uid_eq(uid, ip->i_inode.i_uid)) { error = qdsb_get(sdp, make_kqid_uid(uid), qd); if (error) goto out; @@ -533,7 +534,8 @@ int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) qd++; } - if (gid != NO_GID_QUOTA_CHANGE && gid != ip->i_inode.i_gid) { + if (!gid_eq(gid, NO_GID_QUOTA_CHANGE) && + !gid_eq(gid, ip->i_inode.i_gid)) { error = qdsb_get(sdp, make_kqid_gid(gid), qd); if (error) goto out; -- cgit v1.2.3