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:
parent
6ae09575b3
commit
c988afb5fa
|
@ -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;
|
||||||
|
|
Reference in New Issue