diff options
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/init_main.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 9 | ||||
-rw-r--r-- | sys/kern/kern_fork.c | 5 | ||||
-rw-r--r-- | sys/kern/kern_jail.c | 85 | ||||
-rw-r--r-- | sys/kern/kern_ktrace.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_mib.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_proc.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_prot.c | 47 | ||||
-rw-r--r-- | sys/kern/sysv_msg.c | 10 | ||||
-rw-r--r-- | sys/kern/sysv_sem.c | 8 | ||||
-rw-r--r-- | sys/kern/sysv_shm.c | 12 | ||||
-rw-r--r-- | sys/kern/tty_pty.c | 4 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 2 | ||||
-rw-r--r-- | sys/kern/uipc_usrreq.c | 3 | ||||
-rw-r--r-- | sys/kern/vfs_extattr.c | 3 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 3 |
16 files changed, 131 insertions, 78 deletions
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) |