patch-2.1.23 linux/kernel/sys.c

Next file: linux/kernel/sysctl.c
Previous file: linux/kernel/softirq.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.22/linux/kernel/sys.c linux/kernel/sys.c
@@ -21,6 +21,8 @@
 #include <linux/fcntl.h>
 #include <linux/acct.h>
 #include <linux/tty.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
 #if defined(CONFIG_APM) && defined(CONFIG_APM_POWER_OFF)
 #include <linux/apm_bios.h>
 #endif
@@ -74,13 +76,15 @@
 asmlinkage int sys_setpriority(int which, int who, int niceval)
 {
 	struct task_struct *p;
-	int error = ESRCH;
+	int error = EINVAL;
 	unsigned int priority;
 
+	lock_kernel();
 	if (which > 2 || which < 0)
-		return -EINVAL;
+		goto out;
 
 	/* normalize: avoid signed division (rounding problems) */
+	error = ESRCH;
 	priority = niceval;
 	if (niceval < 0)
 		priority = -niceval;
@@ -109,6 +113,8 @@
 		else
 			p->priority = priority;
 	}
+out:
+	unlock_kernel();
 	return -error;
 }
 
@@ -121,9 +127,11 @@
 {
 	struct task_struct *p;
 	long max_prio = -ESRCH;
+	int ret = -EINVAL;
 
+	lock_kernel();
 	if (which > 2 || which < 0)
-		return -EINVAL;
+		goto out;
 
 	for_each_task (p) {
 		if (!proc_sel(p, which, who))
@@ -135,7 +143,10 @@
 	/* scale the priority from timeslice to 0..40 */
 	if (max_prio > 0)
 		max_prio = (max_prio * 20 + DEF_PRIORITY/2) / DEF_PRIORITY;
-	return max_prio;
+	ret = max_prio;
+out:
+	unlock_kernel();
+	return ret;
 }
 
 #ifndef __alpha__
@@ -194,11 +205,16 @@
  */
 asmlinkage int sys_reboot(int magic, int magic_too, int flag)
 {
+	int error = -EPERM;
+
+	lock_kernel();
 	if (!suser())
-		return -EPERM;
+		goto out;
+	error = -EINVAL;
 	if (magic != 0xfee1dead || 
 	    (magic_too != 672274793 && magic_too != 85072278))
-		return -EINVAL;
+		goto out;
+	error = 0;
 	if (flag == 0x01234567)
 	{
 		notifier_call_chain(&boot_notifier_list, SYS_DOWN, NULL);
@@ -220,8 +236,10 @@
 		notifier_call_chain(&boot_notifier_list, SYS_HALT, NULL);
 		do_exit(0);
 	} else
-		return -EINVAL;
-	return (0);
+		error = -EINVAL;
+out:
+	unlock_kernel();
+	return error;
 }
 
 /*
@@ -260,14 +278,16 @@
 {
 	int old_rgid = current->gid;
 	int old_egid = current->egid;
+	int err = -EPERM;
 
+	lock_kernel();
 	if (rgid != (gid_t) -1) {
 		if ((old_rgid == rgid) ||
 		    (current->egid==rgid) ||
 		    suser())
 			current->gid = rgid;
 		else
-			return(-EPERM);
+			goto out;
 	}
 	if (egid != (gid_t) -1) {
 		if ((old_rgid == egid) ||
@@ -277,7 +297,7 @@
 			current->fsgid = current->egid = egid;
 		else {
 			current->gid = old_rgid;
-			return(-EPERM);
+			goto out;
 		}
 	}
 	if (rgid != (gid_t) -1 ||
@@ -286,7 +306,10 @@
 	current->fsgid = current->egid;
 	if (current->egid != old_egid)
 		current->dumpable = 0;
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -295,16 +318,21 @@
 asmlinkage int sys_setgid(gid_t gid)
 {
 	int old_egid = current->egid;
+	int err = -EPERM;
 
+	lock_kernel();
 	if (suser())
 		current->gid = current->egid = current->sgid = current->fsgid = gid;
 	else if ((gid == current->gid) || (gid == current->sgid))
 		current->egid = current->fsgid = gid;
 	else
-		return -EPERM;
+		goto out;
+	err = 0;
 	if (current->egid != old_egid)
 		current->dumpable = 0;
-	return 0;
+out:
+	unlock_kernel();
+	return err;
 }
   
 static char acct_active = 0;
@@ -353,66 +381,70 @@
 
 asmlinkage int sys_acct(const char *name)
 {
-   struct inode *inode = (struct inode *)0;
-   char *tmp;
-   int error;
-
-   if (!suser())
-      return -EPERM;
-
-   if (name == (char *)0) {
-      if (acct_active) {
-         if (acct_file.f_op->release)
-            acct_file.f_op->release(acct_file.f_inode, &acct_file);
-
-         if (acct_file.f_inode != (struct inode *) 0)
-            iput(acct_file.f_inode);
-
-         acct_active = 0;
-      }
-      return 0;
-   } else {
-      if (!acct_active) {
-
-         if ((error = getname(name, &tmp)) != 0)
-            return (error);
-
-         error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
-         putname(tmp);
-
-         if (error)
-            return (error);
-
-         if (!S_ISREG(inode->i_mode)) {
-            iput(inode);
-            return -EACCES;
-         }
-
-         if (!inode->i_op || !inode->i_op->default_file_ops || 
-             !inode->i_op->default_file_ops->write) {
-            iput(inode);
-            return -EIO;
-         }
-
-         acct_file.f_mode = 3;
-         acct_file.f_flags = 0;
-         acct_file.f_count = 1;
-         acct_file.f_inode = inode;
-         acct_file.f_pos = inode->i_size;
-         acct_file.f_reada = 0;
-         acct_file.f_op = inode->i_op->default_file_ops;
-
-         if (acct_file.f_op->open)
-            if (acct_file.f_op->open(acct_file.f_inode, &acct_file)) {
-               iput(inode);
-               return -EIO;
-            }
-
-         acct_active = 1;
-         return 0;
-      } else
-         return -EBUSY;
-   }
+	struct inode *inode = (struct inode *)0;
+	char *tmp;
+	int error = -EPERM;
+
+	lock_kernel();
+	if (!suser())
+		goto out;
+
+	if (name == (char *)0) {
+		if (acct_active) {
+			if (acct_file.f_op->release)
+				acct_file.f_op->release(acct_file.f_inode, &acct_file);
+
+			if (acct_file.f_inode != (struct inode *) 0)
+				iput(acct_file.f_inode);
+
+			acct_active = 0;
+		}
+		error = 0;
+	} else {
+		error = -EBUSY;
+		if (!acct_active) {
+			if ((error = getname(name, &tmp)) != 0)
+				goto out;
+
+			error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
+			putname(tmp);
+			if (error)
+				goto out;
+
+			error = -EACCES;
+			if (!S_ISREG(inode->i_mode)) {
+				iput(inode);
+				goto out;
+			}
+
+			error = -EIO;
+			if (!inode->i_op || !inode->i_op->default_file_ops || 
+			    !inode->i_op->default_file_ops->write) {
+				iput(inode);
+				goto out;
+			}
+
+			acct_file.f_mode = 3;
+			acct_file.f_flags = 0;
+			acct_file.f_count = 1;
+			acct_file.f_inode = inode;
+			acct_file.f_pos = inode->i_size;
+			acct_file.f_reada = 0;
+			acct_file.f_op = inode->i_op->default_file_ops;
+
+			if(acct_file.f_op->open)
+				if(acct_file.f_op->open(acct_file.f_inode, &acct_file)) {
+					iput(inode);
+					goto out;
+				}
+
+			acct_active = 1;
+			error = 0;
+		}
+	}
+out:
+	unlock_kernel();
+	return error;
 }
 
 #ifndef __alpha__
@@ -467,16 +499,20 @@
  */
 asmlinkage int sys_setreuid(uid_t ruid, uid_t euid)
 {
-	int old_ruid = current->uid;
-	int old_euid = current->euid;
+	int old_ruid;
+	int old_euid;
+	int err = -EPERM;
 
+	lock_kernel();
+	old_ruid = current->uid;
+	old_euid = current->euid;
 	if (ruid != (uid_t) -1) {
 		if ((old_ruid == ruid) || 
 		    (current->euid==ruid) ||
 		    suser())
 			current->uid = ruid;
 		else
-			return(-EPERM);
+			goto out;
 	}
 	if (euid != (uid_t) -1) {
 		if ((old_ruid == euid) ||
@@ -486,7 +522,7 @@
 			current->fsuid = current->euid = euid;
 		else {
 			current->uid = old_ruid;
-			return(-EPERM);
+			goto out;
 		}
 	}
 	if (ruid != (uid_t) -1 ||
@@ -495,7 +531,10 @@
 	current->fsuid = current->euid;
 	if (current->euid != old_euid)
 		current->dumpable = 0;
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -512,16 +551,22 @@
 asmlinkage int sys_setuid(uid_t uid)
 {
 	int old_euid = current->euid;
+	int retval = 0;
 
+	lock_kernel();
 	if (suser())
 		current->uid = current->euid = current->suid = current->fsuid = uid;
 	else if ((uid == current->uid) || (uid == current->suid))
 		current->fsuid = current->euid = uid;
-	else
-		return -EPERM;
+	else {
+		retval = -EPERM;
+		goto out;
+	}
 	if (current->euid != old_euid)
 		current->dumpable = 0;
-	return(0);
+out:
+	unlock_kernel();
+	return retval;
 }
 
 
@@ -532,36 +577,43 @@
 asmlinkage int sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
 {
 	uid_t old_ruid, old_euid, old_suid;
+	int err = -EPERM;
 
+	lock_kernel();
 	old_ruid = current->uid;
 	old_euid = current->euid;
 	old_suid = current->suid;
 
 	if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
 	    (ruid != current->euid) && (ruid != current->suid))
-		return -EPERM;
+		goto out;
 	if ((euid != (uid_t) -1) && (euid != current->uid) &&
 	    (euid != current->euid) && (euid != current->suid))
-		return -EPERM;
+		goto out;
 	if ((suid != (uid_t) -1) && (suid != current->uid) &&
 	    (suid != current->euid) && (suid != current->suid))
-		return -EPERM;
+		goto out;
 	if (ruid != (uid_t) -1)
 		current->uid = ruid;
 	if (euid != (uid_t) -1)
 		current->euid = euid;
 	if (suid != (uid_t) -1)
 		current->suid = suid;
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 asmlinkage int sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
 {
 	int retval;
 
+	lock_kernel();
 	if (!(retval = put_user(current->uid, ruid)) &&
 	    !(retval = put_user(current->euid, euid)))
 		retval = put_user(current->suid, suid);
+	unlock_kernel();
 	return retval;
 }
 
@@ -574,13 +626,16 @@
  */
 asmlinkage int sys_setfsuid(uid_t uid)
 {
-	int old_fsuid = current->fsuid;
+	int old_fsuid;
 
+	lock_kernel();
+	old_fsuid = current->fsuid;
 	if (uid == current->uid || uid == current->euid ||
 	    uid == current->suid || uid == current->fsuid || suser())
 		current->fsuid = uid;
 	if (current->fsuid != old_fsuid)
 		current->dumpable = 0;
+	unlock_kernel();
 	return old_fsuid;
 }
 
@@ -589,19 +644,24 @@
  */
 asmlinkage int sys_setfsgid(gid_t gid)
 {
-	int old_fsgid = current->fsgid;
+	int old_fsgid;
 
+	lock_kernel();
+	old_fsgid = current->fsgid;
 	if (gid == current->gid || gid == current->egid ||
 	    gid == current->sgid || gid == current->fsgid || suser())
 		current->fsgid = gid;
 	if (current->fsgid != old_fsgid)
 		current->dumpable = 0;
+	unlock_kernel();
 	return old_fsgid;
 }
 
 asmlinkage long sys_times(struct tms * tbuf)
 {
 	int error;
+
+	lock_kernel();
 	if (tbuf) {
 		error = put_user(current->utime,&tbuf->tms_utime);
 		if (!error)
@@ -611,9 +671,12 @@
 		if (!error)
 			error =	put_user(current->cstime,&tbuf->tms_cstime);
 		if (error)
-			return error;	
+			goto out;
 	}
-	return jiffies;
+	error = jiffies;
+out:
+	unlock_kernel();
+	return error;
 }
 
 /*
@@ -631,89 +694,127 @@
 asmlinkage int sys_setpgid(pid_t pid, pid_t pgid)
 {
 	struct task_struct * p;
+	int err = -EINVAL;
 
+	lock_kernel();
 	if (!pid)
 		pid = current->pid;
 	if (!pgid)
 		pgid = pid;
 	if (pgid < 0)
-		return -EINVAL;
+		goto out;
 	for_each_task(p) {
 		if (p->pid == pid)
 			goto found_task;
 	}
-	return -ESRCH;
+	err = -ESRCH;
+	goto out;
 
 found_task:
+	err = -ESRCH;
 	if (p->p_pptr == current || p->p_opptr == current) {
+		err = -EPERM;
 		if (p->session != current->session)
-			return -EPERM;
+			goto out;
+		err = -EACCES;
 		if (p->did_exec)
-			return -EACCES;
+			goto out;
 	} else if (p != current)
-		return -ESRCH;
+		goto out;
+	err = -EPERM;
 	if (p->leader)
-		return -EPERM;
+		goto out;
 	if (pgid != pid) {
 		struct task_struct * tmp;
 		for_each_task (tmp) {
 			if (tmp->pgrp == pgid &&
-			 tmp->session == current->session)
+			    tmp->session == current->session)
 				goto ok_pgid;
 		}
-		return -EPERM;
+		goto out;
 	}
 
 ok_pgid:
 	p->pgrp = pgid;
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 asmlinkage int sys_getpgid(pid_t pid)
 {
 	struct task_struct * p;
+	int ret;
 
-	if (!pid)
-		return current->pgrp;
-	for_each_task(p) {
-		if (p->pid == pid)
-			return p->pgrp;
+	lock_kernel();
+	if (!pid) {
+		ret = current->pgrp;
+	} else {
+		for_each_task(p) {
+			if (p->pid == pid) {
+				ret = p->pgrp;
+				goto out;
+			}
+		}
+		ret = -ESRCH;
 	}
-	return -ESRCH;
+out:
+	unlock_kernel();
+	return ret;
 }
 
 asmlinkage int sys_getpgrp(void)
 {
-	return current->pgrp;
+	int ret;
+
+	lock_kernel();
+	ret = current->pgrp;
+	unlock_kernel();
+	return ret;
 }
 
 asmlinkage int sys_getsid(pid_t pid)
 {
 	struct task_struct * p;
+	int ret;
 
-	if (!pid)
-		return current->session;
-	for_each_task(p) {
-		if (p->pid == pid)
-			return p->session;
+	lock_kernel();
+	if (!pid) {
+		ret = current->session;
+	} else {
+		for_each_task(p) {
+			if (p->pid == pid) {
+				ret = p->session;
+				goto out;
+			}
+		}
+		ret = -ESRCH;
 	}
-	return -ESRCH;
+out:
+	unlock_kernel();
+	return ret;
 }
 
 asmlinkage int sys_setsid(void)
 {
 	struct task_struct * p;
+	int err = -EPERM;
 
+	lock_kernel();
 	for_each_task(p) {
 		if (p->pgrp == current->pid)
-		        return -EPERM;
+		        goto out;
 	}
 
 	current->leader = 1;
 	current->session = current->pgrp = current->pid;
 	current->tty = NULL;
 	current->tty_old_pgrp = 0;
-	return current->pgrp;
+	err = current->pgrp;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -721,34 +822,44 @@
  */
 asmlinkage int sys_getgroups(int gidsetsize, gid_t *grouplist)
 {
-	int i;
+	int i, err = -EINVAL;
 
+	lock_kernel();
 	if (gidsetsize < 0)
-		return -EINVAL;
+		goto out;
 	i = current->ngroups;
 	if (gidsetsize) {
+		err = -EINVAL;
 		if (i > gidsetsize)
-		        return -EINVAL;
+		        goto out;
+		err = -EFAULT;
 		if (copy_to_user(grouplist, current->groups, sizeof(gid_t)*i))
-			return -EFAULT;
+			goto out;
 	}
-	return i;
+	err = i;
+out:
+	unlock_kernel();
+	return err;
 }
 
 asmlinkage int sys_setgroups(int gidsetsize, gid_t *grouplist)
 {
-	int	err;
+	int err = -EPERM;
 
+	lock_kernel();
 	if (!suser())
-		return -EPERM;
+		goto out;
+	err = -EINVAL;
 	if ((unsigned) gidsetsize > NGROUPS)
-		return -EINVAL;
+		goto out;
 	err = copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t));
 	if (err) {
 		gidsetsize = 0;
 		err = -EFAULT;
 	} 
 	current->ngroups = gidsetsize;
+out:
+	unlock_kernel();
 	return err;
 }
 
@@ -773,11 +884,17 @@
 
 asmlinkage int sys_newuname(struct new_utsname * name)
 {
+	int err = -EFAULT;
+
+	lock_kernel();
 	if (!name)
-		return -EFAULT;
+		goto out;
 	if (copy_to_user(name,&system_utsname,sizeof *name))
-		return -EFAULT;
-	return 0;
+		goto out;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 #ifndef __alpha__
@@ -788,17 +905,22 @@
  */
 asmlinkage int sys_uname(struct old_utsname * name)
 {
-	int error = -EFAULT;;
+	int error = -EFAULT;
+
+	lock_kernel();
 	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
 		error = 0;
+	unlock_kernel();
 	return error;
 }
 
 asmlinkage int sys_olduname(struct oldold_utsname * name)
 {
-	int error;
+	int error = -EFAULT;
+
+	lock_kernel();
 	if (!name)
-		return -EFAULT;
+		goto out;
 	error = copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
 	if (!error)
 		error = put_user(0,name->sysname+__OLD_UTS_LEN);
@@ -818,36 +940,49 @@
 		error = copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
 	if (!error)
 		error = put_user(0,name->machine+__OLD_UTS_LEN);
-	return error ? -EFAULT : 0;
+	error = error ? -EFAULT : 0;
+out:
+	unlock_kernel();
+	return error;
 }
 
 #endif
 
 asmlinkage int sys_sethostname(char *name, int len)
 {
-	int error;
+	int error = -EPERM;
 
+	lock_kernel();
 	if (!suser())
-		return -EPERM;
+		goto out;
+	error = -EINVAL;
 	if (len < 0 || len > __NEW_UTS_LEN)
-		return -EINVAL;
+		goto out;
 	error = copy_from_user(system_utsname.nodename, name, len);
-	if (error)
-		return -EFAULT;
+	if (error) {
+		error = -EFAULT;
+		goto out;
+	}
 	system_utsname.nodename[len] = 0;
-	return 0;
+out:
+	unlock_kernel();
+	return error;
 }
 
 asmlinkage int sys_gethostname(char *name, int len)
 {
-	int i;
+	int i, err = -EINVAL;
 
+	lock_kernel();
 	if (len < 0)
-		return -EINVAL;
+		goto out;
 	i = 1+strlen(system_utsname.nodename);
 	if (i > len)
 		i = len;
-	return copy_to_user(name, system_utsname.nodename, i) ? -EFAULT : 0;
+	err = copy_to_user(name, system_utsname.nodename, i) ? -EFAULT : 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -856,48 +991,66 @@
  */
 asmlinkage int sys_setdomainname(char *name, int len)
 {
-	int error;
+	int error = -EPERM;
 	
+	lock_kernel();
 	if (!suser())
-		return -EPERM;
+		goto out;
+	error = -EINVAL;
 	if (len < 0 || len > __NEW_UTS_LEN)
-		return -EINVAL;
+		goto out;
 	error = copy_from_user(system_utsname.domainname, name, len);
 	if (error)
-		return -EFAULT;
-	system_utsname.domainname[len] = 0;
-	return 0;
+		error = -EFAULT;
+	else
+		system_utsname.domainname[len] = 0;
+out:
+	unlock_kernel();
+	return error;
 }
 
 asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
 {
+	int error;
+
+	lock_kernel();
 	if (resource >= RLIM_NLIMITS)
-		return -EINVAL;
-	return copy_to_user(rlim, current->rlim + resource, sizeof(*rlim)) 
-			? -EFAULT : 0 ;
+		error = -EINVAL;
+	else
+		error = copy_to_user(rlim, current->rlim + resource, sizeof(*rlim))
+			? -EFAULT : 0;
+	unlock_kernel();
+	return error;
 }
 
 asmlinkage int sys_setrlimit(unsigned int resource, struct rlimit *rlim)
 {
 	struct rlimit new_rlim, *old_rlim;
-	int err;
+	int err = -EINVAL;
 
+	lock_kernel();
 	if (resource >= RLIM_NLIMITS)
-		return -EINVAL;
+		goto out;
 	err = copy_from_user(&new_rlim, rlim, sizeof(*rlim));
-	if (err)
-		return -EFAULT;	
+	if (err) {
+		err = -EFAULT;
+		goto out;
+	}
 	old_rlim = current->rlim + resource;
+	err = -EPERM;
 	if (((new_rlim.rlim_cur > old_rlim->rlim_max) ||
 	     (new_rlim.rlim_max > old_rlim->rlim_max)) &&
 	    !suser())
-		return -EPERM;
+		goto out;
 	if (resource == RLIMIT_NOFILE) {
 		if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
-			return -EPERM;
+			goto out;
 	}
 	*old_rlim = new_rlim;
-	return 0;
+	err = 0;
+out:
+	unlock_kernel();
+	return err;
 }
 
 /*
@@ -911,7 +1064,9 @@
 int getrusage(struct task_struct *p, int who, struct rusage *ru)
 {
 	struct rusage r;
+	int err;
 
+	lock_kernel();
 	memset((char *) &r, 0, sizeof(r));
 	switch (who) {
 		case RUSAGE_SELF:
@@ -942,20 +1097,31 @@
 			r.ru_nswap = p->nswap + p->cnswap;
 			break;
 	}
-	return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
+	err = copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
+	unlock_kernel();
+	return err;
 }
 
 asmlinkage int sys_getrusage(int who, struct rusage *ru)
 {
+	int err = -EINVAL;
+
+	lock_kernel();
 	if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
-		return -EINVAL;
-	return getrusage(current, who, ru);
+		goto out;
+	err = getrusage(current, who, ru);
+out:
+	unlock_kernel();
+	return err;
 }
 
 asmlinkage int sys_umask(int mask)
 {
-	int old = current->fs->umask;
+	int old;
 
+	lock_kernel();
+	old = current->fs->umask;
 	current->fs->umask = mask & S_IRWXUGO;
+	unlock_kernel();
 	return (old);
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov