- Push much of the logic for p_cansignal() behind cr_cansignal, which

authorized based on a subject credential rather than a subject process.
  This will permit the same logic to be reused in situations where only
  the credential generating the signal is available, such as in the
  delivery of SIGIO.
- Because of two clauses, the automatic success against curproc,
  and the session semantics for SIGCONT, not all logic can be pushed
  into cr_cansignal(), but those cases should not apply for most other
  consumers of cr_cansignal().
- This brings the base system inter-process authorization code more
  into line with the MAC implementation.

Obtained from:	TrustedBSD Project
Sponsored by:	DARPA, NAI Labs
This commit is contained in:
Robert Watson 2002-01-06 00:20:12 +00:00
parent ee42d0a965
commit c83f8015fa

View File

@ -1354,42 +1354,30 @@ p_cansee(struct proc *p1, struct proc *p2)
}
/*-
* Determine whether p1 may deliver the specified signal to p2.
* Returns: 0 for permitted, an errno value otherwise
* Locks: Sufficient locks to protect various components of p1 and p2
* must be held. Normally, p1 will be curproc, and a lock must
* be held for p2.
* References: p1 and p2 must be valid for the lifetime of the call
* Determine whether cred may deliver the specified signal to proc.
* Returns: 0 for permitted, an errno value otherwise.
* Locks: A lock must be held for proc.
* References: cred and proc must be valid for the lifetime of the call.
*/
int
p_cansignal(struct proc *p1, struct proc *p2, int signum)
cr_cansignal(struct ucred *cred, struct proc *proc, int signum)
{
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.
* Jail semantics limit the scope of signalling to proc in the
* same jail as cred, if cred is in jail.
*/
if ((error = prison_check(p1->p_ucred, p2->p_ucred)))
error = prison_check(cred, proc->p_ucred);
if (error)
return (error);
/*
* UNIX signalling semantics require that processes in the same
* session always be able to deliver SIGCONT to one another,
* overriding the remaining protections.
*/
if (signum == SIGCONT && p1->p_session == p2->p_session)
return (0);
/*
* UNIX signal semantics depend on the status of the P_SUGID
* bit on the target process. If the bit is set, then additional
* restrictions are placed on the set of available signals.
*/
if (p2->p_flag & P_SUGID) {
if (proc->p_flag & P_SUGID) {
switch (signum) {
case 0:
case SIGKILL:
@ -1408,8 +1396,8 @@ p_cansignal(struct proc *p1, struct proc *p2, int signum)
*/
break;
default:
/* Not permitted, privilege is required. */
error = suser_xxx(NULL, p1, PRISON_ROOT);
/* Not permitted without privilege. */
error = suser_xxx(cred, NULL, PRISON_ROOT);
if (error)
return (error);
}
@ -1419,12 +1407,12 @@ p_cansignal(struct proc *p1, struct proc *p2, int signum)
* Generally, the target credential's ruid or svuid must match the
* subject credential's ruid or euid.
*/
if (p1->p_ucred->cr_ruid != p2->p_ucred->cr_ruid &&
p1->p_ucred->cr_ruid != p2->p_ucred->cr_svuid &&
p1->p_ucred->cr_uid != p2->p_ucred->cr_ruid &&
p1->p_ucred->cr_uid != p2->p_ucred->cr_svuid) {
/* Not permitted, try privilege. */
error = suser_xxx(NULL, p1, PRISON_ROOT);
if (cred->cr_ruid != proc->p_ucred->cr_ruid &&
cred->cr_ruid != proc->p_ucred->cr_svuid &&
cred->cr_uid != proc->p_ucred->cr_ruid &&
cred->cr_uid != proc->p_ucred->cr_svuid) {
/* Not permitted without privilege. */
error = suser_xxx(cred, NULL, PRISON_ROOT);
if (error)
return (error);
}
@ -1432,6 +1420,33 @@ p_cansignal(struct proc *p1, struct proc *p2, int signum)
return (0);
}
/*-
* Determine whether p1 may deliver the specified signal to p2.
* Returns: 0 for permitted, an errno value otherwise
* Locks: Sufficient locks to protect various components of p1 and p2
* must be held. Normally, p1 will be curproc, and a lock must
* be held for p2.
* References: p1 and p2 must be valid for the lifetime of the call
*/
int
p_cansignal(struct proc *p1, struct proc *p2, int signum)
{
if (p1 == p2)
return (0);
/*
* UNIX signalling semantics require that processes in the same
* session always be able to deliver SIGCONT to one another,
* overriding the remaining protections.
*/
if (signum == SIGCONT && p1->p_session == p2->p_session)
return (0);
return (cr_cansignal(p1->p_ucred, p2, signum));
}
/*-
* Determine whether p1 may reschedule p2.
* Returns: 0 for permitted, an errno value otherwise