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); }
pgpD9l49q7Dkx.pgp
Description: PGP signature