[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

killgroup security hole



Pkill has a security hole big enough to drive a truck through :) You
can kill any process you like with it, you just have to know (or
guess) its process group and call Pkill with -pgrp! There are no
access checks in killgroup!

The fix is to add an additional parameter to killgroup that tells it
if the signal is generated by the kernel, otherwise unauthorized
accesses are denied.

--- bios.c~	Fri Aug 19 20:13:00 1994
+++ bios.c	Mon Aug 22 22:47:50 1994
@@ -267,7 +267,7 @@
 					iread (b->bdev, (char *) NULL, 0, 1, 0);
 				if (b->tty->pgrp)
 /* ...and here is the long missed :) SIGHUP  */
-					killgroup(b->tty->pgrp, SIGHUP);
+					killgroup(b->tty->pgrp, SIGHUP, 1);
 			}
 			wake(IO_Q, (long)b);
 			wake(IO_Q, (long)&b->tty->state);
@@ -299,7 +299,7 @@
 				if (!(b->tty->sg.sg_flags & T_NOFLSH))
 					iread (b->bdev, (char *) NULL, 0, 1, 0);
 				if (b->tty->pgrp)
-					killgroup(b->tty->pgrp, SIGINT);
+					killgroup(b->tty->pgrp, SIGINT, 1);
 			}
 		} else
 			b->bticks = 0;
@@ -1149,7 +1149,7 @@
 				tty->state &= ~TS_HOLD;
 				if (!(tty->sg.sg_flags & T_NOFLSH))
 				    oldktail = keyrec->head = keyrec->tail;
-				killgroup(tty->pgrp, sig);
+				killgroup(tty->pgrp, sig, 1);
 				ret = 1;
 			}
 			else if (tty->state & TS_HOLD) {
--- debug.c~	Tue Aug 16 19:17:02 1994
+++ debug.c	Mon Aug 22 22:47:38 1994
@@ -606,7 +606,7 @@
 		reboot();
 		break;
 	case UNDO:
-		killgroup(con_tty.pgrp, SIGQUIT);
+		killgroup(con_tty.pgrp, SIGQUIT, 1);
 		break;
 #ifdef DEBUG_INFO
 	case 0x3b:		/* F1: increase debugging level */
--- dossig.c~	Mon Aug  8 04:45:10 1994
+++ dossig.c	Mon Aug 22 22:47:24 1994
@@ -30,9 +30,9 @@
 	}
 
 	if (pid < 0)
-		r = killgroup(-pid, sig);
+		r = killgroup(-pid, sig, 0);
 	else if (pid == 0)
-		r = killgroup(curproc->pgrp, sig);
+		r = killgroup(curproc->pgrp, sig, 0);
 	else {
 		p = pid2proc(pid);
 		if (p == 0 || p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q) {
--- pipefs.c~	Mon Aug 15 20:27:02 1994
+++ pipefs.c	Mon Aug 22 22:47:12 1994
@@ -1166,7 +1166,7 @@
 /* if pty master exits tell the slaves */
 				if (!p->writers && is_terminal(f) &&
 				    (f->flags & O_HEAD) && this->tty->pgrp)
-					killgroup(this->tty->pgrp, SIGHUP);
+					killgroup(this->tty->pgrp, SIGHUP, 1);
 #endif
 			}
 		}
--- proto.h~	Mon Aug  8 08:42:30 1994
+++ proto.h	Mon Aug 22 22:36:02 1994
@@ -278,7 +278,7 @@
 unsigned long gen_average P_((unsigned long *sum, unsigned char *load_ptr, int max_size));
 
 /* signal.c */
-long killgroup P_((int pgrp, int sig));
+long killgroup P_((int pgrp, int sig, int priv));
 void post_sig P_((PROC *p, int sig));
 long ikill P_((int p, int sig));
 void check_sigs P_((void));
--- signal.c~	Fri Jul  1 06:11:14 1994
+++ signal.c	Mon Aug 22 22:47:04 1994
@@ -12,30 +12,39 @@
 short sig_exc;		/* used in intr.s */
 
 /*
- * killgroup(pgrp, sig): send a signal to all members of a process group
+ * killgroup(pgrp, sig, priv): send a signal to all members of a process group
  * returns 0 on success, or an error code on failure
+ * priv is non-zero if the signal is generated by the kernel, otherwise
+ * access privileges are checked
  */
 
 long
-killgroup(pgrp, sig)
-	int pgrp, sig;
+killgroup(pgrp, sig, priv)
+	int pgrp, sig, priv;
 {
 	PROC *p;
 	int found = 0;
+	long retval = EFILNF;
 
 	if (pgrp < 0)
 		return EINTRN;
 
 	for (p = proclist; p; p = p->gl_next) {
 		if (p->pgrp == pgrp) {
+		  if (!priv && sig != SIGCONT && curproc->euid
+		      && curproc->euid != p->euid && curproc->ruid != p->ruid)
+		    retval = EACCDN;
+		  else
+		    {
 			post_sig(p, sig);
 			found++;
+		    }
 		}
 	}
 	if (found) {
 		return 0;
 	} else {
-		return EFILNF;
+		return retval;
 	}
 }
 
