summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/fs/procfs/procfs_dbregs.c2
-rw-r--r--sys/fs/procfs/procfs_fpregs.c2
-rw-r--r--sys/fs/procfs/procfs_mem.c2
-rw-r--r--sys/fs/procfs/procfs_regs.c2
-rw-r--r--sys/fs/procfs/procfs_status.c2
-rw-r--r--sys/fs/procfs/procfs_vnops.c49
-rw-r--r--sys/kern/kern_event.c2
-rw-r--r--sys/kern/kern_ktrace.c2
-rw-r--r--sys/kern/kern_proc.c12
-rw-r--r--sys/kern/kern_prot.c152
-rw-r--r--sys/kern/kern_resource.c21
-rw-r--r--sys/kern/kern_sig.c2
-rw-r--r--sys/kern/sys_process.c14
-rw-r--r--sys/miscfs/procfs/procfs_dbregs.c2
-rw-r--r--sys/miscfs/procfs/procfs_fpregs.c2
-rw-r--r--sys/miscfs/procfs/procfs_mem.c2
-rw-r--r--sys/miscfs/procfs/procfs_regs.c2
-rw-r--r--sys/miscfs/procfs/procfs_status.c2
-rw-r--r--sys/miscfs/procfs/procfs_vnops.c49
-rw-r--r--sys/sys/proc.h15
20 files changed, 255 insertions, 83 deletions
diff --git a/sys/fs/procfs/procfs_dbregs.c b/sys/fs/procfs/procfs_dbregs.c
index 158c3f4..c7ad130 100644
--- a/sys/fs/procfs/procfs_dbregs.c
+++ b/sys/fs/procfs/procfs_dbregs.c
@@ -62,7 +62,7 @@ procfs_dodbregs(curp, p, pfs, uio)
char *kv;
int kl;
- if (p_trespass(curp, p))
+ if (p_can(curp, p, P_CAN_DEBUG, NULL))
return (EPERM);
kl = sizeof(r);
kv = (char *) &r;
diff --git a/sys/fs/procfs/procfs_fpregs.c b/sys/fs/procfs/procfs_fpregs.c
index 353b52b..69dd527 100644
--- a/sys/fs/procfs/procfs_fpregs.c
+++ b/sys/fs/procfs/procfs_fpregs.c
@@ -59,7 +59,7 @@ procfs_dofpregs(curp, p, pfs, uio)
char *kv;
int kl;
- if (p_trespass(curp, p))
+ if (p_can(curp, p, P_CAN_DEBUG, NULL))
return EPERM;
kl = sizeof(r);
kv = (char *) &r;
diff --git a/sys/fs/procfs/procfs_mem.c b/sys/fs/procfs/procfs_mem.c
index b7eed85..6f2c8cb 100644
--- a/sys/fs/procfs/procfs_mem.c
+++ b/sys/fs/procfs/procfs_mem.c
@@ -256,7 +256,7 @@ procfs_domem(curp, p, pfs, uio)
* All in all, quite yucky.
*/
- if (p_trespass(curp, p) &&
+ if (p_can(curp, p, P_CAN_DEBUG, NULL) &&
!(uio->uio_rw == UIO_READ &&
procfs_kmemaccess(curp)))
return EPERM;
diff --git a/sys/fs/procfs/procfs_regs.c b/sys/fs/procfs/procfs_regs.c
index 88f85d3..c2b6d4b 100644
--- a/sys/fs/procfs/procfs_regs.c
+++ b/sys/fs/procfs/procfs_regs.c
@@ -60,7 +60,7 @@ procfs_doregs(curp, p, pfs, uio)
char *kv;
int kl;
- if (p_trespass(curp, p))
+ if (p_can(curp, p, P_CAN_DEBUG, NULL))
return EPERM;
kl = sizeof(r);
kv = (char *) &r;
diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c
index 03149e9..c1adc60 100644
--- a/sys/fs/procfs/procfs_status.c
+++ b/sys/fs/procfs/procfs_status.c
@@ -183,7 +183,7 @@ procfs_docmdline(curp, p, pfs, uio)
* Linux behaviour is to return zero-length in this case.
*/
- if (p->p_args && (ps_argsopen ||!p_trespass(curp, p))) {
+ if (p->p_args && (ps_argsopen || !p_can(curp, p, P_CAN_SEE, NULL))) {
bp = p->p_args->ar_args;
buflen = p->p_args->ar_length;
buf = 0;
diff --git a/sys/fs/procfs/procfs_vnops.c b/sys/fs/procfs/procfs_vnops.c
index 35b3afb..df8e3ca 100644
--- a/sys/fs/procfs/procfs_vnops.c
+++ b/sys/fs/procfs/procfs_vnops.c
@@ -137,7 +137,7 @@ procfs_open(ap)
p2 = PFIND(pfs->pfs_pid);
if (p2 == NULL)
return (ENOENT);
- if (pfs->pfs_pid && !PRISON_CHECK(ap->a_p, p2))
+ if (pfs->pfs_pid && p_can(ap->a_p, p2, P_CAN_SEE, NULL))
return (ENOENT);
switch (pfs->pfs_type) {
@@ -147,7 +147,7 @@ procfs_open(ap)
return (EBUSY);
p1 = ap->a_p;
- if (p_trespass(p1, p2) &&
+ if (p_can(p1, p2, P_CAN_DEBUG, NULL) &&
!procfs_kmemaccess(p1))
return (EPERM);
@@ -239,8 +239,11 @@ procfs_ioctl(ap)
return ENOTTY;
}
- if (p_trespass(p, procp))
- return EPERM;
+ if ((error = p_can(p, procp, P_CAN_DEBUG, NULL))) {
+ if (error == ESRCH)
+ error = ENOENT;
+ return (error);
+ }
switch (ap->a_command) {
case PIOCBIS:
@@ -417,6 +420,9 @@ procfs_getattr(ap)
if (procp == 0 || procp->p_cred == NULL ||
procp->p_ucred == NULL)
return (ENOENT);
+
+ if (p_can(ap->a_p, procp, P_CAN_SEE, NULL))
+ return (ENOENT);
}
error = 0;
@@ -612,16 +618,23 @@ procfs_access(ap)
struct proc *a_p;
} */ *ap;
{
+ struct pfsnode *pfs = VTOPFS(ap->a_vp);
+ struct proc *procp;
struct vattr *vap;
struct vattr vattr;
int error;
- /*
- * If you're the super-user,
- * you always get access.
- */
- if (ap->a_cred->cr_uid == 0)
- return (0);
+ switch (pfs->pfs_type) {
+ case Proot:
+ case Pcurproc:
+ break;
+ default:
+ procp = PFIND(pfs->pfs_pid);
+ if (procp == NULL)
+ return (ENOENT);
+ if (p_can(ap->a_p, procp, P_CAN_SEE, NULL))
+ return (ENOENT);
+ }
vap = &vattr;
error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p);
@@ -674,7 +687,7 @@ procfs_lookup(ap)
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
char *pname = cnp->cn_nameptr;
- /* struct proc *curp = cnp->cn_proc; */
+ struct proc *curp = cnp->cn_proc;
struct proc_target *pt;
pid_t pid;
struct pfsnode *pfs;
@@ -683,7 +696,8 @@ procfs_lookup(ap)
*vpp = NULL;
- if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
+ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME ||
+ cnp->cn_nameiop == CREATE)
return (EROFS);
if (cnp->cn_namelen == 1 && *pname == '.') {
@@ -710,6 +724,9 @@ procfs_lookup(ap)
if (p == 0)
break;
+ if (p_can(curp, p, P_CAN_SEE, NULL))
+ break;
+
return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
case Pproc:
@@ -803,7 +820,7 @@ procfs_readdir(ap)
p = PFIND(pfs->pfs_pid);
if (p == NULL)
break;
- if (!PRISON_CHECK(curproc, p))
+ if (p_can(curproc, p, P_CAN_SEE, NULL))
break;
for (pt = &proc_targets[i];
@@ -838,7 +855,7 @@ procfs_readdir(ap)
int doingzomb = 0;
#endif
int pcnt = 0;
- volatile struct proc *p = allproc.lh_first;
+ struct proc *p = allproc.lh_first;
for (; p && uio->uio_resid >= delen; i++, pcnt++) {
bzero((char *) dp, delen);
@@ -866,11 +883,11 @@ procfs_readdir(ap)
p = p->p_list.le_next;
if (!p)
goto done;
- if (!PRISON_CHECK(curproc, p))
+ if (p_can(curproc, p, P_CAN_SEE, NULL))
continue;
pcnt++;
}
- while (!PRISON_CHECK(curproc, p)) {
+ while (p_can(curproc, p, P_CAN_SEE, NULL)) {
p = p->p_list.le_next;
if (!p)
goto done;
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 74d5fa7..0444d7e 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -200,7 +200,7 @@ filt_procattach(struct knote *kn)
p = pfind(kn->kn_id);
if (p == NULL)
return (ESRCH);
- if (! PRISON_CHECK(curproc, p))
+ if (p_can(curproc, p, P_CAN_SEE, NULL))
return (EACCES);
kn->kn_ptr.p_proc = p;
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index b0530f9..ef82c6c 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -513,6 +513,8 @@ ktrwrite(vp, kth, uio)
* root previously set the tracing status on the target process, and
* so, only root may further change it.
*
+ * XXX: These checks are stronger than for ptrace()
+ *
* TODO: check groups. use caller effective gid.
*/
static int
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 4a4282a..ebff074 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -55,7 +55,7 @@ MALLOC_DEFINE(M_SESSION, "session", "session header");
static MALLOC_DEFINE(M_PROC, "proc", "Proc structures");
MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures");
-static int ps_showallprocs = 1;
+int ps_showallprocs = 1;
SYSCTL_INT(_kern, OID_AUTO, ps_showallprocs, CTLFLAG_RW,
&ps_showallprocs, 0, "");
@@ -586,7 +586,7 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
p = pfind((pid_t)name[0]);
if (!p)
return (0);
- if (!PRISON_CHECK(curproc, p))
+ if (p_can(curproc, p, P_CAN_SEE, NULL))
return (0);
error = sysctl_out_proc(p, req, 0);
return (error);
@@ -611,9 +611,9 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
p = LIST_FIRST(&zombproc);
for (; p != 0; p = LIST_NEXT(p, p_list)) {
/*
- * Show a user only their processes.
+ * Show a user only appropriate processes.
*/
- if ((!ps_showallprocs) && p_trespass(curproc, p))
+ if (p_can(curproc, p, P_CAN_SEE, NULL))
continue;
/*
* Skip embryonic processes.
@@ -655,7 +655,7 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
break;
}
- if (!PRISON_CHECK(curproc, p))
+ if (p_can(curproc, p, P_CAN_SEE, NULL))
continue;
error = sysctl_out_proc(p, req, doingzomb);
@@ -688,7 +688,7 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS)
if (!p)
return (0);
- if ((!ps_argsopen) && p_trespass(curproc, p))
+ if ((!ps_argsopen) && p_can(curproc, p, P_CAN_SEE, NULL))
return (0);
if (req->newptr && curproc != p)
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 33007e7..0750466 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -945,15 +945,15 @@ SYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0,
*/
int
suser(p)
- struct proc *p;
+ const struct proc *p;
{
return suser_xxx(0, p, 0);
}
int
suser_xxx(cred, proc, flag)
- struct ucred *cred;
- struct proc *proc;
+ const struct ucred *cred;
+ const struct proc *proc;
int flag;
{
if (!suser_permitted)
@@ -971,31 +971,165 @@ suser_xxx(cred, proc, flag)
return (0);
}
-/*
- * Return zero if p1 can fondle p2, return errno (EPERM/ESRCH) otherwise.
- */
+static int
+p_cansee(const struct proc *p1, const struct proc *p2, int *privused)
+{
-int
-p_trespass(struct proc *p1, struct proc *p2)
+ if (privused != NULL)
+ *privused = 0;
+
+ if (!PRISON_CHECK(p1, p2))
+ return (ESRCH);
+
+ if (!ps_showallprocs && (p1->p_ucred->cr_uid != p2->p_ucred->cr_uid) &&
+ suser_xxx(NULL, p1, PRISON_ROOT))
+ return (ESRCH);
+
+ return (0);
+}
+
+static int
+p_cankill(const struct proc *p1, const struct proc *p2, int *privused)
+{
+
+ if (privused != NULL)
+ *privused = 0;
+
+ 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);
+ /*
+ * XXX should a process be able to affect another process
+ * acting as the same uid (i.e., a userland nfsd or the like?)
+ */
+ 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)) {
+ 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);
+ }
+#endif
+
+ return (EPERM);
+}
+
+static int
+p_cansched(const struct proc *p1, const struct proc *p2, int *privused)
{
+ if (privused != NULL)
+ *privused = 0;
+
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);
+ /*
+ * XXX should a process be able to affect another process
+ * acting as the same uid (i.e., a userland nfsd or the like?)
+ */
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))
+
+ if (!suser_xxx(0, p1, PRISON_ROOT)) {
+ if (privused != NULL)
+ *privused = 1;
+ return (0);
+ }
+
+#ifdef CAPABILITIES
+ if (!cap_check_xxx(0, p1, CAP_SYS_NICE, PRISON_ROOT)) {
+ if (privused != NULL)
+ *privused = 1;
return (0);
+ }
+#endif
+
return (EPERM);
}
+static int
+p_candebug(const struct proc *p1, const struct proc *p2, int *privused)
+{
+ int error;
+
+ if (privused != NULL)
+ *privused = 0;
+
+ /* XXX it is authorized, but semantics don't permit it */
+ if (p1 == p2)
+ return (0);
+
+ if (!PRISON_CHECK(p1, p2))
+ return (ESRCH);
+
+ /* not owned by you, has done setuid (unless you're root) */
+ /* add a CAP_SYS_PTRACE here? */
+ if ((p1->p_cred->p_ruid != p2->p_cred->p_ruid) ||
+ (p2->p_flag & P_SUGID)) {
+ if ((error = suser_xxx(0, p1, PRISON_ROOT)))
+ return (error);
+ if (privused != NULL)
+ *privused = 1;
+ }
+
+ /* can't trace init when securelevel > 0 */
+ if (securelevel > 0 && p2->p_pid == 1)
+ return (EPERM);
+
+ return (0);
+}
+
+int
+p_can(const struct proc *p1, const struct proc *p2, int operation,
+ int *privused)
+{
+
+ switch(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));
+
+ case P_CAN_DEBUG:
+ return (p_candebug(p1, p2, privused));
+
+ default:
+ panic("p_can: invalid operation");
+ }
+}
+
+
/*
* Allocate a zeroed cred structure.
*/
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index 5af09c9..b3c2ec6 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -88,7 +88,7 @@ getpriority(curp, uap)
p = pfind(uap->who);
if (p == 0)
break;
- if (!PRISON_CHECK(curp, p))
+ if (p_can(curp, p, P_CAN_SEE, NULL))
break;
low = p->p_nice;
break;
@@ -101,7 +101,7 @@ getpriority(curp, uap)
else if ((pg = pgfind(uap->who)) == NULL)
break;
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
- if ((PRISON_CHECK(curp, p) && p->p_nice < low))
+ if (!p_can(curp, p, P_CAN_SEE, NULL) && p->p_nice < low)
low = p->p_nice;
}
break;
@@ -111,7 +111,7 @@ getpriority(curp, uap)
if (uap->who == 0)
uap->who = curp->p_ucred->cr_uid;
LIST_FOREACH(p, &allproc, p_list)
- if (PRISON_CHECK(curp, p) &&
+ if (!p_can(curp, p, P_CAN_SEE, NULL) &&
p->p_ucred->cr_uid == uap->who &&
p->p_nice < low)
low = p->p_nice;
@@ -151,7 +151,7 @@ setpriority(curp, uap)
p = pfind(uap->who);
if (p == 0)
break;
- if (!PRISON_CHECK(curp, p))
+ if (p_can(curp, p, P_CAN_SEE, NULL))
break;
error = donice(curp, p, uap->prio);
found++;
@@ -165,7 +165,7 @@ setpriority(curp, uap)
else if ((pg = pgfind(uap->who)) == NULL)
break;
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
- if (PRISON_CHECK(curp, p)) {
+ if (!p_can(curp, p, P_CAN_SEE, NULL)) {
error = donice(curp, p, uap->prio);
found++;
}
@@ -178,7 +178,7 @@ setpriority(curp, uap)
uap->who = curp->p_ucred->cr_uid;
LIST_FOREACH(p, &allproc, p_list)
if (p->p_ucred->cr_uid == uap->who &&
- PRISON_CHECK(curp, p)) {
+ !p_can(curp, p, P_CAN_SEE, NULL)) {
error = donice(curp, p, uap->prio);
found++;
}
@@ -197,9 +197,10 @@ donice(curp, chgp, n)
register struct proc *curp, *chgp;
register int n;
{
+ int error;
- if (p_trespass(curp, chgp) != 0)
- return (EPERM);
+ if ((error = p_can(curp, chgp, P_CAN_SCHED, NULL)))
+ return (error);
if (n > PRIO_MAX)
n = PRIO_MAX;
if (n < PRIO_MIN)
@@ -250,8 +251,8 @@ rtprio(curp, uap)
case RTP_LOOKUP:
return (copyout(&p->p_rtprio, uap->rtp, sizeof(struct rtprio)));
case RTP_SET:
- if (p_trespass(curp, p) != 0)
- return (EPERM);
+ if ((error = p_can(curp, p, P_CAN_SCHED, NULL)))
+ return (error);
/* disallow setting rtprio in most cases if not superuser */
if (suser(curp) != 0) {
/* can't set someone else's */
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index db3f46f..a2ff2ef 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -97,7 +97,7 @@ SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW,
* Can process p, with pcred pc, send the signal sig to process q?
*/
#define CANSIGNAL(p, q, sig) \
- (!p_trespass(p, q) || \
+ (!p_can(p, q, P_CAN_KILL, NULL) || \
((sig) == SIGCONT && (q)->p_session == (p)->p_session))
/*
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 4740476..0292961 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -217,7 +217,7 @@ ptrace(curp, uap)
if ((p = pfind(uap->pid)) == NULL)
return ESRCH;
}
- if (!PRISON_CHECK(curp, p))
+ if (p_can(curp, p, P_CAN_SEE, NULL))
return (ESRCH);
/*
@@ -237,16 +237,8 @@ ptrace(curp, uap)
if (p->p_flag & P_TRACED)
return EBUSY;
- /* not owned by you, has done setuid (unless you're root) */
- if ((p->p_cred->p_ruid != curp->p_cred->p_ruid) ||
- (p->p_flag & P_SUGID)) {
- if ((error = suser(curp)) != 0)
- return error;
- }
-
- /* can't trace init when securelevel > 0 */
- if (securelevel > 0 && p->p_pid == 1)
- return EPERM;
+ if ((error = p_can(curp, p, P_CAN_DEBUG, NULL)))
+ return error;
/* OK */
break;
diff --git a/sys/miscfs/procfs/procfs_dbregs.c b/sys/miscfs/procfs/procfs_dbregs.c
index 158c3f4..c7ad130 100644
--- a/sys/miscfs/procfs/procfs_dbregs.c
+++ b/sys/miscfs/procfs/procfs_dbregs.c
@@ -62,7 +62,7 @@ procfs_dodbregs(curp, p, pfs, uio)
char *kv;
int kl;
- if (p_trespass(curp, p))
+ if (p_can(curp, p, P_CAN_DEBUG, NULL))
return (EPERM);
kl = sizeof(r);
kv = (char *) &r;
diff --git a/sys/miscfs/procfs/procfs_fpregs.c b/sys/miscfs/procfs/procfs_fpregs.c
index 353b52b..69dd527 100644
--- a/sys/miscfs/procfs/procfs_fpregs.c
+++ b/sys/miscfs/procfs/procfs_fpregs.c
@@ -59,7 +59,7 @@ procfs_dofpregs(curp, p, pfs, uio)
char *kv;
int kl;
- if (p_trespass(curp, p))
+ if (p_can(curp, p, P_CAN_DEBUG, NULL))
return EPERM;
kl = sizeof(r);
kv = (char *) &r;
diff --git a/sys/miscfs/procfs/procfs_mem.c b/sys/miscfs/procfs/procfs_mem.c
index b7eed85..6f2c8cb 100644
--- a/sys/miscfs/procfs/procfs_mem.c
+++ b/sys/miscfs/procfs/procfs_mem.c
@@ -256,7 +256,7 @@ procfs_domem(curp, p, pfs, uio)
* All in all, quite yucky.
*/
- if (p_trespass(curp, p) &&
+ if (p_can(curp, p, P_CAN_DEBUG, NULL) &&
!(uio->uio_rw == UIO_READ &&
procfs_kmemaccess(curp)))
return EPERM;
diff --git a/sys/miscfs/procfs/procfs_regs.c b/sys/miscfs/procfs/procfs_regs.c
index 88f85d3..c2b6d4b 100644
--- a/sys/miscfs/procfs/procfs_regs.c
+++ b/sys/miscfs/procfs/procfs_regs.c
@@ -60,7 +60,7 @@ procfs_doregs(curp, p, pfs, uio)
char *kv;
int kl;
- if (p_trespass(curp, p))
+ if (p_can(curp, p, P_CAN_DEBUG, NULL))
return EPERM;
kl = sizeof(r);
kv = (char *) &r;
diff --git a/sys/miscfs/procfs/procfs_status.c b/sys/miscfs/procfs/procfs_status.c
index 03149e9..c1adc60 100644
--- a/sys/miscfs/procfs/procfs_status.c
+++ b/sys/miscfs/procfs/procfs_status.c
@@ -183,7 +183,7 @@ procfs_docmdline(curp, p, pfs, uio)
* Linux behaviour is to return zero-length in this case.
*/
- if (p->p_args && (ps_argsopen ||!p_trespass(curp, p))) {
+ if (p->p_args && (ps_argsopen || !p_can(curp, p, P_CAN_SEE, NULL))) {
bp = p->p_args->ar_args;
buflen = p->p_args->ar_length;
buf = 0;
diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c
index 35b3afb..df8e3ca 100644
--- a/sys/miscfs/procfs/procfs_vnops.c
+++ b/sys/miscfs/procfs/procfs_vnops.c
@@ -137,7 +137,7 @@ procfs_open(ap)
p2 = PFIND(pfs->pfs_pid);
if (p2 == NULL)
return (ENOENT);
- if (pfs->pfs_pid && !PRISON_CHECK(ap->a_p, p2))
+ if (pfs->pfs_pid && p_can(ap->a_p, p2, P_CAN_SEE, NULL))
return (ENOENT);
switch (pfs->pfs_type) {
@@ -147,7 +147,7 @@ procfs_open(ap)
return (EBUSY);
p1 = ap->a_p;
- if (p_trespass(p1, p2) &&
+ if (p_can(p1, p2, P_CAN_DEBUG, NULL) &&
!procfs_kmemaccess(p1))
return (EPERM);
@@ -239,8 +239,11 @@ procfs_ioctl(ap)
return ENOTTY;
}
- if (p_trespass(p, procp))
- return EPERM;
+ if ((error = p_can(p, procp, P_CAN_DEBUG, NULL))) {
+ if (error == ESRCH)
+ error = ENOENT;
+ return (error);
+ }
switch (ap->a_command) {
case PIOCBIS:
@@ -417,6 +420,9 @@ procfs_getattr(ap)
if (procp == 0 || procp->p_cred == NULL ||
procp->p_ucred == NULL)
return (ENOENT);
+
+ if (p_can(ap->a_p, procp, P_CAN_SEE, NULL))
+ return (ENOENT);
}
error = 0;
@@ -612,16 +618,23 @@ procfs_access(ap)
struct proc *a_p;
} */ *ap;
{
+ struct pfsnode *pfs = VTOPFS(ap->a_vp);
+ struct proc *procp;
struct vattr *vap;
struct vattr vattr;
int error;
- /*
- * If you're the super-user,
- * you always get access.
- */
- if (ap->a_cred->cr_uid == 0)
- return (0);
+ switch (pfs->pfs_type) {
+ case Proot:
+ case Pcurproc:
+ break;
+ default:
+ procp = PFIND(pfs->pfs_pid);
+ if (procp == NULL)
+ return (ENOENT);
+ if (p_can(ap->a_p, procp, P_CAN_SEE, NULL))
+ return (ENOENT);
+ }
vap = &vattr;
error = VOP_GETATTR(ap->a_vp, vap, ap->a_cred, ap->a_p);
@@ -674,7 +687,7 @@ procfs_lookup(ap)
struct vnode **vpp = ap->a_vpp;
struct vnode *dvp = ap->a_dvp;
char *pname = cnp->cn_nameptr;
- /* struct proc *curp = cnp->cn_proc; */
+ struct proc *curp = cnp->cn_proc;
struct proc_target *pt;
pid_t pid;
struct pfsnode *pfs;
@@ -683,7 +696,8 @@ procfs_lookup(ap)
*vpp = NULL;
- if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)
+ if (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME ||
+ cnp->cn_nameiop == CREATE)
return (EROFS);
if (cnp->cn_namelen == 1 && *pname == '.') {
@@ -710,6 +724,9 @@ procfs_lookup(ap)
if (p == 0)
break;
+ if (p_can(curp, p, P_CAN_SEE, NULL))
+ break;
+
return (procfs_allocvp(dvp->v_mount, vpp, pid, Pproc));
case Pproc:
@@ -803,7 +820,7 @@ procfs_readdir(ap)
p = PFIND(pfs->pfs_pid);
if (p == NULL)
break;
- if (!PRISON_CHECK(curproc, p))
+ if (p_can(curproc, p, P_CAN_SEE, NULL))
break;
for (pt = &proc_targets[i];
@@ -838,7 +855,7 @@ procfs_readdir(ap)
int doingzomb = 0;
#endif
int pcnt = 0;
- volatile struct proc *p = allproc.lh_first;
+ struct proc *p = allproc.lh_first;
for (; p && uio->uio_resid >= delen; i++, pcnt++) {
bzero((char *) dp, delen);
@@ -866,11 +883,11 @@ procfs_readdir(ap)
p = p->p_list.le_next;
if (!p)
goto done;
- if (!PRISON_CHECK(curproc, p))
+ if (p_can(curproc, p, P_CAN_SEE, NULL))
continue;
pcnt++;
}
- while (!PRISON_CHECK(curproc, p)) {
+ while (p_can(curproc, p, P_CAN_SEE, NULL)) {
p = p->p_list.le_next;
if (!p)
goto done;
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 6c0d5d0..9865d97 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -293,6 +293,11 @@ struct proc {
#define P_OLDMASK 0x2000000 /* need to restore mask before pause */
#define P_ALTSTACK 0x4000000 /* have alternate signal stack */
+#define P_CAN_SEE 1
+#define P_CAN_KILL 2
+#define P_CAN_SCHED 3
+#define P_CAN_DEBUG 4
+
/*
* MOVE TO ucred.h?
*
@@ -414,6 +419,7 @@ extern int whichidqs; /* Bit mask summary of non-empty Q's. */
extern u_long ps_arg_cache_limit;
extern int ps_argsopen;
+extern int ps_showallprocs;
struct proc *pfind __P((pid_t)); /* Find process by id. */
struct pgrp *pgfind __P((pid_t)); /* Find process group by id. */
@@ -429,15 +435,18 @@ int inferior __P((struct proc *p));
int leavepgrp __P((struct proc *p));
void mi_switch __P((void));
void procinit __P((void));
-int p_trespass __P((struct proc *p1, struct proc *p2));
+int p_can __P((const struct proc *p1, const struct proc *p2, int operation,
+ int *privused));
+
void resetpriority __P((struct proc *));
int roundrobin_interval __P((void));
void schedclock __P((struct proc *));
void setrunnable __P((struct proc *));
void setrunqueue __P((struct proc *));
void sleepinit __P((void));
-int suser __P((struct proc *));
-int suser_xxx __P((struct ucred *cred, struct proc *proc, int flag));
+int suser __P((const struct proc *));
+int suser_xxx __P((const struct ucred *cred, const struct proc *proc,
+ int flag));
void remrunqueue __P((struct proc *));
void cpu_switch __P((struct proc *));
void unsleep __P((struct proc *));
OpenPOWER on IntegriCloud