diff -urN src.orig/sys/kern/kern_jail.c src/sys/kern/kern_jail.c --- src.orig/sys/kern/kern_jail.c Tue Sep 5 16:03:30 2006 +++ src/sys/kern/kern_jail.c Tue Sep 5 16:36:02 2006 @@ -112,7 +112,7 @@ error = copyin(uap->jail, &j, sizeof(j)); if (error) return (error); - if (j.version != 0) + if (j.version != 1) return (EINVAL); MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); @@ -135,7 +135,15 @@ error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); if (error) goto e_dropvnref; - pr->pr_ip = j.ip_number; + if (j.nips >= JAIL_MAX_IPS) + goto e_dropvnref; + MALLOC(pr->pr_ips, u_int32_t *, sizeof(u_int32_t) * j.nips, + M_PRISON, M_WAITOK); + error = copyin(j.ips, pr->pr_ips, sizeof(u_int32_t) * j.nips); + if (error) + goto e_freeips; + pr->pr_nips = j.nips; + pr->pr_linux = NULL; pr->pr_securelevel = securelevel; @@ -151,7 +159,7 @@ if (tryprid == JAIL_MAX) { mtx_unlock(&allprison_mtx); error = EAGAIN; - goto e_dropvnref; + goto e_freeips; } goto next; } @@ -174,6 +182,10 @@ LIST_REMOVE(pr, pr_list); prisoncount--; mtx_unlock(&allprison_mtx); + +e_freeips: + FREE(pr->pr_ips, M_PRISON); + e_dropvnref: mtx_lock(&Giant); vrele(pr->pr_root); @@ -306,6 +318,7 @@ mtx_destroy(&pr->pr_mtx); if (pr->pr_linux != NULL) FREE(pr->pr_linux, M_PRISON); + FREE(pr->pr_ips, M_PRISON); FREE(pr, M_PRISON); } @@ -322,7 +335,7 @@ prison_getip(struct ucred *cred) { - return (cred->cr_prison->pr_ip); + return (cred->cr_prison->pr_ips[0]); } int @@ -338,21 +351,21 @@ tmp = ntohl(*ip); if (tmp == INADDR_ANY) { if (flag) - *ip = cred->cr_prison->pr_ip; + *ip = cred->cr_prison->pr_ips[0]; else - *ip = htonl(cred->cr_prison->pr_ip); + *ip = htonl(cred->cr_prison->pr_ips[0]); return (0); } if (tmp == INADDR_LOOPBACK) { if (flag) - *ip = cred->cr_prison->pr_ip; + *ip = cred->cr_prison->pr_ips[0]; else - *ip = htonl(cred->cr_prison->pr_ip); + *ip = htonl(cred->cr_prison->pr_ips[0]); return (0); } - if (cred->cr_prison->pr_ip != tmp) - return (1); - return (0); + + if (jailed_ip(cred, tmp)) return (0); + return (1); } void @@ -368,15 +381,36 @@ tmp = ntohl(*ip); if (tmp == INADDR_LOOPBACK) { if (flag) - *ip = cred->cr_prison->pr_ip; + *ip = cred->cr_prison->pr_ips[0]; else - *ip = htonl(cred->cr_prison->pr_ip); + *ip = htonl(cred->cr_prison->pr_ips[0]); return; } return; } int +jailed_ip(struct ucred *cred, u_int32_t ip) +{ + register struct prison *pr; + register u_int i; + + if (!jailed(cred)) + return(1); + + pr = cred->cr_prison; + for (i = 0; i < pr->pr_nips; ++i) { + if (pr->pr_ips[i] == ip) + return (1); + } + + return (0); +} + + + + +int prison_if(struct ucred *cred, struct sockaddr *sa) { struct sockaddr_in *sai; @@ -387,7 +421,7 @@ ok = 1; else if (sai->sin_family != AF_INET) ok = 0; - else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr)) + else if (!jailed_ip(cred, ntohl(sai->sin_addr.s_addr))) ok = 1; else ok = 0; @@ -483,7 +517,8 @@ xp->pr_id = pr->pr_id; strlcpy(xp->pr_path, pr->pr_path, sizeof(xp->pr_path)); strlcpy(xp->pr_host, pr->pr_host, sizeof(xp->pr_host)); - xp->pr_ip = pr->pr_ip; + memcpy(xp->pr_ips, pr->pr_ips, sizeof(u_int32_t) * pr->pr_nips); + xp->pr_nips = pr->pr_nips; mtx_unlock(&pr->pr_mtx); xp++; } diff -urN src.orig/sys/netinet/in_pcb.c src/sys/netinet/in_pcb.c --- src.orig/sys/netinet/in_pcb.c Tue Sep 5 16:03:35 2006 +++ src/sys/netinet/in_pcb.c Tue Sep 5 17:36:55 2006 @@ -303,9 +303,8 @@ if (sin->sin_family != AF_INET) return (EAFNOSUPPORT); #endif - if (sin->sin_addr.s_addr != INADDR_ANY) - if (prison_ip(cred, 0, &sin->sin_addr.s_addr)) - return(EINVAL); + if (prison_ip(cred, 0, &sin->sin_addr.s_addr)) + return(EINVAL); if (sin->sin_port != *lportp) { /* Don't allow the port to change. */ if (*lportp != 0) @@ -360,8 +359,9 @@ t->inp_socket->so_cred->cr_uid)) return (EADDRINUSE); } - if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr)) - return (EADDRNOTAVAIL); + if (prison) + if (prison_ip(cred, 0, &sin->sin_addr.s_addr)) + return (EADDRNOTAVAIL); t = in_pcblookup_local(pcbinfo, sin->sin_addr, lport, prison ? 0 : wild); if (t && (t->inp_vflag & INP_TIMEWAIT)) { @@ -388,9 +388,8 @@ u_short first, last; int count; - if (laddr.s_addr != INADDR_ANY) - if (prison_ip(cred, 0, &laddr.s_addr)) - return (EINVAL); + if (prison_ip(cred, 0, &laddr.s_addr)) + return (EINVAL); if (inp->inp_flags & INP_HIGHPORT) { first = ipport_hifirstauto; /* sysctl */ diff -urN src.orig/sys/netinet/raw_ip.c src/sys/netinet/raw_ip.c --- src.orig/sys/netinet/raw_ip.c Tue Sep 5 16:03:35 2006 +++ src/sys/netinet/raw_ip.c Tue Sep 5 17:48:58 2006 @@ -213,8 +213,7 @@ inp->inp_faddr.s_addr != ip->ip_src.s_addr) goto docontinue; if (jailed(inp->inp_socket->so_cred)) - if (htonl(prison_getip(inp->inp_socket->so_cred)) != - ip->ip_dst.s_addr) + if (!jailed_ip(inp->inp_socket->so_cred, ntohl(ip->ip_dst.s_addr))) goto docontinue; if (last) { struct mbuf *n; @@ -286,8 +285,8 @@ INP_LOCK(inp); ip = mtod(m, struct ip *); if (jailed(inp->inp_socket->so_cred)) { - if (ip->ip_src.s_addr != - htonl(prison_getip(inp->inp_socket->so_cred))) { + if (!jailed_ip(inp->inp_socket->so_cred, + ntohl(ip->ip_src.s_addr))) { INP_UNLOCK(inp); m_freem(m); return (EPERM); diff -urN src.orig/sys/sys/jail.h src/sys/sys/jail.h --- src.orig/sys/sys/jail.h Tue Sep 5 16:03:38 2006 +++ src/sys/sys/jail.h Tue Sep 5 17:51:39 2006 @@ -17,17 +17,21 @@ u_int32_t version; char *path; char *hostname; - u_int32_t ip_number; + u_int32_t *ips; + u_int nips; }; +#define JAIL_MAX_IPS 256 + struct xprison { int pr_version; int pr_id; char pr_path[MAXPATHLEN]; char pr_host[MAXHOSTNAMELEN]; - u_int32_t pr_ip; + u_int32_t pr_ips[JAIL_MAX_IPS]; + u_int pr_nips; }; -#define XPRISON_VERSION 1 +#define XPRISON_VERSION 2 #ifndef _KERNEL @@ -66,7 +70,8 @@ char pr_path[MAXPATHLEN]; /* (c) chroot path */ 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_int32_t *pr_ips; /* (c) jail's ips */ + u_int pr_nips; /* (c) number of ips */ void *pr_linux; /* (p) linux abi */ int pr_securelevel; /* (p) securelevel */ struct task pr_task; /* (d) destroy task */ @@ -104,6 +109,7 @@ 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 jailed_ip(struct ucred *cred, u_int32_t ip); #endif /* !_KERNEL */ #endif /* !_SYS_JAIL_H_ */ diff -u src.orig/usr.sbin/jail/jail.c src/usr.sbin/jail/jail.c --- src.orig/usr.sbin/jail/jail.c Sun May 28 06:01:55 2006 +++ src/usr.sbin/jail/jail.c Thu Nov 16 14:38:43 2006 @@ -61,6 +61,9 @@ const char *shell, *p = NULL; long ltmp; FILE *fp; + int c; + char *ip; + iflag = Jflag = lflag = uflag = Uflag = 0; securelevel = -1; @@ -112,12 +115,26 @@ if (chdir(path) != 0) err(1, "chdir: %s", path); memset(&j, 0, sizeof(j)); - j.version = 0; + j.version = 1; j.path = path; j.hostname = argv[1]; - 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); + for (c = 1, ip = argv[2]; *ip; ++ip) { + if (*ip == ',') + ++c; + } + if ((j.ips = (u_int32_t *)malloc(sizeof(u_int32_t) * c)) == NULL) + errx(1, "malloc()"); + for (c = 0, ip = strtok(argv[2], ","); ip; + ++c, ip = strtok(NULL, ",")) { + i = inet_aton(ip, &in); + if (!i) { + free(j.ips); + errx(1, "Couldn't make sense of ip-number\n"); + } + j.ips[c] = ntohl(in.s_addr); + } + j.nips = c; + if (Jflag) { fp = fopen(JidFile, "w"); if (fp == NULL) @@ -178,6 +195,7 @@ exit(0); } + static void usage(void) { @@ -185,6 +203,6 @@ (void)fprintf(stderr, "%s%s%s\n", "usage: jail [-i] [-J jid_file] [-s securelevel] [-l -u ", "username | -U username]", - " path hostname ip-number command ..."); + " path hostname ip1[,ip2,[...]] command ..."); exit(1); } --- src.orig/usr.sbin/jls/jls.c Fri Aug 19 15:09:11 2005 +++ src/usr.sbin/jls/jls.c Thu Nov 23 16:11:03 2006 @@ -43,7 +43,7 @@ { struct xprison *sxp, *xp; struct in_addr in; - size_t i, len; + size_t i, len, ipindex; if (sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1) err(1, "sysctlbyname(): security.jail.list"); @@ -71,11 +71,20 @@ xp->pr_version != XPRISON_VERSION) errx(1, "Kernel and userland out of sync"); - printf(" JID IP Address Hostname Path\n"); + printf(" JID Hostname Path\n"); for (i = 0; i < len / sizeof(*xp); i++) { - in.s_addr = ntohl(xp->pr_ip); - printf("%6d %-15.15s %-29.29s %.74s\n", - xp->pr_id, inet_ntoa(in), xp->pr_host, xp->pr_path); + printf("%6d %-29.29s %.74s\n", + xp->pr_id, xp->pr_host, xp->pr_path); + printf(" IPs: "); + for(ipindex=0;ipindexpr_nips;ipindex++) { + in.s_addr = ntohl(xp->pr_ips[ipindex]); + printf("%s",inet_ntoa(in)); + if(ipindexpr_nips-1) { + printf(", "); + } else { + printf("\n"); + } + } xp++; } free(sxp);