Am Samstag, 13. August 2005 10:53 CEST schrieb David Malone:
> On Fri, Aug 12, 2005 at 08:53:20PM +0200, Emanuel Strobl wrote:
> > Now in the 24-16-24 scheme of th interface id part of the IPv6
> > address, the 16 bits were inserted with the value FFFE. And bit 57 was
> > changed to one! Why???? What if it is alread one? Or isn't tehre any
> > vendor who can have bit 41 of his MAC 1?
>
> Some of the bits of a MAC address are reserved. There is a bit that
> indicates if the address is the address of a group of machines (for
> multicast) or the address of a single machine. The bit that is
> flipped when generating IPv6 addresses is the "local/global" bit,
> that indicates if the address has been assigned locally or by some
> global authority.  For normal ethernet cards, this bit would always
> be 0.
>
> > Now I want to use a dedicated interface, which is in a different
> > subnet, for 5 jails. How do I do that if I want to keep the MAC
> > relation and if I'm not allewd to change the FFFE insert? It isn't
> > possible then, is it? What should I do instead? Invent my own 64-bit
> > scheme?
>
> I'd suggest that you use manually assigned addresses in cases like this.
> You know what sort of addresses will be generated by autoconfiguration,
> so it should be easy for you to choose addresses that won't clash.
>
> Unfortunately jails do not actually support restricting the use of IPv6
> addresses right now.

Thanks a lot for your explanation! I have patches from Olivier Houchard for 
testing which extends jails for IPv6 :)
He wrote it some time ago for RELENG_5 but wasn't sure if it is secure 
enough to committ it.
I think more teseters are welcome,  I have to solve some other IPv6 
proplems first (like auto host config and DNS?), so I attach the patches 
here, I can't imagine why Olivier wouldn't want that.

Best regards,

-Harry


>
>       David.
> _______________________________________________
> freebsd-questions@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-questions
> To unsubscribe, send any mail to
> "[EMAIL PROTECTED]"
Index: sys/kern/kern_jail.c
===================================================================
RCS file: /cognet/ncvs/src/sys/kern/kern_jail.c,v
retrieving revision 1.50
diff -u -p -r1.50 kern_jail.c
--- sys/kern/kern_jail.c	23 Jun 2005 22:13:28 -0000	1.50
+++ sys/kern/kern_jail.c	12 Aug 2005 22:57:21 -0000
@@ -12,6 +12,7 @@ __FBSDID("$FreeBSD: src/sys/kern/kern_ja
 
 #include "opt_mac.h"
 
+#include "opt_inet6.h"
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/kernel.h>
@@ -49,7 +50,7 @@ SYSCTL_INT(_security_jail, OID_AUTO, set
 int	jail_socket_unixiproute_only = 1;
 SYSCTL_INT(_security_jail, OID_AUTO, socket_unixiproute_only, CTLFLAG_RW,
     &jail_socket_unixiproute_only, 0,
-    "Processes in jail are limited to creating UNIX/IPv4/route sockets only");
+    "Processes in jail are limited to creating UNIX/IP/route sockets only");
 
 int	jail_sysvipc_allowed = 0;
 SYSCTL_INT(_security_jail, OID_AUTO, sysvipc_allowed, CTLFLAG_RW,
@@ -134,6 +135,9 @@ jail(struct thread *td, struct jail_args
 	error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0);
 	if (error)
 		goto e_dropvnref;
+#ifdef INET6
+	memcpy(&pr->pr_ip6, &j.ip6_number, sizeof(pr->pr_ip6));
+#endif
 	pr->pr_ip = j.ip_number;
 	pr->pr_linux = NULL;
 	pr->pr_securelevel = securelevel;
@@ -375,18 +379,82 @@ prison_remote_ip(struct ucred *cred, int
 	return;
 }
 
+#ifdef INET6
+void
+prison_getip6(struct ucred *ucred, u_int8_t **ip6)
+{
+
+	memcpy(ip6, &ucred->cr_prison->pr_ip6,
+	    sizeof(ucred->cr_prison->pr_ip6));
+}
+
+int
+prison_ip6(struct ucred *ucred, u_int8_t **ip6)
+{
+	struct in6_addr tmp;
+	
+	if (!jailed(ucred))
+		return (0);
+	memcpy(&tmp, ip6, sizeof(tmp));
+	if (IN6_IS_ADDR_LOOPBACK(&tmp) ||
+	    IN6_IS_ADDR_UNSPECIFIED(&tmp)) {
+		memcpy(ip6, &ucred->cr_prison->pr_ip6, sizeof(tmp));
+		return (0);
+	}
+	if (IN6_ARE_ADDR_EQUAL((struct in6_addr *)ip6,
+	    (struct in6_addr *)&ucred->cr_prison->pr_ip6))
+		return (1);
+	return (0);
+}
+
+void
+prison_remote_ip6(struct ucred *cred, u_int8_t **ip)
+{
+	struct in6_addr tmp;
+
+	if (!jailed(cred))
+		return;
+	memcpy(&tmp, ip, sizeof(tmp));
+	if (IN6_IS_ADDR_LOOPBACK(&tmp)) {
+		memcpy(ip, &cred->cr_prison->pr_ip6, sizeof(tmp));
+		return;
+	}
+	return;
+}
+
+#endif
+
 int
 prison_if(struct ucred *cred, struct sockaddr *sa)
 {
 	struct sockaddr_in *sai;
+#ifdef INET6
+	struct sockaddr_in6 *sa6;
+#endif
 	int ok;
 
 	sai = (struct sockaddr_in *)sa;
-	if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only)
-		ok = 1;
-	else if (sai->sin_family != AF_INET)
-		ok = 0;
-	else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
+#ifdef INET6
+	sa6 = (struct sockaddr_in6 *)sa;
+#endif
+	if (sai->sin_family == AF_INET) {
+		if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr))
+			ok = 1;
+		else
+			ok = 0;
+	} else
+#ifdef INET6
+	if (sai->sin_family == AF_INET6) {
+		if (!IN6_ARE_ADDR_EQUAL((struct in6_addr *)
+		    &cred->cr_prison->pr_ip6,
+		    (struct in6_addr *)&sa6->sin6_addr))
+			ok = 1;
+		else
+			ok = 0;
+	}
+	else
+#endif
+	if (jail_socket_unixiproute_only)
 		ok = 1;
 	else
 		ok = 0;
