diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2010-01-28 19:23:07 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2010-01-28 19:23:07 +0000 |
commit | c8c4525ddb2c026993ac0bce3ef1651951330f8c (patch) | |
tree | b9bf01fbf1cb0cf30f5efa759c63602a982fec30 /sys | |
parent | 2349c69070600289d40ea08fb6b49fa982532d83 (diff) |
Make sure the process tree is is loop-free by forbidding ptrace()
of a direct ancestor, closing a localhost DoS. As an exception,
do permit ptrace() of pid 1 and have inferiors() stop climbing if
it hits that.
ok tedu@ hpux_compat suggestion from miod@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/compat/hpux/hpux_compat.c | 20 | ||||
-rw-r--r-- | sys/kern/kern_proc.c | 10 | ||||
-rw-r--r-- | sys/kern/kern_prot.c | 4 | ||||
-rw-r--r-- | sys/kern/sys_process.c | 10 | ||||
-rw-r--r-- | sys/sys/proc.h | 4 |
5 files changed, 31 insertions, 17 deletions
diff --git a/sys/compat/hpux/hpux_compat.c b/sys/compat/hpux/hpux_compat.c index 73193038c6f..f8baad27585 100644 --- a/sys/compat/hpux/hpux_compat.c +++ b/sys/compat/hpux/hpux_compat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hpux_compat.c,v 1.30 2008/11/01 05:59:21 deraadt Exp $ */ +/* $OpenBSD: hpux_compat.c,v 1.31 2010/01/28 19:23:06 guenther Exp $ */ /* $NetBSD: hpux_compat.c,v 1.35 1997/05/08 16:19:48 mycroft Exp $ */ /* @@ -949,7 +949,7 @@ out: /* * This is the equivalent of BSD getpgrp but with more restrictions. - * Note we do not check the real uid or "saved" uid. + * XXX Need to verify the differences between this and sys_getpgid() */ int hpux_sys_getpgrp2(cp, v, retval) @@ -960,13 +960,19 @@ hpux_sys_getpgrp2(cp, v, retval) struct hpux_sys_getpgrp2_args *uap = v; struct proc *p; + /* If zero, the call applies to the calling process */ if (SCARG(uap, pid) == 0) - SCARG(uap, pid) = cp->p_pid; - p = pfind(SCARG(uap, pid)); - if (p == 0) + p = cp; + else + p = pfind(SCARG(uap, pid)); + if (p == NULL) + return (ESRCH); + /* Skip exiting processes. */ + if (p->p_pgrp->pg_session->s_leader == NULL) return (ESRCH); - if (cp->p_ucred->cr_uid && p->p_ucred->cr_uid != cp->p_ucred->cr_uid && - !inferior(p)) + /* Both processes need to be in the same session. */ + if (cp != p && cp->p_pgrp->pg_session->s_leader->p_pid != + p->p_pgrp->pg_session->s_leader->p_pid) return (EPERM); *retval = p->p_pgid; return (0); diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index ff2854c0dda..8c2eb86af41 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_proc.c,v 1.40 2009/04/15 10:47:46 art Exp $ */ +/* $OpenBSD: kern_proc.c,v 1.41 2010/01/28 19:23:06 guenther Exp $ */ /* $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $ */ /* @@ -151,14 +151,14 @@ chgproccnt(uid_t uid, int diff) } /* - * Is p an inferior of the current process? + * Is p an inferior of parent? */ int -inferior(struct proc *p) +inferior(struct proc *p, struct proc *parent) { - for (; p != curproc; p = p->p_pptr) - if (p->p_pid == 0) + for (; p != parent; p = p->p_pptr) + if (p->p_pid == 0 || p->p_pid == 1) return (0); return (1); } diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 882a083656a..e707c68e0da 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_prot.c,v 1.40 2010/01/14 23:12:11 schwarze Exp $ */ +/* $OpenBSD: kern_prot.c,v 1.41 2010/01/28 19:23:06 guenther Exp $ */ /* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */ /* @@ -282,7 +282,7 @@ sys_setpgid(struct proc *curp, void *v, register_t *retval) newpgrp = pool_get(&pgrp_pool, PR_WAITOK); if (pid != 0 && pid != curp->p_pid) { - if ((targp = pfind(pid)) == 0 || !inferior(targp)) { + if ((targp = pfind(pid)) == 0 || !inferior(targp, curp)) { error = ESRCH; goto out; } diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index cd58c064ddf..72a65276cff 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_process.c,v 1.43 2008/10/31 17:29:51 deraadt Exp $ */ +/* $OpenBSD: sys_process.c,v 1.44 2010/01/28 19:23:06 guenther Exp $ */ /* $NetBSD: sys_process.c,v 1.55 1996/05/15 06:17:47 tls Exp $ */ /*- @@ -167,6 +167,14 @@ sys_ptrace(struct proc *p, void *v, register_t *retval) */ if ((t->p_pid == 1) && (securelevel > -1)) return (EPERM); + + /* + * (6) it's an ancestor of the current process and + * not init (because that would create a loop in + * the process graph). + */ + if (t->p_pid != 1 && inferior(p, t)) + return (EINVAL); break; case PT_READ_I: diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 0c3b8d8413a..47548df5aee 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.122 2009/12/23 07:40:31 guenther Exp $ */ +/* $OpenBSD: proc.h,v 1.123 2010/01/28 19:23:06 guenther Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -419,7 +419,7 @@ int chgproccnt(uid_t uid, int diff); int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *newpgrp, struct session *newsess); void fixjobc(struct proc *p, struct pgrp *pgrp, int entering); -int inferior(struct proc *p); +int inferior(struct proc *, struct proc *); int leavepgrp(struct proc *p); void yield(void); void preempt(struct proc *); |