diff options
author | rwatson <rwatson@FreeBSD.org> | 2001-04-12 02:38:08 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2001-04-12 02:38:08 +0000 |
commit | 366237b31fbdbae545c94f65e8f4042687ec44ae (patch) | |
tree | d92c96379a59106ffbf6652b655ede41bc6d232c /sys | |
parent | c46318678ba76ee6902af48fa7493a07c0c24bd2 (diff) | |
download | FreeBSD-src-366237b31fbdbae545c94f65e8f4042687ec44ae.zip FreeBSD-src-366237b31fbdbae545c94f65e8f4042687ec44ae.tar.gz |
o Replace p_cankill() with p_cansignal(), remove wrappage of p_can()
from signal authorization checking.
o p_cansignal() takes three arguments: subject process, object process,
and signal number, unlike p_cankill(), which only took into account
the processes and not the signal number, improving the abstraction
such that CANSIGNAL() from kern_sig.c can now also be eliminated;
previously CANSIGNAL() special-cased the handling of SIGCONT based
on process session. privused is now deprecated.
o The new p_cansignal() further limits the set of signals that may
be delivered to processes with P_SUGID set, and restructures the
access control check to allow it to be extended more easily.
o These changes take into account work done by the OpenBSD Project,
as well as by Robert Watson and Thomas Moestl on the TrustedBSD
Project.
Obtained from: TrustedBSD Project
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/kern_prot.c | 103 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 13 | ||||
-rw-r--r-- | sys/sys/proc.h | 2 |
3 files changed, 75 insertions, 43 deletions
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 003ff3b..8db2fb6 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1024,48 +1024,90 @@ p_cansee(struct proc *p1, struct proc *p2, int *privused) return (u_cansee(p1->p_ucred, p2->p_ucred)); } -static int -p_cankill(struct proc *p1, struct proc *p2, int *privused) +/* + * Can process p1 send the signal signum to process p2? + */ +int +p_cansignal(struct proc *p1, struct proc *p2, int signum) { - int error; - - if (privused != NULL) - *privused = 0; - + int error; + if (p1 == p2) return (0); + /* + * Jail semantics limit the scope of signalling to p2 in the same + * jail as p1, if p1 is in jail. + */ if ((error = prison_check(p1->p_ucred, p2->p_ucred))) return (error); - if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) - return (0); - if (p1->p_ucred->cr_uid == p2->p_cred->p_ruid) - return (0); /* - * XXX should a process be able to affect another process - * acting as the same uid (i.e., a userland nfsd or the like?) + * UNIX signalling semantics require that processes in the same + * session always be able to deliver SIGCONT to one another, + * overriding the remaining protections. */ - if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid) - return (0); - if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid) + if (signum == SIGCONT && p1->p_session == p2->p_session) return (0); - if (!suser_xxx(0, p1, PRISON_ROOT)) { - if (privused != NULL) - *privused = 1; - return (0); - } - -#ifdef CAPABILITIES - if (!cap_check_xxx(0, p1, CAP_KILL, PRISON_ROOT)) { - if (privused != NULL) - *privused = 1; - return (0); + /* + * UNIX uid semantics depend on the status of the P_SUGID + * bit on the target process. If the bit is set, then more + * restricted signal sets are permitted. + */ + if (p2->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: + /* + * Restricted rules allow a broadish scope of uid + * uid overlap. + * XXX: Maybe too broad. + */ + if (p1->p_cred->p_ruid != p2->p_cred->p_ruid && + p1->p_ucred->cr_uid != p2->p_cred->p_ruid && + p1->p_cred->p_ruid != p2->p_ucred->cr_uid && + p1->p_ucred->cr_uid != p2->p_ucred->cr_uid) { + /* Not permitted, try privilege. */ + error = suser_xxx(NULL, p1, PRISON_ROOT); + if (error) + return (error); + } + break; + default: + /* Not permitted, try privilege. */ + error = suser_xxx(NULL, p1, PRISON_ROOT); + if (error) + return (error); + } + } else { + /* + * Normal rules allow a broad scope of uid overlap. + * XXX: Maybe too broad. + */ + if (p1->p_cred->p_ruid != p2->p_cred->p_ruid && + p1->p_cred->p_ruid != p2->p_cred->p_svuid && + p1->p_ucred->cr_uid != p2->p_cred->p_ruid && + p1->p_ucred->cr_uid != p2->p_cred->p_svuid && + p1->p_cred->p_ruid != p2->p_ucred->cr_uid && + p1->p_ucred->cr_uid != p2->p_ucred->cr_uid) { + /* Not permitted, try privilege. */ + error = suser_xxx(NULL, p1, PRISON_ROOT); + if (error) + return (error); + } } -#endif - return (EPERM); + return (0); } static int @@ -1155,9 +1197,6 @@ p_can(struct proc *p1, struct proc *p2, int operation, case P_CAN_SEE: return (p_cansee(p1, p2, privused)); - case P_CAN_KILL: - return (p_cankill(p1, p2, privused)); - case P_CAN_SCHED: return (p_cansched(p1, p2, privused)); diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 6ed921a..e3f2fdb 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -98,13 +98,6 @@ SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW, "Log processes quitting on abnormal signals to syslog(3)"); /* - * Can process p, with pcred pc, send the signal sig to process q? - */ -#define CANSIGNAL(p, q, sig) \ - (!p_can(p, q, P_CAN_KILL, NULL) || \ - ((sig) == SIGCONT && (q)->p_session == (p)->p_session)) - -/* * Policy -- Can real uid ruid with ucred uc send a signal to process q? */ #define CANSIGIO(ruid, uc, q) \ @@ -910,7 +903,7 @@ killpg1(cp, sig, pgid, all) * XXX: this locking needs work.. specifically the * session checks.. */ - if (!CANSIGNAL(cp, p, sig)) + if (p_cansignal(cp, p, sig)) continue; nfound++; if (sig) { @@ -945,7 +938,7 @@ killpg1(cp, sig, pgid, all) } mtx_unlock_spin(&sched_lock); /* XXX: locking b0rked */ - if (!CANSIGNAL(cp, p, sig)) + if (p_cansignal(cp, p, sig)) continue; nfound++; if (sig) { @@ -979,7 +972,7 @@ kill(cp, uap) if ((p = pfind(uap->pid)) == NULL) return (ESRCH); /* XXX: locking b0rked */ - if (!CANSIGNAL(cp, p, uap->signum)) + if (p_cansignal(cp, p, uap->signum)) return (EPERM); if (uap->signum) { PROC_LOCK(p); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 4a1c3ac..7ddd621 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -329,7 +329,6 @@ struct proc { #define P_MAGIC 0xbeefface #define P_CAN_SEE 1 -#define P_CAN_KILL 2 #define P_CAN_SCHED 3 #define P_CAN_DEBUG 4 @@ -530,6 +529,7 @@ int leavepgrp __P((struct proc *p)); void mi_switch __P((void)); int p_can __P((struct proc *p1, struct proc *p2, int operation, int *privused)); +int p_cansignal __P((struct proc *p1, struct proc *p2, int signum)); int p_trespass __P((struct proc *p1, struct proc *p2)); void procinit __P((void)); void proc_reparent __P((struct proc *child, struct proc *newparent)); |