Index: sys/kern/uipc_socket.c
===================================================================
RCS file: /cognet/ncvs/src/sys/kern/uipc_socket.c,v
retrieving revision 1.242
diff -u -p -r1.242 uipc_socket.c
--- sys/kern/uipc_socket.c	1 Jul 2005 16:28:30 -0000	1.242
+++ sys/kern/uipc_socket.c	12 Aug 2005 22:57:21 -0000
@@ -35,6 +35,7 @@
 __FBSDID("$FreeBSD: src/sys/kern/uipc_socket.c,v 1.242 2005/07/01 16:28:30 ssouhlal Exp $");
 
 #include "opt_inet.h"
+#include "opt_inet6.h"
 #include "opt_mac.h"
 #include "opt_zero.h"
 
@@ -193,6 +194,9 @@ socreate(dom, aso, type, proto, cred, td
 	if (jailed(cred) && jail_socket_unixiproute_only &&
 	    prp->pr_domain->dom_family != PF_LOCAL &&
 	    prp->pr_domain->dom_family != PF_INET &&
+#ifdef INET6
+	    prp->pr_domain->dom_family != PF_INET6 &&
+#endif
 	    prp->pr_domain->dom_family != PF_ROUTE) {
 		return (EPROTONOSUPPORT);
 	}
Index: sys/netinet/tcp_usrreq.c
===================================================================
RCS file: /cognet/ncvs/src/sys/netinet/tcp_usrreq.c,v
retrieving revision 1.124
diff -u -p -r1.124 tcp_usrreq.c
--- sys/netinet/tcp_usrreq.c	1 Jun 2005 12:14:56 -0000	1.124
+++ sys/netinet/tcp_usrreq.c	12 Aug 2005 22:57:21 -0000
@@ -408,6 +408,9 @@ tcp6_usr_connect(struct socket *so, stru
 		in6_sin6_2_sin(&sin, sin6p);
 		inp->inp_vflag |= INP_IPV4;
 		inp->inp_vflag &= ~INP_IPV6;
+		if (td && jailed(td->td_ucred))
+			prison_remote_ip(td->td_ucred, 0, 
+			    &sin.sin_addr.s_addr);
 		if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0)
 			goto out;
 		error = tcp_output(tp);
@@ -416,6 +419,8 @@ tcp6_usr_connect(struct socket *so, stru
 	inp->inp_vflag &= ~INP_IPV4;
 	inp->inp_vflag |= INP_IPV6;
 	inp->inp_inc.inc_isipv6 = 1;
+	if (td && jailed(td->td_ucred))
+		prison_remote_ip6(td->td_ucred, (u_int8_t **)&sin6p->sin6_addr);
 	if ((error = tcp6_connect(tp, nam, td)) != 0)
 		goto out;
 	error = tcp_output(tp);
Index: sys/netinet6/in6_pcb.c
===================================================================
RCS file: /cognet/ncvs/src/sys/netinet6/in6_pcb.c,v
retrieving revision 1.62
diff -u -p -r1.62 in6_pcb.c
--- sys/netinet6/in6_pcb.c	7 Jan 2005 02:30:34 -0000	1.62
+++ sys/netinet6/in6_pcb.c	12 Aug 2005 22:58:39 -0000
@@ -134,6 +134,13 @@ in6_pcbbind(inp, nam, cred)
 
 	if (!in6_ifaddr) /* XXX broken! */
 		return (EADDRNOTAVAIL);
+	if (jailed(cred)) {
+	    struct in6_addr tmp_addr6;
+
+	    prison_getip6(cred, (uint8_t **)&tmp_addr6);
+	    if (IN6_IS_ADDR_UNSPECIFIED(&tmp_addr6))
+		    return (EADDRNOTAVAIL);
+	}
 	if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
 		return (EINVAL);
 	if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
@@ -148,6 +155,9 @@ in6_pcbbind(inp, nam, cred)
 		if (nam->sa_family != AF_INET6)
 			return (EAFNOSUPPORT);
 
+		if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
+		    prison_ip6(cred, (u_int8_t **)&sin6->sin6_addr))
+			return (EINVAL);
 		/* KAME hack: embed scopeid */
 		if (in6_embedscope(&sin6->sin6_addr, sin6, inp, NULL) != 0)
 			return EINVAL;
@@ -186,16 +196,19 @@ in6_pcbbind(inp, nam, cred)
 		}
 		if (lport) {
 			struct inpcb *t;
+			int prison = 1;
 
 			/* GROSS */
 			if (ntohs(lport) < IPV6PORT_RESERVED &&
 			    suser_cred(cred, SUSER_ALLOWJAIL))
 				return (EACCES);
+			if (jailed(cred))
+				prison = 1;
 			if (so->so_cred->cr_uid != 0 &&
 			    !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
 				t = in6_pcblookup_local(pcbinfo,
 				    &sin6->sin6_addr, lport,
-				    INPLOOKUP_WILDCARD);
+				    prison ? 0 : INPLOOKUP_WILDCARD);
 				if (t &&
 				    ((t->inp_vflag & INP_TIMEWAIT) == 0) &&
 				    (so->so_type != SOCK_STREAM ||
@@ -225,6 +238,10 @@ in6_pcbbind(inp, nam, cred)
 						return (EADDRINUSE);
 				}
 			}
+			if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
+			    prison_ip6(cred, (u_int8_t **)
+			    &sin6->sin6_addr))
+				return (EADDRNOTAVAIL);
 			t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
 						lport, wild);
 			if (t && (reuseport & ((t->inp_vflag & INP_TIMEWAIT) ?
@@ -257,6 +274,11 @@ in6_pcbbind(inp, nam, cred)
 		}
 		inp->in6p_laddr = sin6->sin6_addr;
 	}
+	if (!IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)
+	    && prison_ip6(cred, (u_int8_t **)
+	    &inp->in6p_laddr))
+		return (EINVAL);
+	
 	if (lport == 0) {
 		int e;
 		if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, cred)) != 0)