@@ -105,9 +114,9 @@
 		return ERANGE;
 
 	if (pid < 0)
-		r = killgroup(-pid, sig);
+		r = killgroup(-pid, sig, 1);
 	else if (pid == 0)
-		r = killgroup(curproc->pgrp, sig);
+		r = killgroup(curproc->pgrp, sig, 1);
 	else {
 		p = pid2proc(pid);
 		if (p == 0 || p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q) {
--- tty.c~	Fri Aug 19 20:32:32 1994
+++ tty.c	Mon Aug 22 22:46:56 1994
@@ -382,7 +382,7 @@
                  (f->fc.index == curproc->control->fc.index)) {
 		TRACE(("job control: tty pgrp is %d proc pgrp is %d",
 			tty->pgrp, curproc->pgrp));
-		killgroup(curproc->pgrp, SIGTTOU);
+		killgroup(curproc->pgrp, SIGTTOU, 1);
 		check_sigs();
 	}
 }
@@ -859,7 +859,7 @@
 		else
 		  i = 0;
 		tty->wsiz = *sz;
-		if (i && tty->pgrp) killgroup(tty->pgrp, SIGWINCH);
+		if (i && tty->pgrp) killgroup(tty->pgrp, SIGWINCH, 1);
 		return 0;
 	case TIOCGPGRP:
 		*((long *)arg) = tty->pgrp;
@@ -1155,7 +1155,7 @@
             (f->fc.index == curproc->control->fc.index)) {
 		TRACE(("job control: tty pgrp is %d proc pgrp is %d",
 			tty->pgrp, curproc->pgrp));
-		killgroup(curproc->pgrp, SIGTTIN);
+		killgroup(curproc->pgrp, SIGTTIN, 1);
 		check_sigs();
 	}
 
@@ -1212,13 +1212,13 @@
 			if (c == UNDEF)
 				;	/* do nothing */
 			else if (c == tty->ltc.t_dsuspc) {
-				killgroup(curproc->pgrp, SIGTSTP);
+				killgroup(curproc->pgrp, SIGTSTP, 1);
 				check_sigs();
 			} else if (c == tty->tc.t_intrc) {
-				killgroup(curproc->pgrp, SIGINT);
+				killgroup(curproc->pgrp, SIGINT, 1);
 				check_sigs();
 			} else if (c == tty->tc.t_quitc) {
-				killgroup(curproc->pgrp, SIGQUIT);
+				killgroup(curproc->pgrp, SIGQUIT, 1);
 				check_sigs();
 			} else if (c == tty->tc.t_stopc)
 				tty_ioctl(f, TIOCSTOP, 0);
@@ -1264,21 +1264,21 @@
 
 /* see if we're putting control characters into the buffer */
 			if (ch == tty->tc.t_intrc) {
-				killgroup(tty->pgrp, SIGINT);
+				killgroup(tty->pgrp, SIGINT, 1);
 				if (!(tty->sg.sg_flags & T_NOFLSH))
 					tty_ioctl(f, TIOCFLUSH, &r);
 				tty_ioctl (f, TIOCSTART, 0);
 				return 4L;
 			}
 			else if (ch == tty->tc.t_quitc) {
-				killgroup(tty->pgrp, SIGQUIT);
+				killgroup(tty->pgrp, SIGQUIT, 1);
 				if (!(tty->sg.sg_flags & T_NOFLSH))
 					tty_ioctl(f, TIOCFLUSH, &r);
 				tty_ioctl (f, TIOCSTART, 0);
 				return 4L;
 			}
 			else if (ch == tty->ltc.t_suspc) {
-				killgroup(tty->pgrp, SIGTSTP);
+				killgroup(tty->pgrp, SIGTSTP, 1);
 				if (!(tty->sg.sg_flags & T_NOFLSH))
 					tty_ioctl(f, TIOCFLUSH, &r);
 				tty_ioctl (f, TIOCSTART, 0);
@@ -1322,7 +1322,7 @@
                  (f->fc.index == curproc->control->fc.index)) {
 		TRACE(("job control: tty pgrp is %d proc pgrp is %d",
 			tty->pgrp, curproc->pgrp));
-		killgroup(curproc->pgrp, SIGTTOU);
+		killgroup(curproc->pgrp, SIGTTOU, 1);
 	}
 #endif
 
@@ -1352,13 +1352,13 @@
 					;	/* do nothing */
 				else if (c == tty->ltc.t_suspc) {
 					tty_ioctl(f, TIOCSTART, 0);
-					killgroup(tty->pgrp, SIGTSTP);
+					killgroup(tty->pgrp, SIGTSTP, 1);
 				} else if (c == tty->tc.t_intrc) {
 					tty_ioctl(f, TIOCSTART, 0);
-					killgroup(tty->pgrp, SIGINT);
+					killgroup(tty->pgrp, SIGINT, 1);
 				} else if (c == tty->tc.t_quitc) {
 					tty->state &= ~TS_HOLD;
-					killgroup(tty->pgrp, SIGQUIT);
+					killgroup(tty->pgrp, SIGQUIT, 1);
 				} else if (c == tty->tc.t_startc)
 					tty_ioctl(f, TIOCSTART, 0);
 				else if (c == tty->ltc.t_flushc) {