Name resolution from a jail

Simon 'corecode' Schubert corecode at fs.ei.tum.de
Wed Jan 17 07:33:49 PST 2007


Simon 'corecode' Schubert wrote:
This is a multi-part message in MIME format.
--------------000808030508040705030804
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: quoted-printable
YONETANI Tomokazu wrote:
$ w
 6:13PM  up  2:52, 1 user, load averages: 0.19, 0.25, 0.13
USER             TTY      FROM              LOGIN@  IDLE WHAT
(press control+Z here, as it's stuck on reverse name resolution)
$ netstat -anfinet |fgrep .53
udp4       0      0 64.125.66.215.1119    192.168.2.175.53
                    ~~~~~~~~~~~~~
                    this address doesn't belong to our network.
I found a stack reference bug and took the chance to clean up the code.  =
Please have a look at attached patch.  If victor agrees, I'll commit this=
=2E
sorry for the broken MIME.  My enigmail from cvs seems to be quite broken.  patch attached again.

somebody please commit this if it works.

cheers
 simon
--
Serve - BSD     +++  RENT this banner advert  +++    ASCII Ribbon   /"\
Work - Mac      +++  space for low €€€ NOW!1  +++      Campaign     \ /
Party Enjoy Relax   |   http://dragonflybsd.org      Against  HTML   \
Dude 2c 2 the max   !   http://golden-apple.biz       Mail + News   / \
Index: sys/jail.h
===================================================================
RCS file: /home/dcvs/src/sys/sys/jail.h,v
retrieving revision 1.9
diff -u -p -r1.9 jail.h
--- sys/jail.h	29 Dec 2006 18:02:56 -0000	1.9
+++ sys/jail.h	17 Jan 2007 12:45:47 -0000
@@ -68,8 +68,8 @@ MALLOC_DECLARE(M_PRISON);
 /* Used to store the IPs of the jail */
 
 struct jail_ip_storage {
-	SLIST_ENTRY(jail_ip_storage) entries;
 	struct sockaddr_storage ip;
+	SLIST_ENTRY(jail_ip_storage) entries;
 };
 
 /*
@@ -85,10 +85,10 @@ struct prison {
 	struct nchandle pr_root;			/* namecache entry of root */
 	char 		pr_host[MAXHOSTNAMELEN];	/* host name */
 	SLIST_HEAD(iplist, jail_ip_storage) pr_ips;	/* list of IP addresses */
-	struct sockaddr_storage	*local_ip4;		/* cache for a loopback ipv4 address */
-	struct sockaddr_storage	*nonlocal_ip4;		/* cache for a non loopback ipv4 address */
-	struct sockaddr_storage	*local_ip6;		/* cache for a loopback ipv6 address */
-	struct sockaddr_storage	*nonlocal_ip6;		/* cache for a non loopback ipv6 address */
+	struct sockaddr_in	*local_ip4;		/* cache for a loopback ipv4 address */
+	struct sockaddr_in	*nonlocal_ip4;		/* cache for a non loopback ipv4 address */
+	struct sockaddr_in6	*local_ip6;		/* cache for a loopback ipv6 address */
+	struct sockaddr_in6	*nonlocal_ip6;		/* cache for a non loopback ipv6 address */
 	void		*pr_linux;			/* Linux ABI emulation */
 	int		 pr_securelevel;		/* jail securelevel */
 	struct varsymset pr_varsymset;			/* jail varsyms */
@@ -105,8 +105,10 @@ extern int	jail_chflags_allowed;
 void	prison_hold(struct prison *);
 void	prison_free(struct prison *);
 int	jailed_ip(struct prison *, struct sockaddr *);
-int	prison_get_local(struct prison *pr, struct sockaddr *);
-int	prison_get_nonlocal(struct prison *pr, struct sockaddr *);
+struct sockaddr *
+	prison_get_local(struct prison *pr, sa_family_t, struct sockaddr *);
+struct sockaddr *
+	prison_get_nonlocal(struct prison *pr, sa_family_t, struct sockaddr *);
 
 /*
  * Return 1 if the passed credential is in a jail, otherwise 0.
Index: kern/kern_jail.c
===================================================================
RCS file: /home/dcvs/src/sys/kern/kern_jail.c,v
retrieving revision 1.16
diff -u -p -r1.16 kern_jail.c
--- kern/kern_jail.c	1 Jan 2007 19:45:54 -0000	1.16
+++ kern/kern_jail.c	17 Jan 2007 12:53:16 -0000
@@ -59,6 +59,7 @@
 #include <netinet6/in6_var.h>
 
 static struct prison	*prison_find(int);
+static void		prison_ipcache_init(struct prison *);
 
 MALLOC_DEFINE(M_PRISON, "prison", "Prison structures");
 
@@ -195,6 +196,7 @@ sys_jail(struct jail_args *uap)
 	cache_copy(&nd.nl_nch, &pr->pr_root);
 
 	varsymset_init(&pr->pr_varsymset, NULL);
+	prison_ipcache_init(pr);
 
 	tryprid = lastprid + 1;
 	if (tryprid == JAIL_MAX)
@@ -255,6 +257,45 @@ sys_jail_attach(struct jail_attach_args 
 	return(kern_jail_attach(uap->jid));
 }
 
+static void
+prison_ipcache_init(struct prison *pr)
+{
+	struct jail_ip_storage *jis;
+	struct sockaddr_in *ip4;
+	struct sockaddr_in6 *ip6;
+
+	SLIST_FOREACH(jis, &pr->pr_ips, entries) {
+		switch (jis->ip.ss_family) {
+		case AF_INET:
+			ip4 = (struct sockaddr_in *)&jis->ip;
+			if ((ntohl(ip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) ==
+			    IN_LOOPBACKNET) {
+				/* loopback address */
+				if (pr->local_ip4 == NULL)
+					pr->local_ip4 = ip4;
+			} else {
+				/* public address */
+				if (pr->nonlocal_ip4 == NULL)
+					pr->nonlocal_ip4 = ip4;
+			}
+			break;
+
+		case AF_INET6:
+			ip6 = (struct sockaddr_in6 *)&jis->ip;
+			if (IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr)) {
+				/* loopback address */
+				if (pr->local_ip6 == NULL)
+					pr->local_ip6 = ip6;
+			} else {
+				/* public address */
+				if (pr->nonlocal_ip6 == NULL)
+					pr->nonlocal_ip6 = ip6;
+			}
+			break;
+		}
+	}
+}
+
 /* 
  * Changes INADDR_LOOPBACK for a valid jail address.
  * ip is in network byte order.
@@ -284,7 +325,8 @@ prison_replace_wildcards(struct thread *
 	    ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
 	    (ip->sa_family == AF_INET6 &&
 	    IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
-		if (!prison_get_local(pr, ip) && !prison_get_nonlocal(pr, ip))
+		if (!prison_get_local(pr, ip->sa_family, ip) &&
+		    !prison_get_nonlocal(pr, ip->sa_family, ip))
 			return(0);
 		else
 			return(1);
@@ -309,7 +351,8 @@ prison_remote_ip(struct thread *td, stru
 	    ip4->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) ||
 	    (ip->sa_family == AF_INET6 &&
 	    IN6_IS_ADDR_LOOPBACK(&ip6->sin6_addr))) {
-		if (!prison_get_local(pr, ip) && !prison_get_nonlocal(pr, ip))
+		if (!prison_get_local(pr, ip->sa_family, ip) &&
+		    !prison_get_nonlocal(pr, ip->sa_family, ip))
 			return(0);
 		else
 			return(1);
@@ -319,135 +362,68 @@ prison_remote_ip(struct thread *td, stru
 
 /*
  * Prison get non loopback ip:
- * Put on *ip the first IP address that is not a loopback address.
- * af is the address family of the ip we want (AF_INET|AF_INET6).
+ * - af is the address family of the ip we want (AF_INET|AF_INET6).
+ * - If ip != NULL, put the first IP address that is not a loopback address
+ *   into *ip.
+ *
  * ip is in network by order and we don't touch it unless we find a valid ip.
- * Return 1 if we've found a non loopback ip, else return 0.
+ * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
+ * or NULL.  This struct may not be modified.
  */
