patch-2.4.3 linux/kernel/sys.c

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

diff -u --recursive --new-file v2.4.2/linux/kernel/sys.c linux/kernel/sys.c
@@ -330,6 +330,12 @@
 	return 0;
 }
 
+static void deferred_cad(void *dummy)
+{
+	notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
+	machine_restart(NULL);
+}
+
 /*
  * This function gets called by ctrl-alt-del - ie the keyboard interrupt.
  * As it's called within an interrupt, it may NOT sync: the only choice
@@ -337,10 +343,13 @@
  */
 void ctrl_alt_del(void)
 {
-	if (C_A_D) {
-		notifier_call_chain(&reboot_notifier_list, SYS_RESTART, NULL);
-		machine_restart(NULL);
-	} else
+	static struct tq_struct cad_tq = {
+		routine: deferred_cad,
+	};
+
+	if (C_A_D)
+		schedule_task(&cad_tq);
+	else
 		kill_proc(1, SIGINT, 1);
 }
 	
@@ -367,12 +376,14 @@
 {
 	int old_rgid = current->gid;
 	int old_egid = current->egid;
+	int new_rgid = old_rgid;
+	int new_egid = old_egid;
 
 	if (rgid != (gid_t) -1) {
 		if ((old_rgid == rgid) ||
 		    (current->egid==rgid) ||
 		    capable(CAP_SETGID))
-			current->gid = rgid;
+			new_rgid = rgid;
 		else
 			return -EPERM;
 	}
@@ -381,18 +392,22 @@
 		    (current->egid == egid) ||
 		    (current->sgid == egid) ||
 		    capable(CAP_SETGID))
-			current->fsgid = current->egid = egid;
+			new_egid = egid;
 		else {
-			current->gid = old_rgid;
 			return -EPERM;
 		}
 	}
+	if (new_egid != old_egid)
+	{
+		current->dumpable = 0;
+		wmb();
+	}
 	if (rgid != (gid_t) -1 ||
 	    (egid != (gid_t) -1 && egid != old_rgid))
-		current->sgid = current->egid;
-	current->fsgid = current->egid;
-	if (current->egid != old_egid)
-		current->dumpable = 0;
+		current->sgid = new_egid;
+	current->fsgid = new_egid;
+	current->egid = new_egid;
+	current->gid = new_rgid;
 	return 0;
 }
 
@@ -406,14 +421,25 @@
 	int old_egid = current->egid;
 
 	if (capable(CAP_SETGID))
+	{
+		if(old_egid != gid)
+		{
+			current->dumpable=0;
+			wmb();
+		}
 		current->gid = current->egid = current->sgid = current->fsgid = gid;
+	}
 	else if ((gid == current->gid) || (gid == current->sgid))
+	{
+		if(old_egid != gid)
+		{
+			current->dumpable=0;
+			wmb();
+		}
 		current->egid = current->fsgid = gid;
+	}
 	else
 		return -EPERM;
-
-	if (current->egid != old_egid)
-		current->dumpable = 0;
 	return 0;
 }
   
@@ -463,7 +489,7 @@
 	}
 }
 
-static int set_user(uid_t new_ruid)
+static int set_user(uid_t new_ruid, int dumpclear)
 {
 	struct user_struct *new_user, *old_user;
 
@@ -479,6 +505,11 @@
 	atomic_dec(&old_user->processes);
 	atomic_inc(&new_user->processes);
 
+	if(dumpclear)
+	{
+		current->dumpable = 0;
+		wmb();
+	}
 	current->uid = new_ruid;
 	current->user = new_user;
 	free_uid(old_user);
@@ -525,16 +556,19 @@
 			return -EPERM;
 	}
 
-	if (new_ruid != old_ruid && set_user(new_ruid) < 0)
+	if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0)
 		return -EAGAIN;
 
