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-0022.obj>
More information about the Bugs
mailing list