-int
-prison_get_nonlocal(struct prison *pr, struct sockaddr *ip)
+struct sockaddr *
+prison_get_nonlocal(struct prison *pr, sa_family_t af, struct sockaddr *ip)
 {
-	struct jail_ip_storage *jis;
-	struct sockaddr_in *jip4, *ip4;
-	struct sockaddr_in6 *jip6, *ip6;
+	struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
+	struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
 
-	ip4 = (struct sockaddr_in *)ip;
-	ip6 = (struct sockaddr_in6 *)ip;
 	/* Check if it is cached */
-	switch(ip->sa_family) {
-		case AF_INET:
-			/* -1 Means that we don't have any address */
-			if (pr->nonlocal_ip4 == (struct sockaddr_storage *)-1)
-				return(0);
-			if (pr->nonlocal_ip4 != NULL) {
-				jip4 = (struct sockaddr_in *) pr->nonlocal_ip4;
-				ip4->sin_addr.s_addr = jip4->sin_addr.s_addr;
-			}
-		break;
-		case AF_INET6:
-			/* -1 Means that we don't have any address */
-			if (pr->nonlocal_ip6 == (struct sockaddr_storage *)-1)
-				return(0);
-			if (pr->nonlocal_ip6 != NULL) {
-				jip6 = (struct sockaddr_in6 *) pr->nonlocal_ip6;
-				ip6->sin6_addr = jip6->sin6_addr;
-			}
-		break;
-	};
-	SLIST_FOREACH(jis, &pr->pr_ips, entries) {
-		switch (ip->sa_family) {
-		case AF_INET:
-			jip4 = (struct sockaddr_in *) &jis->ip;
-			if (jip4->sin_family == AF_INET &&
-    ((ntohl(jip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT) != IN_LOOPBACKNET)) {
-				pr->nonlocal_ip4 = &jis->ip;
-				ip4->sin_addr.s_addr = jip4->sin_addr.s_addr;
-				return(1);
-			}
-			break;
-		case AF_INET6:
-			jip6 = (struct sockaddr_in6 *) &jis->ip;
-			if ( jip6->sin6_family == AF_INET6 &&
-			     !IN6_IS_ADDR_LOOPBACK(&jip6->sin6_addr)) {
-				pr->nonlocal_ip6 = &jis->ip;
-				ip6->sin6_addr = jip6->sin6_addr;
-				return(1);
-			}
-			break;
-		}
+	switch(af) {
+	case AF_INET:
+		if (ip4 != NULL && pr->nonlocal_ip4 != NULL)
+			ip4->sin_addr.s_addr = pr->nonlocal_ip4->sin_addr.s_addr;
+		return (struct sockaddr *)pr->nonlocal_ip4;
+
+	case AF_INET6:
+		if (ip6 != NULL && pr->nonlocal_ip6 != NULL)
+			ip6->sin6_addr = pr->nonlocal_ip6->sin6_addr;
+		return (struct sockaddr *)pr->nonlocal_ip6;
 	}
-	if (ip->sa_family == AF_INET)
-		pr->nonlocal_ip4 = (struct sockaddr_storage *)-1;
-	else
-		pr->nonlocal_ip6 = (struct sockaddr_storage *)-1;
-	return(0);
+
+	/* NOTREACHED */
+	return NULL;
 }
 
 /*
  * Prison get loopback ip.
- * Put on *ip the first loopback IP address.
- * af is the address family of the ip we want (AF_INET|PF_INET).
- * *ip is in network by order and we don't touch it unless we find a valid ip.
- * return 1 if we've found a loopback ip, else return 0.
+ * - af is the address family of the ip we want (AF_INET|AF_INET6).
+ * - If ip != NULL, put the first IP address that is not a loopback address
+ *   into *ip.
+ *
+ * ip is in network by order and we don't touch it unless we find a valid ip.
+ * No matter if ip == NULL or not, we return either a valid struct sockaddr *,
+ * or NULL.  This struct may not be modified.
  */
-int
-prison_get_local(struct prison *pr, struct sockaddr *ip)
+struct sockaddr *
+prison_get_local(struct prison *pr, sa_family_t af, struct sockaddr *ip)
 {
-	struct jail_ip_storage *jis;
-	struct sockaddr_in *jip4, *ip4;
-	struct sockaddr_in6 *jip6, *ip6;
+	struct sockaddr_in *ip4 = (struct sockaddr_in *)ip;
+	struct sockaddr_in6 *ip6 = (struct sockaddr_in6 *)ip;
 
-	ip4 = (struct sockaddr_in *)ip;
-	ip6 = (struct sockaddr_in6 *)ip;
 	/* Check if it is cached */
-	switch(ip->sa_family) {
-		case AF_INET:
-			/* -1 Means that we don't have any address */
-			if (pr->local_ip4 == (struct sockaddr_storage *)-1)
-				return(0);
-			if (pr->local_ip4 != NULL) {
-				jip4 = (struct sockaddr_in *) pr->local_ip4;
-				ip4->sin_addr.s_addr = jip4->sin_addr.s_addr;
-			}
-		break;
-		case AF_INET6:
-			/* -1 Means that we don't have any address */
-			if (pr->local_ip6 == (struct sockaddr_storage *)-1)
-				return(0);
-			if (pr->local_ip6 != NULL) {
-				jip6 = (struct sockaddr_in6 *) pr->local_ip6;
-				ip6->sin6_addr = jip6->sin6_addr;
-			}
-		break;
-	};
-	SLIST_FOREACH(jis, &pr->pr_ips, entries) {
-		switch(ip->sa_family) {
-		case AF_INET:
-			jip4 = (struct sockaddr_in *) &jis->ip;
-			if (jip4->sin_family == AF_INET &&
-			    ((ntohl(jip4->sin_addr.s_addr) >> IN_CLASSA_NSHIFT)
-			    == IN_LOOPBACKNET)) {
-				pr->local_ip4 = &jis->ip;
-				ip4->sin_addr.s_addr = jip4->sin_addr.s_addr;
-				return(1);
-			}
-			break;
-		case AF_INET6:
-			jip6 = (struct sockaddr_in6 *) &jis->ip;
-			if (jip6->sin6_family == AF_INET6 &&
-			     IN6_IS_ADDR_LOOPBACK(&jip6->sin6_addr)) {
-				pr->local_ip6 = &jis->ip;
-				ip6->sin6_addr = jip6->sin6_addr;
-				return(1);
-			}
-			break;
-		}
+	switch(af) {
+	case AF_INET:
+		if (ip4 != NULL && pr->local_ip4 != NULL)
+			ip4->sin_addr.s_addr = pr->local_ip4->sin_addr.s_addr;
+		return (struct sockaddr *)pr->local_ip4;
+
+	case AF_INET6:
+		if (ip6 != NULL && pr->local_ip6 != NULL)
+			ip6->sin6_addr = pr->local_ip6->sin6_addr;
+		return (struct sockaddr *)pr->local_ip6;
 	}
-	if (ip->sa_family == AF_INET)
-		pr->local_ip4 = (struct sockaddr_storage *)-1;
-	else
-		pr->local_ip6 = (struct sockaddr_storage *)-1;
-	return(0);
+
+	/* NOTREACHED */
+	return NULL;
 }
 
 /* Check if the IP is among ours, if it is return 1, else 0 */
Index: netinet/in_pcb.c
===================================================================
RCS file: /home/dcvs/src/sys/netinet/in_pcb.c,v
retrieving revision 1.41
diff -u -p -r1.41 in_pcb.c
--- netinet/in_pcb.c	29 Dec 2006 18:02:56 -0000	1.41
+++ netinet/in_pcb.c	17 Jan 2007 12:58:07 -0000
@@ -457,7 +457,7 @@ in_pcbladdr(struct inpcb *inp, struct so
 	struct in_ifaddr *ia;
 	struct ucred *cred = NULL;
 	struct sockaddr_in *sin = (struct sockaddr_in *)nam;
-	struct sockaddr_in jsin;
+	struct sockaddr *jsin;
 	int jailed = 0;
 
 	if (nam->sa_len != sizeof *sin)
@@ -579,14 +579,13 @@ in_pcbladdr(struct inpcb *inp, struct so
 		 * Don't do pcblookup call here; return interface in plocal_sin
 		 * and exit to caller, that will do the lookup.
 		 */
-		if (jailed) {
-			jsin.sin_family = AF_INET;
-			if (!prison_get_nonlocal(cred->cr_prison,
-			    sintosa(&jsin)) &&
-			    !prison_get_local(cred->cr_prison, sintosa(&jsin)))
-					/* IPv6 only Jail */
-					return (EADDRNOTAVAIL);
-			*plocal_sin = &jsin;
+		if (ia == NULL && jailed) {
+			if ((jsin = prison_get_nonlocal(cred->cr_prison, AF_INET, NULL)) != NULL ||
+			    (jsin = prison_get_local(cred->cr_prison, AF_INET, NULL)) != NULL)
+				*plocal_sin = satosin(jsin);
+			else
+				/* IPv6 only Jail */
+				return (EADDRNOTAVAIL);
 		} else {
 			*plocal_sin = &ia->ia_addr;
 		}
Attachment:
signature.asc
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pgp00012.pgp
Type: application/octet-stream
Size: 252 bytes
Desc: "Description: OpenPGP digital signature"
URL: <http://lists.dragonflybsd.org/pipermail/bugs/attachments/20070117/d8413edb/attachment-0020.obj>


More information about the Bugs mailing list