patch-2.1.23 linux/kernel/signal.c

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

diff -u --recursive --new-file v2.1.22/linux/kernel/signal.c linux/kernel/signal.c
@@ -12,6 +12,8 @@
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/smp_lock.h>
 
 #include <asm/uaccess.h>
 
@@ -31,10 +33,11 @@
 	sigset_t new_set, old_set = current->blocked;
 	int error;
 
+	lock_kernel();
 	if (set) {
 		error = get_user(new_set, set);
 		if (error)
-			return error;	
+			goto out;
 		new_set &= _BLOCKABLE;
 		switch (how) {
 		case SIG_BLOCK:
@@ -47,15 +50,19 @@
 			current->blocked = new_set;
 			break;
 		default:
-			return -EINVAL;
+			error = -EINVAL;
+			goto out;
 		}
 	}
 	if (oset) {
 		error = put_user(old_set, oset);
 		if (error)
-			return error;	
+			goto out;
 	}
-	return 0;
+	error = 0;
+out:
+	unlock_kernel();
+	return error;
 }
 
 /*
@@ -63,14 +70,22 @@
  */
 asmlinkage int sys_sgetmask(void)
 {
-	return current->blocked;
+	int ret;
+
+	lock_kernel();
+	ret = current->blocked;
+	unlock_kernel();
+	return ret;
 }
 
 asmlinkage int sys_ssetmask(int newmask)
 {
-	int old=current->blocked;
+	int old;
 
+	lock_kernel();
+	old = current->blocked;
 	current->blocked = newmask & _BLOCKABLE;
+	unlock_kernel();
 	return old;
 }
 
@@ -78,8 +93,13 @@
 
 asmlinkage int sys_sigpending(sigset_t *set)
 {
+	int ret;
+
 	/* fill in "set" with signals pending but blocked. */
-	return put_user(current->blocked & current->signal, set);
+	lock_kernel();
+	ret = put_user(current->blocked & current->signal, set);
+	unlock_kernel();
+	return ret;
 }
 
 /*
@@ -97,7 +117,7 @@
  * isn't actually ignored, but does automatic child reaping, while
  * SIG_DFL is explicitly said by POSIX to force the signal to be ignored..
  */
-static inline void check_pending(int signum)
+inline void check_pending(int signum)
 {
 	struct sigaction *p;
 
@@ -120,17 +140,19 @@
  */
 asmlinkage unsigned long sys_signal(int signum, __sighandler_t handler)
 {
-	int err;
+	unsigned long err;
 	struct sigaction tmp;
 
+	lock_kernel();
+	err = -EINVAL;
 	if (signum<1 || signum>32)
-		return -EINVAL;
+		goto out;
 	if (signum==SIGKILL || signum==SIGSTOP)
-		return -EINVAL;
+		goto out;
 	if (handler != SIG_DFL && handler != SIG_IGN) {
 		err = verify_area(VERIFY_READ, handler, 1);
 		if (err)
-			return err;
+			goto out;
 	}
 	memset(&tmp, 0, sizeof(tmp));
 	tmp.sa_handler = handler;
@@ -138,39 +160,52 @@
 	handler = current->sig->action[signum-1].sa_handler;
 	current->sig->action[signum-1] = tmp;
 	check_pending(signum);
-	return (unsigned long) handler;
+	err = (unsigned long) handler;
+out:
+	unlock_kernel();
+	return err;
 }
 #endif
 
+#ifndef __sparc__
 asmlinkage int sys_sigaction(int signum, const struct sigaction * action,
 	struct sigaction * oldaction)
 {
 	struct sigaction new_sa, *p;
+	int ret = -EINVAL;
 
+	lock_kernel();
 	if (signum<1 || signum>32)
-		return -EINVAL;
+		goto out;
 	p = signum - 1 + current->sig->action;
 	if (action) {
-		int err = verify_area(VERIFY_READ, action, sizeof(*action));
-		if (err)
-			return err;
+		ret = verify_area(VERIFY_READ, action, sizeof(*action));
+		if (ret)
+			goto out;
+		ret = -EINVAL;
 		if (signum==SIGKILL || signum==SIGSTOP)
-			return -EINVAL;
+			goto out;
+		ret = -EFAULT;
 		if (copy_from_user(&new_sa, action, sizeof(struct sigaction)))
-			return -EFAULT;	
+			goto out;
 		if (new_sa.sa_handler != SIG_DFL && new_sa.sa_handler != SIG_IGN) {
-			err = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
-			if (err)
-				return err;
+			ret = verify_area(VERIFY_READ, new_sa.sa_handler, 1);
+			if (ret)
+				goto out;
 		}
 	}
+	ret = -EFAULT;
 	if (oldaction) {
 		if (copy_to_user(oldaction, p, sizeof(struct sigaction)))
-			return -EFAULT;	
+			goto out;	
 	}
 	if (action) {
 		*p = new_sa;
 		check_pending(signum);
 	}
-	return 0;
+	ret = 0;
+out:
+	unlock_kernel();
+	return ret;
 }
+#endif

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