Introduce the new function
p_trespass(struct proc *p1, struct proc *p2) which returns zero or an errno depending on the legality of p1 trespassing on p2. Replace kern_sig.c:CANSIGNAL() with call to p_trespass() and one extra signal related check. Replace procfs.h:CHECKIO() macros with calls to p_trespass(). Only show command lines to process which can trespass on the target process.
This commit is contained in:
parent
7183c3f848
commit
a9e0361b4a
|
@ -90,19 +90,6 @@ struct pfsnode {
|
||||||
|
|
||||||
#define KMEM_GROUP 2
|
#define KMEM_GROUP 2
|
||||||
|
|
||||||
/*
|
|
||||||
* Check to see whether access to target process is allowed
|
|
||||||
* Evaluates to 1 if access is allowed.
|
|
||||||
*/
|
|
||||||
#define CHECKIO(p1, p2) \
|
|
||||||
((p1) == (p2) || \
|
|
||||||
(PRISON_CHECK(p1, p2) && \
|
|
||||||
((((p1)->p_ucred->cr_uid == (p2)->p_cred->p_ruid) && \
|
|
||||||
((p1)->p_cred->p_ruid == (p2)->p_cred->p_ruid) && \
|
|
||||||
((p1)->p_cred->p_svuid == (p2)->p_cred->p_ruid) && \
|
|
||||||
((p2)->p_flag & P_SUGID) == 0) || \
|
|
||||||
(suser_xxx(0, (p1), PRISON_ROOT) == 0))))
|
|
||||||
|
|
||||||
#define PROCFS_FILENO(pid, type) \
|
#define PROCFS_FILENO(pid, type) \
|
||||||
(((type) < Pproc) ? \
|
(((type) < Pproc) ? \
|
||||||
((type) + 2) : \
|
((type) + 2) : \
|
||||||
|
|
|
@ -63,7 +63,7 @@ procfs_dodbregs(curp, p, pfs, uio)
|
||||||
char *kv;
|
char *kv;
|
||||||
int kl;
|
int kl;
|
||||||
|
|
||||||
if (!CHECKIO(curp, p))
|
if (p_trespass(curp, p))
|
||||||
return (EPERM);
|
return (EPERM);
|
||||||
kl = sizeof(r);
|
kl = sizeof(r);
|
||||||
kv = (char *) &r;
|
kv = (char *) &r;
|
||||||
|
|
|
@ -60,7 +60,7 @@ procfs_dofpregs(curp, p, pfs, uio)
|
||||||
char *kv;
|
char *kv;
|
||||||
int kl;
|
int kl;
|
||||||
|
|
||||||
if (!CHECKIO(curp, p))
|
if (p_trespass(curp, p))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
kl = sizeof(r);
|
kl = sizeof(r);
|
||||||
kv = (char *) &r;
|
kv = (char *) &r;
|
||||||
|
|
|
@ -296,7 +296,7 @@ procfs_domem(curp, p, pfs, uio)
|
||||||
* All in all, quite yucky.
|
* All in all, quite yucky.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!CHECKIO(curp, p) &&
|
if (p_trespass(curp, p) &&
|
||||||
!(uio->uio_rw == UIO_READ &&
|
!(uio->uio_rw == UIO_READ &&
|
||||||
procfs_kmemaccess(curp)))
|
procfs_kmemaccess(curp)))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
|
|
|
@ -60,7 +60,7 @@ procfs_doregs(curp, p, pfs, uio)
|
||||||
char *kv;
|
char *kv;
|
||||||
int kl;
|
int kl;
|
||||||
|
|
||||||
if (!CHECKIO(curp, p))
|
if (p_trespass(curp, p))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
kl = sizeof(r);
|
kl = sizeof(r);
|
||||||
kv = (char *) &r;
|
kv = (char *) &r;
|
||||||
|
|
|
@ -183,7 +183,7 @@ procfs_docmdline(curp, p, pfs, uio)
|
||||||
* Linux behaviour is to return zero-length in this case.
|
* Linux behaviour is to return zero-length in this case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (p->p_args) {
|
if (p->p_args && !p_trespass(curp, p)) {
|
||||||
bp = p->p_args->ar_args;
|
bp = p->p_args->ar_args;
|
||||||
buflen = p->p_args->ar_length;
|
buflen = p->p_args->ar_length;
|
||||||
buf = 0;
|
buf = 0;
|
||||||
|
|
|
@ -146,7 +146,7 @@ procfs_open(ap)
|
||||||
return (EBUSY);
|
return (EBUSY);
|
||||||
|
|
||||||
p1 = ap->a_p;
|
p1 = ap->a_p;
|
||||||
if (!CHECKIO(p1, p2) &&
|
if (p_trespass(p1, p2) &&
|
||||||
!procfs_kmemaccess(p1))
|
!procfs_kmemaccess(p1))
|
||||||
return (EPERM);
|
return (EPERM);
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ procfs_ioctl(ap)
|
||||||
return ENOTTY;
|
return ENOTTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CHECKIO(p, procp))
|
if (p_trespass(p, procp))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
|
|
||||||
switch (ap->a_command) {
|
switch (ap->a_command) {
|
||||||
|
|
|
@ -633,7 +633,7 @@ sysctl_kern_proc_args SYSCTL_HANDLER_ARGS
|
||||||
if (!p)
|
if (!p)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (!PRISON_CHECK(curproc, p))
|
if (p_trespass(curproc, p))
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (req->newptr && curproc != p)
|
if (req->newptr && curproc != p)
|
||||||
|
|
|
@ -792,6 +792,31 @@ suser_xxx(cred, proc, flag)
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int
|
||||||
|
p_trespass(struct proc *p1, struct proc *p2)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (p1 == p2)
|
||||||
|
return (0);
|
||||||
|
if (!PRISON_CHECK(p1, p2))
|
||||||
|
return (ESRCH);
|
||||||
|
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);
|
||||||
|
if (p1->p_cred->p_ruid == p2->p_ucred->cr_uid)
|
||||||
|
return (0);
|
||||||
|
if (p1->p_ucred->cr_uid == p2->p_ucred->cr_uid)
|
||||||
|
return (0);
|
||||||
|
if (!suser_xxx(0, p1, PRISON_ROOT))
|
||||||
|
return (0);
|
||||||
|
return (EPERM);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a zeroed cred structure.
|
* Allocate a zeroed cred structure.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -88,13 +88,9 @@ SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW,
|
||||||
/*
|
/*
|
||||||
* Can process p, with pcred pc, send the signal sig to process q?
|
* Can process p, with pcred pc, send the signal sig to process q?
|
||||||
*/
|
*/
|
||||||
#define CANSIGNAL(p, pc, q, sig) \
|
#define CANSIGNAL(p, q, sig) \
|
||||||
(PRISON_CHECK(p, q) && ((pc)->pc_ucred->cr_uid == 0 || \
|
(!p_trespass(p, q) || \
|
||||||
(pc)->p_ruid == (q)->p_cred->p_ruid || \
|
((sig) == SIGCONT && (q)->p_session == (p)->p_session))
|
||||||
(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 || \
|
|
||||||
((sig) == SIGCONT && (q)->p_session == (p)->p_session)))
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Policy -- Can real uid ruid with ucred uc send a signal to process q?
|
* Policy -- Can real uid ruid with ucred uc send a signal to process q?
|
||||||
|
@ -799,7 +795,6 @@ killpg1(cp, sig, pgid, all)
|
||||||
int sig, pgid, all;
|
int sig, pgid, all;
|
||||||
{
|
{
|
||||||
register struct proc *p;
|
register struct proc *p;
|
||||||
register struct pcred *pc = cp->p_cred;
|
|
||||||
struct pgrp *pgrp;
|
struct pgrp *pgrp;
|
||||||
int nfound = 0;
|
int nfound = 0;
|
||||||
|
|
||||||
|
@ -809,7 +804,7 @@ killpg1(cp, sig, pgid, all)
|
||||||
*/
|
*/
|
||||||
LIST_FOREACH(p, &allproc, p_list) {
|
LIST_FOREACH(p, &allproc, p_list) {
|
||||||
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
|
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
|
||||||
p == cp || !CANSIGNAL(cp, pc, p, sig))
|
p == cp || !CANSIGNAL(cp, p, sig))
|
||||||
continue;
|
continue;
|
||||||
nfound++;
|
nfound++;
|
||||||
if (sig)
|
if (sig)
|
||||||
|
@ -829,7 +824,7 @@ killpg1(cp, sig, pgid, all)
|
||||||
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
|
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
|
||||||
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
|
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
|
||||||
p->p_stat == SZOMB ||
|
p->p_stat == SZOMB ||
|
||||||
!CANSIGNAL(cp, pc, p, sig))
|
!CANSIGNAL(cp, p, sig))
|
||||||
continue;
|
continue;
|
||||||
nfound++;
|
nfound++;
|
||||||
if (sig)
|
if (sig)
|
||||||
|
@ -852,7 +847,6 @@ kill(cp, uap)
|
||||||
register struct kill_args *uap;
|
register struct kill_args *uap;
|
||||||
{
|
{
|
||||||
register struct proc *p;
|
register struct proc *p;
|
||||||
register struct pcred *pc = cp->p_cred;
|
|
||||||
|
|
||||||
if ((u_int)uap->signum > _SIG_MAXSIG)
|
if ((u_int)uap->signum > _SIG_MAXSIG)
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
|
@ -860,7 +854,7 @@ kill(cp, uap)
|
||||||
/* kill single process */
|
/* kill single process */
|
||||||
if ((p = pfind(uap->pid)) == NULL)
|
if ((p = pfind(uap->pid)) == NULL)
|
||||||
return (ESRCH);
|
return (ESRCH);
|
||||||
if (!CANSIGNAL(cp, pc, p, uap->signum))
|
if (!CANSIGNAL(cp, p, uap->signum))
|
||||||
return (EPERM);
|
return (EPERM);
|
||||||
if (uap->signum)
|
if (uap->signum)
|
||||||
psignal(p, uap->signum);
|
psignal(p, uap->signum);
|
||||||
|
|
|
@ -420,8 +420,7 @@ ptrace(curp, uap)
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
}
|
}
|
||||||
if (ptrace_read_u_check(p,(vm_offset_t) uap->addr,
|
if (ptrace_read_u_check(p,(vm_offset_t) uap->addr,
|
||||||
sizeof(int)) &&
|
sizeof(int))) {
|
||||||
!procfs_kmemaccess(curp)) {
|
|
||||||
return EFAULT;
|
return EFAULT;
|
||||||
}
|
}
|
||||||
error = 0;
|
error = 0;
|
||||||
|
|
|
@ -90,19 +90,6 @@ struct pfsnode {
|
||||||
|
|
||||||
#define KMEM_GROUP 2
|
#define KMEM_GROUP 2
|
||||||
|
|
||||||
/*
|
|
||||||
* Check to see whether access to target process is allowed
|
|
||||||
* Evaluates to 1 if access is allowed.
|
|
||||||
*/
|
|
||||||
#define CHECKIO(p1, p2) \
|
|
||||||
((p1) == (p2) || \
|
|
||||||
(PRISON_CHECK(p1, p2) && \
|
|
||||||
((((p1)->p_ucred->cr_uid == (p2)->p_cred->p_ruid) && \
|
|
||||||
((p1)->p_cred->p_ruid == (p2)->p_cred->p_ruid) && \
|
|
||||||
((p1)->p_cred->p_svuid == (p2)->p_cred->p_ruid) && \
|
|
||||||
((p2)->p_flag & P_SUGID) == 0) || \
|
|
||||||
(suser_xxx(0, (p1), PRISON_ROOT) == 0))))
|
|
||||||
|
|
||||||
#define PROCFS_FILENO(pid, type) \
|
#define PROCFS_FILENO(pid, type) \
|
||||||
(((type) < Pproc) ? \
|
(((type) < Pproc) ? \
|
||||||
((type) + 2) : \
|
((type) + 2) : \
|
||||||
|
|
|
@ -63,7 +63,7 @@ procfs_dodbregs(curp, p, pfs, uio)
|
||||||
char *kv;
|
char *kv;
|
||||||
int kl;
|
int kl;
|
||||||
|
|
||||||
if (!CHECKIO(curp, p))
|
if (p_trespass(curp, p))
|
||||||
return (EPERM);
|
return (EPERM);
|
||||||
kl = sizeof(r);
|
kl = sizeof(r);
|
||||||
kv = (char *) &r;
|
kv = (char *) &r;
|
||||||
|
|
|
@ -60,7 +60,7 @@ procfs_dofpregs(curp, p, pfs, uio)
|
||||||
char *kv;
|
char *kv;
|
||||||
int kl;
|
int kl;
|
||||||
|
|
||||||
if (!CHECKIO(curp, p))
|
if (p_trespass(curp, p))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
kl = sizeof(r);
|
kl = sizeof(r);
|
||||||
kv = (char *) &r;
|
kv = (char *) &r;
|
||||||
|
|
|
@ -296,7 +296,7 @@ procfs_domem(curp, p, pfs, uio)
|
||||||
* All in all, quite yucky.
|
* All in all, quite yucky.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (!CHECKIO(curp, p) &&
|
if (p_trespass(curp, p) &&
|
||||||
!(uio->uio_rw == UIO_READ &&
|
!(uio->uio_rw == UIO_READ &&
|
||||||
procfs_kmemaccess(curp)))
|
procfs_kmemaccess(curp)))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
|
|
|
@ -60,7 +60,7 @@ procfs_doregs(curp, p, pfs, uio)
|
||||||
char *kv;
|
char *kv;
|
||||||
int kl;
|
int kl;
|
||||||
|
|
||||||
if (!CHECKIO(curp, p))
|
if (p_trespass(curp, p))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
kl = sizeof(r);
|
kl = sizeof(r);
|
||||||
kv = (char *) &r;
|
kv = (char *) &r;
|
||||||
|
|
|
@ -183,7 +183,7 @@ procfs_docmdline(curp, p, pfs, uio)
|
||||||
* Linux behaviour is to return zero-length in this case.
|
* Linux behaviour is to return zero-length in this case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (p->p_args) {
|
if (p->p_args && !p_trespass(curp, p)) {
|
||||||
bp = p->p_args->ar_args;
|
bp = p->p_args->ar_args;
|
||||||
buflen = p->p_args->ar_length;
|
buflen = p->p_args->ar_length;
|
||||||
buf = 0;
|
buf = 0;
|
||||||
|
|
|
@ -146,7 +146,7 @@ procfs_open(ap)
|
||||||
return (EBUSY);
|
return (EBUSY);
|
||||||
|
|
||||||
p1 = ap->a_p;
|
p1 = ap->a_p;
|
||||||
if (!CHECKIO(p1, p2) &&
|
if (p_trespass(p1, p2) &&
|
||||||
!procfs_kmemaccess(p1))
|
!procfs_kmemaccess(p1))
|
||||||
return (EPERM);
|
return (EPERM);
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ procfs_ioctl(ap)
|
||||||
return ENOTTY;
|
return ENOTTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CHECKIO(p, procp))
|
if (p_trespass(p, procp))
|
||||||
return EPERM;
|
return EPERM;
|
||||||
|
|
||||||
switch (ap->a_command) {
|
switch (ap->a_command) {
|
||||||
|
|
|
@ -399,6 +399,7 @@ int inferior __P((struct proc *p));
|
||||||
int leavepgrp __P((struct proc *p));
|
int leavepgrp __P((struct proc *p));
|
||||||
void mi_switch __P((void));
|
void mi_switch __P((void));
|
||||||
void procinit __P((void));
|
void procinit __P((void));
|
||||||
|
int p_trespass __P((struct proc *p1, struct proc *p2));
|
||||||
void resetpriority __P((struct proc *));
|
void resetpriority __P((struct proc *));
|
||||||
int roundrobin_interval __P((void));
|
int roundrobin_interval __P((void));
|
||||||
void setrunnable __P((struct proc *));
|
void setrunnable __P((struct proc *));
|
||||||
|
|
Loading…
Reference in New Issue