diff options
34 files changed, 190 insertions, 124 deletions
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index 749d16a..8ba6c41 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -44,7 +44,6 @@ #include <sys/param.h> #include <sys/blist.h> #include <sys/dkstat.h> -#include <sys/jail.h> #include <sys/kernel.h> #include <sys/proc.h> #include <sys/resourcevar.h> @@ -52,6 +51,7 @@ #include <sys/systm.h> #include <sys/tty.h> #include <sys/vnode.h> +#include <sys/jail.h> #include <vm/vm.h> #include <vm/pmap.h> diff --git a/sys/compat/linprocfs/linprocfs_misc.c b/sys/compat/linprocfs/linprocfs_misc.c index 749d16a..8ba6c41 100644 --- a/sys/compat/linprocfs/linprocfs_misc.c +++ b/sys/compat/linprocfs/linprocfs_misc.c @@ -44,7 +44,6 @@ #include <sys/param.h> #include <sys/blist.h> #include <sys/dkstat.h> -#include <sys/jail.h> #include <sys/kernel.h> #include <sys/proc.h> #include <sys/resourcevar.h> @@ -52,6 +51,7 @@ #include <sys/systm.h> #include <sys/tty.h> #include <sys/vnode.h> +#include <sys/jail.h> #include <vm/vm.h> #include <vm/pmap.h> diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c index 8482dd9..35d4a25 100644 --- a/sys/compat/linux/linux_mib.c +++ b/sys/compat/linux/linux_mib.c @@ -117,10 +117,11 @@ get_prison(struct proc *p) register struct prison *pr; register struct linux_prison *lpr; - pr = p->p_prison; - if (pr == NULL) + if (!jailed(p->p_ucred)) return (NULL); + pr = p->p_ucred->cr_prison; + if (pr->pr_linux == NULL) { MALLOC(lpr, struct linux_prison *, sizeof *lpr, M_PRISON, M_WAITOK|M_ZERO); @@ -137,7 +138,7 @@ linux_get_osname(p) register struct prison *pr; register struct linux_prison *lpr; - pr = p->p_prison; + pr = p->p_ucred->cr_prison; if (pr != NULL && pr->pr_linux != NULL) { lpr = pr->pr_linux; if (lpr->pr_osname[0]) @@ -170,7 +171,7 @@ linux_get_osrelease(p) register struct prison *pr; register struct linux_prison *lpr; - pr = p->p_prison; + pr = p->p_ucred->cr_prison; if (pr != NULL && pr->pr_linux != NULL) { lpr = pr->pr_linux; if (lpr->pr_osrelease[0]) @@ -203,7 +204,7 @@ linux_get_oss_version(p) register struct prison *pr; register struct linux_prison *lpr; - pr = p->p_prison; + pr = p->p_ucred->cr_prison; if (pr != NULL && pr->pr_linux != NULL) { lpr = pr->pr_linux; if (lpr->pr_oss_version) diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c index 680109b..3d40681 100644 --- a/sys/compat/svr4/svr4_misc.c +++ b/sys/compat/svr4/svr4_misc.c @@ -1299,15 +1299,6 @@ loop: q->p_cred = NULL; } - /* - * Destroy empty prisons - */ - if (q->p_prison && !--q->p_prison->pr_ref) { - if (q->p_prison->pr_linux != NULL) - FREE(q->p_prison->pr_linux, M_PRISON); - FREE(q->p_prison, M_PRISON); - } - /* * Remove unused arguments */ diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c index 14c8fb4..7b2256c 100644 --- a/sys/fs/procfs/procfs_status.c +++ b/sys/fs/procfs/procfs_status.c @@ -163,9 +163,9 @@ procfs_dostatus(curp, p, pfs, uio) DOCHECK(); } - if (p->p_prison) + if (jailed(p->p_ucred)) ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, - " %s", p->p_prison->pr_host); + " %s", p->p_ucred->cr_prison->pr_host); else ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " -"); DOCHECK(); diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 7f9a3f9..8eca076 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -324,9 +324,7 @@ proc0_init(void *dummy __unused) p->p_ucred = crget(); p->p_ucred->cr_ngroups = 1; /* group 0 */ p->p_ucred->cr_uidinfo = uifind(0); - - /* Don't jail it */ - p->p_prison = 0; + p->p_ucred->cr_prison = NULL; /* Don't jail it. */ /* Create procsig. */ p->p_procsig = &procsig0; diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 71e6288..440ee3a 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -528,15 +528,6 @@ loop: } /* - * Destroy empty prisons - */ - if (p->p_prison && !--p->p_prison->pr_ref) { - if (p->p_prison->pr_linux != NULL) - FREE(p->p_prison->pr_linux, M_PRISON); - FREE(p->p_prison, M_PRISON); - } - - /* * Remove unused arguments */ if (p->p_args && --p->p_args->ar_ref == 0) diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index c754e5d..7f6be26 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -394,11 +394,6 @@ again: crhold(p1->p_ucred); uihold(p1->p_cred->p_uidinfo); - if (p2->p_prison) { - p2->p_prison->pr_ref++; - p2->p_flag |= P_JAILED; - } - if (p2->p_args) p2->p_args->ar_ref++; diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c index 97bb2bb..c417667 100644 --- a/sys/kern/kern_jail.c +++ b/sys/kern/kern_jail.c @@ -46,16 +46,17 @@ SYSCTL_INT(_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW, int jail(p, uap) - struct proc *p; - struct jail_args /* { - syscallarg(struct jail *) jail; - } */ *uap; + struct proc *p; + struct jail_args /* { + syscallarg(struct jail *) jail; + } */ *uap; { int error; struct prison *pr; struct jail j; struct chroot_args ca; + /* Implicitly fail if already in jail. */ error = suser(p); if (error) return (error); @@ -75,9 +76,9 @@ jail(p, uap) if (error) goto bail; - pr->pr_ref++; - p->p_prison = pr; - p->p_flag |= P_JAILED; + p->p_ucred = crcopy(p->p_ucred); + p->p_ucred->cr_prison = pr; + pr->pr_ref = 1; return (0); bail: @@ -85,12 +86,31 @@ bail: return (error); } +void +prison_free(struct prison *pr) +{ + + pr->pr_ref--; + if (pr->pr_ref == 0) { + if (pr->pr_linux != NULL) + FREE(pr->pr_linux, M_PRISON); + FREE(pr, M_PRISON); + } +} + +void +prison_hold(struct prison *pr) +{ + + pr->pr_ref++; +} + int -prison_ip(struct proc *p, int flag, u_int32_t *ip) +prison_ip(struct ucred *cred, int flag, u_int32_t *ip) { u_int32_t tmp; - if (!p->p_prison) + if (!jailed(cred)) return (0); if (flag) tmp = *ip; @@ -98,22 +118,22 @@ prison_ip(struct proc *p, int flag, u_int32_t *ip) tmp = ntohl(*ip); if (tmp == INADDR_ANY) { if (flag) - *ip = p->p_prison->pr_ip; + *ip = cred->cr_prison->pr_ip; else - *ip = htonl(p->p_prison->pr_ip); + *ip = htonl(cred->cr_prison->pr_ip); return (0); } - if (p->p_prison->pr_ip != tmp) + if (cred->cr_prison->pr_ip != tmp) return (1); return (0); } void -prison_remote_ip(struct proc *p, int flag, u_int32_t *ip) +prison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip) { u_int32_t tmp; - if (!p || !p->p_prison) + if (!jailed(cred)) return; if (flag) tmp = *ip; @@ -121,16 +141,16 @@ prison_remote_ip(struct proc *p, int flag, u_int32_t *ip) tmp = ntohl(*ip); if (tmp == 0x7f000001) { if (flag) - *ip = p->p_prison->pr_ip; + *ip = cred->cr_prison->pr_ip; else - *ip = htonl(p->p_prison->pr_ip); + *ip = htonl(cred->cr_prison->pr_ip); return; } return; } int -prison_if(struct proc *p, struct sockaddr *sa) +prison_if(struct ucred *cred, struct sockaddr *sa) { struct sockaddr_in *sai = (struct sockaddr_in*) sa; int ok; @@ -139,9 +159,38 @@ prison_if(struct proc *p, struct sockaddr *sa) ok = 1; else if (sai->sin_family != AF_INET) ok = 0; - else if (p->p_prison->pr_ip != ntohl(sai->sin_addr.s_addr)) + else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr)) ok = 1; else ok = 0; return (ok); } + +/* + * Return 0 if jails permit p1 to frob p2, otherwise ESRCH. + */ +int +prison_check(cred1, cred2) + struct ucred *cred1, *cred2; +{ + + if (jailed(cred1)) { + if (!jailed(cred2)) + return (ESRCH); + if (cred2->cr_prison != cred1->cr_prison) + return (ESRCH); + } + + return (0); +} + +/* + * Return 1 if the passed credential is in a jail, otherwise 0. + */ +int +jailed(cred) + struct ucred *cred; +{ + + return (cred->cr_prison != NULL); +} diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index ce408ca..149bc4c 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -48,6 +48,7 @@ #include <sys/ktrace.h> #include <sys/malloc.h> #include <sys/syslog.h> +#include <sys/jail.h> static MALLOC_DEFINE(M_KTRACE, "KTRACE", "KTRACE"); @@ -519,6 +520,7 @@ ktrwrite(vp, kth, uio) * so, only root may further change it. * * XXX: These checks are stronger than for ptrace() + * XXX: This check should be p_can(... P_CAN_DEBUG ...); * * TODO: check groups. use caller effective gid. */ @@ -529,7 +531,7 @@ ktrcanset(callp, targetp) register struct pcred *caller = callp->p_cred; register struct pcred *target = targetp->p_cred; - if (!PRISON_CHECK(callp, targetp)) + if (prison_check(callp->p_ucred, targetp->p_ucred)) return (0); if ((caller->pc_ucred->cr_uid == target->p_ruid && target->p_ruid == target->p_svuid && diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c index 0826ea0..bb9f640 100644 --- a/sys/kern/kern_mib.c +++ b/sys/kern/kern_mib.c @@ -146,12 +146,12 @@ sysctl_hostname(SYSCTL_HANDLER_ARGS) { int error; - if (req->p->p_prison) { + if (jailed(req->p->p_ucred)) { if (!jail_set_hostname_allowed && req->newptr) return(EPERM); error = sysctl_handle_string(oidp, - req->p->p_prison->pr_host, - sizeof req->p->p_prison->pr_host, req); + req->p->p_ucred->cr_prison->pr_host, + sizeof req->p->p_ucred->cr_prison->pr_host, req); } else error = sysctl_handle_string(oidp, hostname, sizeof hostname, req); diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 0461e83..dc37bc7 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -49,6 +49,7 @@ #include <vm/vm_map.h> #include <sys/user.h> #include <vm/vm_zone.h> +#include <sys/jail.h> static MALLOC_DEFINE(M_PGRP, "pgrp", "process group header"); MALLOC_DEFINE(M_SESSION, "session", "session header"); @@ -478,6 +479,9 @@ fill_kinfo_proc(p, kp) kp->ki_xstat = p->p_xstat; kp->ki_acflag = p->p_acflag; kp->ki_flag = p->p_flag; + /* If jailed(p->p_ucred), emulate the old P_JAILED flag. */ + if (jailed(p->p_ucred)) + kp->ki_flag |= P_JAILED; kp->ki_lock = p->p_lock; PROC_UNLOCK(p); PROCTREE_LOCK(PT_SHARED); diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 4d8c4e3..9d92ff7 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -56,6 +56,7 @@ #include <sys/pioctl.h> #include <sys/resourcevar.h> #include <sys/sysctl.h> +#include <sys/jail.h> static MALLOC_DEFINE(M_CRED, "cred", "credentials"); @@ -941,15 +942,15 @@ SYSCTL_INT(_kern, OID_AUTO, suser_permitted, CTLFLAG_RW, &suser_permitted, 0, */ int suser(p) - const struct proc *p; + struct proc *p; { return suser_xxx(0, p, 0); } int suser_xxx(cred, proc, flag) - const struct ucred *cred; - const struct proc *proc; + struct ucred *cred; + struct proc *proc; int flag; { if (!suser_permitted) @@ -962,20 +963,21 @@ suser_xxx(cred, proc, flag) cred = proc->p_ucred; if (cred->cr_uid != 0) return (EPERM); - if (proc && proc->p_prison && !(flag & PRISON_ROOT)) + if (jailed(cred) && !(flag & PRISON_ROOT)) return (EPERM); return (0); } static int -p_cansee(const struct proc *p1, const struct proc *p2, int *privused) +p_cansee(struct proc *p1, struct proc *p2, int *privused) { + int error; if (privused != NULL) *privused = 0; - if (!PRISON_CHECK(p1, p2)) - return (ESRCH); + if ((error = prison_check(p1->p_ucred, p2->p_ucred))) + return (error); if (!ps_showallprocs && p1->p_ucred->cr_uid != p2->p_ucred->cr_uid) { if (suser_xxx(NULL, p1, PRISON_ROOT) == 0) { @@ -990,8 +992,9 @@ p_cansee(const struct proc *p1, const struct proc *p2, int *privused) } static int -p_cankill(const struct proc *p1, const struct proc *p2, int *privused) +p_cankill(struct proc *p1, struct proc *p2, int *privused) { + int error; if (privused != NULL) *privused = 0; @@ -999,8 +1002,8 @@ p_cankill(const struct proc *p1, const struct proc *p2, int *privused) if (p1 == p2) return (0); - if (!PRISON_CHECK(p1, p2)) - return (ESRCH); + if ((error = prison_check(p1->p_ucred, p2->p_ucred))) + return (error); if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) return (0); @@ -1033,8 +1036,9 @@ p_cankill(const struct proc *p1, const struct proc *p2, int *privused) } static int -p_cansched(const struct proc *p1, const struct proc *p2, int *privused) +p_cansched(struct proc *p1, struct proc *p2, int *privused) { + int error; if (privused != NULL) *privused = 0; @@ -1042,8 +1046,8 @@ p_cansched(const struct proc *p1, const struct proc *p2, int *privused) if (p1 == p2) return (0); - if (!PRISON_CHECK(p1, p2)) - return (ESRCH); + if ((error = prison_check(p1->p_ucred, p2->p_ucred))) + return (error); if (p1->p_cred->p_ruid == p2->p_cred->p_ruid) return (0); @@ -1076,9 +1080,9 @@ p_cansched(const struct proc *p1, const struct proc *p2, int *privused) } static int -p_candebug(const struct proc *p1, const struct proc *p2, int *privused) +p_candebug(struct proc *p1, struct proc *p2, int *privused) { - int error; + int error; if (privused != NULL) *privused = 0; @@ -1087,8 +1091,8 @@ p_candebug(const struct proc *p1, const struct proc *p2, int *privused) if (p1 == p2) return (0); - if (!PRISON_CHECK(p1, p2)) - return (ESRCH); + if ((error = prison_check(p1->p_ucred, p2->p_ucred))) + return (error); /* not owned by you, has done setuid (unless you're root) */ /* add a CAP_SYS_PTRACE here? */ @@ -1110,7 +1114,7 @@ p_candebug(const struct proc *p1, const struct proc *p2, int *privused) } int -p_can(const struct proc *p1, const struct proc *p2, int operation, +p_can(struct proc *p1, struct proc *p2, int operation, int *privused) { @@ -1180,6 +1184,11 @@ crfree(cr) */ if (cr->cr_uidinfo != NULL) uifree(cr->cr_uidinfo); + /* + * Free a prison, if any. + */ + if (jailed(cr)) + prison_free(cr->cr_prison); FREE((caddr_t)cr, M_CRED); } else { mtx_unlock(&cr->cr_mtx); @@ -1219,6 +1228,8 @@ crdup(cr) *newcr = *cr; mtx_init(&newcr->cr_mtx, "ucred", MTX_DEF); uihold(newcr->cr_uidinfo); + if (jailed(newcr)) + prison_hold(newcr->cr_prison); newcr->cr_ref = 1; return (newcr); } diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c index db4a90a..f2b3ba7 100644 --- a/sys/kern/sysv_msg.c +++ b/sys/kern/sysv_msg.c @@ -278,7 +278,7 @@ msgsys(p, uap) } */ *uap; { - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); if (uap->which >= sizeof(msgcalls)/sizeof(msgcalls[0])) @@ -334,7 +334,7 @@ msgctl(p, uap) printf("call to msgctl(%d, %d, 0x%x)\n", msqid, cmd, user_msqptr); #endif - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); msqid = IPCID_TO_IX(msqid); @@ -473,7 +473,7 @@ msgget(p, uap) printf("msgget(0x%x, 0%o)\n", key, msgflg); #endif - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); if (key != IPC_PRIVATE) { @@ -588,7 +588,7 @@ msgsnd(p, uap) msgflg); #endif - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); msqid = IPCID_TO_IX(msqid); @@ -915,7 +915,7 @@ msgrcv(p, uap) msgsz, msgtyp, msgflg); #endif - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); msqid = IPCID_TO_IX(msqid); diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index 3fab556..cc2f2d4 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -255,7 +255,7 @@ semsys(p, uap) } */ *uap; { - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); if (uap->which >= sizeof(semcalls)/sizeof(semcalls[0])) @@ -464,7 +464,7 @@ __semctl(p, uap) printf("call to semctl(%d, %d, %d, 0x%x)\n", semid, semnum, cmd, arg); #endif - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); semid = IPCID_TO_IX(semid); @@ -627,7 +627,7 @@ semget(p, uap) printf("semget(0x%x, %d, 0%o)\n", key, nsems, semflg); #endif - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); if (key != IPC_PRIVATE) { @@ -748,7 +748,7 @@ semop(p, uap) printf("call to semop(%d, 0x%x, %d)\n", semid, sops, nsops); #endif - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); semid = IPCID_TO_IX(semid); /* Convert back to zero origin */ diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 19efaf9..3bfd49a 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -229,7 +229,7 @@ shmdt(p, uap) struct shmmap_state *shmmap_s; int i; - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; @@ -266,7 +266,7 @@ shmat(p, uap) vm_size_t size; int rv; - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; @@ -360,7 +360,7 @@ oshmctl(p, uap) struct shmid_ds *shmseg; struct oshmid_ds outbuf; - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); shmseg = shm_find_segment_by_shmid(uap->shmid); @@ -411,7 +411,7 @@ shmctl(p, uap) struct shmid_ds inbuf; struct shmid_ds *shmseg; - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); shmseg = shm_find_segment_by_shmid(uap->shmid); @@ -590,7 +590,7 @@ shmget(p, uap) { int segnum, mode, error; - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); mode = uap->shmflg & ACCESSPERMS; @@ -621,7 +621,7 @@ shmsys(p, uap) } */ *uap; { - if (!jail_sysvipc_allowed && p->p_prison != NULL) + if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); if (uap->which >= sizeof(shmcalls)/sizeof(shmcalls[0])) diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c index b6063fc..501dde1 100644 --- a/sys/kern/tty_pty.c +++ b/sys/kern/tty_pty.c @@ -187,7 +187,7 @@ ptsopen(dev, flag, devtype, p) tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; } else if (tp->t_state & TS_XCLUDE && suser(p)) { return (EBUSY); - } else if (pti->pt_prison != p->p_prison) { + } else if (pti->pt_prison != p->p_ucred->cr_prison) { return (EBUSY); } if (tp->t_oproc) /* Ctrlr still around. */ @@ -348,7 +348,7 @@ ptcopen(dev, flag, devtype, p) (void)(*linesw[tp->t_line].l_modem)(tp, 1); tp->t_lflag &= ~EXTPROC; pti = dev->si_drv1; - pti->pt_prison = p->p_prison; + pti->pt_prison = p->p_ucred->cr_prison; pti->pt_flags = 0; pti->pt_send = 0; pti->pt_ucntl = 0; diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 85667de..2f0cdd3 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -141,7 +141,7 @@ socreate(dom, aso, type, proto, p) if (prp == 0 || prp->pr_usrreqs->pru_attach == 0) return (EPROTONOSUPPORT); - if (p->p_prison && jail_socket_unixiproute_only && + if (jailed(p->p_ucred) && jail_socket_unixiproute_only && prp->pr_domain->dom_family != PF_LOCAL && prp->pr_domain->dom_family != PF_INET && prp->pr_domain->dom_family != PF_ROUTE) { diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 79477c9..de295b1 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -54,6 +54,7 @@ #include <sys/un.h> #include <sys/unpcb.h> #include <sys/vnode.h> +#include <sys/jail.h> #include <vm/vm_zone.h> @@ -725,7 +726,7 @@ unp_abort(unp) static int prison_unpcb(struct proc *p, struct unpcb *unp) { - if (!p->p_prison) + if (!jailed(p->p_ucred)) return (0); if (p->p_fd->fd_rdir == unp->unp_rvnode) return (0); diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 709736c..0651257 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -64,6 +64,7 @@ #include <sys/proc.h> #include <sys/dirent.h> #include <sys/extattr.h> +#include <sys/jail.h> #include <machine/limits.h> #include <miscfs/union/union.h> @@ -610,7 +611,7 @@ quotactl(p, uap) int error; struct nameidata nd; - if (p->p_prison && !prison_quotas) + if (jailed(p->p_ucred) && !prison_quotas) return (EPERM); NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 709736c..0651257 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -64,6 +64,7 @@ #include <sys/proc.h> #include <sys/dirent.h> #include <sys/extattr.h> +#include <sys/jail.h> #include <machine/limits.h> #include <miscfs/union/union.h> @@ -610,7 +611,7 @@ quotactl(p, uap) int error; struct nameidata nd; - if (p->p_prison && !prison_quotas) + if (jailed(p->p_ucred) && !prison_quotas) return (EPERM); NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) diff --git a/sys/miscfs/procfs/procfs_status.c b/sys/miscfs/procfs/procfs_status.c index 14c8fb4..7b2256c 100644 --- a/sys/miscfs/procfs/procfs_status.c +++ b/sys/miscfs/procfs/procfs_status.c @@ -163,9 +163,9 @@ procfs_dostatus(curp, p, pfs, uio) DOCHECK(); } - if (p->p_prison) + if (jailed(p->p_ucred)) ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, - " %s", p->p_prison->pr_host); + " %s", p->p_ucred->cr_prison->pr_host); else ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, " -"); DOCHECK(); diff --git a/sys/net/if.c b/sys/net/if.c index dc434f3..2f06afd 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -50,6 +50,7 @@ #include <sys/sockio.h> #include <sys/syslog.h> #include <sys/sysctl.h> +#include <sys/jail.h> #include <net/if.h> #include <net/if_arp.h> @@ -1080,7 +1081,8 @@ ifconf(cmd, data) for ( ; space > sizeof (ifr) && ifa; ifa = TAILQ_NEXT(ifa, ifa_link)) { register struct sockaddr *sa = ifa->ifa_addr; - if (curproc->p_prison && prison_if(curproc, sa)) + if (jailed(curproc->p_ucred) && + prison_if(curproc->p_ucred, sa)) continue; addrs++; #ifdef COMPAT_43 diff --git a/sys/net/if.h b/sys/net/if.h index bcc10ad..6cdaa53 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -265,8 +265,6 @@ __END_DECLS #ifdef _KERNEL struct proc; -int prison_if __P((struct proc *p, struct sockaddr *sa)); - /* XXX - this should go away soon. */ #include <net/if_var.h> #endif diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index 2dba7d9..dc4ae26 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -46,6 +46,7 @@ #include <sys/socketvar.h> #include <sys/domain.h> #include <sys/protosw.h> +#include <sys/jail.h> #include <net/if.h> #include <net/route.h> @@ -915,7 +916,8 @@ sysctl_iflist(af, w) while ((ifa = TAILQ_NEXT(ifa, ifa_link)) != 0) { if (af && af != ifa->ifa_addr->sa_family) continue; - if (curproc->p_prison && prison_if(curproc, ifa->ifa_addr)) + if (jailed(curproc->p_ucred) && + prison_if(curproc->p_ucred, ifa->ifa_addr)) continue; ifaaddr = ifa->ifa_addr; netmask = ifa->ifa_netmask; diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 1ce8dfd..e7ab99f 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -487,9 +487,6 @@ int in_localaddr __P((struct in_addr)); char *inet_ntoa __P((struct in_addr)); /* in libkern */ char *inet_ntoa_r __P((struct in_addr ina, char *buf)); /* in libkern */ -int prison_ip __P((struct proc *p, int flag, u_int32_t *ip)); -void prison_remote_ip __P((struct proc *p, int flag, u_int32_t *ip)); - #endif #endif diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 7195be9..c114eca 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -199,7 +199,7 @@ in_pcbbind(inp, nam, p) return (EAFNOSUPPORT); #endif if (sin->sin_addr.s_addr != INADDR_ANY) - if (prison_ip(p, 0, &sin->sin_addr.s_addr)) + if (prison_ip(p->p_ucred, 0, &sin->sin_addr.s_addr)) return(EINVAL); lport = sin->sin_port; if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { @@ -219,12 +219,11 @@ in_pcbbind(inp, nam, p) } if (lport) { struct inpcb *t; - /* GROSS */ if (ntohs(lport) < IPPORT_RESERVED && p && suser_xxx(0, p, PRISON_ROOT)) return (EACCES); - if (p && p->p_prison) + if (p && jailed(p->p_ucred)) prison = 1; if (so->so_cred->cr_uid != 0 && !IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { @@ -274,7 +273,7 @@ in_pcbbind(inp, nam, p) int count; if (inp->inp_laddr.s_addr != INADDR_ANY) - if (prison_ip(p, 0, &inp->inp_laddr.s_addr )) + if (prison_ip(p->p_ucred, 0, &inp->inp_laddr.s_addr )) return (EINVAL); inp->inp_flags |= INP_ANONPORT; @@ -345,7 +344,7 @@ in_pcbbind(inp, nam, p) } } inp->inp_lport = lport; - if (prison_ip(p, 0, &inp->inp_laddr.s_addr)) + if (prison_ip(p->p_ucred, 0, &inp->inp_laddr.s_addr)) return(EINVAL); if (in_pcbinshash(inp) != 0) { inp->inp_laddr.s_addr = INADDR_ANY; @@ -492,11 +491,13 @@ in_pcbconnect(inp, nam, p) struct sockaddr_in *ifaddr; struct sockaddr_in *sin = (struct sockaddr_in *)nam; struct sockaddr_in sa; + struct ucred *cred; int error; - if (inp->inp_laddr.s_addr == INADDR_ANY && p->p_prison != NULL) { + cred = inp->inp_socket->so_cred; + if (inp->inp_laddr.s_addr == INADDR_ANY && jailed(cred)) { bzero(&sa, sizeof (sa)); - sa.sin_addr.s_addr = htonl(p->p_prison->pr_ip); + sa.sin_addr.s_addr = htonl(cred->cr_prison->pr_ip); sa.sin_len=sizeof (sa); sa.sin_family = AF_INET; error = in_pcbbind(inp, (struct sockaddr *)&sa, p); @@ -1068,9 +1069,9 @@ in_pcbremlists(inp) int prison_xinpcb(struct proc *p, struct inpcb *inp) { - if (!p->p_prison) + if (!jailed(p->p_ucred)) return (0); - if (ntohl(inp->inp_laddr.s_addr) == p->p_prison->pr_ip) + if (ntohl(inp->inp_laddr.s_addr) == p->p_ucred->cr_prison->pr_ip) return (0); return (1); } diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index ac1eee9..1d64581 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -49,6 +49,8 @@ #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/protosw.h> +#include <sys/proc.h> +#include <sys/jail.h> #include <net/if.h> #include <net/route.h> @@ -328,7 +330,8 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct proc *p) goto out; } - prison_remote_ip(p, 0, &sinp->sin_addr.s_addr); + if (p && jailed(p->p_ucred)) + prison_remote_ip(p->p_ucred, 0, &sinp->sin_addr.s_addr); if ((error = tcp_connect(tp, nam, p)) != 0) goto out; diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 7edcfcd..60c80d2 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -49,6 +49,7 @@ #include <sys/socketvar.h> #include <sys/sysctl.h> #include <sys/syslog.h> +#include <sys/jail.h> #include <vm/vm_zone.h> @@ -675,7 +676,8 @@ udp_output(inp, m, addr, control, p) if (addr) { sin = (struct sockaddr_in *)addr; - prison_remote_ip(p, 0, &sin->sin_addr.s_addr); + if (p && jailed(p->p_ucred)) + prison_remote_ip(p->p_ucred, 0, &sin->sin_addr.s_addr); laddr = inp->inp_laddr; if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; @@ -848,7 +850,8 @@ udp_connect(struct socket *so, struct sockaddr *nam, struct proc *p) return EISCONN; s = splnet(); sin = (struct sockaddr_in *)nam; - prison_remote_ip(p, 0, &sin->sin_addr.s_addr); + if (p && jailed(p->p_ucred)) + prison_remote_ip(p->p_ucred, 0, &sin->sin_addr.s_addr); error = in_pcbconnect(inp, nam, p); splx(s); if (error == 0) diff --git a/sys/sys/capability.h b/sys/sys/capability.h index 4dc1fbc..cc56c58 100644 --- a/sys/sys/capability.h +++ b/sys/sys/capability.h @@ -167,7 +167,7 @@ typedef struct cap *cap_t; struct proc; struct ucred; struct vnode; -int cap_check(const struct ucred *, const struct proc *, cap_value_t, int); +int cap_check(struct ucred *, struct proc *, cap_value_t, int); int cap_change_on_inherit(struct cap *cap_p); int cap_inherit(struct vnode *vp, struct proc *p); void cap_init_proc0(struct cap *); diff --git a/sys/sys/jail.h b/sys/sys/jail.h index a4227d9..fcd1d13 100644 --- a/sys/sys/jail.h +++ b/sys/sys/jail.h @@ -32,8 +32,11 @@ MALLOC_DECLARE(M_PRISON); /* * This structure describes a prison. It is pointed to by all struct - * proc's of the inmates. pr_ref keeps track of them and is used to + * ucreds's of the inmates. pr_ref keeps track of them and is used to * delete the struture when the last inmate is dead. + * + * XXX: Note: this structure needs a mutex to protect the reference count + * and other mutable fields (pr_host, pr_linux). */ struct prison { @@ -50,5 +53,18 @@ extern int jail_set_hostname_allowed; extern int jail_socket_unixiproute_only; extern int jail_sysvipc_allowed; +/* + * Kernel support functions for jail(). + */ +struct ucred; +struct sockaddr; +int jailed __P((struct ucred *cred)); +int prison_check __P((struct ucred *cred1, struct ucred *cred2)); +void prison_free __P((struct prison *pr)); +void prison_hold __P((struct prison *pr)); +int prison_if __P((struct ucred *cred, struct sockaddr *sa)); +int prison_ip __P((struct ucred *cred, int flag, u_int32_t *ip)); +void prison_remote_ip __P((struct ucred *cred, int flags, u_int32_t *ip)); + #endif /* !_KERNEL */ #endif /* !_SYS_JAIL_H_ */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 7880448..81b5551 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -258,7 +258,6 @@ struct proc { struct pgrp *p_pgrp; /* (e?/c?) Pointer to process group. */ struct sysentvec *p_sysent; /* (b) System call dispatch information. */ - struct prison *p_prison; /* (b?) jail(4). */ struct pargs *p_args; /* (b?) Process arguments. */ /* End area that is copied on creation. */ @@ -539,7 +538,7 @@ void fork_return __P((struct proc *, struct trapframe *)); int inferior __P((struct proc *p)); int leavepgrp __P((struct proc *p)); void mi_switch __P((void)); -int p_can __P((const struct proc *p1, const struct proc *p2, int operation, +int p_can __P((struct proc *p1, struct proc *p2, int operation, int *privused)); int p_trespass __P((struct proc *p1, struct proc *p2)); void procinit __P((void)); diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 54b303d..454f5ee 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -161,9 +161,8 @@ void setstatclockrate __P((int hzrate)); /* flags for suser_xxx() */ #define PRISON_ROOT 1 -int suser __P((const struct proc *)); -int suser_xxx __P((const struct ucred *cred, const struct proc *proc, - int flag)); +int suser __P((struct proc *)); +int suser_xxx __P((struct ucred *cred, struct proc *proc, int flag)); char *getenv __P((char *name)); int getenv_int __P((char *name, int *data)); diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h index 63adce8..7735091 100644 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -51,6 +51,7 @@ struct ucred { short cr_ngroups; /* number of groups */ gid_t cr_groups[NGROUPS]; /* groups */ struct uidinfo *cr_uidinfo; /* per uid resource consumption */ + struct prison *cr_prison; /* jail(4) */ struct mtx cr_mtx; /* protect refcount */ }; #define cr_gid cr_groups[0] |