Date: Mon, 17 Feb 2003 08:09:07 +0100 From: Pawel Jakub Dawidek <nick@garage.freebsd.pl> To: freebsd-hackers@freebsd.org Cc: rwatson@freebsd.org, phk@freebsd.org Subject: Re: Multi-level jailing. Message-ID: <20030217070907.GF10767@garage.freebsd.pl> In-Reply-To: <20030217070554.GE10767@garage.freebsd.pl> References: <20030217070554.GE10767@garage.freebsd.pl>
next in thread | previous in thread | raw e-mail | index | archive | help
--uAWY5bLVMBeN1y53 Content-Type: multipart/mixed; boundary="4xmAKYnxoHNXa3WQ" Content-Disposition: inline --4xmAKYnxoHNXa3WQ Content-Type: text/plain; charset=iso-8859-2 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable Now patch is attached:) --=20 Pawel Jakub Dawidek UNIX Systems Administrator http://garage.freebsd.pl Am I Evil? Yes, I Am. --4xmAKYnxoHNXa3WQ Content-Type: text/plain; charset=iso-8859-2 Content-Disposition: attachment; filename="mljail.patch" Content-Transfer-Encoding: quoted-printable diff -ru /usr/src/sys/kern/kern_jail.c ./sys/kern/kern_jail.c --- /usr/src/sys/kern/kern_jail.c Tue Jan 21 09:55:54 2003 +++ ./sys/kern/kern_jail.c Mon Feb 17 07:11:42 2003 @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning= Kamp * -----------------------------------------------------------------------= ----- * - * $FreeBSD: src/sys/kern/kern_jail.c,v 1.29 2003/01/21 08:55:54 alfred Ex= p $ + * $FreeBSD$ * */ =20 @@ -28,6 +28,14 @@ =20 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures"); =20 +#ifndef OLDJAIL +SLIST_HEAD(, prison_children) prison_head =3D + SLIST_HEAD_INITIALIZER(&prison_head); +struct mtx prison_head_mtx; +MTX_SYSINIT(prison_head_lock, &prison_head_mtx, "prison_head mutex lock", + MTX_DEF); +#endif + SYSCTL_DECL(_security); SYSCTL_NODE(_security, OID_AUTO, jail, CTLFLAG_RW, 0, "Jail rules"); @@ -65,11 +73,18 @@ struct jail j; struct chroot_args ca; struct ucred *newcred =3D NULL, *oldcred; +#ifndef OLDJAIL + u_int i; +#endif =20 error =3D copyin(uap->jail, &j, sizeof j); if (error) return (error); +#ifdef OLDJAIL if (j.version !=3D 0) +#else + if (j.version !=3D 1) +#endif return (EINVAL); =20 MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_ZERO); @@ -85,12 +100,40 @@ if (error) goto bail; newcred =3D crget(); +#ifdef OLDJAIL pr->pr_ip =3D j.ip_number; +#else + MALLOC(pr->pr_ips, u_int32_t *, sizeof(u_int32_t) * j.nips, M_PRISON, + 0); + error =3D copyin(j.ips, pr->pr_ips, sizeof(u_int32_t) * j.nips); + if (error) { + FREE(pr->pr_ips, M_PRISON); + goto bail; + } + if (jailed(p->p_ucred)) { + for (i =3D 0; i < j.nips; ++i) { + if (!prison_validip(p->p_ucred, pr->pr_ips[i])) { + error =3D EINVAL; + FREE(pr->pr_ips, M_PRISON); + goto bail; + } + } + } + pr->pr_nips =3D j.nips; +#endif + +#ifdef OLDJAIL PROC_LOCK(p); /* Implicitly fail if already in jail. */ error =3D suser_cred(p->p_ucred, 0); if (error) goto badcred; +#else + pr->pr_pprison =3D p->p_ucred->cr_prison; + SLIST_INIT(&pr->pr_children); + prison_addchild(p->p_ucred->cr_prison, pr); + PROC_LOCK(p); +#endif oldcred =3D p->p_ucred; crcopy(newcred, oldcred); p->p_ucred =3D newcred; @@ -99,7 +142,9 @@ PROC_UNLOCK(p); crfree(oldcred); return (0); +#ifdef OLDJAIL badcred: +#endif PROC_UNLOCK(p); crfree(newcred); bail: @@ -111,14 +156,56 @@ void prison_free(struct prison *pr) { +#ifndef OLDJAIL + struct prison_children *pc; + struct prison *ppr; +#endif =20 mtx_lock(&pr->pr_mtx); pr->pr_ref--; if (pr->pr_ref =3D=3D 0) { +#ifndef OLDJAIL + ppr =3D pr->pr_pprison; + pc =3D NULL; + if (ppr =3D=3D NULL) { + mtx_lock(&prison_head_mtx); + SLIST_FOREACH(pc, &prison_head, pc_next) { + if (pc->pc_child =3D=3D pr) + break; + } + SLIST_REMOVE(&prison_head, pc, prison_children, + pc_next); + } else { + SLIST_FOREACH(pc, &ppr->pr_children, pc_next) { + if (pc->pc_child =3D=3D pr) + break; + } + SLIST_REMOVE(&ppr->pr_children, pc, prison_children, + pc_next); + } + KASSERT(pc !=3D NULL, ("Child have to be on list.")); + FREE(pc, M_PRISON); + SLIST_FOREACH(pc, &pr->pr_children, pc_next) { + mtx_lock(&pc->pc_child->pr_mtx); + pc->pc_child->pr_pprison =3D ppr; + mtx_unlock(&pc->pc_child->pr_mtx); + if (ppr =3D=3D NULL) + SLIST_INSERT_HEAD(&prison_head, pc, pc_next); + else { + SLIST_INSERT_HEAD(&ppr->pr_children, pc, + pc_next); + } + } + if (ppr =3D=3D NULL) + mtx_unlock(&prison_head_mtx); +#endif /* !OLDJAIL */ mtx_unlock(&pr->pr_mtx); mtx_destroy(&pr->pr_mtx); if (pr->pr_linux !=3D NULL) FREE(pr->pr_linux, M_PRISON); +#ifndef OLDJAIL + FREE(pr->pr_ips, M_PRISON); +#endif FREE(pr, M_PRISON); return; } @@ -138,7 +225,36 @@ prison_getip(struct ucred *cred) { =20 +#ifdef OLDJAIL return (cred->cr_prison->pr_ip); +#else + return (cred->cr_prison->pr_ips[0]); +#endif + +} + +/* + * Returns 1 if IP belongs to prison, otherwise 0. + */ +int +prison_validip(struct ucred *cred, u_int32_t ip) +{ +#ifndef OLDJAIL + register struct prison *pr; + register u_int i; +#endif + +#ifdef OLDJAIL + return (cred->cr_prison->pr_ip =3D=3D ip); +#else + pr =3D cred->cr_prison; + for (i =3D 0; i < pr->pr_nips; ++i) { + if (ip =3D=3D pr->pr_ips[i]) + return (1); + } + + return (0); +#endif } =20 int @@ -152,23 +268,14 @@ tmp =3D *ip; else tmp =3D ntohl(*ip); - if (tmp =3D=3D INADDR_ANY) { + if (tmp =3D=3D INADDR_ANY || tmp =3D=3D INADDR_LOOPBACK) { if (flag)=20 - *ip =3D cred->cr_prison->pr_ip; + *ip =3D prison_getip(cred); else - *ip =3D htonl(cred->cr_prison->pr_ip); + *ip =3D htonl(prison_getip(cred)); return (0); } - if (tmp =3D=3D INADDR_LOOPBACK) { - if (flag) - *ip =3D cred->cr_prison->pr_ip; - else - *ip =3D htonl(cred->cr_prison->pr_ip); - return (0); - } - if (cred->cr_prison->pr_ip !=3D tmp) - return (1); - return (0); + return (!prison_validip(cred, tmp)); } =20 void @@ -184,9 +291,9 @@ tmp =3D ntohl(*ip); if (tmp =3D=3D INADDR_LOOPBACK) { if (flag) - *ip =3D cred->cr_prison->pr_ip; + *ip =3D prison_getip(cred); else - *ip =3D htonl(cred->cr_prison->pr_ip); + *ip =3D htonl(prison_getip(cred)); return; } return; @@ -202,7 +309,7 @@ ok =3D 1; else if (sai->sin_family !=3D AF_INET) ok =3D 0; - else if (cred->cr_prison->pr_ip !=3D ntohl(sai->sin_addr.s_addr)) + else if (!prison_validip(cred, ntohl(sai->sin_addr.s_addr))) ok =3D 1; else ok =3D 0; @@ -217,14 +324,17 @@ struct ucred *cred1, *cred2; { =20 - if (jailed(cred1)) { - if (!jailed(cred2)) - return (ESRCH); - if (cred2->cr_prison !=3D cred1->cr_prison) - return (ESRCH); - } - - return (0); + if (!jailed(cred1)) + return (0); + if (!jailed(cred2)) + return (ESRCH); + if (cred2->cr_prison =3D=3D cred1->cr_prison) + return (0); +#ifndef OLDJAIL + if (prison_ischild(cred1->cr_prison, cred2->cr_prison)) + return (0); +#endif + return (ESRCH); } =20 /* @@ -256,3 +366,52 @@ else strlcpy(buf, hostname, size); } + +int +prison_maxseclvl(int seclvl, register struct prison *pr) +{ + +#ifndef OLDJAIL + for (; pr !=3D NULL; pr =3D pr->pr_pprison) + seclvl =3D imax(seclvl, pr->pr_securelevel); + return (seclvl); +#else + return (imax(seclvl, pr->pr_securelevel)); +#endif +} + +#ifndef OLDJAIL +void +prison_addchild(struct prison *parent, struct prison *child) +{ + struct prison_children *pc; + + MALLOC(pc, struct prison_children *, sizeof *pc , M_PRISON, M_ZERO); + pc->pc_child =3D child; + if (parent =3D=3D NULL) { + mtx_lock(&prison_head_mtx); + SLIST_INSERT_HEAD(&prison_head, pc, pc_next); + mtx_unlock(&prison_head_mtx); + return; + } + mtx_lock(&parent->pr_mtx); + SLIST_INSERT_HEAD(&parent->pr_children, pc, pc_next); + mtx_unlock(&parent->pr_mtx); +} + +/* + * Returns 1 if pr2 is a child of pr1, otherwise 0. + */ +int +prison_ischild(register struct prison *pr1, register struct prison *pr2) +{ + + for (pr2 =3D pr2->pr_pprison; pr2 !=3D NULL; pr2 =3D pr2->pr_pprison) { + if (pr1 =3D=3D pr2) + return (1); + } + + return (0); + +} +#endif diff -ru /usr/src/sys/kern/kern_mib.c ./sys/kern/kern_mib.c --- /usr/src/sys/kern/kern_mib.c Sun Jan 5 04:48:14 2003 +++ ./sys/kern/kern_mib.c Mon Feb 17 05:51:16 2003 @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * @(#)kern_sysctl.c 8.4 (Berkeley) 4/14/94 - * $FreeBSD: src/sys/kern/kern_mib.c,v 1.64 2003/01/05 03:48:14 jake Exp $ + * $FreeBSD$ */ =20 #include "opt_posix.h" @@ -248,12 +248,12 @@ * If the process is in jail, return the maximum of the global and * local levels; otherwise, return the global level. */ + level =3D securelevel; if (pr !=3D NULL) { mtx_lock(&pr->pr_mtx); - level =3D imax(securelevel, pr->pr_securelevel); + level =3D prison_maxseclvl(level, pr); mtx_unlock(&pr->pr_mtx); - } else - level =3D securelevel; + } error =3D sysctl_handle_int(oidp, &level, 0, req); if (error || !req->newptr) return (error); @@ -264,7 +264,7 @@ if (pr !=3D NULL) { mtx_lock(&pr->pr_mtx); if (!regression_securelevel_nonmonotonic && - (level < imax(securelevel, pr->pr_securelevel))) { + (level < prison_maxseclvl(securelevel, pr))) { mtx_unlock(&pr->pr_mtx); return (EPERM); } diff -ru /usr/src/sys/kern/kern_prot.c ./sys/kern/kern_prot.c --- /usr/src/sys/kern/kern_prot.c Mon Feb 10 05:42:20 2003 +++ ./sys/kern/kern_prot.c Mon Feb 17 05:51:16 2003 @@ -37,7 +37,7 @@ * SUCH DAMAGE. * * @(#)kern_prot.c 8.6 (Berkeley) 1/21/94 - * $FreeBSD: src/sys/kern/kern_prot.c,v 1.166 2003/02/10 04:42:20 jake Exp= $ + * $FreeBSD$ */ =20 /* @@ -1303,8 +1303,8 @@ KASSERT(cr !=3D NULL, ("securelevel_gt: null cr")); if (cr->cr_prison !=3D NULL) { mtx_lock(&cr->cr_prison->pr_mtx); - active_securelevel =3D imax(cr->cr_prison->pr_securelevel, - active_securelevel); + active_securelevel =3D prison_maxseclvl(active_securelevel, + cr->cr_prison); mtx_unlock(&cr->cr_prison->pr_mtx); } return (active_securelevel > level ? EPERM : 0); @@ -1319,8 +1319,8 @@ KASSERT(cr !=3D NULL, ("securelevel_ge: null cr")); if (cr->cr_prison !=3D NULL) { mtx_lock(&cr->cr_prison->pr_mtx); - active_securelevel =3D imax(cr->cr_prison->pr_securelevel, - active_securelevel); + active_securelevel =3D prison_maxseclvl(active_securelevel, + cr->cr_prison); mtx_unlock(&cr->cr_prison->pr_mtx); } return (active_securelevel >=3D level ? EPERM : 0); diff -ru /usr/src/sys/netinet/in_pcb.c ./sys/netinet/in_pcb.c --- /usr/src/sys/netinet/in_pcb.c Thu Feb 13 00:55:07 2003 +++ ./sys/netinet/in_pcb.c Mon Feb 17 05:51:16 2003 @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)in_pcb.c 8.4 (Berkeley) 5/24/95 - * $FreeBSD: src/sys/netinet/in_pcb.c,v 1.117 2003/02/12 23:55:07 hsu Exp $ + * $FreeBSD$ */ =20 #include "opt_ipsec.h" @@ -1142,7 +1142,7 @@ { if (!jailed(td->td_ucred)) return (0); - if (ntohl(inp->inp_laddr.s_addr) =3D=3D prison_getip(td->td_ucred)) + if (prison_validip(td->td_ucred, ntohl(inp->inp_laddr.s_addr))) return (0); return (1); } diff -ru /usr/src/sys/sys/jail.h ./sys/sys/jail.h --- /usr/src/sys/sys/jail.h Mon May 6 05:13:08 2002 +++ ./sys/sys/jail.h Mon Feb 17 07:02:24 2003 @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning= Kamp * -----------------------------------------------------------------------= ----- * - * $FreeBSD: src/sys/sys/jail.h,v 1.17 2002/05/06 03:13:08 bde Exp $ + * $FreeBSD$ * */ =20 @@ -17,7 +17,12 @@ u_int32_t version; char *path; char *hostname; +#ifdef OLDJAIL u_int32_t ip_number; +#else + u_int32_t *ips; + size_t nips; +#endif }; =20 #ifndef _KERNEL @@ -34,6 +39,14 @@ MALLOC_DECLARE(M_PRISON); #endif =20 +#ifndef OLDJAIL +struct prison; +struct prison_children { + struct prison *pc_child; + SLIST_ENTRY(prison_children) pc_next; +}; +#endif + /* * This structure describes a prison. It is pointed to by all struct * ucreds's of the inmates. pr_ref keeps track of them and is used to @@ -48,9 +61,18 @@ struct prison { int pr_ref; /* (p) refcount */ char pr_host[MAXHOSTNAMELEN]; /* (p) jail hostname */ +#ifdef OLDJAIL u_int32_t pr_ip; /* (c) ip addr host */ +#else + size_t pr_nips; /* numer of ips in table */ + u_int32_t *pr_ips; /* table with ips */ +#endif void *pr_linux; /* (p) linux abi */ int pr_securelevel; /* (p) securelevel */ +#ifndef OLDJAIL + struct prison *pr_pprison; /* parent prison */ + SLIST_HEAD(, prison_children) pr_children; /* prison's children */ +#endif struct mtx pr_mtx; }; =20 @@ -77,6 +99,12 @@ int prison_if(struct ucred *cred, struct sockaddr *sa); int prison_ip(struct ucred *cred, int flag, u_int32_t *ip); void prison_remote_ip(struct ucred *cred, int flags, u_int32_t *ip); +int prison_maxseclvl(int seclvl, register struct prison *pr); +int prison_validip(struct ucred *cred, u_int32_t ip); +#ifndef OLDJAIL +void prison_addchild(struct prison *parent, struct prison *child); +int prison_ischild(register struct prison *pr1, register struct prison *pr= 2); +#endif =20 #endif /* !_KERNEL */ #endif /* !_SYS_JAIL_H_ */ diff -ru /usr/src/usr.sbin/jail/jail.c ./usr.sbin/jail/jail.c --- /usr/src/usr.sbin/jail/jail.c Mon Apr 22 15:44:43 2002 +++ ./usr.sbin/jail/jail.c Mon Feb 17 05:53:39 2003 @@ -6,7 +6,7 @@ * this stuff is worth it, you can buy me a beer in return. Poul-Henning= Kamp * -----------------------------------------------------------------------= ----- *=20 - * $FreeBSD: src/usr.sbin/jail/jail.c,v 1.8 2002/04/22 13:44:43 des Exp $ + * $FreeBSD$ *=20 */ =20 @@ -27,22 +27,55 @@ { struct jail j; int i; +#ifndef OLDJAIL + int c; +#endif struct in_addr in; =20 - if (argc < 5)=20 + if (argc < 5) { +#ifdef OLDJAIL errx(1, "usage: %s path hostname ip-number command ...\n", argv[0]); +#else + errx(1, "Usage: %s path hostname ip1[,ip2[...]] command ...\n", + argv[0]); +#endif + } i =3D chdir(argv[1]); if (i) err(1, "chdir %s", argv[1]); memset(&j, 0, sizeof(j)); +#ifdef OLDJAIL j.version =3D 0; +#else + j.version =3D 1; +#endif j.path =3D argv[1]; j.hostname =3D argv[2]; +#ifdef OLDJAIL i =3D inet_aton(argv[3], &in); if (!i) errx(1, "Couldn't make sense of ip-number\n"); j.ip_number =3D ntohl(in.s_addr); +#else + for (c =3D 1, ip =3D argv[3]; *ip; ++ip) { + if (*ip =3D=3D ',') + ++c; + } + if ((j.ips =3D (u_int32_t *)malloc(sizeof(u_int32_t) * c)) =3D=3D NULL) + errx(1, "malloc()"); + + for (c =3D 0, ip =3D strtok(argv[3], ","); ip; + ++c, ip =3D strtok(NULL, ",")) { + i =3D inet_aton(ip, &in); + if (!i) { + free(j.ips); + errx(1, "Couldn't make sense of ip-number\n"); + } + j.ips[c] =3D ntohl(in.s_addr); + } + j.nips =3D c; +#endif /* !OLDJAIL */ i =3D jail(&j); if (i) err(1, "Imprisonment failed"); --4xmAKYnxoHNXa3WQ-- --uAWY5bLVMBeN1y53 Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.0.7 (FreeBSD) iQCVAwUBPlCKkz/PhmMH/Mf1AQHENAQApxRXHWh3z3kSKhnLOUXm0dQRQAxcLJB/ FlK2zen5HAwl5CQd1oHJnx1sHRLQYtGnfOErZ22KBKaDa/xLkq6lAEv9oQ0rFtJN l1zK0mbhgpdFd6ctt1Wiliyjcil2fbaI9FdUxdmdwm3eSf/mZVk4WOfRaTwUg7tX dPwk3tR7byg= =qHgZ -----END PGP SIGNATURE----- --uAWY5bLVMBeN1y53-- To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030217070907.GF10767>