dect
/
linux-2.6
Archived
13
0
Fork 0

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>
This commit is contained in:
Christoph Hellwig 2010-02-16 03:44:50 -05:00 committed by Jan Kara
parent 6ae09575b3
commit c988afb5fa
1 changed files with 31 additions and 61 deletions

View File

@ -21,69 +21,30 @@
#include <net/netlink.h> #include <net/netlink.h>
#include <net/genetlink.h> #include <net/genetlink.h>
/* Check validity of generic quotactl commands */ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
qid_t id)
{ {
if (type >= MAXQUOTAS) switch (cmd) {
return -EINVAL; /* these commands do not require any special privilegues */
if (!sb && cmd != Q_SYNC) case Q_GETFMT:
return -ENODEV; case Q_SYNC:
/* Is operation supported? */ case Q_GETINFO:
if (sb && !sb->s_qcop) case Q_XGETQSTAT:
return -ENOSYS; case Q_XQUOTASYNC:
break;
/* Check privileges */ /* allow to query information for dquots we "own" */
if (cmd == Q_GETQUOTA) { case Q_GETQUOTA:
if (((type == USRQUOTA && current_euid() != id) || case Q_XGETQUOTA:
(type == GRPQUOTA && !in_egroup_p(id))) && if ((type == USRQUOTA && current_euid() == id) ||
!capable(CAP_SYS_ADMIN)) (type == GRPQUOTA && in_egroup_p(id)))
return -EPERM; break;
} /*FALLTHROUGH*/
else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO) default:
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
return 0;
}
/* Check validity of XFS Quota Manager commands */
static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd,
qid_t id)
{
if (type >= XQM_MAXQUOTAS)
return -EINVAL;
if (!sb)
return -ENODEV;
if (!sb->s_qcop)
return -ENOSYS;
/* Check privileges */
if (cmd == Q_XGETQUOTA) {
if (((type == XQM_USRQUOTA && current_euid() != id) ||
(type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
!capable(CAP_SYS_ADMIN))
return -EPERM;
} else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) {
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
} }
return 0; return security_quotactl(cmd, type, id, sb);
}
static int check_quotactl_valid(struct super_block *sb, int type, int cmd,
qid_t id)
{
int error;
if (XQM_COMMAND(cmd))
error = xqm_quotactl_valid(sb, type, cmd, id);
else
error = generic_quotactl_valid(sb, type, cmd, id);
if (!error)
error = security_quotactl(cmd, type, id, sb);
return error;
} }
#ifdef CONFIG_QUOTA #ifdef CONFIG_QUOTA
@ -313,6 +274,17 @@ static int quota_getxquota(struct super_block *sb, int type, qid_t id,
static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
void __user *addr) void __user *addr)
{ {
int ret;
if (type >= (XQM_COMMAND(cmd) ? XQM_MAXQUOTAS : MAXQUOTAS))
return -EINVAL;
if (!sb->s_qcop)
return -ENOSYS;
ret = check_quotactl_permission(sb, type, cmd, id);
if (ret < 0)
return ret;
switch (cmd) { switch (cmd) {
case Q_QUOTAON: case Q_QUOTAON:
return quota_quotaon(sb, type, cmd, id, addr); return quota_quotaon(sb, type, cmd, id, addr);
@ -413,9 +385,7 @@ SYSCALL_DEFINE4(quotactl, unsigned int, cmd, const char __user *, special,
if (IS_ERR(sb)) if (IS_ERR(sb))
return PTR_ERR(sb); return PTR_ERR(sb);
ret = check_quotactl_valid(sb, type, cmds, id); ret = do_quotactl(sb, type, cmds, id, addr);
if (ret >= 0)
ret = do_quotactl(sb, type, cmds, id, addr);
drop_super(sb); drop_super(sb);
return ret; return ret;