? compile/ALSVID ? i386/conf/DEBUG ? i386/conf/BRIDGE ? i386/conf/FFSEXTATTR ? i386/conf/AMALTHEA.hints ? i386/conf/AMALTHEA ? i386/conf/ALSVID ? kern/assar.diff ? kern/vfs_vnops.c.notyet ? netinet/if_ether.c.oldpatch ? netinet/arpintr-patch.current ? sys/acl.h.almost ? ufs/ufs/ufs_vnops.c_good_fix Index: kern/kern_event.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_event.c,v retrieving revision 1.15 diff -u -r1.15 kern_event.c --- kern/kern_event.c 2000/08/07 16:45:42 1.15 +++ kern/kern_event.c 2000/08/29 14:50:48 @@ -200,7 +200,7 @@ 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; Index: kern/kern_ktrace.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_ktrace.c,v retrieving revision 1.40 diff -u -r1.40 kern_ktrace.c --- kern/kern_ktrace.c 2000/07/11 22:07:43 1.40 +++ kern/kern_ktrace.c 2000/08/29 14:50:52 @@ -513,6 +513,8 @@ * 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 Index: kern/kern_proc.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_proc.c,v retrieving revision 1.71 diff -u -r1.71 kern_proc.c --- kern/kern_proc.c 2000/08/29 11:28:01 1.71 +++ kern/kern_proc.c 2000/08/29 14:50:56 @@ -55,7 +55,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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) Index: kern/kern_prot.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_prot.c,v retrieving revision 1.59 diff -u -r1.59 kern_prot.c --- kern/kern_prot.c 2000/06/22 22:27:15 1.59 +++ kern/kern_prot.c 2000/08/29 14:51:02 @@ -945,15 +945,15 @@ */ 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) @@ -968,35 +968,167 @@ return (EPERM); if (proc && proc->p_prison && !(flag & PRISON_ROOT)) return (EPERM); - if (proc) - proc->p_acflag |= ASU; 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. Index: kern/kern_resource.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_resource.c,v retrieving revision 1.59 diff -u -r1.59 kern_resource.c --- kern/kern_resource.c 2000/08/24 04:54:31 1.59 +++ kern/kern_resource.c 2000/08/29 14:51:06 @@ -88,7 +88,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 */ Index: kern/kern_sig.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_sig.c,v retrieving revision 1.83 diff -u -r1.83 kern_sig.c --- kern/kern_sig.c 2000/08/26 02:27:01 1.83 +++ kern/kern_sig.c 2000/08/29 14:51:16 @@ -97,7 +97,7 @@ * 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)) /* Index: kern/sys_process.c =================================================================== RCS file: /home/ncvs/src/sys/kern/sys_process.c,v retrieving revision 1.51 diff -u -r1.51 sys_process.c --- kern/sys_process.c 1999/11/21 19:03:10 1.51 +++ kern/sys_process.c 2000/08/29 14:51:20 @@ -217,7 +217,7 @@ 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 @@ 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; Index: miscfs/procfs/procfs_dbregs.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_dbregs.c,v retrieving revision 1.4 diff -u -r1.4 procfs_dbregs.c --- miscfs/procfs/procfs_dbregs.c 1999/12/08 08:59:36 1.4 +++ miscfs/procfs/procfs_dbregs.c 2000/08/29 14:51:23 @@ -62,7 +62,7 @@ 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; Index: miscfs/procfs/procfs_fpregs.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_fpregs.c,v retrieving revision 1.11 diff -u -r1.11 procfs_fpregs.c --- miscfs/procfs/procfs_fpregs.c 1999/12/08 08:59:37 1.11 +++ miscfs/procfs/procfs_fpregs.c 2000/08/29 14:51:24 @@ -59,7 +59,7 @@ 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; Index: miscfs/procfs/procfs_mem.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_mem.c,v retrieving revision 1.46 diff -u -r1.46 procfs_mem.c --- miscfs/procfs/procfs_mem.c 1999/12/20 18:26:58 1.46 +++ miscfs/procfs/procfs_mem.c 2000/08/29 14:51:26 @@ -256,7 +256,7 @@ * 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; Index: miscfs/procfs/procfs_regs.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_regs.c,v retrieving revision 1.10 diff -u -r1.10 procfs_regs.c --- miscfs/procfs/procfs_regs.c 1999/11/21 19:03:19 1.10 +++ miscfs/procfs/procfs_regs.c 2000/08/29 14:51:26 @@ -60,7 +60,7 @@ 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; Index: miscfs/procfs/procfs_status.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_status.c,v retrieving revision 1.20 diff -u -r1.20 procfs_status.c --- miscfs/procfs/procfs_status.c 1999/12/27 16:03:38 1.20 +++ miscfs/procfs/procfs_status.c 2000/08/29 14:51:28 @@ -183,7 +183,7 @@ * 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; Index: miscfs/procfs/procfs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/miscfs/procfs/procfs_vnops.c,v retrieving revision 1.80 diff -u -r1.80 procfs_vnops.c --- miscfs/procfs/procfs_vnops.c 2000/08/18 10:01:00 1.80 +++ miscfs/procfs/procfs_vnops.c 2000/08/29 14:51:34 @@ -137,7 +137,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ *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 @@ 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 @@ 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 @@ 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 @@ 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; Index: sys/proc.h =================================================================== RCS file: /home/ncvs/src/sys/sys/proc.h,v retrieving revision 1.108 diff -u -r1.108 proc.h --- sys/proc.h 2000/08/29 11:28:06 1.108 +++ sys/proc.h 2000/08/29 14:51:47 @@ -293,6 +293,11 @@ #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 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 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 *));