+	if (new_euid != old_euid)
+	{
+		current->dumpable=0;
+		wmb();
+	}
 	current->fsuid = current->euid = new_euid;
 	if (ruid != (uid_t) -1 ||
 	    (euid != (uid_t) -1 && euid != old_ruid))
 		current->suid = current->euid;
 	current->fsuid = current->euid;
-	if (current->euid != old_euid)
-		current->dumpable = 0;
 
 	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
 		cap_emulate_setxuid(old_ruid, old_euid, old_suid);
@@ -559,21 +593,26 @@
 asmlinkage long sys_setuid(uid_t uid)
 {
 	int old_euid = current->euid;
-	int old_ruid, old_suid, new_ruid;
+	int old_ruid, old_suid, new_ruid, new_suid;
 
 	old_ruid = new_ruid = current->uid;
 	old_suid = current->suid;
+	new_suid = old_suid;
+	
 	if (capable(CAP_SETUID)) {
-		if (uid != old_ruid && set_user(uid) < 0)
+		if (uid != old_ruid && set_user(uid, old_euid != uid) < 0)
 			return -EAGAIN;
-		current->suid = uid;
-	} else if ((uid != current->uid) && (uid != current->suid))
+		new_suid = uid;
+	} else if ((uid != current->uid) && (uid != new_suid))
 		return -EPERM;
 
-	current->fsuid = current->euid = uid;
-
 	if (old_euid != uid)
+	{
 		current->dumpable = 0;
+		wmb();
+	}
+	current->fsuid = current->euid = uid;
+	current->suid = new_suid;
 
 	if (!issecure(SECURE_NO_SETUID_FIXUP)) {
 		cap_emulate_setxuid(old_ruid, old_euid, old_suid);
@@ -605,12 +644,15 @@
 			return -EPERM;
 	}
 	if (ruid != (uid_t) -1) {
-		if (ruid != current->uid && set_user(ruid) < 0)
+		if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0)
 			return -EAGAIN;
 	}
 	if (euid != (uid_t) -1) {
 		if (euid != current->euid)
+		{
 			current->dumpable = 0;
+			wmb();
+		}
 		current->euid = euid;
 		current->fsuid = euid;
 	}
@@ -640,7 +682,7 @@
  */
 asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
 {
-       if (!capable(CAP_SETGID)) {
+	if (!capable(CAP_SETGID)) {
 		if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
 		    (rgid != current->egid) && (rgid != current->sgid))
 			return -EPERM;
@@ -651,14 +693,17 @@
 		    (sgid != current->egid) && (sgid != current->sgid))
 			return -EPERM;
 	}
-	if (rgid != (gid_t) -1)
-		current->gid = rgid;
 	if (egid != (gid_t) -1) {
 		if (egid != current->egid)
+		{
 			current->dumpable = 0;
+			wmb();
+		}
 		current->egid = egid;
 		current->fsgid = egid;
 	}
+	if (rgid != (gid_t) -1)
+		current->gid = rgid;
 	if (sgid != (gid_t) -1)
 		current->sgid = sgid;
 	return 0;
@@ -690,9 +735,14 @@
 	if (uid == current->uid || uid == current->euid ||
 	    uid == current->suid || uid == current->fsuid || 
 	    capable(CAP_SETUID))
+	{
+		if (uid != old_fsuid)
+		{
+			current->dumpable = 0;
+			wmb();
+		}
 		current->fsuid = uid;
-	if (current->fsuid != old_fsuid)
-		current->dumpable = 0;
+	}
 
 	/* We emulate fsuid by essentially doing a scaled-down version
 	 * of what we did in setresuid and friends. However, we only
@@ -727,10 +777,14 @@
 	if (gid == current->gid || gid == current->egid ||
 	    gid == current->sgid || gid == current->fsgid || 
 	    capable(CAP_SETGID))
+	{
+		if (gid != old_fsgid)
+		{
+			current->dumpable = 0;
+			wmb();
+		}
 		current->fsgid = gid;
-	if (current->fsgid != old_fsgid)
-		current->dumpable = 0;
-
+	}
 	return old_fsgid;
 }
 

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)