diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-02-16 03:44:50 -0500 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2010-03-04 18:20:22 -0500 |
commit | c988afb5fa3fc450207c3dfc0ce535f4bfdae4d1 (patch) | |
tree | dcb9b4e11c4429ee79198ee3a7de43d734c1cbfe /fs/quota | |
parent | 6ae09575b3c951ad77c07d068b8dbbc09031b2d1 (diff) |
quota: simplify permission checking
Stop having complicated different routines for checking permissions for
XQM vs "VFS" quotas. Instead do the checks for having sb->s_qcop and
a valid type directly in do_quotactl, and munge the *quotactl_valid functions
into a check_quotactl_permission helper that only checks for permissions.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/quota')
-rw-r--r-- | fs/quota/quota.c | 92 |
1 files changed, 31 insertions, 61 deletions
diff --git a/fs/quota/quota.c b/fs/quota/quota.c index 9fde5cd84f8d..d0efe302b1c1 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c | |||
@@ -21,69 +21,30 @@ | |||
21 | #include <net/netlink.h> | 21 | #include <net/netlink.h> |
22 | #include <net/genetlink.h> | 22 | #include <net/genetlink.h> |
23 | 23 | ||
24 | /* Check validity of generic quotactl commands */ | 24 | static int check_quotactl_permission(struct super_block *sb, int type, int cmd, |
25 | static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, | 25 | qid_t id) |
26 | qid_t id) | ||
27 | { | 26 | { |
28 | if (type >= MAXQUOTAS) | 27 | switch (cmd) { |
29 | return -EINVAL; | 28 | /* these commands do not require any special privilegues */ |
30 | if (!sb && cmd != Q_SYNC) | 29 | case Q_GETFMT: |
31 | return -ENODEV; | 30 | case Q_SYNC: |
32 | /* Is operation supported? */ | 31 | case Q_GETINFO: |
33 | if (sb && !sb->s_qcop) | 32 | case Q_XGETQSTAT: |
34 | return -ENOSYS; | 33 | case Q_XQUOTASYNC: |
35 | 34 | break; | |
36 | /* Check privileges */ | 35 | /* allow to query information for dquots we "own" */ |
37 | if (cmd == Q_GETQUOTA) { | 36 | case Q_GETQUOTA: |
38 | if (((type == USRQUOTA && current_euid() != id) || | 37 | case Q_XGETQUOTA: |
39 | (type == GRPQUOTA && !in_egroup_p(id))) && | 38 | if ((type == USRQUOTA && current_euid() == id) || |
40 | !capable(CAP_SYS_ADMIN)) | 39 | (type == GRPQUOTA && in_egroup_p(id))) |
41 | return -EPERM; | 40 | break; |
42 | } | 41 | /*FALLTHROUGH*/ |
43 | else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO) | 42 | default: |
44 | if (!capable(CAP_SYS_ADMIN)) | ||
45 | return -EPERM; | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | /* Check validity of XFS Quota Manager commands */ | ||
51 | static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, | ||
52 | qid_t id) | ||
53 | { | ||
54 | if (type >= XQM_MAXQUOTAS) | ||
55 | return -EINVAL; | ||
56 | if (!sb) | ||
57 | return -ENODEV; | ||
58 | if (!sb->s_qcop) | ||
59 | return -ENOSYS; | ||
60 | |||
61 | /* Check privileges */ | ||
62 | if (cmd == Q_XGETQUOTA) { | ||
63 | if (((type == XQM_USRQUOTA && current_euid() != id) || | ||
64 | (type == XQM_GRPQUOTA && !in_egroup_p(id))) && | ||
65 | !capable(CAP_SYS_ADMIN)) | ||
66 | return -EPERM; | ||
67 | } else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) { | ||
68 | if (!capable(CAP_SYS_ADMIN)) | 43 | if (!capable(CAP_SYS_ADMIN)) |
69 | return -EPERM; | 44 | return -EPERM; |
70 | } | 45 | } |
71 | 46 | ||
72 | return 0; | 47 | return security_quotactl(cmd, type, id, sb); |
73 | } | ||
74 | |||
75 | static int check_quotactl_valid(struct super_block *sb, int type, int cmd, | ||
76 | qid_t id) | ||
77 | { | ||
78 | int error; | ||
79 | |||
80 | if (XQM_COMMAND(cmd)) | ||
81 | error = xqm_quotactl_valid(sb, type, cmd, id); | ||
82 | else | ||
83 | error = generic_quotactl_valid(sb, type, cmd, id); | ||
84 | if (!error) | ||
85 | error = security_quotactl(cmd, type, id, sb); | ||
86 | return error; | ||
87 | } | 48 | } |
88 | 49 | ||
89 | #ifdef CONFIG_QUOTA | 50 | #ifdef CONFIG_QUOTA |
@@ -313,6 +274,17 @@ static int quota_getxquota(struct super_block *sb, int type, qid_t id, | |||
313 | static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, | 274 | static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, |
314 | void __user *addr) | 275 | void __user *addr) |
315 | { | 276 | { |
277 | int ret; | ||
278 | |||
279 | if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS)) | ||
280 | return -EINVAL; | ||
281 | if (!sb->s_qcop) | ||
282 | return -ENOSYS; | ||
283 | |||
284 | ret = check_quotactl_permission(sb, type, cmd, id); | ||
285 | if (ret < 0) | ||
286 | return ret; | ||
287 | |||
316 | switch (cmd) { | 288 | switch (cmd) { |
317 | case Q_QUOTAON: | 289 | case Q_QUOTAON: |
318 | return quota_quotaon(sb, type, cmd, id, addr); | 290 | return quota_quotaon(sb, type, cmd, id, addr); |
@@ -413,9 +385,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special, | |||
413 | if (IS_ERR(sb)) | 385 | if (IS_ERR(sb)) |
414 | return PTR_ERR(sb); | 386 | return PTR_ERR(sb); |
415 | 387 | ||
416 | ret = check_quotactl_valid(sb, type, cmds, id); | 388 | ret = do_quotactl(sb, type, cmds, id, addr); |
417 | if (ret >= 0) | ||
418 | ret = do_quotactl(sb, type, cmds, id, addr); | ||
419 | 389 | ||
420 | drop_super(sb); | 390 | drop_super(sb); |
421 | return ret; | 391 | return ret; |