diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2011-04-02 17:04:36 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2011-04-02 17:04:36 +0000 |
commit | 99a2057acb47dac10d8566bc4ab6a117de267634 (patch) | |
tree | 1901b960139f21d0cb0248fa97c5c61ccfe5bb17 | |
parent | 11ae302ebcf8bbe27cb1c13a64dce31c551cdac8 (diff) |
Move P_SUGID and P_SUGIDEXEC from struct proc to struct process, so
that you can't evade the checks by doing the dirty work in an rthread
ok blambert@, deraadt@
-rw-r--r-- | sys/dev/systrace.c | 22 | ||||
-rw-r--r-- | sys/kern/kern_descrip.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_event.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_exec.c | 29 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_ktrace.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_prot.c | 18 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 8 | ||||
-rw-r--r-- | sys/kern/sys_process.c | 10 | ||||
-rw-r--r-- | sys/miscfs/procfs/procfs_vnops.c | 4 | ||||
-rw-r--r-- | sys/sys/proc.h | 8 |
11 files changed, 56 insertions, 59 deletions
diff --git a/sys/dev/systrace.c b/sys/dev/systrace.c index ba219bc732b..8c58eaff34f 100644 --- a/sys/dev/systrace.c +++ b/sys/dev/systrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: systrace.c,v 1.53 2010/07/21 18:44:01 deraadt Exp $ */ +/* $OpenBSD: systrace.c,v 1.54 2011/04/02 17:04:35 guenther Exp $ */ /* * Copyright 2002 Niels Provos <provos@citi.umich.edu> * All rights reserved. @@ -720,13 +720,12 @@ systrace_redirect(int code, struct proc *p, void *v, register_t *retval) * but we wait until it executes something unprivileged. * A non-root user may only monitor if the real uid and * real gid match the monitored process. Changing the - * uid or gid causes P_SUGID to be set. + * uid or gid causes PS_SUGID to be set. */ if (fst->issuser) { maycontrol = 1; issuser = 1; - } else if (!ISSET(p->p_flag, P_SUGID) && - !ISSET(p->p_flag, P_SUGIDEXEC)) { + } else if (!ISSET(p->p_p->ps_flags, PS_SUGID | PS_SUGIDEXEC)) { maycontrol = fst->p_ruid == p->p_cred->p_ruid && fst->p_rgid == p->p_cred->p_rgid; } @@ -846,7 +845,7 @@ systrace_redirect(int code, struct proc *p, void *v, register_t *retval) systrace_replacefree(strp); - if (ISSET(p->p_flag, P_SUGID) || ISSET(p->p_flag, P_SUGIDEXEC)) { + if (ISSET(p->p_p->ps_flags, PS_SUGID | PS_SUGIDEXEC)) { if ((fst = strp->parent) == NULL || !fst->issuser) { systrace_unlock(); return (error); @@ -914,7 +913,7 @@ systrace_seteuid(struct proc *p, uid_t euid) */ pc->pc_ucred = crcopy(pc->pc_ucred); pc->pc_ucred->cr_uid = euid; - atomic_setbits_int(&p->p_flag, P_SUGID); + atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (oeuid); } @@ -933,7 +932,7 @@ systrace_setegid(struct proc *p, gid_t egid) */ pc->pc_ucred = crcopy(pc->pc_ucred); pc->pc_ucred->cr_gid = egid; - atomic_setbits_int(&p->p_flag, P_SUGID); + atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (oegid); } @@ -1252,15 +1251,14 @@ systrace_attach(struct fsystrace *fst, pid_t pid) * gave us setuid/setgid privs (unless * you're root), or... * - * [Note: once P_SUGID or P_SUGIDEXEC gets set in execve(), + * [Note: once PS_SUGID or PS_SUGIDEXEC gets set in execve(), * it stays set until the process does another execve(). Hence * this prevents a setuid process which revokes its * special privileges using setuid() from being * traced. This is good security.] */ if ((proc->p_cred->p_ruid != p->p_cred->p_ruid || - ISSET(proc->p_flag, P_SUGID) || - ISSET(proc->p_flag, P_SUGIDEXEC)) && + ISSET(proc->p_flag, PS_SUGID | PS_SUGIDEXEC)) && (error = suser(p, 0)) != 0) goto out; @@ -1478,8 +1476,8 @@ systrace_scriptname(struct proc *p, char *dst) rw_enter_write(&fst->lock); systrace_unlock(); - if (!fst->issuser && (ISSET(p->p_flag, P_SUGID) || - ISSET(p->p_flag, P_SUGIDEXEC) || + if (!fst->issuser && + (ISSET(p->p_p->ps_flags, PS_SUGID | PS_SUGIDEXEC) || fst->p_ruid != p->p_cred->p_ruid || fst->p_rgid != p->p_cred->p_rgid)) { error = EPERM; diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index e669c3e365a..0d3a6d1a627 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_descrip.c,v 1.85 2010/07/26 01:56:27 guenther Exp $ */ +/* $OpenBSD: kern_descrip.c,v 1.86 2011/04/02 17:04:35 guenther Exp $ */ /* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */ /* @@ -1192,7 +1192,7 @@ dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode, int error) * Assume that the filename was user-specified; applications do * not tend to open /dev/fd/# when they can just call dup() */ - if ((curproc->p_flag & (P_SUGIDEXEC | P_SUGID))) { + if ((curproc->p_p->ps_flags & (PS_SUGIDEXEC | PS_SUGID))) { if (curproc->p_descfd == 255) return (EPERM); if (curproc->p_descfd != curproc->p_dupfd) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 19c250de2fc..412b9a91c27 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_event.c,v 1.38 2010/08/02 19:54:07 guenther Exp $ */ +/* $OpenBSD: kern_event.c,v 1.39 2011/04/02 17:04:35 guenther Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> @@ -208,7 +208,7 @@ filt_procattach(struct knote *kn) */ if (p->p_p != curproc->p_p && (p->p_cred->p_ruid != curproc->p_cred->p_ruid || - (p->p_flag & P_SUGID)) && suser(curproc, 0) != 0) + (p->p_p->ps_flags & PS_SUGID)) && suser(curproc, 0) != 0) return (EACCES); kn->kn_ptr.p_proc = p; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 555e4cf2163..74b5647c3c3 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exec.c,v 1.114 2010/11/24 21:05:20 miod Exp $ */ +/* $OpenBSD: kern_exec.c,v 1.115 2011/04/02 17:04:35 guenther Exp $ */ /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */ /*- @@ -246,6 +246,7 @@ sys_execve(struct proc *p, void *v, register_t *retval) struct ucred *cred = p->p_ucred; char *argp; char * const *cpp, *dp, *sp; + struct process *pr = p->p_p; long argc, envc; size_t len, sgap; #ifdef MACHINE_STACK_GROWS_UP @@ -257,8 +258,7 @@ sys_execve(struct proc *p, void *v, register_t *retval) char **tmpfap; extern struct emul emul_native; #if NSYSTRACE > 0 - int wassugid = - ISSET(p->p_flag, P_SUGID) || ISSET(p->p_flag, P_SUGIDEXEC); + int wassugid = ISSET(pr->ps_flags, PS_SUGID | PS_SUGIDEXEC); size_t pathbuflen; #endif char *pathbuf = NULL; @@ -468,22 +468,22 @@ sys_execve(struct proc *p, void *v, register_t *retval) p->p_textvp = pack.ep_vp; atomic_setbits_int(&p->p_flag, P_EXEC); - if (p->p_p->ps_mainproc->p_flag & P_PPWAIT) { - atomic_clearbits_int(&p->p_p->ps_mainproc->p_flag, P_PPWAIT); - wakeup(p->p_p->ps_pptr); + if (pr->ps_mainproc->p_flag & P_PPWAIT) { + atomic_clearbits_int(&pr->ps_mainproc->p_flag, P_PPWAIT); + wakeup(pr->ps_pptr); } /* * If process does execve() while it has a mismatched real, - * effective, or saved uid/gid, we set P_SUGIDEXEC. + * effective, or saved uid/gid, we set PS_SUGIDEXEC. */ if (p->p_ucred->cr_uid != p->p_cred->p_ruid || p->p_ucred->cr_uid != p->p_cred->p_svuid || p->p_ucred->cr_gid != p->p_cred->p_rgid || p->p_ucred->cr_gid != p->p_cred->p_svgid) - atomic_setbits_int(&p->p_flag, P_SUGIDEXEC); + atomic_setbits_int(&pr->ps_flags, PS_SUGIDEXEC); else - atomic_clearbits_int(&p->p_flag, P_SUGIDEXEC); + atomic_clearbits_int(&pr->ps_flags, PS_SUGIDEXEC); /* * deal with set[ug]id. @@ -492,7 +492,7 @@ sys_execve(struct proc *p, void *v, register_t *retval) if ((attr.va_mode & (VSUID | VSGID)) && proc_cansugid(p)) { int i; - atomic_setbits_int(&p->p_flag, P_SUGID|P_SUGIDEXEC); + atomic_setbits_int(&pr->ps_flags, PS_SUGID|PS_SUGIDEXEC); #ifdef KTRACE /* @@ -573,11 +573,11 @@ sys_execve(struct proc *p, void *v, register_t *retval) } } } else - atomic_clearbits_int(&p->p_flag, P_SUGID); + atomic_clearbits_int(&pr->ps_flags, PS_SUGID); p->p_cred->p_svuid = p->p_ucred->cr_uid; p->p_cred->p_svgid = p->p_ucred->cr_gid; - if (p->p_flag & P_SUGIDEXEC) { + if (pr->ps_flags & PS_SUGIDEXEC) { int i, s = splclock(); timeout_del(&p->p_realit_to); @@ -599,7 +599,7 @@ sys_execve(struct proc *p, void *v, register_t *retval) /* * notify others that we exec'd */ - KNOTE(&p->p_p->ps_klist, NOTE_EXEC); + KNOTE(&pr->ps_klist, NOTE_EXEC); /* setup new registers and do misc. setup. */ if (pack.ep_emul->e_fixup != NULL) { @@ -664,8 +664,7 @@ sys_execve(struct proc *p, void *v, register_t *retval) #if NSYSTRACE > 0 if (ISSET(p->p_flag, P_SYSTRACE) && - wassugid && !ISSET(p->p_flag, P_SUGID) && - !ISSET(p->p_flag, P_SUGIDEXEC)) + wassugid && !ISSET(pr->ps_flags, PS_SUGID | PS_SUGIDEXEC)) systrace_execve1(pathbuf, p); #endif diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index d3f98721754..8707f472ac1 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.123 2010/10/31 00:03:44 guenther Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.124 2011/04/02 17:04:35 guenther Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -184,6 +184,7 @@ process_new(struct proc *newproc, struct proc *parentproc) crhold(parent->ps_cred->pc_ucred); pr->ps_limit->p_refcnt++; + pr->ps_flags = parent->ps_flags & (PS_SUGID | PS_SUGIDEXEC); if (parent->ps_session->s_ttyvp != NULL && parent->ps_flags & PS_CONTROLT) atomic_setbits_int(&pr->ps_flags, PS_CONTROLT); @@ -303,7 +304,6 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize, */ if (p1->p_flag & P_PROFIL) startprofclock(p2); - atomic_setbits_int(&p2->p_flag, p1->p_flag & (P_SUGID | P_SUGIDEXEC)); if (flags & FORK_PTRACE) atomic_setbits_int(&p2->p_flag, p1->p_flag & P_TRACED); diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index a5312566288..cb12ee1bd2b 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_ktrace.c,v 1.49 2010/07/26 01:56:27 guenther Exp $ */ +/* $OpenBSD: kern_ktrace.c,v 1.50 2011/04/02 17:04:35 guenther Exp $ */ /* $NetBSD: kern_ktrace.c,v 1.23 1996/02/09 18:59:36 christos Exp $ */ /* @@ -515,7 +515,7 @@ ktrcanset(struct proc *callp, struct proc *targetp) caller->p_rgid == target->p_rgid && /* XXX */ target->p_rgid == target->p_svgid && (targetp->p_traceflag & KTRFAC_ROOT) == 0 && - !ISSET(targetp->p_flag, P_SUGID)) || + !ISSET(targetp->p_p->ps_flags, PS_SUGID)) || caller->pc_ucred->cr_uid == 0) return (1); diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index a34714c4ba5..5b058ee605b 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_prot.c,v 1.46 2010/07/26 01:56:27 guenther Exp $ */ +/* $OpenBSD: kern_prot.c,v 1.47 2011/04/02 17:04:35 guenther Exp $ */ /* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */ /* @@ -160,7 +160,7 @@ sys_geteuid(struct proc *p, void *v, register_t *retval) int sys_issetugid(struct proc *p, void *v, register_t *retval) { - if (p->p_flag & P_SUGIDEXEC) + if (p->p_p->ps_flags & PS_SUGIDEXEC) *retval = 1; else *retval = 0; @@ -404,7 +404,7 @@ sys_setresuid(struct proc *p, void *v, register_t *retval) if (suid != (uid_t)-1 && suid != pc->p_svuid) pc->p_svuid = suid; - atomic_setbits_int(&p->p_flag, P_SUGID); + atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); } @@ -498,7 +498,7 @@ sys_setresgid(struct proc *p, void *v, register_t *retval) if (sgid != (gid_t)-1) pc->p_svgid = sgid; - atomic_setbits_int(&p->p_flag, P_SUGID); + atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); } @@ -607,7 +607,7 @@ sys_setuid(struct proc *p, void *v, register_t *retval) */ pc->pc_ucred = crcopy(pc->pc_ucred); pc->pc_ucred->cr_uid = uid; - atomic_setbits_int(&p->p_flag, P_SUGID); + atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); } @@ -636,7 +636,7 @@ sys_seteuid(struct proc *p, void *v, register_t *retval) */ pc->pc_ucred = crcopy(pc->pc_ucred); pc->pc_ucred->cr_uid = euid; - atomic_setbits_int(&p->p_flag, P_SUGID); + atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); } @@ -675,7 +675,7 @@ sys_setgid(struct proc *p, void *v, register_t *retval) */ pc->pc_ucred = crcopy(pc->pc_ucred); pc->pc_ucred->cr_gid = gid; - atomic_setbits_int(&p->p_flag, P_SUGID); + atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); } @@ -704,7 +704,7 @@ sys_setegid(struct proc *p, void *v, register_t *retval) */ pc->pc_ucred = crcopy(pc->pc_ucred); pc->pc_ucred->cr_gid = egid; - atomic_setbits_int(&p->p_flag, P_SUGID); + atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); } @@ -731,7 +731,7 @@ sys_setgroups(struct proc *p, void *v, register_t *retval) if (error) return (error); pc->pc_ucred->cr_ngroups = ngrp; - atomic_setbits_int(&p->p_flag, P_SUGID); + atomic_setbits_int(&p->p_p->ps_flags, PS_SUGID); return (0); } diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 3d900be04b4..39bf31572e7 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sig.c,v 1.117 2011/03/07 07:07:13 guenther Exp $ */ +/* $OpenBSD: kern_sig.c,v 1.118 2011/04/02 17:04:35 guenther Exp $ */ /* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */ /* @@ -103,7 +103,7 @@ cansignal(struct proc *p, struct pcred *pc, struct proc *q, int signum) * Using kill(), only certain signals can be sent to setugid * child processes */ - if (q->p_flag & P_SUGID) { + if (q->p_p->ps_flags & PS_SUGID) { switch (signum) { case 0: case SIGKILL: @@ -1395,8 +1395,8 @@ coredump(struct proc *p) * group privileges, unless the nosuidcoredump sysctl is set to 2, * in which case dumps are put into /var/crash/. */ - if (((p->p_flag & P_SUGID) && (error = suser(p, 0))) || - ((p->p_flag & P_SUGID) && nosuidcoredump)) { + if (((p->p_p->ps_flags & PS_SUGID) && (error = suser(p, 0))) || + ((p->p_p->ps_flags & PS_SUGID) && nosuidcoredump)) { if (nosuidcoredump == 2) dir = "/var/crash/"; else diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index e38e673e7e5..cfc19e44305 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_process.c,v 1.47 2010/07/26 01:56:27 guenther Exp $ */ +/* $OpenBSD: sys_process.c,v 1.48 2011/04/02 17:04:35 guenther Exp $ */ /* $NetBSD: sys_process.c,v 1.55 1996/05/15 06:17:47 tls Exp $ */ /*- @@ -146,15 +146,14 @@ sys_ptrace(struct proc *p, void *v, register_t *retval) * gave us setuid/setgid privs (unless * you're root), or... * - * [Note: once P_SUGID or P_SUGIDEXEC gets set in + * [Note: once PS_SUGID or PS_SUGIDEXEC gets set in * execve(), they stay set until the process does * another execve(). Hence this prevents a setuid * process which revokes its special privileges using * setuid() from being traced. This is good security.] */ if ((t->p_cred->p_ruid != p->p_cred->p_ruid || - ISSET(t->p_flag, P_SUGIDEXEC) || - ISSET(t->p_flag, P_SUGID)) && + ISSET(t->p_p->ps_flags, PS_SUGIDEXEC | PS_SUGID)) && (error = suser(p, 0)) != 0) return (error); @@ -579,8 +578,7 @@ process_checkioperm(struct proc *p, struct proc *t) int error; if ((t->p_cred->p_ruid != p->p_cred->p_ruid || - ISSET(t->p_flag, P_SUGIDEXEC) || - ISSET(t->p_flag, P_SUGID)) && + ISSET(t->p_p->ps_flags, PS_SUGIDEXEC | PS_SUGID)) && (error = suser(p, 0)) != 0) return (error); diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c index da9edb7c185..5ef2fb8bae9 100644 --- a/sys/miscfs/procfs/procfs_vnops.c +++ b/sys/miscfs/procfs/procfs_vnops.c @@ -1,4 +1,4 @@ -/* $OpenBSD: procfs_vnops.c,v 1.50 2010/12/21 20:14:43 thib Exp $ */ +/* $OpenBSD: procfs_vnops.c,v 1.51 2011/04/02 17:04:35 guenther Exp $ */ /* $NetBSD: procfs_vnops.c,v 1.40 1996/03/16 23:52:55 christos Exp $ */ /* @@ -461,7 +461,7 @@ procfs_getattr(void *v) * privilege, then rip away read/write permission so * that only root can gain access. */ - if (procp->p_flag & P_SUGID) + if (procp->p_p->ps_flags & PS_SUGID) vap->va_mode &= ~(S_IRUSR|S_IWUSR); /* FALLTHROUGH */ case Pctl: diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 4c5b8fb4164..b27ed7c0915 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.133 2011/03/07 07:07:13 guenther Exp $ */ +/* $OpenBSD: proc.h,v 1.134 2011/04/02 17:04:35 guenther Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -322,7 +322,7 @@ struct proc { #define P_PROFIL 0x000020 /* Has started profiling. */ #define P_SELECT 0x000040 /* Selecting; wakeup/waiting danger. */ #define P_SINTR 0x000080 /* Sleep is interruptible. */ -#define P_SUGID 0x000100 /* Had set id privs since last exec. */ +#define _P_SUGID 0x000100 /* Had set id privs since last exec. */ #define P_SYSTEM 0x000200 /* No sigs, stats or swapping. */ #define P_TIMEOUT 0x000400 /* Timing out during sleep. */ #define P_TRACED 0x000800 /* Debugged process being traced. */ @@ -336,7 +336,7 @@ struct proc { /* XXX Not sure what to do with these, yet. */ #define P_SSTEP 0x020000 /* proc needs single-step fixup ??? */ -#define P_SUGIDEXEC 0x040000 /* last execve() was set[ug]id */ +#define _P_SUGIDEXEC 0x040000 /* last execve() was set[ug]id */ #define P_NOCLDWAIT 0x080000 /* Let pid 1 wait for my children */ #define P_NOZOMBIE 0x100000 /* Pid 1 waits for me instead of dad */ @@ -352,6 +352,8 @@ struct proc { #ifndef _KERNEL #define P_CONTROLT _P_CONTROLT +#define P_SUGID _P_SUGID +#define P_SUGIDEXEC _P_SUGIDEXEC #endif #define P_BITS \ |