@@ -264,6 +286,7 @@ in6_pcbbind(inp, nam, cred)
 	}
 	else {
 		inp->inp_lport = lport;
+		
 		if (in_pcbinshash(inp) != 0) {
 			inp->in6p_laddr = in6addr_any;
 			inp->inp_lport = 0;
@@ -360,6 +383,20 @@ in6_pcbconnect(inp, nam, cred)
 	INP_INFO_WLOCK_ASSERT(inp->inp_pcbinfo);
 	INP_LOCK_ASSERT(inp);
 
+	if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) && jailed(cred)) {
+		struct sockaddr_in6 sa6;
+
+		bzero(&sa6, sizeof(sa6));
+		prison_getip6(cred, (u_int8_t **)&sa6.sin6_addr);
+		if (IN6_IS_ADDR_UNSPECIFIED(&sa6.sin6_addr))
+			return (EADDRNOTAVAIL);
+		sa6.sin6_len = sizeof(sa6);
+		sa6.sin6_family = AF_INET6;
+		/* XXX scope_id ? */
+		error = in6_pcbbind(inp, (struct sockaddr *)&sa6, cred);
+		if (error)
+			return (error);
+	}
 	/*
 	 * Call inner routine, to assign local interface address.
 	 * in6_pcbladdr() may automatically fill in sin6_scope_id.
Index: sys/netinet6/udp6_usrreq.c
===================================================================
RCS file: /cognet/ncvs/src/sys/netinet6/udp6_usrreq.c,v
retrieving revision 1.54
diff -u -p -r1.54 udp6_usrreq.c
--- sys/netinet6/udp6_usrreq.c	1 Jun 2005 11:38:19 -0000	1.54
+++ sys/netinet6/udp6_usrreq.c	12 Aug 2005 22:57:21 -0000
@@ -80,6 +80,7 @@
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/systm.h>
+#include <sys/jail.h>
 
 #include <net/if.h>
 #include <net/if_types.h>
@@ -461,7 +462,7 @@ udp6_getcred(SYSCTL_HANDLER_ARGS)
 	struct inpcb *inp;
 	int error, s;
 
-	error = suser(req->td);
+	error = suser_cred(req->td->td_ucred, SUSER_ALLOWJAIL);
 	if (error)
 		return (error);
 
@@ -481,6 +482,9 @@ udp6_getcred(SYSCTL_HANDLER_ARGS)
 		error = ENOENT;
 		goto out;
 	}
+	error = cr_canseesocket(req->td->td_ucred, inp->inp_socket);
+	if (error)
+		goto out;
 	cru2x(inp->inp_socket->so_cred, &xuc);
 	error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
 out:
@@ -488,8 +492,8 @@ out:
 	return (error);
 }
 
-SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
-	    0, 0,
+SYSCTL_PROC(_net_inet6_udp6, OID_AUTO, getcred, 
+    	    CTLTYPE_OPAQUE|CTLFLAG_RW|CTLFLAG_PRISON, 0, 0,
 	    udp6_getcred, "S,xucred", "Get the xucred of a UDP6 connection");
 
 static int
@@ -629,6 +633,9 @@ udp6_connect(struct socket *so, struct s
 				return EISCONN;
 			in6_sin6_2_sin(&sin, sin6_p);
 			s = splnet();
+			if (td && jailed(td->td_ucred))
+				prison_remote_ip(td->td_ucred, 0,
+				    &sin.sin_addr.s_addr);
 			error = in_pcbconnect(inp, (struct sockaddr *)&sin,
 			    td->td_ucred);
 			splx(s);
@@ -645,6 +652,11 @@ udp6_connect(struct socket *so, struct s
 		goto out;
 	}
 	s = splnet();
+	if (td && jailed(td->td_ucred)) {
+		struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam;
+
+		prison_remote_ip6(td->td_ucred, (uint8_t **)&sin6->sin6_addr);
+	}
 	error = in6_pcbconnect(inp, nam, td->td_ucred);
 	splx(s);
 	if (error == 0) {
Index: sys/sys/jail.h
===================================================================
RCS file: /cognet/ncvs/src/sys/sys/jail.h,v
retrieving revision 1.26
diff -u -p -r1.26 jail.h
--- sys/sys/jail.h	9 Jun 2005 18:49:19 -0000	1.26
+++ sys/sys/jail.h	12 Aug 2005 22:57:21 -0000
@@ -18,6 +18,7 @@ struct jail {
 	char		*path;
 	char		*hostname;
 	u_int32_t	ip_number;
+	u_int8_t	ip6_number[16];
 };
 
 struct xprison {
@@ -26,6 +27,7 @@ struct xprison {
 	char		 pr_path[MAXPATHLEN];
 	char 		 pr_host[MAXHOSTNAMELEN];
 	u_int32_t	 pr_ip;
+	u_int8_t	 pr_ip6[16];
 };
 #define	XPRISON_VERSION	1
 
@@ -69,6 +71,7 @@ struct prison {
 	struct vnode	*pr_root;			/* (c) vnode to rdir */
 	char 		 pr_host[MAXHOSTNAMELEN];	/* (p) jail hostname */
 	u_int32_t	 pr_ip;				/* (c) ip addr host */
