This is revision 4 of this patch. Apply by doing cd /usr/src/sys/kern patch -p0 < kill.patch Then rebuild the kernel you use. Index: kern_sig.c =================================================================== RCS file: /cvs/src/sys/kern/kern_sig.c,v retrieving revision 1.26 retrieving revision 1.30 diff -u -r1.26 -r1.30 --- kern_sig.c 1998/02/20 14:46:18 1.26 +++ kern_sig.c 1998/06/07 20:17:25 1.30 @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.26 1998/02/20 14:46:18 niklas Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.30 1998/06/07 20:17:25 deraadt Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -73,19 +73,64 @@ void stop __P((struct proc *p)); void killproc __P((struct proc *, char *)); +int cansignal __P((struct proc *, struct pcred *, struct proc *, int)); /* * Can process p, with pcred pc, send the signal signum to process q? */ -#define CANSIGNAL(p, pc, q, signum) \ - ((pc)->pc_ucred->cr_uid == 0 || \ - (pc)->p_ruid == (q)->p_cred->p_ruid || \ - (pc)->p_ruid == (q)->p_cred->p_svuid || \ - (pc)->pc_ucred->cr_uid == (q)->p_cred->p_ruid || \ - (pc)->pc_ucred->cr_uid == (q)->p_cred->p_svuid || \ - (pc)->p_ruid == (q)->p_ucred->cr_uid || \ - (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \ - ((signum) == SIGCONT && (q)->p_session == (p)->p_session)) +int +cansignal(p, pc, q, signum) + struct proc *p; + struct pcred *pc; + struct proc *q; + int signum; +{ + if (pc->pc_ucred->cr_uid == 0) + return (1); /* root can always signal */ + + if (signum == SIGCONT && q->p_session == p->p_session) + return (1); /* SIGCONT in session */ + + /* + * Using kill(), only certain signals can be sent to setugid + * child processes + */ + if (q->p_flag & P_SUGID) { + switch (signum) { + case 0: + case SIGKILL: + case SIGINT: + case SIGTERM: + case SIGSTOP: + case SIGTTIN: + case SIGTTOU: + case SIGTSTP: + case SIGHUP: + case SIGUSR1: + case SIGUSR2: + if (pc->p_ruid == q->p_cred->p_ruid || + pc->pc_ucred->cr_uid == q->p_cred->p_ruid || + pc->p_ruid == q->p_ucred->cr_uid || + pc->pc_ucred->cr_uid == q->p_ucred->cr_uid) + return (1); + } + return (0); + } + + /* XXX + * because the P_SUGID test exists, this has extra tests which + * could be removed. + */ + if (pc->p_ruid == q->p_cred->p_ruid || + pc->p_ruid == q->p_cred->p_svuid || + pc->pc_ucred->cr_uid == q->p_cred->p_ruid || + pc->pc_ucred->cr_uid == q->p_cred->p_svuid || + pc->p_ruid == q->p_ucred->cr_uid || + pc->pc_ucred->cr_uid == q->p_ucred->cr_uid) + return (1); + return (0); +} + /* ARGSUSED */ int @@ -433,7 +478,7 @@ /* kill single process */ if ((p = pfind(SCARG(uap, pid))) == NULL) return (ESRCH); - if (!CANSIGNAL(cp, pc, p, SCARG(uap, signum))) + if (!cansignal(cp, pc, p, SCARG(uap, signum))) return (EPERM); if (SCARG(uap, signum)) psignal(p, SCARG(uap, signum)); @@ -470,7 +515,7 @@ */ for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || - p == cp || !CANSIGNAL(cp, pc, p, signum)) + p == cp || !cansignal(cp, pc, p, signum)) continue; nfound++; if (signum) @@ -489,7 +534,7 @@ } for (p = pgrp->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || - !CANSIGNAL(cp, pc, p, signum)) + !cansignal(cp, pc, p, signum)) continue; nfound++; if (signum)