Commit 74a8a103789465c4e67f38d1abb5cea770002601

Authored by Eric W. Biederman
1 parent e8a3e4719b

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>

Showing 7 changed files with 48 additions and 30 deletions Side-by-side Diff

... ... @@ -1469,7 +1469,7 @@
1469 1469 return 0;
1470 1470 }
1471 1471  
1472   -static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id,
  1472 +static int gfs2_get_dqblk(struct super_block *sb, struct kqid qid,
1473 1473 struct fs_disk_quota *fdq)
1474 1474 {
1475 1475 struct gfs2_sbd *sdp = sb->s_fs_info;
1476 1476  
1477 1477  
1478 1478  
... ... @@ -1477,20 +1477,21 @@
1477 1477 struct gfs2_quota_data *qd;
1478 1478 struct gfs2_holder q_gh;
1479 1479 int error;
  1480 + int type;
1480 1481  
1481 1482 memset(fdq, 0, sizeof(struct fs_disk_quota));
1482 1483  
1483 1484 if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
1484 1485 return -ESRCH; /* Crazy XFS error code */
1485 1486  
1486   - if (type == USRQUOTA)
  1487 + if (qid.type == USRQUOTA)
1487 1488 type = QUOTA_USER;
1488   - else if (type == GRPQUOTA)
  1489 + else if (qid.type == GRPQUOTA)
1489 1490 type = QUOTA_GROUP;
1490 1491 else
1491 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 1495 if (error)
1495 1496 return error;
1496 1497 error = do_glock(qd, FORCE, &q_gh);
... ... @@ -1500,7 +1501,7 @@
1500 1501 qlvb = (struct gfs2_quota_lvb *)qd->qd_gl->gl_lvb;
1501 1502 fdq->d_version = FS_DQUOT_VERSION;
1502 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 1505 fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift;
1505 1506 fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift;
1506 1507 fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift;
... ... @@ -1514,7 +1515,7 @@
1514 1515 /* GFS2 only supports a subset of the XFS fields */
1515 1516 #define GFS2_FIELDMASK (FS_DQ_BSOFT|FS_DQ_BHARD|FS_DQ_BCOUNT)
1516 1517  
1517   -static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id,
  1518 +static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid,
1518 1519 struct fs_disk_quota *fdq)
1519 1520 {
1520 1521 struct gfs2_sbd *sdp = sb->s_fs_info;
1521 1522  
... ... @@ -1526,11 +1527,12 @@
1526 1527 int alloc_required;
1527 1528 loff_t offset;
1528 1529 int error;
  1530 + int type;
1529 1531  
1530 1532 if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF)
1531 1533 return -ESRCH; /* Crazy XFS error code */
1532 1534  
1533   - switch(type) {
  1535 + switch(qid.type) {
1534 1536 case USRQUOTA:
1535 1537 type = QUOTA_USER;
1536 1538 if (fdq->d_flags != FS_USER_QUOTA)
1537 1539  
... ... @@ -1547,10 +1549,10 @@
1547 1549  
1548 1550 if (fdq->d_fieldmask & ~GFS2_FIELDMASK)
1549 1551 return -EINVAL;
1550   - if (fdq->d_id != id)
  1552 + if (fdq->d_id != from_kqid(&init_user_ns, qid))
1551 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 1556 if (error)
1555 1557 return error;
1556 1558  
... ... @@ -2376,12 +2376,12 @@
2376 2376 spin_unlock(&dq_data_lock);
2377 2377 }
2378 2378  
2379   -int dquot_get_dqblk(struct super_block *sb, int type, qid_t id,
  2379 +int dquot_get_dqblk(struct super_block *sb, struct kqid qid,
2380 2380 struct fs_disk_quota *di)
2381 2381 {
2382 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 2385 if (!dquot)
2386 2386 return -ESRCH;
2387 2387 do_get_dqblk(dquot, di);
2388 2388  
... ... @@ -2488,13 +2488,13 @@
2488 2488 return 0;
2489 2489 }
2490 2490  
2491   -int dquot_set_dqblk(struct super_block *sb, int type, qid_t id,
  2491 +int dquot_set_dqblk(struct super_block *sb, struct kqid qid,
2492 2492 struct fs_disk_quota *di)
2493 2493 {
2494 2494 struct dquot *dquot;
2495 2495 int rc;
2496 2496  
2497   - dquot = dqget(sb, id, type);
  2497 + dquot = dqget(sb, qid.type, from_kqid(&init_user_ns, qid));
2498 2498 if (!dquot) {
2499 2499 rc = -ESRCH;
2500 2500 goto out;
... ... @@ -32,8 +32,8 @@
32 32 /* allow to query information for dquots we "own" */
33 33 case Q_GETQUOTA:
34 34 case Q_XGETQUOTA:
35   - if ((type == USRQUOTA && current_euid() == id) ||
36   - (type == GRPQUOTA && in_egroup_p(id)))
  35 + if ((type == USRQUOTA && uid_eq(current_euid(), make_kuid(current_user_ns(), id))) ||
  36 + (type == GRPQUOTA && in_egroup_p(make_kgid(current_user_ns(), id))))
37 37 break;
38 38 /*FALLTHROUGH*/
39 39 default:
40 40  
... ... @@ -130,13 +130,17 @@
130 130 static int quota_getquota(struct super_block *sb, int type, qid_t id,
131 131 void __user *addr)
132 132 {
  133 + struct kqid qid;
133 134 struct fs_disk_quota fdq;
134 135 struct if_dqblk idq;
135 136 int ret;
136 137  
137 138 if (!sb->s_qcop->get_dqblk)
138 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 144 if (ret)
141 145 return ret;
142 146 copy_to_if_dqblk(&idq, &fdq);
143 147  
144 148  
... ... @@ -176,13 +180,17 @@
176 180 {
177 181 struct fs_disk_quota fdq;
178 182 struct if_dqblk idq;
  183 + struct kqid qid;
179 184  
180 185 if (copy_from_user(&idq, addr, sizeof(idq)))
181 186 return -EFAULT;
182 187 if (!sb->s_qcop->set_dqblk)
183 188 return -ENOSYS;
  189 + qid = make_kqid(current_user_ns(), type, id);
  190 + if (!qid_valid(qid))
  191 + return -EINVAL;
184 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  
188 196 static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr)
189 197  
190 198  
191 199  
... ... @@ -213,23 +221,31 @@
213 221 void __user *addr)
214 222 {
215 223 struct fs_disk_quota fdq;
  224 + struct kqid qid;
216 225  
217 226 if (copy_from_user(&fdq, addr, sizeof(fdq)))
218 227 return -EFAULT;
219 228 if (!sb->s_qcop->set_dqblk)
220 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  
224 236 static int quota_getxquota(struct super_block *sb, int type, qid_t id,
225 237 void __user *addr)
226 238 {
227 239 struct fs_disk_quota fdq;
  240 + struct kqid qid;
228 241 int ret;
229 242  
230 243 if (!sb->s_qcop->get_dqblk)
231 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 249 if (!ret && copy_to_user(addr, &fdq, sizeof(fdq)))
234 250 return -EFAULT;
235 251 return ret;
fs/xfs/xfs_quotaops.c
... ... @@ -97,8 +97,7 @@
97 97 STATIC int
98 98 xfs_fs_get_dqblk(
99 99 struct super_block *sb,
100   - int type,
101   - qid_t id,
  100 + struct kqid qid,
102 101 struct fs_disk_quota *fdq)
103 102 {
104 103 struct xfs_mount *mp = XFS_M(sb);
105 104  
... ... @@ -108,14 +107,14 @@
108 107 if (!XFS_IS_QUOTA_ON(mp))
109 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  
114 114 STATIC int
115 115 xfs_fs_set_dqblk(
116 116 struct super_block *sb,
117   - int type,
118   - qid_t id,
  117 + struct kqid qid,
119 118 struct fs_disk_quota *fdq)
120 119 {
121 120 struct xfs_mount *mp = XFS_M(sb);
... ... @@ -127,7 +126,8 @@
127 126 if (!XFS_IS_QUOTA_ON(mp))
128 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  
133 133 const struct quotactl_ops xfs_quotactl_operations = {
include/linux/quota.h
... ... @@ -461,8 +461,8 @@
461 461 int (*quota_sync)(struct super_block *, int);
462 462 int (*get_info)(struct super_block *, int, struct if_dqinfo *);
463 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 *);
465   - int (*set_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 *, struct kqid, struct fs_disk_quota *);
466 466 int (*get_xstate)(struct super_block *, struct fs_quota_stat *);
467 467 int (*set_xstate)(struct super_block *, unsigned int, int);
468 468 };
include/linux/quotaops.h
... ... @@ -87,9 +87,9 @@
87 87 int dquot_quota_sync(struct super_block *sb, int type);
88 88 int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
89 89 int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
90   -int dquot_get_dqblk(struct super_block *sb, int type, qid_t id,
  90 +int dquot_get_dqblk(struct super_block *sb, struct kqid id,
91 91 struct fs_disk_quota *di);
92   -int dquot_set_dqblk(struct super_block *sb, int type, qid_t id,
  92 +int dquot_set_dqblk(struct super_block *sb, struct kqid id,
93 93 struct fs_disk_quota *di);
94 94  
95 95 int __dquot_transfer(struct inode *inode, struct dquot **transfer_to);
... ... @@ -928,7 +928,7 @@
928 928 depends on IMA = n
929 929 depends on EVM = n
930 930 depends on QUOTA = n
931   - depends on QUOTACTL = n
  931 + depends on QUOTA_NETLINK_INTERFACE = n
932 932  
933 933 # Networking
934 934 depends on NET_9P = n