patch-2.1.36 linux/kernel/sys.c
Next file: linux/kernel/time.c
Previous file: linux/kernel/signal.c
Back to the patch index
Back to the overall index
- Lines: 648
- Date:
Tue Apr 22 22:53:52 1997
- Orig file:
v2.1.35/linux/kernel/sys.c
- Orig date:
Sun Apr 13 10:18:22 1997
diff -u --recursive --new-file v2.1.35/linux/kernel/sys.c linux/kernel/sys.c
@@ -87,12 +87,11 @@
asmlinkage int sys_setpriority(int which, int who, int niceval)
{
struct task_struct *p;
- int error = EINVAL;
unsigned int priority;
+ int error;
- lock_kernel();
if (which > 2 || which < 0)
- goto out;
+ return -EINVAL;
/* normalize: avoid signed division (rounding problems) */
error = ESRCH;
@@ -109,6 +108,7 @@
priority = 1;
}
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (!proc_sel(p, which, who))
continue;
@@ -124,8 +124,8 @@
else
p->priority = priority;
}
-out:
- unlock_kernel();
+ read_unlock(&tasklist_lock);
+
return -error;
}
@@ -138,26 +138,23 @@
{
struct task_struct *p;
long max_prio = -ESRCH;
- int ret = -EINVAL;
- lock_kernel();
if (which > 2 || which < 0)
- goto out;
+ return -EINVAL;
+ read_lock(&tasklist_lock);
for_each_task (p) {
if (!proc_sel(p, which, who))
continue;
if (p->priority > max_prio)
max_prio = p->priority;
}
+ read_unlock(&tasklist_lock);
/* scale the priority from timeslice to 0..40 */
if (max_prio > 0)
max_prio = (max_prio * 20 + DEF_PRIORITY/2) / DEF_PRIORITY;
- ret = max_prio;
-out:
- unlock_kernel();
- return ret;
+ return max_prio;
}
#ifndef __alpha__
@@ -304,21 +301,22 @@
* The general idea is that a program which uses just setregid() will be
* 100% compatible with BSD. A program which uses just setgid() will be
* 100% compatible with POSIX w/ Saved ID's.
+ *
+ * SMP: There are not races, the gid's are checked only by filesystem
+ * operations (as far as semantic preservation is concerned).
*/
asmlinkage int sys_setregid(gid_t rgid, gid_t egid)
{
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
- goto out;
+ return -EPERM;
}
if (egid != (gid_t) -1) {
if ((old_rgid == egid) ||
@@ -328,7 +326,7 @@
current->fsgid = current->egid = egid;
else {
current->gid = old_rgid;
- goto out;
+ return -EPERM;
}
}
if (rgid != (gid_t) -1 ||
@@ -337,33 +335,28 @@
current->fsgid = current->egid;
if (current->egid != old_egid)
current->dumpable = 0;
- err = 0;
-out:
- unlock_kernel();
- return err;
+ return 0;
}
/*
* setgid() is implemented like SysV w/ SAVED_IDS
+ *
+ * SMP: Same implicit races as above.
*/
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
- goto out;
- err = 0;
+ return -EPERM;
+
if (current->egid != old_egid)
current->dumpable = 0;
-out:
- unlock_kernel();
- return err;
+ return 0;
}
static char acct_active = 0;
@@ -532,9 +525,7 @@
{
int old_ruid;
int old_euid;
- int err = -EPERM;
- lock_kernel();
old_ruid = current->uid;
old_euid = current->euid;
if (ruid != (uid_t) -1) {
@@ -543,7 +534,7 @@
suser())
current->uid = ruid;
else
- goto out;
+ return -EPERM;
}
if (euid != (uid_t) -1) {
if ((old_ruid == euid) ||
@@ -553,7 +544,7 @@
current->fsuid = current->euid = euid;
else {
current->uid = old_ruid;
- goto out;
+ return -EPERM;
}
}
if (ruid != (uid_t) -1 ||
@@ -562,10 +553,7 @@
current->fsuid = current->euid;
if (current->euid != old_euid)
current->dumpable = 0;
- err = 0;
-out:
- unlock_kernel();
- return err;
+ return 0;
}
/*
@@ -582,22 +570,17 @@
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 {
- retval = -EPERM;
- goto out;
- }
+ else
+ return -EPERM;
+
if (current->euid != old_euid)
current->dumpable = 0;
-out:
- unlock_kernel();
- return retval;
+ return 0;
}
@@ -608,43 +591,37 @@
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))
- goto out;
+ return -EPERM;
if ((euid != (uid_t) -1) && (euid != current->uid) &&
(euid != current->euid) && (euid != current->suid))
- goto out;
+ return -EPERM;
if ((suid != (uid_t) -1) && (suid != current->uid) &&
(suid != current->euid) && (suid != current->suid))
- goto out;
+ return -EPERM;
if (ruid != (uid_t) -1)
current->uid = ruid;
if (euid != (uid_t) -1)
current->euid = euid;
if (suid != (uid_t) -1)
current->suid = suid;
- err = 0;
-out:
- unlock_kernel();
- return err;
+ return 0;
}
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;
}
@@ -659,14 +636,13 @@
{
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;
}
@@ -677,14 +653,13 @@
{
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;
}
@@ -727,21 +702,29 @@
struct task_struct * p;
int err = -EINVAL;
- lock_kernel();
if (!pid)
pid = current->pid;
if (!pgid)
pgid = pid;
if (pgid < 0)
- goto out;
+ return -EINVAL;
+
+ read_lock(&tasklist_lock);
for_each_task(p) {
- if (p->pid == pid)
+ if (p->pid == pid) {
+ /* NOTE: I haven't dropped tasklist_lock, this is
+ * on purpose. -DaveM
+ */
goto found_task;
+ }
}
- err = -ESRCH;
- goto out;
+ read_unlock(&tasklist_lock);
+ return -ESRCH;
found_task:
+ /* From this point forward we keep holding onto the tasklist lock
+ * so that our parent does not change from under us. -DaveM
+ */
err = -ESRCH;
if (p->p_pptr == current || p->p_opptr == current) {
err = -EPERM;
@@ -769,30 +752,29 @@
p->pgrp = pgid;
err = 0;
out:
- unlock_kernel();
+ /* All paths lead to here, thus we are safe. -DaveM */
+ read_unlock(&tasklist_lock);
return err;
}
asmlinkage int sys_getpgid(pid_t pid)
{
- struct task_struct * p;
- int ret;
-
- lock_kernel();
if (!pid) {
- ret = current->pgrp;
+ return current->pgrp;
} else {
+ struct task_struct *p;
+ int ret = -ESRCH;
+
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->pid == pid) {
ret = p->pgrp;
- goto out;
+ break;
}
}
- ret = -ESRCH;
+ read_unlock(&tasklist_lock);
+ return ret;
}
-out:
- unlock_kernel();
- return ret;
}
asmlinkage int sys_getpgrp(void)
@@ -810,17 +792,16 @@
if (!pid) {
ret = current->session;
} else {
- /* Walking the process table needs locks */
- lock_kernel();
+ ret = -ESRCH;
+
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->pid == pid) {
ret = p->session;
- goto out;
+ break;
}
}
- ret = -ESRCH;
-out:
- unlock_kernel();
+ read_unlock(&tasklist_lock);
}
return ret;
}
@@ -830,7 +811,7 @@
struct task_struct * p;
int err = -EPERM;
- lock_kernel();
+ read_lock(&tasklist_lock);
for_each_task(p) {
if (p->pgrp == current->pid)
goto out;
@@ -842,7 +823,7 @@
current->tty_old_pgrp = 0;
err = current->pgrp;
out:
- unlock_kernel();
+ read_unlock(&tasklist_lock);
return err;
}
@@ -908,17 +889,11 @@
asmlinkage int sys_newuname(struct new_utsname * name)
{
- int err = -EFAULT;
-
- lock_kernel();
if (!name)
- goto out;
+ return -EFAULT;
if (copy_to_user(name,&system_utsname,sizeof *name))
- goto out;
- err = 0;
-out:
- unlock_kernel();
- return err;
+ return -EFAULT;
+ return 0;
}
#ifndef __alpha__
@@ -927,26 +902,24 @@
* Move these to arch dependent dir since they are for
* backward compatibility only?
*/
+
+#ifndef __sparc__
asmlinkage int sys_uname(struct old_utsname * name)
{
- int error = -EFAULT;
-
- lock_kernel();
if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
- error = 0;
- unlock_kernel();
- return error;
+ return 0;
+ return -EFAULT;
}
+#endif
asmlinkage int sys_olduname(struct oldold_utsname * name)
{
- int error = -EFAULT;
+ int error;
- lock_kernel();
if (!name)
- goto out;
+ return -EFAULT;
if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
- goto out;
+ return -EFAULT;
error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
@@ -959,8 +932,7 @@
error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
error = __put_user(0,name->machine+__OLD_UTS_LEN);
error = error ? -EFAULT : 0;
-out:
- unlock_kernel();
+
return error;
}
@@ -968,39 +940,26 @@
asmlinkage int sys_sethostname(char *name, int len)
{
- int error = -EPERM;
-
- lock_kernel();
if (!suser())
- goto out;
- error = -EINVAL;
+ return -EPERM;
if (len < 0 || len > __NEW_UTS_LEN)
- goto out;
- error = copy_from_user(system_utsname.nodename, name, len);
- if (error) {
- error = -EFAULT;
- goto out;
- }
+ return -EINVAL;
+ if(copy_from_user(system_utsname.nodename, name, len))
+ return -EFAULT;
system_utsname.nodename[len] = 0;
-out:
- unlock_kernel();
- return error;
+ return 0;
}
asmlinkage int sys_gethostname(char *name, int len)
{
- int i, err = -EINVAL;
+ int i;
- lock_kernel();
if (len < 0)
- goto out;
- i = 1+strlen(system_utsname.nodename);
+ return -EINVAL;
+ i = 1 + strlen(system_utsname.nodename);
if (i > len)
i = len;
- err = copy_to_user(name, system_utsname.nodename, i) ? -EFAULT : 0;
-out:
- unlock_kernel();
- return err;
+ return copy_to_user(name, system_utsname.nodename, i) ? -EFAULT : 0;
}
/*
@@ -1009,66 +968,44 @@
*/
asmlinkage int sys_setdomainname(char *name, int len)
{
- int error = -EPERM;
-
- lock_kernel();
if (!suser())
- goto out;
- error = -EINVAL;
+ return -EPERM;
if (len < 0 || len > __NEW_UTS_LEN)
- goto out;
- error = copy_from_user(system_utsname.domainname, name, len);
- if (error)
- error = -EFAULT;
- else
- system_utsname.domainname[len] = 0;
-out:
- unlock_kernel();
- return error;
+ return -EINVAL;
+ if(copy_from_user(system_utsname.domainname, name, len))
+ return -EFAULT;
+ system_utsname.domainname[len] = 0;
+ return 0;
}
asmlinkage int sys_getrlimit(unsigned int resource, struct rlimit *rlim)
{
- int error;
-
- lock_kernel();
if (resource >= RLIM_NLIMITS)
- error = -EINVAL;
+ return -EINVAL;
else
- error = copy_to_user(rlim, current->rlim + resource, sizeof(*rlim))
+ return 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 = -EINVAL;
- lock_kernel();
if (resource >= RLIM_NLIMITS)
- goto out;
- err = copy_from_user(&new_rlim, rlim, sizeof(*rlim));
- if (err) {
- err = -EFAULT;
- goto out;
- }
+ return -EINVAL;
+ if(copy_from_user(&new_rlim, rlim, sizeof(*rlim)))
+ return -EFAULT;
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())
- goto out;
+ return -EPERM;
if (resource == RLIMIT_NOFILE) {
if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
- goto out;
+ return -EPERM;
}
*old_rlim = new_rlim;
- err = 0;
-out:
- unlock_kernel();
- return err;
+ return 0;
}
/*
@@ -1078,13 +1015,18 @@
* make sense to do this. It will make moving the rest of the information
* a lot simpler! (Which we're not doing right now because we're not
* measuring them yet).
+ *
+ * This is SMP safe. Either we are called from sys_getrusage on ourselves
+ * below (we know we aren't going to exit/disappear and only we change our
+ * rusage counters), or we are called from wait4() on a process which is
+ * either stopped or zombied. In the zombied case the task won't get
+ * reaped till shortly after the call to getrusage(), in both cases the
+ * task being examined is in a frozen state so the counters won't change.
*/
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:
@@ -1115,22 +1057,14 @@
r.ru_nswap = p->nswap + p->cnswap;
break;
}
- err = copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
- unlock_kernel();
- return err;
+ return copy_to_user(ru, &r, sizeof(r)) ? -EFAULT : 0;
}
asmlinkage int sys_getrusage(int who, struct rusage *ru)
{
- int err = -EINVAL;
-
- lock_kernel();
if (who != RUSAGE_SELF && who != RUSAGE_CHILDREN)
- goto out;
- err = getrusage(current, who, ru);
-out:
- unlock_kernel();
- return err;
+ return -EINVAL;
+ return getrusage(current, who, ru);
}
asmlinkage int sys_umask(int mask)
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov