diff options
Diffstat (limited to 'fs/dquot.c')
-rw-r--r-- | fs/dquot.c | 67 |
1 files changed, 37 insertions, 30 deletions
diff --git a/fs/dquot.c b/fs/dquot.c index 2c8778995..5236ed38e 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -13,12 +13,13 @@ * diskquota system. This implementation is not based on any BSD * kernel sourcecode. * - * Version: $Id: dquot.c,v 5.6 1995/11/15 20:30:27 mvw Exp mvw $ + * Version: $Id: dquot.c,v 1.11 1997/01/06 06:53:02 davem Exp $ * * Author: Marco van Wieringen <mvw@mcs.ow.nl> <mvw@tnix.net> * * Fixes: Dmitry Gorodchanin <begemot@bgm.rosprint.net>, 11 Feb 96 * removed race conditions in dqput(), dqget() and iput(). + * Andi Kleen removed all verify_area() calls, 31 Dec 96 * * (C) Copyright 1994, 1995 Marco van Wieringen * @@ -34,6 +35,8 @@ #include <linux/tty.h> #include <linux/malloc.h> #include <linux/mount.h> +#include <linux/smp.h> +#include <linux/smp_lock.h> #include <asm/uaccess.h> @@ -585,15 +588,13 @@ static int set_dqblk(kdev_t dev, int id, short type, int flags, struct dqblk *dq { struct dquot *dquot; struct dqblk dq_dqblk; - int error; if (dqblk == (struct dqblk *)NULL) return(-EFAULT); if (flags & QUOTA_SYSCALL) { - if ((error = verify_area(VERIFY_READ, dqblk, sizeof(struct dqblk))) != 0) - return(error); - copy_from_user(&dq_dqblk, dqblk, sizeof(struct dqblk)); + if (copy_from_user(&dq_dqblk, dqblk, sizeof(struct dqblk))) + return -EFAULT; } else { memcpy(&dq_dqblk, dqblk, sizeof(struct dqblk)); } @@ -649,13 +650,10 @@ static int get_quota(kdev_t dev, int id, short type, struct dqblk *dqblk) if (dqblk == (struct dqblk *)NULL) return(-EFAULT); - if ((error = verify_area(VERIFY_WRITE, dqblk, sizeof(struct dqblk))) != 0) - return(error); - if ((dquot = dqget(dev, id, type)) != NODQUOT) { - copy_to_user(dqblk, (char *)&dquot->dq_dqb, sizeof(struct dqblk)); + error = copy_to_user(dqblk, (char *)&dquot->dq_dqb, sizeof(struct dqblk)); dqput(dquot); - return(0); + return error ? -EFAULT : 0; } } return(-ESRCH); @@ -663,15 +661,10 @@ static int get_quota(kdev_t dev, int id, short type, struct dqblk *dqblk) static int get_stats(caddr_t addr) { - int error; - - if ((error = verify_area(VERIFY_WRITE, addr, sizeof(struct dqstats))) != 0) - return(error); - dqstats.allocated_dquots = nr_dquots; dqstats.free_dquots = nr_free_dquots; - copy_to_user(addr, (caddr_t)&dqstats, sizeof(struct dqstats)); - return(0); + return copy_to_user(addr, (caddr_t)&dqstats, sizeof(struct dqstats)) + ? -EFAULT : 0; } /* @@ -1014,12 +1007,15 @@ asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr) int cmds = 0, type = 0, flags = 0; struct inode *ino; kdev_t dev; + int ret = -EINVAL; + lock_kernel(); cmds = cmd >> SUBCMDSHIFT; type = cmd & SUBCMDMASK; if ((u_int) type >= MAXQUOTAS) - return(-EINVAL); + goto out; + ret = -EPERM; switch (cmds) { case Q_SYNC: case Q_GETSTATS: @@ -1027,33 +1023,39 @@ asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr) case Q_GETQUOTA: if (((type == USRQUOTA && current->uid != id) || (type == GRPQUOTA && current->gid != id)) && !fsuser()) - return(-EPERM); + goto out; break; default: if (!fsuser()) - return(-EPERM); + goto out; } + ret = -EINVAL; if (special == (char *)NULL && (cmds == Q_SYNC || cmds == Q_GETSTATS)) dev = 0; else { if (namei(special, &ino)) - return(-EINVAL); + goto out; dev = ino->i_rdev; + ret = -ENOTBLK; if (!S_ISBLK(ino->i_mode)) { iput(ino); - return(-ENOTBLK); + goto out; } iput(ino); } + ret = -EINVAL; switch (cmds) { case Q_QUOTAON: - return(quota_on(dev, type, (char *) addr)); + ret = quota_on(dev, type, (char *) addr); + goto out; case Q_QUOTAOFF: - return(quota_off(dev, type)); + ret = quota_off(dev, type); + goto out; case Q_GETQUOTA: - return(get_quota(dev, id, type, (struct dqblk *) addr)); + ret = get_quota(dev, id, type, (struct dqblk *) addr); + goto out; case Q_SETQUOTA: flags |= SET_QUOTA; break; @@ -1064,15 +1066,20 @@ asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr) flags |= SET_QLIMIT; break; case Q_SYNC: - return(sync_dquots(dev, type)); + ret = sync_dquots(dev, type); + goto out; case Q_GETSTATS: - return(get_stats(addr)); + ret = get_stats(addr); default: - return(-EINVAL); + goto out; } flags |= QUOTA_SYSCALL; if (has_quota_enabled(dev, type)) - return(set_dqblk(dev, id, type, flags, (struct dqblk *) addr)); - return(-ESRCH); + ret = set_dqblk(dev, id, type, flags, (struct dqblk *) addr); + else + ret = -ESRCH; +out: + unlock_kernel(); + return ret; } |