diff options
64 files changed, 710 insertions, 157 deletions
diff --git a/bin/ps/print.c b/bin/ps/print.c index 19560ce..f60cab6 100644 --- a/bin/ps/print.c +++ b/bin/ps/print.c @@ -36,7 +36,7 @@ static char sccsid[] = "@(#)print.c 8.6 (Berkeley) 4/16/94"; #endif static const char rcsid[] = - "$Id: print.c,v 1.33 1998/11/25 09:34:00 dfr Exp $"; + "$Id: print.c,v 1.34 1999/04/06 03:17:57 peter Exp $"; #endif /* not lint */ #include <sys/param.h> @@ -222,6 +222,8 @@ state(k, ve) *cp++ = 's'; if ((flag & P_CONTROLT) && KI_EPROC(k)->e_pgid == KI_EPROC(k)->e_tpgid) *cp++ = '+'; + if (flag & P_JAILED) + *cp++ = 'J'; *cp = '\0'; (void)printf("%-*s", v->width, buf); } diff --git a/bin/ps/ps.1 b/bin/ps/ps.1 index cfdbe20..5283558 100644 --- a/bin/ps/ps.1 +++ b/bin/ps/ps.1 @@ -30,7 +30,7 @@ .\" SUCH DAMAGE. .\" .\" @(#)ps.1 8.3 (Berkeley) 4/18/94 -.\" $Id: ps.1,v 1.19 1998/06/04 07:02:59 jkoshy Exp $ +.\" $Id: ps.1,v 1.20 1999/04/06 03:18:57 peter Exp $ .\" .Dd April 18, 1994 .Dt PS 1 @@ -243,6 +243,11 @@ The first letter indicates the run state of the process: Marks a process in disk (or other short term, uninterruptible) wait. .It I Marks a process that is idle (sleeping for longer than about 20 seconds). +.It J +Marks a process which is in +.Xr jail 2 . +The hostname of the prison can be found in +.Ql Li /proc/<pid>/status . .It R Marks a runnable process. .It S diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc index dd065f1..292860d 100644 --- a/lib/libc/sys/Makefile.inc +++ b/lib/libc/sys/Makefile.inc @@ -1,5 +1,5 @@ # @(#)Makefile.inc 8.3 (Berkeley) 10/24/94 -# $Id: Makefile.inc,v 1.60 1999/04/05 07:38:07 bde Exp $ +# $Id: Makefile.inc,v 1.61 1999/04/11 21:14:40 dt Exp $ # sys sources .PATH: ${.CURDIR}/../libc/${MACHINE_ARCH}/sys ${.CURDIR}/../libc/sys @@ -82,7 +82,7 @@ MAN2+= _exit.2 accept.2 access.2 acct.2 adjtime.2 aio_read.2 \ getpeername.2 getpgrp.2 getpid.2 getpriority.2 getrlimit.2 \ getrusage.2 getsid.2 getsockname.2 \ getsockopt.2 gettimeofday.2 getuid.2 \ - intro.2 ioctl.2 issetugid.2 kill.2 \ + intro.2 ioctl.2 issetugid.2 jail.2 kill.2 \ kldfind.2 kldfirstmod.2 kldload.2 kldnext.2 kldstat.2 kldunload.2 \ ktrace.2 link.2 listen.2 lseek.2 \ madvise.2 mincore.2 minherit.2 mkdir.2 mkfifo.2 mknod.2 mlock.2 mmap.2 \ diff --git a/lib/libc/sys/jail.2 b/lib/libc/sys/jail.2 new file mode 100644 index 0000000..0fe7398 --- /dev/null +++ b/lib/libc/sys/jail.2 @@ -0,0 +1,87 @@ +.\" +.\"---------------------------------------------------------------------------- +.\""THE BEER-WARE LICENSE" (Revision 42): +.\"<phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you +.\"can do whatever you want with this stuff. If we meet some day, and you think +.\"this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp +.\"---------------------------------------------------------------------------- +.\" +.\"$Id: malloc.c,v 1.44 1999/03/28 14:16:05 phk Exp $ +.\" +.\" +.Dd April 28, 1999 +.Dt JAIL 2 +.Os FreeBSD 4.0 +.Sh NAME +.Nm jail +.Nd Imprison current process and future decendants. +.Sh SYNOPSIS +.Fd #include <sys/types.h> +.Fd #include <sys/jail.h> +.Ft int +.Fn jail "struct *jail" +.Sh DESCRIPTION +The +.Nm +system call sets up a jail and locks the current process in it. +.Pp +The argument is a pointer to a structure describing the prison: +.Bd -literal -offset indent +struct jail { + char *path; + char *hostname; + u_int32_t ip_number; +}; +.Ed +.Pp +The +.Dq Li path +pointer should be set to the directory which is to be the root of the +prison. +.Pp +The +.Dq Li hostname +pointer can be set the hostname of the prison. This can be changed +from the inside of the prison. +.Pp +The +.Dq Li ip_number +can be set to the IP number assigned to the prison. +.Sh PRISON ? +Once a process has been put in a prison, it and its decendants cannot escape +the prison. It is not possible to add a process to a preexisting prison. +.Pp +Inside the prison, the concept of "superuser" is very diluted, in general +it can be assumed that nothing can be mangled from inside a prison, that +doesn't exist inside that prison (ie: the directory tree below +.Dq Li path . +.Pp +All IP activity will be forced to happen to/from the IP number specified, +which should be an alias on one of the systems interfaces. +.Pp +It is possible to identify a process as jailed by examining +.Dq Li /proc/<pid>/status : +it will show a field near the end of the line, either as +a single hyphen for a process at large, or the hostname currently +set for the prison for jailed processes. +.Sh ERRORS +.Fn Jail +calls +.Xr chroot 2 +internally, so the it can fail for all the same reasons. +Please consult the +.Xr chroot 2 +manual page for details. +.Sh SEE ALSO +.Xr chroot 2 +.Xr chdir 2 +.Sh HISTORY +The +.Fn jail +function call appeared in +.Fx 4.0 . +.Pp +The jail feature was written by Poul-Henning Kamp for +R&D Associates +.Dq Li http://www.rndassociates.com/ +who contributed it to FreeBSD. diff --git a/share/man/man9/suser.9 b/share/man/man9/suser.9 index 916ceec..39d5ed36 100644 --- a/share/man/man9/suser.9 +++ b/share/man/man9/suser.9 @@ -31,7 +31,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: suser.9,v 1.4 1997/03/07 02:53:37 jmg Exp $ +.\" $Id: suser.9,v 1.5 1998/01/16 18:06:23 bde Exp $ .\" .Dd Oct 15, 1996 .Dt SUSER 9 @@ -43,25 +43,60 @@ .Fd #include <sys/param.h> .Fd #include <sys/ucred.h> .Ft int -.Fn suser "struct ucred *cred, u_short *acflag" +.Fn suser "struct proc *proc" +.Ft int +.Fn suser_xxx "struct ucred *cred, struct proc *proc, int flags" .Sh DESCRIPTION The .Nm -function checks if the credentials given include superuser powers. +and +.Nm suser_xxx +functions checks if the credentials given include superuser powers. +.Pp +The +.Nm +function is the most common, and should be used unless special +circumstances dictate otherwise. +.Pp +The +.Nm suser_xxx +function should be used when the credentials to be checked are +not the process' own, when there is no process or when superuser +powers should be extended to prisoned roots. +.Pp +By default a process does not command superuser powers if it has +been imprisoned by the +.Xr jail 2 +system call. +There are cases however where this is appropriate, and this can +be done by setting the +.Ql PRISON_ROOT +bit in the flags argument to the +.Nm suser_xxx +function. It is important to review carefully in each case that +this does not weaken the prison. Generally only where the action +is protected by the +.Xr chroot 2 +implicit in +.Xr jail 2 +call should such powers be granted. .Pp The .Nm -routine notes the fact that superuser powers have been used in the -word pointed to by the second argument which should be a pointer to -the p_acflags word of the proc structure. If the second argument is NULL -then the usage is not noted. Because part of it's function is to notice +and +.Nm suser_xxx +functions notes the fact that superuser powers have been used in the +process structure of the process specified. +Because part of its function is to notice whether super powers have been used, -.Nm -should be called after other permission possibilities have been exhausted. +the functions should only be called after other permission +possibilities have been exhausted. .Sh RETURN VALUES The .Nm -function returns 0 if the user has super powers and EPERM otherwise. +and +.Nm suser_xxx +functions returns 0 if the user has super powers and EPERM otherwise. This is the .Em reverse logic of some other implementations of diff --git a/sys/conf/files b/sys/conf/files index bbf2f6a..e06b7b2 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -275,6 +275,7 @@ kern/kern_environment.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fork.c standard +kern/kern_jail.c standard kern/kern_ktrace.c standard kern/kern_lock.c standard kern/kern_lockf.c standard diff --git a/sys/fs/msdosfs/msdosfs_vnops.c b/sys/fs/msdosfs/msdosfs_vnops.c index 00f576b..108aab0 100644 --- a/sys/fs/msdosfs/msdosfs_vnops.c +++ b/sys/fs/msdosfs/msdosfs_vnops.c @@ -1,4 +1,4 @@ -/* $Id: msdosfs_vnops.c,v 1.81 1999/01/27 22:42:09 dillon Exp $ */ +/* $Id: msdosfs_vnops.c,v 1.82 1999/04/27 11:16:51 phk Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.68 1998/02/10 14:10:04 mrg Exp $ */ /*- @@ -431,7 +431,7 @@ msdosfs_setattr(ap) if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != pmp->pm_uid && - (error = suser_xxx(cred, &ap->a_p->p_acflag))) + (error = suser_xxx(cred, ap->a_p, PRISON_ROOT))) return (error); /* * We are very inconsistent about handling unsupported @@ -472,7 +472,7 @@ msdosfs_setattr(ap) gid = pmp->pm_gid; if ((cred->cr_uid != pmp->pm_uid || uid != pmp->pm_uid || (gid != pmp->pm_gid && !groupmember(gid, cred))) && - (error = suser_xxx(cred, &ap->a_p->p_acflag))) + (error = suser_xxx(cred, ap->a_p, PRISON_ROOT))) return error; if (uid != pmp->pm_uid || gid != pmp->pm_gid) return EINVAL; @@ -504,7 +504,7 @@ msdosfs_setattr(ap) if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != pmp->pm_uid && - (error = suser_xxx(cred, &ap->a_p->p_acflag)) && + (error = suser_xxx(cred, ap->a_p, PRISON_ROOT)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || (error = VOP_ACCESS(ap->a_vp, VWRITE, cred, ap->a_p)))) return (error); @@ -527,7 +527,7 @@ msdosfs_setattr(ap) if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != pmp->pm_uid && - (error = suser_xxx(cred, &ap->a_p->p_acflag))) + (error = suser_xxx(cred, ap->a_p, PRISON_ROOT))) return (error); if (vp->v_type != VDIR) { /* We ignore the read and execute bits. */ diff --git a/sys/fs/procfs/procfs.h b/sys/fs/procfs/procfs.h index 180a47f..d9b333b 100644 --- a/sys/fs/procfs/procfs.h +++ b/sys/fs/procfs/procfs.h @@ -37,7 +37,7 @@ * @(#)procfs.h 8.9 (Berkeley) 5/14/95 * * From: - * $Id: procfs.h,v 1.21 1999/01/05 03:53:06 peter Exp $ + * $Id: procfs.h,v 1.22 1999/04/27 11:16:35 phk Exp $ */ /* @@ -92,7 +92,8 @@ struct pfsnode { * Evaluates to 1 if access is allowed. */ #define CHECKIO(p1, p2) \ - ((((p1)->p_cred->pc_ucred->cr_uid == (p2)->p_cred->p_ruid) && \ + (PRISON_CHECK(p1, p2) && \ + (((p1)->p_cred->pc_ucred->cr_uid == (p2)->p_cred->p_ruid) && \ ((p1)->p_cred->p_ruid == (p2)->p_cred->p_ruid) && \ ((p1)->p_cred->p_svuid == (p2)->p_cred->p_ruid) && \ ((p2)->p_flag & P_SUGID) == 0) || (suser((p1)) == 0)) diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c index 3176a64..ba1abe4 100644 --- a/sys/fs/procfs/procfs_status.c +++ b/sys/fs/procfs/procfs_status.c @@ -37,12 +37,13 @@ * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94 * * From: - * $Id: procfs_status.c,v 1.11 1998/07/11 07:45:45 bde Exp $ + * $Id: procfs_status.c,v 1.12 1999/01/05 03:53:06 peter Exp $ */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/jail.h> #include <sys/vnode.h> #include <sys/tty.h> #include <sys/resourcevar.h> @@ -134,6 +135,11 @@ procfs_dostatus(curp, p, pfs, uio) for (i = 0; i < cr->cr_ngroups; i++) ps += sprintf(ps, ",%lu", (u_long)cr->cr_groups[i]); + + if (p->p_prison) + ps += sprintf(ps, " %s", p->p_prison->pr_host); + else + ps += sprintf(ps, " -"); ps += sprintf(ps, "\n"); xlen = ps - psbuf; diff --git a/sys/fs/procfs/procfs_vnops.c b/sys/fs/procfs/procfs_vnops.c index ffab3e8..4f0b8fe 100644 --- a/sys/fs/procfs/procfs_vnops.c +++ b/sys/fs/procfs/procfs_vnops.c @@ -36,7 +36,7 @@ * * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 * - * $Id: procfs_vnops.c,v 1.64 1999/01/27 22:42:07 dillon Exp $ + * $Id: procfs_vnops.c,v 1.65 1999/04/27 11:16:39 phk Exp $ */ /* @@ -134,6 +134,8 @@ procfs_open(ap) p2 = PFIND(pfs->pfs_pid); if (p2 == NULL) return (ENOENT); + if (!PRISON_CHECK(ap->a_p, p2)) + return (ENOENT); switch (pfs->pfs_type) { case Pmem: @@ -835,6 +837,8 @@ procfs_readdir(ap) p = PFIND(pfs->pfs_pid); if (p == NULL) break; + if (!PRISON_CHECK(curproc, p)) + break; for (pt = &proc_targets[i]; uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) { @@ -893,7 +897,14 @@ procfs_readdir(ap) default: while (pcnt < i) { + p = p->p_list.le_next; + if (!p) + goto done; + if (!PRISON_CHECK(curproc, p)) + continue; pcnt++; + } + while (!PRISON_CHECK(curproc, p)) { p = p->p_list.le_next; if (!p) goto done; diff --git a/sys/gnu/ext2fs/ext2_vnops.c b/sys/gnu/ext2fs/ext2_vnops.c index 9f6a965..c3b1263 100644 --- a/sys/gnu/ext2fs/ext2_vnops.c +++ b/sys/gnu/ext2fs/ext2_vnops.c @@ -1157,7 +1157,7 @@ ext2_makeinode(mode, dvp, vpp, cnp) tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ ip->i_nlink = 1; if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && - suser_xxx(cnp->cn_cred, NULL)) + suser_xxx(cnp->cn_cred, 0, PRISON_ROOT)) ip->i_mode &= ~ISGID; if (cnp->cn_flags & ISWHITEOUT) diff --git a/sys/gnu/fs/ext2fs/ext2_vnops.c b/sys/gnu/fs/ext2fs/ext2_vnops.c index 9f6a965..c3b1263 100644 --- a/sys/gnu/fs/ext2fs/ext2_vnops.c +++ b/sys/gnu/fs/ext2fs/ext2_vnops.c @@ -1157,7 +1157,7 @@ ext2_makeinode(mode, dvp, vpp, cnp) tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ ip->i_nlink = 1; if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && - suser_xxx(cnp->cn_cred, NULL)) + suser_xxx(cnp->cn_cred, 0, PRISON_ROOT)) ip->i_mode &= ~ISGID; if (cnp->cn_flags & ISWHITEOUT) diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index bf6ec7f..ed93f6f 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -39,7 +39,7 @@ * SUCH DAMAGE. * * @(#)init_main.c 8.9 (Berkeley) 1/21/94 - * $Id: init_main.c,v 1.113 1999/04/24 18:50:48 dt Exp $ + * $Id: init_main.c,v 1.114 1999/04/28 01:04:25 luoqi Exp $ */ #include "opt_devfs.h" @@ -409,6 +409,9 @@ proc0_init(dummy) p->p_ucred = crget(); p->p_ucred->cr_ngroups = 1; /* group 0 */ + /* Don't jail it */ + p->p_prison = 0; + /* Create procsig. */ p->p_procsig = &procsig0; p->p_procsig->ps_refcnt = 1; diff --git a/sys/kern/init_sysent.c b/sys/kern/init_sysent.c index 3a8b931..43b325d 100644 --- a/sys/kern/init_sysent.c +++ b/sys/kern/init_sysent.c @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * created from Id: syscalls.master,v 1.57 1999/04/04 21:41:16 dt Exp + * created from Id: syscalls.master,v 1.58 1999/04/28 11:28:49 phk Exp */ #include "opt_compat.h" @@ -357,4 +357,5 @@ struct sysent sysent[] = { { 2, (sy_call_t *)utrace }, /* 335 = utrace */ { 8, (sy_call_t *)sendfile }, /* 336 = sendfile */ { 3, (sy_call_t *)kldsym }, /* 337 = kldsym */ + { 1, (sy_call_t *)jail }, /* 338 = jail */ }; diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 0e97656..fd66be8 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_exit.c 8.7 (Berkeley) 2/12/94 - * $Id: kern_exit.c,v 1.78 1999/04/17 08:36:04 peter Exp $ + * $Id: kern_exit.c,v 1.79 1999/04/28 01:04:26 luoqi Exp $ */ #include "opt_compat.h" @@ -60,6 +60,7 @@ #include <sys/shm.h> #include <sys/sem.h> #include <sys/aio.h> +#include <sys/jail.h> #ifdef COMPAT_43 #include <machine/reg.h> @@ -508,6 +509,12 @@ loop: } /* + * Destroy empty prisons + */ + if (p->p_prison && !--p->p_prison->pr_ref) + FREE(p->p_prison, M_PRISON); + + /* * Finally finished with old proc entry. * Unlink it from its process group and free it. */ diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index d3f40ea..d5870b5 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_fork.c 8.6 (Berkeley) 4/8/94 - * $Id: kern_fork.c,v 1.59 1999/04/24 11:25:01 dt Exp $ + * $Id: kern_fork.c,v 1.60 1999/04/28 01:04:27 luoqi Exp $ */ #include "opt_ktrace.h" @@ -54,6 +54,7 @@ #include <sys/acct.h> #include <sys/ktrace.h> #include <sys/unistd.h> +#include <sys/jail.h> #include <vm/vm.h> #include <sys/lock.h> @@ -308,6 +309,11 @@ again: p2->p_cred->p_refcnt = 1; crhold(p1->p_ucred); + if (p2->p_prison) { + p2->p_prison->pr_ref++; + p2->p_flag |= P_JAILED; + } + if (flags & RFSIGSHARE) { p2->p_procsig = p1->p_procsig; p2->p_procsig->ps_refcnt++; diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c new file mode 100644 index 0000000..20cb8941 --- /dev/null +++ b/sys/kern/kern_jail.c @@ -0,0 +1,114 @@ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/errno.h> +#include <sys/sysproto.h> +#include <sys/malloc.h> +#include <sys/proc.h> +#include <sys/jail.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> + +MALLOC_DEFINE(M_PRISON, "prison", "Prison structures"); + +int +jail(p, uap) + struct proc *p; + struct jail_args /* { + syscallarg(struct jail *) jail; + } */ *uap; +{ + int error; + struct prison *pr; + struct jail j; + struct chroot_args ca; + + error = suser(p); + if (error) + return (error); + error = copyin(uap->jail, &j, sizeof j); + if (error) + return (error); + MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK); + bzero((caddr_t)pr, sizeof *pr); + error = copyinstr(j.hostname, &pr->pr_host, sizeof pr->pr_host, 0); + if (error) + goto bail; + pr->pr_ip = j.ip_number; + + ca.path = j.path; + error = chroot(p, &ca); + if (error) + goto bail; + + pr->pr_ref++; + p->p_prison = pr; + p->p_flag |= P_JAILED; + return (0); + +bail: + FREE(pr, M_PRISON); + return (error); +} + +int +prison_ip(struct proc *p, int flag, u_int32_t *ip) +{ + u_int32_t tmp; + + if (!p->p_prison) + return (0); + if (flag) + tmp = *ip; + else + tmp = ntohl(*ip); + if (tmp == INADDR_ANY) { + if (flag) + *ip = p->p_prison->pr_ip; + else + *ip = htonl(p->p_prison->pr_ip); + return (0); + } + if (p->p_prison->pr_ip != tmp) + return (1); + return (0); +} + +void +prison_remote_ip(struct proc *p, int flag, u_int32_t *ip) +{ + u_int32_t tmp; + + if (!p->p_prison) + return; + if (flag) + tmp = *ip; + else + tmp = ntohl(*ip); + if (tmp == 0x7f000001) { + if (flag) + *ip = p->p_prison->pr_ip; + else + *ip = htonl(p->p_prison->pr_ip); + return; + } + return; +} + +int +prison_if(struct proc *p, struct sockaddr *sa) +{ + struct sockaddr_in *sai = (struct sockaddr_in*) sa; + int ok; + + if (sai->sin_family != AF_INET) + ok = 0; + else if (p->p_prison->pr_ip != ntohl(sai->sin_addr.s_addr)) + ok = 1; + else + ok = 0; + return (ok); +} diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 7a6d237..86579cb 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)kern_ktrace.c 8.2 (Berkeley) 9/23/93 - * $Id: kern_ktrace.c,v 1.24 1998/11/10 09:16:29 peter Exp $ + * $Id: kern_ktrace.c,v 1.25 1998/12/10 01:47:41 rvb Exp $ */ #include "opt_ktrace.h" @@ -515,6 +515,8 @@ ktrcanset(callp, targetp) register struct pcred *caller = callp->p_cred; register struct pcred *target = targetp->p_cred; + if (!PRISON_CHECK(callp, targetp)) + return (0); if ((caller->pc_ucred->cr_uid == target->p_ruid && target->p_ruid == target->p_svuid && caller->p_rgid == target->p_rgid && /* XXX */ diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c index 9a8f65c..90afa9f 100644 --- a/sys/kern/kern_mib.c +++ b/sys/kern/kern_mib.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 - * $Id: kern_mib.c,v 1.17 1999/01/25 18:26:09 dillon Exp $ + * $Id: kern_mib.c,v 1.18 1999/01/26 07:37:11 dillon Exp $ */ #include <sys/param.h> @@ -45,6 +45,7 @@ #include <sys/systm.h> #include <sys/sysctl.h> #include <sys/proc.h> +#include <sys/jail.h> #include <sys/unistd.h> #if defined(SMP) @@ -73,6 +74,9 @@ SYSCTL_NODE(, CTL_USER, user, CTLFLAG_RW, 0, SYSCTL_NODE(, CTL_P1003_1B, p1003_1b, CTLFLAG_RW, 0, "p1003_1b, (see p1003_1b.h)"); +SYSCTL_NODE(_kern, OID_AUTO, prison, CTLFLAG_RW, 0, + "Prison rules"); + SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD, osrelease, 0, ""); SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD, 0, BSD, ""); @@ -124,8 +128,24 @@ SYSCTL_STRING(_hw, HW_MACHINE_ARCH, machine_arch, CTLFLAG_RD, char hostname[MAXHOSTNAMELEN]; -SYSCTL_STRING(_kern, KERN_HOSTNAME, hostname, CTLFLAG_RW, - hostname, sizeof(hostname), ""); +static int +sysctl_hostname SYSCTL_HANDLER_ARGS +{ + int error; + + if (req->p->p_prison) + error = sysctl_handle_string(oidp, + req->p->p_prison->pr_host, + sizeof req->p->p_prison->pr_host, req); + else + error = sysctl_handle_string(oidp, + hostname, sizeof hostname, req); + return (error); +} + +SYSCTL_PROC(_kern, KERN_HOSTNAME, hostname, + CTLTYPE_STRING|CTLFLAG_RW|CTLFLAG_PRISON, + 0, 0, sysctl_hostname, "A", ""); int securelevel = -1; diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index bfb7df9..3dfbfab 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)kern_proc.c 8.7 (Berkeley) 2/14/95 - * $Id: kern_proc.c,v 1.45 1999/01/28 00:57:47 dillon Exp $ + * $Id: kern_proc.c,v 1.46 1999/02/19 14:25:34 luoqi Exp $ */ #include <sys/param.h> @@ -500,6 +500,8 @@ sysctl_kern_proc SYSCTL_HANDLER_ARGS p = pfind((pid_t)name[0]); if (!p) return (0); + if (!PRISON_CHECK(curproc, p)) + return (0); error = sysctl_out_proc(p, req, 0); return (error); } @@ -561,6 +563,9 @@ sysctl_kern_proc SYSCTL_HANDLER_ARGS break; } + if (!PRISON_CHECK(curproc, p)) + continue; + error = sysctl_out_proc(p, req, doingzomb); if (error) return (error); diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c index 56606f4..e4ad6f5 100644 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 - * $Id: kern_prot.c,v 1.45 1999/04/27 11:16:01 phk Exp $ + * $Id: kern_prot.c,v 1.46 1999/04/27 12:21:06 phk Exp $ */ /* @@ -395,7 +395,7 @@ setuid(p, uap) #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ uid != pc->pc_ucred->cr_uid && /* allow setuid(geteuid()) */ #endif - (error = suser(p))) + (error = suser_xxx(0, p, PRISON_ROOT))) return (error); #ifdef _POSIX_SAVED_IDS @@ -407,7 +407,7 @@ setuid(p, uap) #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ uid == pc->pc_ucred->cr_uid || #endif - suser(p) == 0) /* we are using privs */ + suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ #endif { /* @@ -467,7 +467,7 @@ seteuid(p, uap) euid = uap->euid; if (euid != pc->p_ruid && /* allow seteuid(getuid()) */ euid != pc->p_svuid && /* allow seteuid(saved uid) */ - (error = suser(p))) + (error = suser_xxx(0, p, PRISON_ROOT))) return (error); /* * Everything's okay, do it. Copy credentials so other references do @@ -515,7 +515,7 @@ setgid(p, uap) #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ gid != pc->pc_ucred->cr_groups[0] && /* allow setgid(getegid()) */ #endif - (error = suser(p))) + (error = suser_xxx(0, p, PRISON_ROOT))) return (error); #ifdef _POSIX_SAVED_IDS @@ -527,7 +527,7 @@ setgid(p, uap) #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ gid == pc->pc_ucred->cr_groups[0] || #endif - suser(p) == 0) /* we are using privs */ + suser_xxx(0, p, PRISON_ROOT) == 0) /* we are using privs */ #endif { /* @@ -579,7 +579,7 @@ setegid(p, uap) egid = uap->egid; if (egid != pc->p_rgid && /* allow setegid(getgid()) */ egid != pc->p_svgid && /* allow setegid(saved gid) */ - (error = suser(p))) + (error = suser_xxx(0, p, PRISON_ROOT))) return (error); if (pc->pc_ucred->cr_groups[0] != egid) { pc->pc_ucred = crcopy(pc->pc_ucred); @@ -605,7 +605,7 @@ setgroups(p, uap) register u_int ngrp; int error; - if ((error = suser(p))) + if ((error = suser_xxx(0, p, PRISON_ROOT))) return (error); ngrp = uap->gidsetsize; if (ngrp > NGROUPS) @@ -654,7 +654,7 @@ setreuid(p, uap) if (((ruid != (uid_t)-1 && ruid != pc->p_ruid && ruid != pc->p_svuid) || (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid && euid != pc->p_ruid && euid != pc->p_svuid)) && - (error = suser(p)) != 0) + (error = suser_xxx(0, p, PRISON_ROOT)) != 0) return (error); if (euid != (uid_t)-1 && pc->pc_ucred->cr_uid != euid) { @@ -697,7 +697,7 @@ setregid(p, uap) if (((rgid != (gid_t)-1 && rgid != pc->p_rgid && rgid != pc->p_svgid) || (egid != (gid_t)-1 && egid != pc->pc_ucred->cr_groups[0] && egid != pc->p_rgid && egid != pc->p_svgid)) && - (error = suser(p)) != 0) + (error = suser_xxx(0, p, PRISON_ROOT)) != 0) return (error); if (egid != (gid_t)-1 && pc->pc_ucred->cr_groups[0] != egid) { @@ -769,20 +769,28 @@ int suser(p) struct proc *p; { - return suser_xxx(p->p_ucred, &p->p_acflag); + return suser_xxx(0, p, 0); } int -suser_xxx(cred, acflag) +suser_xxx(cred, proc, flag) struct ucred *cred; - u_short *acflag; + struct proc *proc; + int flag; { - if (cred->cr_uid == 0) { - if (acflag) - *acflag |= ASU; - return (0); + if (!cred && !proc) { + printf("suser_xxx(): THINK!\n"); + return (EPERM); } - return (EPERM); + if (!cred) + cred = proc->p_ucred; + if (cred->cr_uid != 0) + return (EPERM); + if (proc && proc->p_prison && !(flag & PRISON_ROOT)) + return (EPERM); + if (proc) + proc->p_acflag |= ASU; + return (0); } /* @@ -883,7 +891,7 @@ setlogin(p, uap) int error; char logintmp[MAXLOGNAME]; - if ((error = suser(p))) + if ((error = suser_xxx(0, p, PRISON_ROOT))) return (error); error = copyinstr((caddr_t) uap->namebuf, (caddr_t) logintmp, sizeof(logintmp), (size_t *)0); diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c index bd07411..811ccf4 100644 --- a/sys/kern/kern_resource.c +++ b/sys/kern/kern_resource.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_resource.c 8.5 (Berkeley) 1/21/94 - * $Id: kern_resource.c,v 1.46 1999/04/27 11:16:02 phk Exp $ + * $Id: kern_resource.c,v 1.47 1999/04/27 12:21:07 phk Exp $ */ #include "opt_compat.h" @@ -387,7 +387,7 @@ dosetrlimit(p, which, limp) if (limp->rlim_cur > alimp->rlim_max || limp->rlim_max > alimp->rlim_max) - if ((error = suser(p))) + if ((error = suser_xxx(0, p, PRISON_ROOT))) return (error); if (limp->rlim_cur > limp->rlim_max) limp->rlim_cur = limp->rlim_max; diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 5da4725..6749e76 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)kern_sig.c 8.7 (Berkeley) 4/18/94 - * $Id: kern_sig.c,v 1.53 1999/01/10 01:58:24 eivind Exp $ + * $Id: kern_sig.c,v 1.54 1999/01/26 02:38:10 julian Exp $ */ #include "opt_compat.h" @@ -79,12 +79,12 @@ SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW, &kern_logsigexit, 0, * Can process p, with pcred pc, send the signal signum to process q? */ #define CANSIGNAL(p, pc, q, signum) \ - ((pc)->pc_ucred->cr_uid == 0 || \ + (PRISON_CHECK(p, q) && ((pc)->pc_ucred->cr_uid == 0 || \ (pc)->p_ruid == (q)->p_cred->p_ruid || \ (pc)->pc_ucred->cr_uid == (q)->p_cred->p_ruid || \ (pc)->p_ruid == (q)->p_ucred->cr_uid || \ (pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \ - ((signum) == SIGCONT && (q)->p_session == (p)->p_session)) + ((signum) == SIGCONT && (q)->p_session == (p)->p_session))) /* * Policy -- Can real uid ruid with ucred uc send a signal to process q? diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index fc0a204..15f5359 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 - * $Id: kern_sysctl.c,v 1.86 1999/03/30 09:00:45 phk Exp $ + * $Id: kern_sysctl.c,v 1.87 1999/04/27 11:16:05 phk Exp $ */ #include "opt_compat.h" @@ -764,7 +764,8 @@ found: /* Most likely only root can write */ if (!(oid->oid_kind & CTLFLAG_ANYBODY) && req->newptr && req->p && - (i = suser(req->p))) + (i = suser_xxx(0, req->p, + (oid->oid_kind & CTLFLAG_PRISON) ? PRISON_ROOT : 0))) return (i); if (!oid->oid_handler) diff --git a/sys/kern/kern_xxx.c b/sys/kern/kern_xxx.c index 42b563f..92b26ce 100644 --- a/sys/kern/kern_xxx.c +++ b/sys/kern/kern_xxx.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)kern_xxx.c 8.2 (Berkeley) 11/14/93 - * $Id: kern_xxx.c,v 1.28 1998/08/24 08:39:38 dfr Exp $ + * $Id: kern_xxx.c,v 1.29 1999/04/27 11:16:09 phk Exp $ */ #include "opt_compat.h" @@ -85,7 +85,7 @@ osethostname(p, uap) name[0] = CTL_KERN; name[1] = KERN_HOSTNAME; - if ((error = suser(p))) + if ((error = suser_xxx(0, p, PRISON_ROOT))) return (error); return (userland_sysctl(p, name, 2, 0, 0, 0, uap->hostname, uap->len, 0)); diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index 62e6736..6ed8ef1 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: sys_process.c,v 1.43 1999/03/29 08:29:22 dfr Exp $ + * $Id: sys_process.c,v 1.44 1999/04/27 11:16:13 phk Exp $ */ #include <sys/param.h> @@ -218,6 +218,8 @@ ptrace(curp, uap) if ((p = pfind(uap->pid)) == NULL) return ESRCH; } + if (!PRISON_CHECK(curp, p)) + return (ESRCH); /* * Permissions check diff --git a/sys/kern/syscalls.c b/sys/kern/syscalls.c index bd49409..1359833 100644 --- a/sys/kern/syscalls.c +++ b/sys/kern/syscalls.c @@ -2,7 +2,7 @@ * System call names. * * DO NOT EDIT-- this file is automatically generated. - * created from Id: syscalls.master,v 1.57 1999/04/04 21:41:16 dt Exp + * created from Id: syscalls.master,v 1.58 1999/04/28 11:28:49 phk Exp */ char *syscallnames[] = { @@ -344,4 +344,5 @@ char *syscallnames[] = { "utrace", /* 335 = utrace */ "sendfile", /* 336 = sendfile */ "kldsym", /* 337 = kldsym */ + "jail", /* 338 = jail */ }; diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index 292ce70..52823be 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * From: @(#)uipc_usrreq.c 8.3 (Berkeley) 1/4/94 - * $Id: uipc_usrreq.c,v 1.41 1999/04/11 02:17:47 eivind Exp $ + * $Id: uipc_usrreq.c,v 1.42 1999/04/12 14:34:52 eivind Exp $ */ #include <sys/param.h> @@ -490,6 +490,7 @@ unp_attach(so) unp_count++; LIST_INIT(&unp->unp_refs); unp->unp_socket = so; + unp->unp_rvnode = curproc->p_fd->fd_rdir; LIST_INSERT_HEAD(so->so_type == SOCK_DGRAM ? &unp_dhead : &unp_shead, unp, unp_link); so->so_pcb = (caddr_t)unp; @@ -710,6 +711,16 @@ unp_abort(unp) #endif static int +prison_unpcb(struct proc *p, struct unpcb *unp) +{ + if (!p->p_prison) + return (0); + if (p->p_fd->fd_rdir == unp->unp_rvnode) + return (0); + return (1); +} + +static int unp_pcblist SYSCTL_HANDLER_ARGS { int error, i, n; @@ -754,7 +765,7 @@ unp_pcblist SYSCTL_HANDLER_ARGS for (unp = head->lh_first, i = 0; unp && i < n; unp = unp->unp_link.le_next) { - if (unp->unp_gencnt <= gencnt) + if (unp->unp_gencnt <= gencnt && !prison_unpcb(req->p, unp)) unp_list[i++] = unp; } n = i; /* in case we lost some during malloc */ diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 43c0bcc..dd464d7 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 - * $Id: vfs_syscalls.c,v 1.121 1999/03/23 14:26:40 phk Exp $ + * $Id: vfs_syscalls.c,v 1.122 1999/04/27 11:16:25 phk Exp $ */ /* For 4.3 integer FS ID compatibility */ @@ -132,7 +132,7 @@ mount(p, uap) /* * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users */ - if (suser_xxx(p->p_ucred, (u_short *)NULL)) + if (suser_xxx(p->p_ucred, 0, 0)) SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; /* * Get vnode to be covered @@ -562,6 +562,12 @@ sync(p, uap) return (0); } +/* XXX PRISON: could be per prison flag */ +static int prison_quotas; +#if 0 +SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); +#endif + /* * Change filesystem quotas. */ @@ -588,6 +594,8 @@ quotactl(p, uap) int error; struct nameidata nd; + if (p->p_prison && !prison_quotas) + return (EPERM); NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); @@ -631,7 +639,7 @@ statfs(p, uap) if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser_xxx(p->p_ucred, (u_short *)NULL)) { + if (suser_xxx(p->p_ucred, 0, 0)) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; sp = &sb; @@ -671,7 +679,7 @@ fstatfs(p, uap) if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser_xxx(p->p_ucred, (u_short *)NULL)) { + if (suser_xxx(p->p_ucred, 0, 0)) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; sp = &sb; @@ -886,7 +894,7 @@ chroot(p, uap) int error; struct nameidata nd; - error = suser(p); + error = suser_xxx(0, p, PRISON_ROOT); if (error) return (error); if (chroot_allow_open_directories == 0 || @@ -1076,7 +1084,15 @@ mknod(p, uap) int whiteout = 0; struct nameidata nd; - error = suser(p); + switch (SCARG(uap, mode) & S_IFMT) { + case S_IFCHR: + case S_IFBLK: + error = suser(p); + break; + default: + error = suser_xxx(0, p, PRISON_ROOT); + break; + } if (error) return (error); NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); @@ -2977,7 +2993,7 @@ revoke(p, uap) if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) goto out; if (p->p_ucred->cr_uid != vattr.va_uid && - (error = suser(p))) + (error = suser_xxx(0, p, PRISON_ROOT))) goto out; if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) VOP_REVOKE(vp, REVOKEALL); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 43c0bcc..dd464d7 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 - * $Id: vfs_syscalls.c,v 1.121 1999/03/23 14:26:40 phk Exp $ + * $Id: vfs_syscalls.c,v 1.122 1999/04/27 11:16:25 phk Exp $ */ /* For 4.3 integer FS ID compatibility */ @@ -132,7 +132,7 @@ mount(p, uap) /* * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users */ - if (suser_xxx(p->p_ucred, (u_short *)NULL)) + if (suser_xxx(p->p_ucred, 0, 0)) SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; /* * Get vnode to be covered @@ -562,6 +562,12 @@ sync(p, uap) return (0); } +/* XXX PRISON: could be per prison flag */ +static int prison_quotas; +#if 0 +SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); +#endif + /* * Change filesystem quotas. */ @@ -588,6 +594,8 @@ quotactl(p, uap) int error; struct nameidata nd; + if (p->p_prison && !prison_quotas) + return (EPERM); NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); if ((error = namei(&nd)) != 0) return (error); @@ -631,7 +639,7 @@ statfs(p, uap) if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser_xxx(p->p_ucred, (u_short *)NULL)) { + if (suser_xxx(p->p_ucred, 0, 0)) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; sp = &sb; @@ -671,7 +679,7 @@ fstatfs(p, uap) if (error) return (error); sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; - if (suser_xxx(p->p_ucred, (u_short *)NULL)) { + if (suser_xxx(p->p_ucred, 0, 0)) { bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; sp = &sb; @@ -886,7 +894,7 @@ chroot(p, uap) int error; struct nameidata nd; - error = suser(p); + error = suser_xxx(0, p, PRISON_ROOT); if (error) return (error); if (chroot_allow_open_directories == 0 || @@ -1076,7 +1084,15 @@ mknod(p, uap) int whiteout = 0; struct nameidata nd; - error = suser(p); + switch (SCARG(uap, mode) & S_IFMT) { + case S_IFCHR: + case S_IFBLK: + error = suser(p); + break; + default: + error = suser_xxx(0, p, PRISON_ROOT); + break; + } if (error) return (error); NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); @@ -2977,7 +2993,7 @@ revoke(p, uap) if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) goto out; if (p->p_ucred->cr_uid != vattr.va_uid && - (error = suser(p))) + (error = suser_xxx(0, p, PRISON_ROOT))) goto out; if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) VOP_REVOKE(vp, REVOKEALL); diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index 802c437..0300ba5 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)vfs_vnops.c 8.2 (Berkeley) 1/21/94 - * $Id: vfs_vnops.c,v 1.66 1999/04/21 05:56:45 alc Exp $ + * $Id: vfs_vnops.c,v 1.67 1999/04/27 11:16:27 phk Exp $ */ #include <sys/param.h> @@ -422,7 +422,7 @@ vn_stat(vp, sb, p) sb->st_ctimespec = vap->va_ctime; sb->st_blksize = vap->va_blocksize; sb->st_flags = vap->va_flags; - if (suser_xxx(p->p_ucred, (u_short *)NULL)) + if (suser_xxx(p->p_ucred, 0, 0)) sb->st_gen = 0; else sb->st_gen = vap->va_gen; diff --git a/sys/miscfs/devfs/devfs_vnops.c b/sys/miscfs/devfs/devfs_vnops.c index 64387e6..b924ef5 100644 --- a/sys/miscfs/devfs/devfs_vnops.c +++ b/sys/miscfs/devfs/devfs_vnops.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: devfs_vnops.c,v 1.70 1999/02/25 16:06:51 bde Exp $ + * $Id: devfs_vnops.c,v 1.71 1999/04/27 11:16:31 phk Exp $ */ @@ -381,7 +381,7 @@ found: * but only use suser_xxx prives as a last resort * (Use of super powers is recorded in ap->a_p->p_acflag) */ - if( suser_xxx(cred, &ap->a_p->p_acflag) == 0) /* XXX what if no proc? */ + if( suser_xxx(cred, ap->a_p, 0) == 0) /* XXX what if no proc? */ return 0; return (EACCES); } @@ -519,7 +519,7 @@ DBPRINT(("setattr\n")); #endif if (((vap->va_vaflags & VA_UTIMES_NULL) == 0) && (cred->cr_uid != file_node->uid) && - suser_xxx(cred, &p->p_acflag)) + suser_xxx(cred, p, 0)) return (EPERM); if(VOP_ACCESS(vp, VWRITE, cred, p)) return (EACCES); @@ -534,7 +534,7 @@ DBPRINT(("setattr\n")); */ if (vap->va_mode != (u_short)VNOVAL) { if ((cred->cr_uid != file_node->uid) - && suser_xxx(cred, &p->p_acflag)) + && suser_xxx(cred, p, 0)) return (EPERM); /* set drwxwxrwx stuff */ file_node->mode &= ~07777; @@ -545,7 +545,7 @@ DBPRINT(("setattr\n")); * Change the owner.. must be root to do this. */ if (vap->va_uid != (uid_t)VNOVAL) { - if (suser_xxx(cred, &p->p_acflag)) + if (suser_xxx(cred, p, 0)) return (EPERM); file_node->uid = vap->va_uid; } @@ -568,7 +568,7 @@ DBPRINT(("setattr\n")); * we can't do it with normal privs, * do we have an ace up our sleeve? */ - if( suser_xxx(cred, &p->p_acflag)) + if( suser_xxx(cred, p, 0)) return (EPERM); cando: file_node->gid = vap->va_gid; @@ -580,7 +580,7 @@ cando: * flags should be handled some day */ if (vap->va_flags != VNOVAL) { - if (error = suser_xxx(cred, &p->p_acflag)) + if (error = suser_xxx(cred, p, 0)) return error; if (cred->cr_uid == 0) ; diff --git a/sys/miscfs/procfs/procfs.h b/sys/miscfs/procfs/procfs.h index 180a47f..d9b333b 100644 --- a/sys/miscfs/procfs/procfs.h +++ b/sys/miscfs/procfs/procfs.h @@ -37,7 +37,7 @@ * @(#)procfs.h 8.9 (Berkeley) 5/14/95 * * From: - * $Id: procfs.h,v 1.21 1999/01/05 03:53:06 peter Exp $ + * $Id: procfs.h,v 1.22 1999/04/27 11:16:35 phk Exp $ */ /* @@ -92,7 +92,8 @@ struct pfsnode { * Evaluates to 1 if access is allowed. */ #define CHECKIO(p1, p2) \ - ((((p1)->p_cred->pc_ucred->cr_uid == (p2)->p_cred->p_ruid) && \ + (PRISON_CHECK(p1, p2) && \ + (((p1)->p_cred->pc_ucred->cr_uid == (p2)->p_cred->p_ruid) && \ ((p1)->p_cred->p_ruid == (p2)->p_cred->p_ruid) && \ ((p1)->p_cred->p_svuid == (p2)->p_cred->p_ruid) && \ ((p2)->p_flag & P_SUGID) == 0) || (suser((p1)) == 0)) diff --git a/sys/miscfs/procfs/procfs_status.c b/sys/miscfs/procfs/procfs_status.c index 3176a64..ba1abe4 100644 --- a/sys/miscfs/procfs/procfs_status.c +++ b/sys/miscfs/procfs/procfs_status.c @@ -37,12 +37,13 @@ * @(#)procfs_status.c 8.4 (Berkeley) 6/15/94 * * From: - * $Id: procfs_status.c,v 1.11 1998/07/11 07:45:45 bde Exp $ + * $Id: procfs_status.c,v 1.12 1999/01/05 03:53:06 peter Exp $ */ #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/jail.h> #include <sys/vnode.h> #include <sys/tty.h> #include <sys/resourcevar.h> @@ -134,6 +135,11 @@ procfs_dostatus(curp, p, pfs, uio) for (i = 0; i < cr->cr_ngroups; i++) ps += sprintf(ps, ",%lu", (u_long)cr->cr_groups[i]); + + if (p->p_prison) + ps += sprintf(ps, " %s", p->p_prison->pr_host); + else + ps += sprintf(ps, " -"); ps += sprintf(ps, "\n"); xlen = ps - psbuf; diff --git a/sys/miscfs/procfs/procfs_vnops.c b/sys/miscfs/procfs/procfs_vnops.c index ffab3e8..4f0b8fe 100644 --- a/sys/miscfs/procfs/procfs_vnops.c +++ b/sys/miscfs/procfs/procfs_vnops.c @@ -36,7 +36,7 @@ * * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 * - * $Id: procfs_vnops.c,v 1.64 1999/01/27 22:42:07 dillon Exp $ + * $Id: procfs_vnops.c,v 1.65 1999/04/27 11:16:39 phk Exp $ */ /* @@ -134,6 +134,8 @@ procfs_open(ap) p2 = PFIND(pfs->pfs_pid); if (p2 == NULL) return (ENOENT); + if (!PRISON_CHECK(ap->a_p, p2)) + return (ENOENT); switch (pfs->pfs_type) { case Pmem: @@ -835,6 +837,8 @@ procfs_readdir(ap) p = PFIND(pfs->pfs_pid); if (p == NULL) break; + if (!PRISON_CHECK(curproc, p)) + break; for (pt = &proc_targets[i]; uio->uio_resid >= UIO_MX && i < nproc_targets; pt++, i++) { @@ -893,7 +897,14 @@ procfs_readdir(ap) default: while (pcnt < i) { + p = p->p_list.le_next; + if (!p) + goto done; + if (!PRISON_CHECK(curproc, p)) + continue; pcnt++; + } + while (!PRISON_CHECK(curproc, p)) { p = p->p_list.le_next; if (!p) goto done; diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c index 00f576b..108aab0 100644 --- a/sys/msdosfs/msdosfs_vnops.c +++ b/sys/msdosfs/msdosfs_vnops.c @@ -1,4 +1,4 @@ -/* $Id: msdosfs_vnops.c,v 1.81 1999/01/27 22:42:09 dillon Exp $ */ +/* $Id: msdosfs_vnops.c,v 1.82 1999/04/27 11:16:51 phk Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.68 1998/02/10 14:10:04 mrg Exp $ */ /*- @@ -431,7 +431,7 @@ msdosfs_setattr(ap) if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != pmp->pm_uid && - (error = suser_xxx(cred, &ap->a_p->p_acflag))) + (error = suser_xxx(cred, ap->a_p, PRISON_ROOT))) return (error); /* * We are very inconsistent about handling unsupported @@ -472,7 +472,7 @@ msdosfs_setattr(ap) gid = pmp->pm_gid; if ((cred->cr_uid != pmp->pm_uid || uid != pmp->pm_uid || (gid != pmp->pm_gid && !groupmember(gid, cred))) && - (error = suser_xxx(cred, &ap->a_p->p_acflag))) + (error = suser_xxx(cred, ap->a_p, PRISON_ROOT))) return error; if (uid != pmp->pm_uid || gid != pmp->pm_gid) return EINVAL; @@ -504,7 +504,7 @@ msdosfs_setattr(ap) if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != pmp->pm_uid && - (error = suser_xxx(cred, &ap->a_p->p_acflag)) && + (error = suser_xxx(cred, ap->a_p, PRISON_ROOT)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || (error = VOP_ACCESS(ap->a_vp, VWRITE, cred, ap->a_p)))) return (error); @@ -527,7 +527,7 @@ msdosfs_setattr(ap) if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != pmp->pm_uid && - (error = suser_xxx(cred, &ap->a_p->p_acflag))) + (error = suser_xxx(cred, ap->a_p, PRISON_ROOT))) return (error); if (vp->v_type != VDIR) { /* We ignore the read and execute bits. */ diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 0c37a7a..5b6dd2f 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -37,7 +37,7 @@ * * @(#)bpf.c 8.2 (Berkeley) 3/28/94 * - * $Id: bpf.c,v 1.47 1999/01/27 22:42:13 dillon Exp $ + * $Id: bpf.c,v 1.48 1999/04/28 01:18:13 msmith Exp $ */ #include "bpfilter.h" @@ -346,6 +346,9 @@ bpfopen(dev, flags, fmt, p) { register struct bpf_d *d; + if (p->p_prison) + return (EPERM); + if (minor(dev) >= NBPFILTER) return (ENXIO); /* @@ -1014,12 +1017,12 @@ bpfpoll(dev, events, p) d = &bpf_dtab[minor(dev)]; s = splimp(); - if (events & (POLLIN | POLLRDNORM)) + if (events & (POLLIN | POLLRDNORM)) { if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0)) revents |= events & (POLLIN | POLLRDNORM); else selrecord(p, &d->bd_sel); - + } splx(s); return (revents); } diff --git a/sys/net/if.c b/sys/net/if.c index bb36fa4..e91445e 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)if.c 8.3 (Berkeley) 1/4/94 - * $Id: if.c,v 1.68 1999/04/26 09:02:40 peter Exp $ + * $Id: if.c,v 1.69 1999/04/27 11:16:56 phk Exp $ */ #include "opt_compat.h" @@ -857,7 +857,7 @@ ifconf(cmd, data) ifrp = ifc->ifc_req; for (; space > sizeof (ifr) && ifp; ifp = ifp->if_link.tqe_next) { char workbuf[64]; - int ifnlen; + int ifnlen, addrs; ifnlen = snprintf(workbuf, sizeof(workbuf), "%s%d", ifp->if_name, ifp->if_unit); @@ -867,17 +867,14 @@ ifconf(cmd, data) strcpy(ifr.ifr_name, workbuf); } - if ((ifa = ifp->if_addrhead.tqh_first) == 0) { - bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); - error = copyout((caddr_t)&ifr, (caddr_t)ifrp, - sizeof (ifr)); - if (error) - break; - space -= sizeof (ifr), ifrp++; - } else - for ( ; space > sizeof (ifr) && ifa; - ifa = ifa->ifa_link.tqe_next) { + addrs = 0; + ifa = ifp->if_addrhead.tqh_first; + for ( ; space > sizeof (ifr) && ifa; + ifa = ifa->ifa_link.tqe_next) { register struct sockaddr *sa = ifa->ifa_addr; + if (curproc->p_prison && prison_if(curproc, sa)) + continue; + addrs++; #ifdef COMPAT_43 if (cmd == OSIOCGIFCONF) { struct osockaddr *osa = @@ -910,6 +907,14 @@ ifconf(cmd, data) break; space -= sizeof (ifr); } + if (!addrs) { + bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr)); + error = copyout((caddr_t)&ifr, (caddr_t)ifrp, + sizeof (ifr)); + if (error) + break; + space -= sizeof (ifr), ifrp++; + } } ifc->ifc_len -= space; return (error); diff --git a/sys/net/if.h b/sys/net/if.h index e4f0046..4ca0661 100644 --- a/sys/net/if.h +++ b/sys/net/if.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)if.h 8.1 (Berkeley) 6/10/93 - * $Id: if.h,v 1.49 1998/03/21 13:36:20 peter Exp $ + * $Id: if.h,v 1.50 1999/02/19 13:41:35 phk Exp $ */ #ifndef _NET_IF_H_ @@ -221,6 +221,7 @@ MALLOC_DECLARE(M_IFMADDR); /* XXX - this should go away soon */ #ifdef KERNEL +int prison_if __P((struct proc *p, struct sockaddr *sa)); #include <net/if_var.h> #endif diff --git a/sys/net/rtsock.c b/sys/net/rtsock.c index bf5da6e..a57b518 100644 --- a/sys/net/rtsock.c +++ b/sys/net/rtsock.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)rtsock.c 8.5 (Berkeley) 11/2/94 - * $Id: rtsock.c,v 1.37 1997/10/31 08:53:13 davidg Exp $ + * $Id: rtsock.c,v 1.38 1999/01/27 22:42:14 dillon Exp $ */ @@ -911,6 +911,8 @@ sysctl_iflist(af, w) while ((ifa = ifa->ifa_link.tqe_next) != 0) { if (af && af != ifa->ifa_addr->sa_family) continue; + if (curproc->p_prison && prison_if(curproc, ifa->ifa_addr)) + continue; ifaaddr = ifa->ifa_addr; netmask = ifa->ifa_netmask; brdaddr = ifa->ifa_dstaddr; diff --git a/sys/netinet/in.h b/sys/netinet/in.h index 1542e24..0fe16f4 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)in.h 8.3 (Berkeley) 1/3/94 - * $Id: in.h,v 1.38 1998/12/14 18:09:13 luigi Exp $ + * $Id: in.h,v 1.39 1999/04/20 13:32:04 peter Exp $ */ #ifndef _NETINET_IN_H_ @@ -433,6 +433,9 @@ int in_cksum __P((struct mbuf *, int)); int in_localaddr __P((struct in_addr)); char *inet_ntoa __P((struct in_addr)); /* 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 /* KERNEL */ #endif diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index 7788c9b..2f13bf1 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95 - * $Id: in_pcb.c,v 1.47 1999/01/27 22:42:24 dillon Exp $ + * $Id: in_pcb.c,v 1.48 1999/04/27 11:17:31 phk Exp $ */ #include <sys/param.h> @@ -42,6 +42,7 @@ #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/proc.h> +#include <sys/jail.h> #include <sys/kernel.h> #include <sys/sysctl.h> @@ -154,7 +155,7 @@ in_pcbbind(inp, nam, p) struct inpcbinfo *pcbinfo = inp->inp_pcbinfo; u_short lport = 0; int wild = 0, reuseport = (so->so_options & SO_REUSEPORT); - int error; + int error, prison = 0; if (TAILQ_EMPTY(&in_ifaddrhead)) /* XXX broken! */ return (EADDRNOTAVAIL); @@ -174,6 +175,8 @@ in_pcbbind(inp, nam, p) if (sin->sin_family != AF_INET) return (EAFNOSUPPORT); #endif + if (prison_ip(p, 0, &sin->sin_addr.s_addr)) + return(EINVAL); lport = sin->sin_port; if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { /* @@ -195,12 +198,15 @@ in_pcbbind(inp, nam, p) /* GROSS */ if (ntohs(lport) < IPPORT_RESERVED && p && - suser(p)) + suser_xxx(0, p, PRISON_ROOT)) return (EACCES); + if (p && p->p_prison) + prison = 1; if (so->so_uid && !IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) { t = in_pcblookup_local(inp->inp_pcbinfo, - sin->sin_addr, lport, INPLOOKUP_WILDCARD); + sin->sin_addr, lport, + prison ? 0 : INPLOOKUP_WILDCARD); if (t && (ntohl(sin->sin_addr.s_addr) != INADDR_ANY || ntohl(t->inp_laddr.s_addr) != INADDR_ANY || @@ -210,7 +216,7 @@ in_pcbbind(inp, nam, p) return (EADDRINUSE); } t = in_pcblookup_local(pcbinfo, sin->sin_addr, - lport, wild); + lport, prison ? 0 : wild); if (t && (reuseport & t->inp_socket->so_options) == 0) return (EADDRINUSE); } @@ -220,6 +226,8 @@ in_pcbbind(inp, nam, p) ushort first, last; int count; + if (prison_ip(p, 0, &inp->inp_laddr.s_addr )) + return (EINVAL); inp->inp_flags |= INP_ANONPORT; if (inp->inp_flags & INP_HIGHPORT) { @@ -227,7 +235,7 @@ in_pcbbind(inp, nam, p) last = ipport_hilastauto; lastport = &pcbinfo->lasthi; } else if (inp->inp_flags & INP_LOWPORT) { - if (p && (error = suser(p))) + if (p && (error = suser_xxx(0, p, PRISON_ROOT))) return error; first = ipport_lowfirstauto; /* 1023 */ last = ipport_lowlastauto; /* 600 */ @@ -895,3 +903,13 @@ in_pcbremlists(inp) LIST_REMOVE(inp, inp_list); inp->inp_pcbinfo->ipi_count--; } + +int +prison_xinpcb(struct proc *p, struct inpcb *inp) +{ + if (!p->p_prison) + return (0); + if (ntohl(inp->inp_laddr.s_addr) == p->p_prison->pr_ip) + return (0); + return (1); +} diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index aa2d0be..33d8d7a 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)in_pcb.h 8.1 (Berkeley) 6/10/93 - * $Id: in_pcb.h,v 1.25 1998/03/28 10:18:22 bde Exp $ + * $Id: in_pcb.h,v 1.26 1998/05/15 20:11:33 wollman Exp $ */ #ifndef _NETINET_IN_PCB_H_ @@ -168,6 +168,7 @@ void in_pcbnotify __P((struct inpcbhead *, struct sockaddr *, void in_pcbrehash __P((struct inpcb *)); int in_setpeeraddr __P((struct socket *so, struct sockaddr **nam)); int in_setsockaddr __P((struct socket *so, struct sockaddr **nam)); +int prison_xinpcb __P((struct proc *p, struct inpcb *inp)); #endif /* KERNEL */ #endif /* !_NETINET_IN_PCB_H_ */ diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c index b9355da..ed0acd4 100644 --- a/sys/netinet/tcp_subr.c +++ b/sys/netinet/tcp_subr.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95 - * $Id: tcp_subr.c,v 1.51 1999/02/04 03:02:56 msmith Exp $ + * $Id: tcp_subr.c,v 1.52 1999/02/04 03:27:43 msmith Exp $ */ #include "opt_compat.h" @@ -541,7 +541,7 @@ tcp_pcblist SYSCTL_HANDLER_ARGS s = splnet(); for (inp = tcbinfo.listhead->lh_first, i = 0; inp && i < n; inp = inp->inp_list.le_next) { - if (inp->inp_gencnt <= gencnt) + if (inp->inp_gencnt <= gencnt && !prison_xinpcb(req->p, inp)) inp_list[i++] = inp; } splx(s); diff --git a/sys/netinet/tcp_timewait.c b/sys/netinet/tcp_timewait.c index b9355da..ed0acd4 100644 --- a/sys/netinet/tcp_timewait.c +++ b/sys/netinet/tcp_timewait.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)tcp_subr.c 8.2 (Berkeley) 5/24/95 - * $Id: tcp_subr.c,v 1.51 1999/02/04 03:02:56 msmith Exp $ + * $Id: tcp_subr.c,v 1.52 1999/02/04 03:27:43 msmith Exp $ */ #include "opt_compat.h" @@ -541,7 +541,7 @@ tcp_pcblist SYSCTL_HANDLER_ARGS s = splnet(); for (inp = tcbinfo.listhead->lh_first, i = 0; inp && i < n; inp = inp->inp_list.le_next) { - if (inp->inp_gencnt <= gencnt) + if (inp->inp_gencnt <= gencnt && !prison_xinpcb(req->p, inp)) inp_list[i++] = inp; } splx(s); diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 5d231c9..02a281f 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94 - * $Id: tcp_usrreq.c,v 1.40 1999/01/20 17:31:59 fenner Exp $ + * $Id: tcp_usrreq.c,v 1.41 1999/04/24 18:25:35 ache Exp $ */ #include "opt_tcpdebug.h" @@ -239,6 +239,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 ((error = tcp_connect(tp, nam, p)) != 0) goto out; error = tcp_output(tp); diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index 3462c70..7fc09d2c 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)udp_usrreq.c 8.6 (Berkeley) 5/23/95 - * $Id: udp_usrreq.c,v 1.48 1998/08/24 07:47:39 dfr Exp $ + * $Id: udp_usrreq.c,v 1.49 1998/12/03 20:23:21 dillon Exp $ */ #include <sys/param.h> @@ -410,7 +410,7 @@ udp_pcblist SYSCTL_HANDLER_ARGS s = splnet(); for (inp = udbinfo.listhead->lh_first, i = 0; inp && i < n; inp = inp->inp_list.le_next) { - if (inp->inp_gencnt <= gencnt) + if (inp->inp_gencnt <= gencnt && !prison_xinpcb(req->p, inp)) inp_list[i++] = inp; } splx(s); @@ -462,6 +462,7 @@ udp_output(inp, m, addr, control, p) register struct udpiphdr *ui; register int len = m->m_pkthdr.len; struct in_addr laddr; + struct sockaddr_in *sin; int s = 0, error = 0; if (control) @@ -473,6 +474,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); laddr = inp->inp_laddr; if (inp->inp_faddr.s_addr != INADDR_ANY) { error = EISCONN; @@ -614,6 +617,7 @@ udp_connect(struct socket *so, struct sockaddr *nam, struct proc *p) { struct inpcb *inp; int s, error; + struct sockaddr_in *sin; inp = sotoinpcb(so); if (inp == 0) @@ -621,6 +625,8 @@ udp_connect(struct socket *so, struct sockaddr *nam, struct proc *p) if (inp->inp_faddr.s_addr != INADDR_ANY) return EISCONN; s = splnet(); + sin = (struct sockaddr_in *)nam; + prison_remote_ip(p, 0, &sin->sin_addr.s_addr); error = in_pcbconnect(inp, nam, p); splx(s); if (error == 0) diff --git a/sys/nfs/nfs_serv.c b/sys/nfs/nfs_serv.c index d60f265..63e8e39 100644 --- a/sys/nfs/nfs_serv.c +++ b/sys/nfs/nfs_serv.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95 - * $Id: nfs_serv.c,v 1.73 1999/02/16 10:49:53 dfr Exp $ + * $Id: nfs_serv.c,v 1.74 1999/04/27 11:17:49 phk Exp $ */ /* @@ -1445,7 +1445,7 @@ nfsrv_create(nfsd, slp, procp, mrq) if (vap->va_type == VCHR && rdev == 0xffffffff) vap->va_type = VFIFO; if (vap->va_type != VFIFO && - (error = suser_xxx(cred, (u_short *)0))) { + (error = suser_xxx(cred, 0, 0))) { vrele(nd.ni_startdir); zfree(namei_zone, nd.ni_cnd.cn_pnbuf); VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); @@ -1642,7 +1642,7 @@ nfsrv_mknod(nfsd, slp, procp, mrq) if (!error) zfree(namei_zone, nd.ni_cnd.cn_pnbuf); } else { - if (vtyp != VFIFO && (error = suser_xxx(cred, (u_short *)0))) { + if (vtyp != VFIFO && (error = suser_xxx(cred, 0, 0))) { vrele(nd.ni_startdir); zfree(namei_zone, nd.ni_cnd.cn_pnbuf); VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c index d60f265..63e8e39 100644 --- a/sys/nfsserver/nfs_serv.c +++ b/sys/nfsserver/nfs_serv.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95 - * $Id: nfs_serv.c,v 1.73 1999/02/16 10:49:53 dfr Exp $ + * $Id: nfs_serv.c,v 1.74 1999/04/27 11:17:49 phk Exp $ */ /* @@ -1445,7 +1445,7 @@ nfsrv_create(nfsd, slp, procp, mrq) if (vap->va_type == VCHR && rdev == 0xffffffff) vap->va_type = VFIFO; if (vap->va_type != VFIFO && - (error = suser_xxx(cred, (u_short *)0))) { + (error = suser_xxx(cred, 0, 0))) { vrele(nd.ni_startdir); zfree(namei_zone, nd.ni_cnd.cn_pnbuf); VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); @@ -1642,7 +1642,7 @@ nfsrv_mknod(nfsd, slp, procp, mrq) if (!error) zfree(namei_zone, nd.ni_cnd.cn_pnbuf); } else { - if (vtyp != VFIFO && (error = suser_xxx(cred, (u_short *)0))) { + if (vtyp != VFIFO && (error = suser_xxx(cred, 0, 0))) { vrele(nd.ni_startdir); zfree(namei_zone, nd.ni_cnd.cn_pnbuf); VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); diff --git a/sys/sys/jail.h b/sys/sys/jail.h new file mode 100644 index 0000000..aea9bf5 --- /dev/null +++ b/sys/sys/jail.h @@ -0,0 +1,41 @@ +/* + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + * + * $Id: loran.c,v 1.15 1999/04/11 03:06:06 eivind Exp $ + * + */ + +#ifndef _SYS_JAIL_H_ +#define _SYS_JAIL_H_ + +struct jail { + char *path; + char *hostname; + u_int32_t ip_number; +}; + +#ifdef KERNEL + +#ifdef MALLOC_DECLARE +MALLOC_DECLARE(M_PRISON); +#endif + +/* + * 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 + * delete the struture when the last inmate is dead. + */ + +struct prison { + int pr_ref; + char pr_host[MAXHOSTNAMELEN]; + u_int32_t pr_ip; +}; + +#endif /* !KERNEL */ +#endif /* !_SYS_JAIL_H_ */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 12b809b7..90305845 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)proc.h 8.15 (Berkeley) 5/19/95 - * $Id: proc.h,v 1.79 1999/04/27 11:18:32 phk Exp $ + * $Id: proc.h,v 1.80 1999/04/28 01:04:33 luoqi Exp $ */ #ifndef _SYS_PROC_H_ @@ -107,6 +107,9 @@ struct pasleep { * which might be addressable only on a processor on which the process * is running. */ + +struct jail; + struct proc { TAILQ_ENTRY(proc) p_procq; /* run/sleep queue. */ LIST_ENTRY(proc) p_list; /* List of all processes. */ @@ -206,6 +209,7 @@ struct proc { struct sysentvec *p_sysent; /* System call dispatch information. */ struct rtprio p_rtprio; /* Realtime priority. */ + struct prison *p_prison; /* End area that is copied on creation. */ #define p_endcopy p_addr struct user *p_addr; /* Kernel virtual addr of u-area (PROC ONLY). */ @@ -268,6 +272,8 @@ struct proc { #define P_NOCLDWAIT 0x400000 /* No zombies if child dies */ #define P_DEADLKTREAT 0x800000 /* lock aquisition - deadlock treatment */ +#define P_JAILED 0x1000000 /* Process is in jail */ + /* * MOVE TO ucred.h? * @@ -292,6 +298,14 @@ MALLOC_DECLARE(M_SUBPROC); MALLOC_DECLARE(M_ZOMBIE); #endif +/* flags for suser_xxx() */ +#define PRISON_ROOT 1 + +/* Handy macro to determine of p1 can mangle p2 */ + +#define PRISON_CHECK(p1, p2) \ + ((!(p1)->p_prison) || (p1)->p_prison == (p2)->p_prison) + /* * We use process IDs <= PID_MAX; PID_MAX + 1 must also fit in a pid_t, * as it is used to represent "no process group". @@ -376,6 +390,7 @@ 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)); void remrq __P((struct proc *)); void cpu_switch __P((struct proc *)); void unsleep __P((struct proc *)); diff --git a/sys/sys/syscall-hide.h b/sys/sys/syscall-hide.h index e7feea1..cba0b9d 100644 --- a/sys/sys/syscall-hide.h +++ b/sys/sys/syscall-hide.h @@ -2,7 +2,7 @@ * System call hiders. * * DO NOT EDIT-- this file is automatically generated. - * created from Id: syscalls.master,v 1.57 1999/04/04 21:41:16 dt Exp + * created from Id: syscalls.master,v 1.58 1999/04/28 11:28:49 phk Exp */ HIDE_POSIX(fork) @@ -251,3 +251,4 @@ HIDE_POSIX(sched_rr_get_interval) HIDE_BSD(utrace) HIDE_BSD(sendfile) HIDE_BSD(kldsym) +HIDE_BSD(jail) diff --git a/sys/sys/syscall.h b/sys/sys/syscall.h index f20a43d..79441f1 100644 --- a/sys/sys/syscall.h +++ b/sys/sys/syscall.h @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * created from Id: syscalls.master,v 1.57 1999/04/04 21:41:16 dt Exp + * created from Id: syscalls.master,v 1.58 1999/04/28 11:28:49 phk Exp */ #define SYS_syscall 0 @@ -257,4 +257,5 @@ #define SYS_utrace 335 #define SYS_sendfile 336 #define SYS_kldsym 337 -#define SYS_MAXSYSCALL 338 +#define SYS_jail 338 +#define SYS_MAXSYSCALL 339 diff --git a/sys/sys/syscall.mk b/sys/sys/syscall.mk index 732435c..832bb16 100644 --- a/sys/sys/syscall.mk +++ b/sys/sys/syscall.mk @@ -1,6 +1,6 @@ # FreeBSD system call names. # DO NOT EDIT-- this file is automatically generated. -# created from Id: syscalls.master,v 1.57 1999/04/04 21:41:16 dt Exp +# created from Id: syscalls.master,v 1.58 1999/04/28 11:28:49 phk Exp MIASM = \ syscall.o \ exit.o \ @@ -212,4 +212,5 @@ MIASM = \ sched_rr_get_interval.o \ utrace.o \ sendfile.o \ - kldsym.o + kldsym.o \ + jail.o diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 003222b..0f949d8 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)sysctl.h 8.1 (Berkeley) 6/2/93 - * $Id: sysctl.h,v 1.71 1999/02/16 10:49:55 dfr Exp $ + * $Id: sysctl.h,v 1.72 1999/02/28 17:38:28 dt Exp $ */ #ifndef _SYS_SYSCTL_H_ @@ -79,6 +79,7 @@ struct ctlname { #define CTLFLAG_NOLOCK 0x20000000 /* XXX Don't Lock */ #define CTLFLAG_ANYBODY 0x10000000 /* All users can set this var */ #define CTLFLAG_SECURE 0x08000000 /* Permit set only if securelevel<=0 */ +#define CTLFLAG_PRISON 0x04000000 /* Prisoned roots can fiddle */ /* * USE THIS instead of a hardwired number from the categories below diff --git a/sys/sys/sysproto.h b/sys/sys/sysproto.h index 7c18bd1..43666d8 100644 --- a/sys/sys/sysproto.h +++ b/sys/sys/sysproto.h @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * created from Id: syscalls.master,v 1.57 1999/04/04 21:41:16 dt Exp + * created from Id: syscalls.master,v 1.58 1999/04/28 11:28:49 phk Exp */ #ifndef _SYS_SYSPROTO_H_ @@ -907,6 +907,9 @@ struct kldsym_args { int cmd; char cmd_[PAD_(int)]; void * data; char data_[PAD_(void *)]; }; +struct jail_args { + struct jail * jail; char jail_[PAD_(struct jail *)]; +}; int nosys __P((struct proc *, struct nosys_args *)); void exit __P((struct proc *, struct rexit_args *)) __dead2; int fork __P((struct proc *, struct fork_args *)); @@ -1116,6 +1119,7 @@ int sched_rr_get_interval __P((struct proc *, struct sched_rr_get_interval_args int utrace __P((struct proc *, struct utrace_args *)); int sendfile __P((struct proc *, struct sendfile_args *)); int kldsym __P((struct proc *, struct kldsym_args *)); +int jail __P((struct proc *, struct jail_args *)); #ifdef COMPAT_43 diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h index d95b0d8..f65dbe0 100644 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)ucred.h 8.4 (Berkeley) 1/9/95 - * $Id: ucred.h,v 1.10 1999/01/31 10:05:59 bde Exp $ + * $Id: ucred.h,v 1.11 1999/04/27 11:18:38 phk Exp $ */ #ifndef _SYS_UCRED_H_ @@ -41,7 +41,7 @@ * Credentials. * * Please do not inspect cr_uid directly to determine superuserness. - * Only the suser_xxx() function should be used for this. + * Only the suser()/suser_xxx() function should be used for this. */ struct ucred { u_short cr_ref; /* reference count */ @@ -60,7 +60,6 @@ struct ucred *crcopy __P((struct ucred *cr)); struct ucred *crdup __P((struct ucred *cr)); void crfree __P((struct ucred *cr)); struct ucred *crget __P((void)); -int suser_xxx __P((struct ucred *cred, u_short *acflag)); int groupmember __P((gid_t gid, struct ucred *cred)); #endif /* KERNEL */ diff --git a/sys/sys/unpcb.h b/sys/sys/unpcb.h index 1419153..7c38812 100644 --- a/sys/sys/unpcb.h +++ b/sys/sys/unpcb.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)unpcb.h 8.1 (Berkeley) 6/2/93 - * $Id: unpcb.h,v 1.6 1997/08/16 19:16:16 wollman Exp $ + * $Id: unpcb.h,v 1.7 1998/05/15 20:11:40 wollman Exp $ */ #ifndef _SYS_UNPCB_H_ @@ -71,6 +71,7 @@ struct unpcb { LIST_ENTRY(unpcb) unp_link; /* glue on list of all PCBs */ struct socket *unp_socket; /* pointer back to socket */ struct vnode *unp_vnode; /* if associated with file */ + struct vnode *unp_rvnode; /* root vp for creating process */ ino_t unp_ino; /* fake inode number */ struct unpcb *unp_conn; /* control block of connected socket */ struct unp_head unp_refs; /* referencing socket linked list */ diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c index d9333b2..55eb12d 100644 --- a/sys/ufs/ufs/ufs_vfsops.c +++ b/sys/ufs/ufs/ufs_vfsops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)ufs_vfsops.c 8.8 (Berkeley) 5/20/95 - * $Id: ufs_vfsops.c,v 1.13 1999/01/28 00:57:56 dillon Exp $ + * $Id: ufs_vfsops.c,v 1.14 1999/04/27 11:18:43 phk Exp $ */ #include "opt_quota.h" @@ -115,7 +115,7 @@ ufs_quotactl(mp, cmds, uid, arg, p) break; /* fall through */ default: - if ((error = suser(p)) != 0) + if ((error = suser_xxx(0, p, PRISON_ROOT)) != 0) return (error); } diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index f2a0859..411f2fe 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95 - * $Id: ufs_vnops.c,v 1.111 1999/03/02 05:31:47 imp Exp $ + * $Id: ufs_vnops.c,v 1.112 1999/04/27 11:18:44 phk Exp $ */ #include "opt_quota.h" @@ -448,7 +448,7 @@ ufs_setattr(ap) if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != ip->i_uid && - (error = suser_xxx(cred, &p->p_acflag))) + (error = suser_xxx(cred, p, PRISON_ROOT))) return (error); if (cred->cr_uid == 0) { if ((ip->i_flags @@ -504,7 +504,7 @@ ufs_setattr(ap) if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); if (cred->cr_uid != ip->i_uid && - (error = suser_xxx(cred, &p->p_acflag)) && + (error = suser_xxx(cred, p, PRISON_ROOT)) && ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || (error = VOP_ACCESS(vp, VWRITE, cred, p)))) return (error); @@ -546,7 +546,7 @@ ufs_chmod(vp, mode, cred, p) int error; if (cred->cr_uid != ip->i_uid) { - error = suser_xxx(cred, &p->p_acflag); + error = suser_xxx(cred, p, PRISON_ROOT); if (error) return (error); } @@ -594,7 +594,7 @@ ufs_chown(vp, uid, gid, cred, p) */ if ((cred->cr_uid != ip->i_uid || uid != ip->i_uid || (gid != ip->i_gid && !groupmember((gid_t)gid, cred))) && - (error = suser_xxx(cred, &p->p_acflag))) + (error = suser_xxx(cred, p, PRISON_ROOT))) return (error); ogid = ip->i_gid; ouid = ip->i_uid; @@ -2166,7 +2166,7 @@ ufs_makeinode(mode, dvp, vpp, cnp) if (DOINGSOFTDEP(tvp)) softdep_increase_linkcnt(ip); if ((ip->i_mode & ISGID) && !groupmember(ip->i_gid, cnp->cn_cred) && - suser_xxx(cnp->cn_cred, NULL)) + suser_xxx(cnp->cn_cred, 0, 0)) ip->i_mode &= ~ISGID; if (cnp->cn_flags & ISWHITEOUT) diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 4cd11ba..576a238 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -1,5 +1,5 @@ # From: @(#)Makefile 5.20 (Berkeley) 6/12/93 -# $Id: Makefile,v 1.151 1999/04/07 04:12:02 msmith Exp $ +# $Id: Makefile,v 1.152 1999/04/28 08:00:50 obrien Exp $ # XXX MISSING: mkproto SUBDIR= IPXrouted \ @@ -31,6 +31,7 @@ SUBDIR= IPXrouted \ ipresend \ ipsend \ iptest \ + jail \ kbdcontrol \ kbdmap \ kernbb \ diff --git a/usr.sbin/jail/Makefile b/usr.sbin/jail/Makefile new file mode 100644 index 0000000..f90553d --- /dev/null +++ b/usr.sbin/jail/Makefile @@ -0,0 +1,4 @@ +PROG= jail +MAN8= jail.8 + +.include <bsd.prog.mk> diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8 new file mode 100644 index 0000000..e1108fa --- /dev/null +++ b/usr.sbin/jail/jail.8 @@ -0,0 +1,32 @@ +.Dd April 28, 1999 +.Dt JAIL 8 +.Os FreeBSD 4.0 +.Sh NAME +.Nm jail +.Nd imprison process and decendants. +.Sh SYNOPSIS +.Nm jail +.Ar path +.Ar hostname +.Ar ip-number +.Sh DESCRIPTION +The +.Nm +command imprisons a process and all future decendants. +.Pp +Please see the +.Xr jail 2 +Manual page for further details. +.Sh SEE ALSO +.Xr chroot 2 , +.Xr jail 2 +.Sh HISTORY +The +.Fn jail +function call appeared in +.Fx 4.0 . +.Pp +The jail feature was written by Poul-Henning Kamp for +R&D Associates +.Dq Li http://www.rndassociates.com/ +who contributed it to FreeBSD. diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c new file mode 100644 index 0000000..938c50b --- /dev/null +++ b/usr.sbin/jail/jail.c @@ -0,0 +1,32 @@ +#include <stdio.h> +#include <err.h> +#include <sys/types.h> +#include <sys/jail.h> +#include <netinet/in.h> + +int +main(int argc, char **argv) +{ + struct jail j; + int i; + struct in_addr in; + + if (argc < 5) + errx(1, "Usage: %s path hostname ip command ...\n", argv[0]); + i = chdir(argv[1]); + if (i) + err(1, "chdir %s", argv[1]); + j.path = argv[1]; + j.hostname = argv[2]; + i = inet_aton(argv[3], &in); + if (!i) + errx(1, "Couldn't make sense if ip number\n"); + j.ip_number = in.s_addr; + i = jail(&j); + if (i) + err(1, "Imprisonment failed"); + i = execv(argv[4], argv + 4); + if (i) + err(1, "execv(%s)", argv[4]); + exit (0); +} |