+	u_int8_t	 pr_ip6[16];			/* (c) ip6 addr host */
 	void		*pr_linux;			/* (p) linux abi */
 	int		 pr_securelevel;		/* (p) securelevel */
 	struct task	 pr_task;			/* (d) destroy task */
@@ -110,7 +113,11 @@ u_int32_t prison_getip(struct ucred *cre
 void prison_hold(struct prison *pr);
 int prison_if(struct ucred *cred, struct sockaddr *sa);
 int prison_ip(struct ucred *cred, int flag, u_int32_t *ip);
+#ifdef INET6
+void prison_getip6(struct ucred *cred, u_int8_t **ip6);
+int prison_ip6(struct ucred *cred, u_int8_t **ip6);
+void prison_remote_ip6(struct ucred *cred, u_int8_t **ip6);
+#endif
 void prison_remote_ip(struct ucred *cred, int flags, u_int32_t *ip);
-
 #endif /* _KERNEL */
 #endif /* !_SYS_JAIL_H_ */
Index: usr.sbin/jail/jail.8
===================================================================
RCS file: /cognet/ncvs/src/usr.sbin/jail/jail.8,v
retrieving revision 1.67.2.1
diff -u -p -r1.67.2.1 jail.8
--- usr.sbin/jail/jail.8	10 Aug 2005 19:00:43 -0000	1.67.2.1
+++ usr.sbin/jail/jail.8	12 Aug 2005 22:57:21 -0000
@@ -43,6 +43,7 @@
 .Nm
 .Op Fl i
 .Op Fl l u Ar username | Fl U Ar username
+.Op Fl 6 Ar ip6-number
 .Ar path hostname ip-number command ...
 .Sh DESCRIPTION
 The
@@ -77,6 +78,8 @@ should run.
 The user name from jailed environment as whom the
 .Ar command
 should run.
+.It Fl 6 Ar ip6 addr
+set the IPv6 address assigned to the prison.
 .It Ar path
 Directory which is to be the root of the prison.
 .It Ar hostname
Index: usr.sbin/jail/jail.c
===================================================================
RCS file: /cognet/ncvs/src/usr.sbin/jail/jail.c,v
retrieving revision 1.20
diff -u -p -r1.20 jail.c
--- usr.sbin/jail/jail.c	17 Nov 2004 10:01:48 -0000	1.20
+++ usr.sbin/jail/jail.c	12 Aug 2005 22:57:21 -0000
@@ -12,6 +12,7 @@ __FBSDID("$FreeBSD: src/usr.sbin/jail/ja
 
 #include <sys/param.h>
 #include <sys/jail.h>
+#include <sys/socket.h>
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -56,13 +57,14 @@ main(int argc, char **argv)
 	gid_t groups[NGROUPS];
 	int ch, i, iflag, lflag, ngroups, uflag, Uflag;
 	char path[PATH_MAX], *username;
+	char *ipv6 = NULL;
 	static char *cleanenv;
 	const char *shell, *p = NULL;
 
 	iflag = lflag = uflag = Uflag = 0;
 	username = cleanenv = NULL;
 
-	while ((ch = getopt(argc, argv, "ilu:U:")) != -1) {
+	while ((ch = getopt(argc, argv, "ilu:U6:")) != -1) {
 		switch (ch) {
 		case 'i':
 			iflag = 1;
@@ -78,6 +80,9 @@ main(int argc, char **argv)
 		case 'l':
 			lflag = 1;
 			break;
+		case '6':
+			ipv6 = optarg;
+			break;
 		default:
 			usage();
 		}
@@ -103,6 +108,11 @@ main(int argc, char **argv)
 	if (inet_aton(argv[2], &in) == 0)
 		errx(1, "Could not make sense of ip-number: %s", argv[2]);
 	j.ip_number = ntohl(in.s_addr);
+	if (ipv6) {
+		if (inet_pton(AF_INET6, ipv6, &j.ip6_number) != 1)
+			errx(1, "Could not make sense of ipv6: %s", ipv6);
+	} else
+		bzero(&j.ip6_number, sizeof(j.ip6_number));
 	i = jail(&j);
 	if (i == -1)
 		err(1, "jail");
@@ -149,7 +159,7 @@ usage(void)
 {
 
 	(void)fprintf(stderr, "%s%s\n",
-	     "usage: jail [-i] [-l -u username | -U username]",
+	     "usage: jail [-i] [-6 ip6-number] [-l -u username | -U username]",
 	     " path hostname ip-number command ...");
 	exit(1);
 }

Attachment: pgpD9l49q7Dkx.pgp
Description: PGP signature

Reply via email to