aboutsummaryrefslogtreecommitdiffstats
path: root/fs/quota
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 /fs/quota
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>
Diffstat (limited to 'fs/quota')
-rw-r--r--fs/quota/dquot.c8
-rw-r--r--fs/quota/quota.c28
2 files changed, 26 insertions, 10 deletions
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;