diff options
| author | Robert Watson <rwatson@FreeBSD.org> | 2001-04-12 02:38:08 +0000 |
|---|---|---|
| committer | Robert Watson <rwatson@FreeBSD.org> | 2001-04-12 02:38:08 +0000 |
| commit | 4c5eb9c397746249c3ebcf440283ef6e04199934 (patch) | |
| tree | dbc6cfa598c2e7948a5a37df2960e3ed4318fa7a /sys/kern | |
| parent | a9304a4eb552437c798f9a5b40ed870b4fca5371 (diff) | |
Notes
Diffstat (limited to 'sys/kern')
| -rw-r--r-- | sys/kern/kern_prot.c | 103 | ||||
| -rw-r--r-- | sys/kern/kern_sig.c | 13 |
2 files changed, 74 insertions, 42 deletions
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 003ff3b49d11..8db2fb65be85 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 6ed921a1cd39..e3f2fdbe5a01 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); |
