Skip site navigation (1)Skip section navigation (2)
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>