aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-09-16 05:07:49 -0400
committerEric W. Biederman <ebiederm@xmission.com>2012-09-18 04:01:39 -0400
commit74a8a103789465c4e67f38d1abb5cea770002601 (patch)
treeac650aebb368b353226651a74361d9ecc3da0d11
parente8a3e4719b7ec19288c56f22623f537cb78885c1 (diff)
userns: Convert qutoactl
Update the quotactl user space interface to successfull compile with user namespaces support enabled and to hand off quota identifiers to lower layers of the kernel in struct kqid instead of type and qid pairs. The quota on function is not converted because while it takes a quota type and an id. The id is the on disk quota format to use, which is something completely different. The signature of two struct quotactl_ops methods were changed to take struct kqid argumetns get_dqblk and set_dqblk. The dquot, xfs, and ocfs2 implementations of get_dqblk and set_dqblk are minimally changed so that the code continues to work with the change in parameter type. This is the first in a series of changes to always store quota identifiers in the kernel in struct kqid and only use raw type and qid values when interacting with on disk structures or userspace. Always using struct kqid internally makes it hard to miss places that need conversion to or from the kernel internal values. Cc: Jan Kara <jack@suse.cz> Cc: Dave Chinner <david@fromorbit.com> Cc: Mark Fasheh <mfasheh@suse.com> Cc: Joel Becker <jlbec@evilplan.org> Cc: Ben Myers <bpm@sgi.com> Cc: Alex Elder <elder@kernel.org> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r--fs/gfs2/quota.c20
-rw-r--r--fs/quota/dquot.c8
-rw-r--r--fs/quota/quota.c28
-rw-r--r--fs/xfs/xfs_quotaops.c12
-rw-r--r--include/linux/quota.h4
-rw-r--r--include/linux/quotaops.h4
-rw-r--r--init/Kconfig2
7 files changed, 48 insertions, 30 deletions
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index a3bde91645c2..b3115392d68f 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -1469,7 +1469,7 @@ static int gfs2_quota_get_xstate(struct super_block *sb,
1469 return 0; 1469 return 0;
1470} 1470}
1471 1471
1472static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id, 1472static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
1473 struct fs_disk_quota *fdq) 1473 struct fs_disk_quota *fdq)
1474{ 1474{
1475 struct gfs2_sbd *sdp = sb->s_fs_info; 1475 struct gfs2_sbd *sdp = sb->s_fs_info;
@@ -1477,20 +1477,21 @@ static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id,
1477 struct gfs2_quota_data *qd; 1477 struct gfs2_quota_data *qd;
1478 struct gfs2_holder q_gh; 1478 struct gfs2_holder q_gh;
1479 int error; 1479 int error;
1480 int type;
1480 1481
1481 memset(fdq, 0, sizeof(struct fs_disk_quota)); 1482 memset(fdq, 0, sizeof(struct fs_disk_quota));
1482 1483
1483 if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) 1484 if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
1484 return -ESRCH; /* Crazy XFS error code */ 1485 return -ESRCH; /* Crazy XFS error code */
1485 1486
1486 if (type == USRQUOTA) 1487 if (qid.type == USRQUOTA)
1487 type = QUOTA_USER; 1488 type = QUOTA_USER;
1488 else if (type == GRPQUOTA) 1489 else if (qid.type == GRPQUOTA)
1489 type = QUOTA_GROUP; 1490 type = QUOTA_GROUP;
1490 else 1491 else
1491 return -EINVAL; 1492 return -EINVAL;
1492 1493
1493 error = qd_get(sdp, type, id, &qd); 1494 error = qd_get(sdp, type, from_kqid(&init_user_ns, qid), &qd);
1494 if (error) 1495 if (error)
1495 return error; 1496 return error;
1496 error = do_glock(qd, FORCE, &q_gh); 1497 error = do_glock(qd, FORCE, &q_gh);
@@ -1500,7 +1501,7 @@ static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id,
1500 qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb; 1501 qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
1501 fdq->d_version = FS_DQUOT_VERSION; 1502 fdq->d_version = FS_DQUOT_VERSION;
1502 fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA; 1503 fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA;
1503 fdq->d_id = id; 1504 fdq->d_id = from_kqid(&init_user_ns, qid);
1504 fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift; 1505 fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift;
1505 fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift; 1506 fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift;
1506 fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift; 1507 fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift;
@@ -1514,7 +1515,7 @@ out:
1514/* GFS2 only supports a subset of the XFS fields */ 1515/* GFS2 only supports a subset of the XFS fields */
1515#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD|FS_DQ_BCOUNT) 1516#define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD|FS_DQ_BCOUNT)
1516 1517
1517static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id, 1518static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
1518 struct fs_disk_quota *fdq) 1519 struct fs_disk_quota *fdq)
1519{ 1520{
1520 struct gfs2_sbd *sdp = sb->s_fs_info; 1521 struct gfs2_sbd *sdp = sb->s_fs_info;
@@ -1526,11 +1527,12 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
1526 int alloc_required; 1527 int alloc_required;
1527 loff_t offset; 1528 loff_t offset;
1528 int error; 1529 int error;
1530 int type;
1529 1531
1530 if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) 1532 if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
1531 return -ESRCH; /* Crazy XFS error code */ 1533 return -ESRCH; /* Crazy XFS error code */
1532 1534
1533 switch(type) { 1535 switch(qid.type) {
1534 case USRQUOTA: 1536 case USRQUOTA:
1535 type = QUOTA_USER; 1537 type = QUOTA_USER;
1536 if (fdq->d_flags != FS_USER_QUOTA) 1538 if (fdq->d_flags != FS_USER_QUOTA)
@@ -1547,10 +1549,10 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
1547 1549
1548 if (fdq->d_fieldmask & ~GFS2_FIELDMASK) 1550 if (fdq->d_fieldmask & ~GFS2_FIELDMASK)
1549 return -EINVAL; 1551 return -EINVAL;
1550 if (fdq->d_id != id) 1552 if (fdq->d_id != from_kqid(&init_user_ns, qid))
1551 return -EINVAL; 1553 return -EINVAL;
1552 1554
1553 error = qd_get(sdp, type, id, &qd); 1555 error = qd_get(sdp, type, from_kqid(&init_user_ns, qid), &qd);
1554 if (error) 1556 if (error)
1555 return error; 1557 return error;
1556 1558
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 36a29b753c79..7714b169d646 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -2376,12 +2376,12 @@ static void do_get_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
2376 spin_unlock(&dq_data_lock); 2376 spin_unlock(&dq_data_lock);
2377} 2377}
2378 2378
2379int dquot_get_dqblk(struct super_block *sb, int type, qid_t id, 2379int dquot_get_dqblk(struct super_block *sb, struct kqid qid,
2380 struct fs_disk_quota *di) 2380 struct fs_disk_quota *di)
2381{ 2381{
2382 struct dquot *dquot; 2382 struct dquot *dquot;
2383 2383
2384 dquot = dqget(sb, id, type); 2384 dquot = dqget(sb, qid.type, from_kqid(&init_user_ns, qid));
2385 if (!dquot) 2385 if (!dquot)
2386 return -ESRCH; 2386 return -ESRCH;
2387 do_get_dqblk(dquot, di); 2387 do_get_dqblk(dquot, di);
@@ -2488,13 +2488,13 @@ static int do_set_dqblk(struct dquot *dquot, struct fs_disk_quota *di)
2488 return 0; 2488 return 0;
2489} 2489}
2490 2490
2491int dquot_set_dqblk(struct super_block *sb, int type, qid_t id, 2491int dquot_set_dqblk(struct super_block *sb, struct kqid qid,
2492 struct fs_disk_quota *di) 2492 struct fs_disk_quota *di)
2493{ 2493{
2494 struct dquot *dquot; 2494 struct dquot *dquot;
2495 int rc; 2495 int rc;
2496 2496
2497 dquot = dqget(sb, id, type); 2497 dquot = dqget(sb, qid.type, from_kqid(&init_user_ns, qid));
2498 if (!dquot) { 2498 if (!dquot) {
2499 rc = -ESRCH; 2499 rc = -ESRCH;
2500 goto out; 2500 goto out;
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 6f155788cbc6..ff0135d6bc51 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -32,8 +32,8 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
32 /* allow to query information for dquots we "own" */ 32 /* allow to query information for dquots we "own" */
33 case Q_GETQUOTA: 33 case Q_GETQUOTA:
34 case Q_XGETQUOTA: 34 case Q_XGETQUOTA:
35 if ((type == USRQUOTA && current_euid() == id) || 35 if ((type == USRQUOTA && uid_eq(current_euid(), make_kuid(current_user_ns(), id))) ||
36 (type == GRPQUOTA && in_egroup_p(id))) 36 (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id))))
37 break; 37 break;
38 /*FALLTHROUGH*/ 38 /*FALLTHROUGH*/
39 default: 39 default:
@@ -130,13 +130,17 @@ static void copy_to_if_dqblk(struct if_dqblk *dst, struct fs_disk_quota *src)
130static int quota_getquota(struct super_block *sb, int type, qid_t id, 130static int quota_getquota(struct super_block *sb, int type, qid_t id,
131 void __user *addr) 131 void __user *addr)
132{ 132{
133 struct kqid qid;
133 struct fs_disk_quota fdq; 134 struct fs_disk_quota fdq;
134 struct if_dqblk idq; 135 struct if_dqblk idq;
135 int ret; 136 int ret;
136 137
137 if (!sb->s_qcop->get_dqblk) 138 if (!sb->s_qcop->get_dqblk)
138 return -ENOSYS; 139 return -ENOSYS;
139 ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq); 140 qid = make_kqid(current_user_ns(), type, id);
141 if (!qid_valid(qid))
142 return -EINVAL;
143 ret = sb->s_qcop->get_dqblk(sb, qid, &fdq);
140 if (ret) 144 if (ret)
141 return ret; 145 return ret;
142 copy_to_if_dqblk(&idq, &fdq); 146 copy_to_if_dqblk(&idq, &fdq);
@@ -176,13 +180,17 @@ static int quota_setquota(struct super_block *sb, int type, qid_t id,
176{ 180{
177 struct fs_disk_quota fdq; 181 struct fs_disk_quota fdq;
178 struct if_dqblk idq; 182 struct if_dqblk idq;
183 struct kqid qid;
179 184
180 if (copy_from_user(&idq, addr, sizeof(idq))) 185 if (copy_from_user(&idq, addr, sizeof(idq)))
181 return -EFAULT; 186 return -EFAULT;
182 if (!sb->s_qcop->set_dqblk) 187 if (!sb->s_qcop->set_dqblk)
183 return -ENOSYS; 188 return -ENOSYS;
189 qid = make_kqid(current_user_ns(), type, id);
190 if (!qid_valid(qid))
191 return -EINVAL;
184 copy_from_if_dqblk(&fdq, &idq); 192 copy_from_if_dqblk(&fdq, &idq);
185 return sb->s_qcop->set_dqblk(sb, type, id, &fdq); 193 return sb->s_qcop->set_dqblk(sb, qid, &fdq);
186} 194}
187 195
188static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr) 196static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
@@ -213,23 +221,31 @@ static int quota_setxquota(struct super_block *sb, int type, qid_t id,
213 void __user *addr) 221 void __user *addr)
214{ 222{
215 struct fs_disk_quota fdq; 223 struct fs_disk_quota fdq;
224 struct kqid qid;
216 225
217 if (copy_from_user(&fdq, addr, sizeof(fdq))) 226 if (copy_from_user(&fdq, addr, sizeof(fdq)))
218 return -EFAULT; 227 return -EFAULT;
219 if (!sb->s_qcop->set_dqblk) 228 if (!sb->s_qcop->set_dqblk)
220 return -ENOSYS; 229 return -ENOSYS;
221 return sb->s_qcop->set_dqblk(sb, type, id, &fdq); 230 qid = make_kqid(current_user_ns(), type, id);
231 if (!qid_valid(qid))
232 return -EINVAL;
233 return sb->s_qcop->set_dqblk(sb, qid, &fdq);
222} 234}
223 235
224static int quota_getxquota(struct super_block *sb, int type, qid_t id, 236static int quota_getxquota(struct super_block *sb, int type, qid_t id,
225 void __user *addr) 237 void __user *addr)
226{ 238{
227 struct fs_disk_quota fdq; 239 struct fs_disk_quota fdq;
240 struct kqid qid;
228 int ret; 241 int ret;
229 242
230 if (!sb->s_qcop->get_dqblk) 243 if (!sb->s_qcop->get_dqblk)
231 return -ENOSYS; 244 return -ENOSYS;
232 ret = sb->s_qcop->get_dqblk(sb, type, id, &fdq); 245 qid = make_kqid(current_user_ns(), type, id);
246 if (!qid_valid(qid))
247 return -EINVAL;
248 ret = sb->s_qcop->get_dqblk(sb, qid, &fdq);
233 if (!ret && copy_to_user(addr, &fdq, sizeof(fdq))) 249 if (!ret && copy_to_user(addr, &fdq, sizeof(fdq)))
234 return -EFAULT; 250 return -EFAULT;
235 return ret; 251 return ret;
diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c
index fed504fc2999..71926d630527 100644
--- a/fs/xfs/xfs_quotaops.c
+++ b/fs/xfs/xfs_quotaops.c
@@ -97,8 +97,7 @@ xfs_fs_set_xstate(
97STATIC int 97STATIC int
98xfs_fs_get_dqblk( 98xfs_fs_get_dqblk(
99 struct super_block *sb, 99 struct super_block *sb,
100 int type, 100 struct kqid qid,
101 qid_t id,
102 struct fs_disk_quota *fdq) 101 struct fs_disk_quota *fdq)
103{ 102{
104 struct xfs_mount *mp = XFS_M(sb); 103 struct xfs_mount *mp = XFS_M(sb);
@@ -108,14 +107,14 @@ xfs_fs_get_dqblk(
108 if (!XFS_IS_QUOTA_ON(mp)) 107 if (!XFS_IS_QUOTA_ON(mp))
109 return -ESRCH; 108 return -ESRCH;
110 109
111 return -xfs_qm_scall_getquota(mp, id, xfs_quota_type(type), fdq); 110 return -xfs_qm_scall_getquota(mp, from_kqid(&init_user_ns, qid),
111 xfs_quota_type(qid.type), fdq);
112} 112}
113 113
114STATIC int 114STATIC int
115xfs_fs_set_dqblk( 115xfs_fs_set_dqblk(
116 struct super_block *sb, 116 struct super_block *sb,
117 int type, 117 struct kqid qid,
118 qid_t id,
119 struct fs_disk_quota *fdq) 118 struct fs_disk_quota *fdq)
120{ 119{
121 struct xfs_mount *mp = XFS_M(sb); 120 struct xfs_mount *mp = XFS_M(sb);
@@ -127,7 +126,8 @@ xfs_fs_set_dqblk(
127 if (!XFS_IS_QUOTA_ON(mp)) 126 if (!XFS_IS_QUOTA_ON(mp))
128 return -ESRCH; 127 return -ESRCH;
129 128
130 return -xfs_qm_scall_setqlim(mp, id, xfs_quota_type(type), fdq); 129 return -xfs_qm_scall_setqlim(mp, from_kqid(&init_user_ns, qid),
130 xfs_quota_type(qid.type), fdq);
131} 131}
132 132
133const struct quotactl_ops xfs_quotactl_operations = { 133const struct quotactl_ops xfs_quotactl_operations = {
diff --git a/include/linux/quota.h b/include/linux/quota.h
index 00ac8d846c14..f96427a949b2 100644
--- a/include/linux/quota.h
+++ b/include/linux/quota.h
@@ -461,8 +461,8 @@ struct quotactl_ops {
461 int (*quota_sync)(struct super_block *, int); 461 int (*quota_sync)(struct super_block *, int);
462 int (*get_info)(struct super_block *, int, struct if_dqinfo *); 462 int (*get_info)(struct super_block *, int, struct if_dqinfo *);
463 int (*set_info)(struct super_block *, int, struct if_dqinfo *); 463 int (*set_info)(struct super_block *, int, struct if_dqinfo *);
464 int (*get_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *); 464 int (*get_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *);
465 int (*set_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *); 465 int (*set_dqblk)(struct super_block *, struct kqid, struct fs_disk_quota *);
466 int (*get_xstate)(struct super_block *, struct fs_quota_stat *); 466 int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
467 int (*set_xstate)(struct super_block *, unsigned int, int); 467 int (*set_xstate)(struct super_block *, unsigned int, int);
468}; 468};
diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h
index ec6b65feaaba..bd3730d76fd9 100644
--- a/include/linux/quotaops.h
+++ b/include/linux/quotaops.h
@@ -87,9 +87,9 @@ int dquot_writeback_dquots(struct super_block *sb, int type);
87int dquot_quota_sync(struct super_block *sb, int type); 87int dquot_quota_sync(struct super_block *sb, int type);
88int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); 88int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
89int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii); 89int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
90int dquot_get_dqblk(struct super_block *sb, int type, qid_t id, 90int dquot_get_dqblk(struct super_block *sb, struct kqid id,
91 struct fs_disk_quota *di); 91 struct fs_disk_quota *di);
92int dquot_set_dqblk(struct super_block *sb, int type, qid_t id, 92int dquot_set_dqblk(struct super_block *sb, struct kqid id,
93 struct fs_disk_quota *di); 93 struct fs_disk_quota *di);
94 94
95int __dquot_transfer(struct inode *inode, struct dquot **transfer_to); 95int __dquot_transfer(struct inode *inode, struct dquot **transfer_to);
diff --git a/init/Kconfig b/init/Kconfig
index 33d231cd3cc6..15bb1dcdebef 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -928,7 +928,7 @@ config UIDGID_CONVERTED
928 depends on IMA = n 928 depends on IMA = n
929 depends on EVM = n 929 depends on EVM = n
930 depends on QUOTA = n 930 depends on QUOTA = n
931 depends on QUOTACTL = n 931 depends on QUOTA_NETLINK_INTERFACE = n
932 932
933 # Networking 933 # Networking
934 depends on NET_9P = n 934 depends on NET_9P = n