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 | |
| 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>
| -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 9fde5cd84f8..d0efe302b1c 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; |
