Commit 90e50069 authored by Jan Kara's avatar Jan Kara Committed by Linus Torvalds

[PATCH] Quotactl changes for XFS

Attached patch from Nathan splits the checks done in quotactl() in XFS and
VFS parts (it's mostly just moving of code back and forth).  It's done
mainly because XFS guys would like to implement more types of quotas and I
don't want them to slow down the general VFS case.
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a5f17cb2
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
#include <linux/syscalls.h> #include <linux/syscalls.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
/* Check validity of quotactl */ /* Check validity of generic quotactl commands */
static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
{ {
if (type >= MAXQUOTAS) if (type >= MAXQUOTAS)
return -EINVAL; return -EINVAL;
...@@ -58,6 +58,48 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t ...@@ -58,6 +58,48 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t
if (sb && !sb->s_qcop->quota_sync) if (sb && !sb->s_qcop->quota_sync)
return -ENOSYS; return -ENOSYS;
break; break;
default:
return -EINVAL;
}
/* Is quota turned on for commands which need it? */
switch (cmd) {
case Q_GETFMT:
case Q_GETINFO:
case Q_QUOTAOFF:
case Q_SETINFO:
case Q_SETQUOTA:
case Q_GETQUOTA:
/* This is just informative test so we are satisfied without a lock */
if (!sb_has_quota_enabled(sb, type))
return -ESRCH;
}
/* Check privileges */
if (cmd == Q_GETQUOTA) {
if (((type == USRQUOTA && current->euid != id) ||
(type == GRPQUOTA && !in_egroup_p(id))) &&
!capable(CAP_SYS_ADMIN))
return -EPERM;
}
else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO)
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;
switch (cmd) {
case Q_XQUOTAON: case Q_XQUOTAON:
case Q_XQUOTAOFF: case Q_XQUOTAOFF:
case Q_XQUOTARM: case Q_XQUOTARM:
...@@ -80,30 +122,31 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t ...@@ -80,30 +122,31 @@ static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t
return -EINVAL; return -EINVAL;
} }
/* Is quota turned on for commands which need it? */
switch (cmd) {
case Q_GETFMT:
case Q_GETINFO:
case Q_QUOTAOFF:
case Q_SETINFO:
case Q_SETQUOTA:
case Q_GETQUOTA:
/* This is just informative test so we are satisfied without a lock */
if (!sb_has_quota_enabled(sb, type))
return -ESRCH;
}
/* Check privileges */ /* Check privileges */
if (cmd == Q_GETQUOTA || cmd == Q_XGETQUOTA) { if (cmd == Q_XGETQUOTA) {
if (((type == USRQUOTA && current->euid != id) || if (((type == XQM_USRQUOTA && current->euid != id) ||
(type == GRPQUOTA && !in_egroup_p(id))) && (type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
!capable(CAP_SYS_ADMIN)) !capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
} } else if (cmd != Q_XGETQSTAT) {
else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO && cmd != Q_XGETQSTAT)
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
}
return 0;
}
static int check_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id)
{
int error;
return security_quotactl (cmd, type, id, sb); 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;
} }
static struct super_block *get_super_to_sync(int type) static struct super_block *get_super_to_sync(int type)
......
...@@ -28,6 +28,12 @@ ...@@ -28,6 +28,12 @@
*/ */
#define XQM_CMD(x) (('X'<<8)+(x)) /* note: forms first QCMD argument */ #define XQM_CMD(x) (('X'<<8)+(x)) /* note: forms first QCMD argument */
#define XQM_COMMAND(x) (((x) & (0xff<<8)) == ('X'<<8)) /* test if for XFS */
#define XQM_USRQUOTA 0 /* system call user quota type */
#define XQM_GRPQUOTA 1 /* system call group quota type */
#define XQM_MAXQUOTAS 2
#define Q_XQUOTAON XQM_CMD(1) /* enable accounting/enforcement */ #define Q_XQUOTAON XQM_CMD(1) /* enable accounting/enforcement */
#define Q_XQUOTAOFF XQM_CMD(2) /* disable accounting/enforcement */ #define Q_XQUOTAOFF XQM_CMD(2) /* disable accounting/enforcement */
#define Q_XGETQUOTA XQM_CMD(3) /* get disk limits and usage */ #define Q_XGETQUOTA XQM_CMD(3) /* get disk limits and usage */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment