diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/gfs2/quota.c | 20 | ||||
-rw-r--r-- | fs/quota/dquot.c | 8 | ||||
-rw-r--r-- | fs/quota/quota.c | 28 | ||||
-rw-r--r-- | fs/xfs/xfs_quotaops.c | 12 |
4 files changed, 43 insertions, 25 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 | ||
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 | 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 | ||
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 | 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 | ||
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 | 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 | ||
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 | 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) | |||
130 | static int quota_getquota(struct super_block *sb, int type, qid_t id, | 130 | static 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 | ||
188 | static int quota_setxstate(struct super_block *sb, int cmd, void __user *addr) | 196 | static 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 | ||
224 | static int quota_getxquota(struct super_block *sb, int type, qid_t id, | 236 | static 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( | |||
97 | STATIC int | 97 | STATIC int |
98 | xfs_fs_get_dqblk( | 98 | xfs_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 | ||
114 | STATIC int | 114 | STATIC int |
115 | xfs_fs_set_dqblk( | 115 | xfs_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 | ||
133 | const struct quotactl_ops xfs_quotactl_operations = { | 133 | const struct quotactl_ops xfs_quotactl_operations = { |