Date: Wed, 14 Jul 2004 21:21:30 +0200 From: "Meno Abels" <abels@adviser.com> To: FreeBSD-gnats-submit@FreeBSD.org Cc: Meno Abels <abels@adviser.com> Subject: kern/69064: No multiple ip4/6's could assigned to a jail. Message-ID: <20040714192137.A623484040@pmff.de> Resent-Message-ID: <200407141930.i6EJUWVY016744@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 69064 >Category: kern >Synopsis: No multiple ip4/6's could assigned to a jail. >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Wed Jul 14 19:30:32 GMT 2004 >Closed-Date: >Last-Modified: >Originator: Meno Abels >Release: FreeBSD 5.2-CURRENT >Organization: Adviser.com >Environment: System: FreeBSD race 5.2-CURRENT FreeBSD 5.2-CURRENT #29: Fri May 28 23:44:16 CEST 2004 root@neo.abels.adviser.com:/usr/obj/usr/src/sys/DISKLESS i386 >Description: I missed the feature that a jail is able to handle multiple ip numbers. Also i want that ipv6 is working with the jail. >How-To-Repeat: no way >Fix: Here is the patch for this feature. I tested it, but I'am not very safe about the ipv6 stuff. I'am not a expert in ipv6 so it could be that i missed some checks for the prison. I also change the jail/jls utility. Index: sys/kern/kern_fork.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/kern/kern_fork.c,v retrieving revision 1.228 diff -r1.228 kern_fork.c 303c303 < if ((nprocs >= maxproc - 10 && suser(td->td_ucred) != 0) || --- > if ((nprocs >= maxproc - 10 && suser(td) != 0) || Index: sys/kern/kern_jail.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/kern/kern_jail.c,v retrieving revision 1.44 diff -r1.44 kern_jail.c 35a36 > #include <netinet6/in6_var.h> 37a39,40 > MALLOC_DEFINE(M_PRISON_IP4, "prison", "Prison ipv4 addresses"); > MALLOC_DEFINE(M_PRISON_IP6, "prison", "Prison ipv6 addresses"); 77a81,85 > static int prison_add_ip4(struct in_addr *tmpv4, struct prison *pr, void *pr_new, void **pr_old); > static int prison_add_ip6(struct in6_addr *tmpv4, struct prison *pr, void *pr_new, void **pr_old); > static int prison_del_ip4(struct in_addr *tmpv4, struct prison *pr, void *pr_new, void **pr_old); > static int prison_del_ip6(struct in6_addr *tmpv4, struct prison *pr, void *pr_new, void **pr_old); > static int prison_check_duplicate(char *hostname, char *path); 98,99c106,107 < int < jail(struct thread *td, struct jail_args *uap) --- > static int > jail_createjail(struct thread *td, char *user_hostname, char *user_path, struct prison **pr) 100a109 > int error; 102,105d110 < struct prison *pr, *tpr; < struct jail j; < struct jail_attach_args jaa; < int error, tryprid; 107c112,115 < error = copyin(uap->jail, &j, sizeof(j)); --- > MALLOC(*pr, struct prison *, sizeof(**pr), M_PRISON, M_WAITOK | M_ZERO); > mtx_init(&(*pr)->pr_mtx, "jail mutex", NULL, MTX_DEF); > (*pr)->pr_ref = 1; > error = copyinstr(user_path, &(*pr)->pr_path, sizeof((*pr)->pr_path), 0); 109,116c117,118 < return (error); < if (j.version != 0) < return (EINVAL); < < MALLOC(pr, struct prison *, sizeof(*pr), M_PRISON, M_WAITOK | M_ZERO); < mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF); < pr->pr_ref = 1; < error = copyinstr(j.path, &pr->pr_path, sizeof(pr->pr_path), 0); --- > goto e_killmtx; > error = copyinstr(user_hostname, &(*pr)->pr_host, sizeof((*pr)->pr_host), 0); 118a121,125 > if (prison_check_duplicate((*pr)->pr_host, (*pr)->pr_path)) { > error = EAGAIN; > goto e_killmtx; > } > 120c127 < NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, pr->pr_path, td); --- > NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, (*pr)->pr_path, td); 126c133 < pr->pr_root = nd.ni_vp; --- > (*pr)->pr_root = nd.ni_vp; 130,135d136 < error = copyinstr(j.hostname, &pr->pr_host, sizeof(pr->pr_host), 0); < if (error) < goto e_dropvnref; < pr->pr_ip = j.ip_number; < pr->pr_linux = NULL; < pr->pr_securelevel = securelevel; 136a138,278 > (*pr)->pr_linux = NULL; > (*pr)->pr_securelevel = securelevel; > return (0); > > e_killmtx: > mtx_destroy(&(*pr)->pr_mtx); > FREE(*pr, M_PRISON); > return (error); > > } > > > static void > jail_dropvnref(struct prison *pr) > { > mtx_lock(&Giant); > vrele(pr->pr_root); > mtx_unlock(&Giant); > } > > int > jail(struct thread *td, struct jail_args *uap) > { > struct prison *pr, *tpr; > struct jail j; > struct jail_attach_args jaa; > int error, tryprid; > void *pr_new = 0; > void *pr_old = 0; > > error = copyin(uap->jail, &j, sizeof(j)); > if (error) > return (error); > if (j.version < XPRISON_VERSION) > { > struct in_addr tmpv4; > > error = jail_createjail(td, j.u.v1.hostname, j.u.v1.path, &pr); > if (error) { > return error; > } > MALLOC(pr_new, void *, sizeof(struct in_addr)*1, M_PRISON_IP4, M_WAITOK | M_ZERO); > tmpv4.s_addr = htonl(j.u.v1.ip_number); > mtx_lock(&pr->pr_mtx); > error = prison_add_ip4(&tmpv4, pr, pr_new, &pr_old); > mtx_unlock(&pr->pr_mtx); > if (error) { > jail_dropvnref(pr); > } > } > else > { > if (j.u.v2.function == CREATEJAIL) { > error = jail_createjail(td, j.u.v2.u.createjail.hostname, j.u.v2.u.createjail.path, &pr); > if (error) { > return error; > } > } > else { > int cnt = 0; > struct malloc_type *alloc_type; > retry_alloc: > mtx_lock(&allprison_mtx); > pr = prison_find(j.u.v2.u.add_del.id); > if (pr) { > cnt = (j.u.v2.function == ADDIP4 || j.u.v2.function == DELIP4) ? > pr->pr_ip4s : pr->pr_ip6s; > } > mtx_unlock(&pr->pr_mtx); > mtx_unlock(&allprison_mtx); > if (pr == NULL) { > return (EINVAL); > } > if (j.u.v2.function == ADDIP4 || j.u.v2.function == DELIP4) { > alloc_type=M_PRISON_IP4; > if (pr->pr_ip4s >= (j.u.v2.function == DELIP4 ? 2 : 0)) { > MALLOC(pr_new, void *, > sizeof(struct in_addr)*(pr->pr_ip4s+ > (j.u.v2.function == DELIP4 ? -1 : +1)), > alloc_type, M_WAITOK | M_ZERO); > /*printf("pr_ip4s:%d\n", pr->pr_ip4s);*/ > } > } > else { > alloc_type=M_PRISON_IP6; > if (pr->pr_ip6s >= (j.u.v2.function == DELIP6 ? 2 : 0)) { > MALLOC(pr_new, void *, > sizeof(struct in6_addr)*(pr->pr_ip6s+ > (j.u.v2.function == DELIP6 ? -1 : +1)), > alloc_type, M_WAITOK | M_ZERO); > /*printf("pr_ip4s:%d\n", pr->pr_ip6s);*/ > } > } > mtx_lock(&allprison_mtx); > pr = prison_find(j.u.v2.u.add_del.id); > if (pr) > { > if (cnt != ((j.u.v2.function == ADDIP4 || j.u.v2.function == DELIP4) ? > pr->pr_ip4s : pr->pr_ip6s)) > { > /* should i sleep ? */ > mtx_unlock(&pr->pr_mtx); > mtx_unlock(&allprison_mtx); > FREE(pr_new, alloc_type); > /*printf("jail retry alloc\n");*/ > goto retry_alloc; > } > mtx_unlock(&allprison_mtx); > } > else > { > mtx_unlock(&allprison_mtx); > return (EINVAL); > } > > switch (j.u.v2.function) { > case ADDIP4: > error = prison_add_ip4(&j.u.v2.u.add_del.v4_6.ip4_num, pr, pr_new, &pr_old); > break; > case ADDIP6: > error = prison_add_ip6(&j.u.v2.u.add_del.v4_6.ip6_num, pr, pr_new, &pr_old); > break; > case DELIP4: > error = prison_del_ip4(&j.u.v2.u.add_del.v4_6.ip4_num, pr, pr_new, &pr_old); > break; > case DELIP6: > error = prison_del_ip6(&j.u.v2.u.add_del.v4_6.ip6_num, pr, pr_new, &pr_old); > break; > default: > mtx_unlock(&pr->pr_mtx); > return EINVAL; > } > mtx_unlock(&pr->pr_mtx); > if (pr_old) { > /*printf("jail free:%p\n", pr_old);*/ > FREE(pr_old, alloc_type); > } > return (error); > } > } > /* REST of Create Code */ 149c291,292 < goto e_dropvnref; --- > jail_dropvnref(pr); > return error; 166a310 > 172,178c316 < e_dropvnref: < mtx_lock(&Giant); < vrele(pr->pr_root); < mtx_unlock(&Giant); < e_killmtx: < mtx_destroy(&pr->pr_mtx); < FREE(pr, M_PRISON); --- > jail_dropvnref(pr); 250a389,414 > /* return 0 on not duplicate */ > static int > prison_check_duplicate(char *hostname, char *path) > { > struct prison *pr; > mtx_lock(&allprison_mtx); > LIST_FOREACH(pr, &allprison, pr_list) { > if (!strncmp(hostname, pr->pr_host, sizeof(pr->pr_host))) { > mtx_unlock(&allprison_mtx); > return 1; > } > /* this is not perfect remove of trailing / or duplicated // > should be done, who knows the kernel method for this-:) > */ > /* > if (!strncmp(path, pr->pr_path, sizeof(pr->pr_path))) { > mtx_unlock(&allprison_mtx); > return 1; > } > */ > } > mtx_unlock(&allprison_mtx); > return 0; > } > > 301a466,469 > if (pr->pr_ip4 != NULL) > FREE(pr->pr_ip4, M_PRISON_IP4); > if (pr->pr_ip6 != NULL) > FREE(pr->pr_ip6, M_PRISON_IP6); 316,317c484,485 < u_int32_t < prison_getip(struct ucred *cred) --- > int > prison_first_ip4(struct ucred *cred, struct in_addr *out) 318a487,495 > int errno = 0; > mtx_lock(&cred->cr_prison->pr_mtx); > if (cred->cr_prison->pr_ip4s) > *out = cred->cr_prison->pr_ip4[0]; > else > errno = EADDRNOTAVAIL; > mtx_unlock(&cred->cr_prison->pr_mtx); > return errno; > } 320c497,507 < return (cred->cr_prison->pr_ip); --- > int > prison_first_ip6(struct ucred *cred, struct in6_addr *out) > { > int errno = 0; > mtx_lock(&cred->cr_prison->pr_mtx); > if (cred->cr_prison->pr_ip6s) > *out = cred->cr_prison->pr_ip6[0]; > else > errno = EADDRNOTAVAIL; > mtx_unlock(&cred->cr_prison->pr_mtx); > return errno; 324c511 < prison_ip(struct ucred *cred, int flag, u_int32_t *ip) --- > prison_match_ip4(struct ucred *cred, struct in_addr *ip) 330,345c517,537 < if (flag) < tmp = *ip; < else < tmp = ntohl(*ip); < if (tmp == INADDR_ANY) { < if (flag) < *ip = cred->cr_prison->pr_ip; < else < *ip = htonl(cred->cr_prison->pr_ip); < return (0); < } < if (tmp == INADDR_LOOPBACK) { < if (flag) < *ip = cred->cr_prison->pr_ip; < else < *ip = htonl(cred->cr_prison->pr_ip); --- > > for (tmp = 0; tmp < cred->cr_prison->pr_ip4s; ++tmp) > { > if (cred->cr_prison->pr_ip4[tmp].s_addr == ip->s_addr) > { > return 0; > } > } > return (1); > } > > int > prison_redirect_ip4(struct ucred *cred, struct in_addr *ip) > { > if (!jailed(cred)) > return (0); > if (cred->cr_prison->pr_ip4s <= 0) > return (0); > > if (ip->s_addr == htonl(INADDR_ANY)) { > *ip = cred->cr_prison->pr_ip4[0]; 348,350c540,544 < if (cred->cr_prison->pr_ip != tmp) < return (1); < return (0); --- > if (ip->s_addr == htonl(INADDR_LOOPBACK)) { > *ip = cred->cr_prison->pr_ip4[0]; > return (0); > } > return prison_match_ip4(cred, ip); 353,354c547,548 < void < prison_remote_ip(struct ucred *cred, int flag, u_int32_t *ip) --- > int > prison_match_ip6(struct ucred *cred, struct in6_addr *ip) 358a553,588 > return (0); > > for (tmp = 0; tmp < cred->cr_prison->pr_ip6s; ++tmp) > { > if (IN6_ARE_ADDR_EQUAL(&(cred->cr_prison->pr_ip6[tmp]), ip)) > { > return 0; > } > } > return (1); > } > > > int > prison_redirect_ip6(struct ucred *cred, struct in6_addr *ip) > { > if (!jailed(cred)) > return (0); > if (cred->cr_prison->pr_ip6s <= 0) > return (0); > > if (IN6_ARE_ADDR_EQUAL(ip, &in6addr_any)) { > *ip = cred->cr_prison->pr_ip6[0]; > return (0); > } > if (IN6_IS_ADDR_LOOPBACK(ip)) { > *ip = cred->cr_prison->pr_ip6[0]; > return (0); > } > return prison_match_ip6(cred, ip); > } > > void > prison_remote_ip4(struct ucred *cred, struct in_addr *ip) > { > if (!jailed(cred)) 360,368c590,607 < if (flag) < tmp = *ip; < else < tmp = ntohl(*ip); < if (tmp == INADDR_LOOPBACK) { < if (flag) < *ip = cred->cr_prison->pr_ip; < else < *ip = htonl(cred->cr_prison->pr_ip); --- > if (cred->cr_prison->pr_ip4s <= 0) > return; > if (ip->s_addr == INADDR_LOOPBACK) { > *ip = cred->cr_prison->pr_ip4[0]; > return; > } > return; > } > > void > prison_remote_ip6(struct ucred *cred, struct in6_addr *ip) > { > if (!jailed(cred)) > return; > if (cred->cr_prison->pr_ip6s <= 0) > return; > if (IN6_IS_ADDR_LOOPBACK(ip)) { > *ip = cred->cr_prison->pr_ip6[0]; 377,378c616 < struct sockaddr_in *sai; < int ok; --- > int ok = 0; 380,381c618,619 < sai = (struct sockaddr_in *)sa; < if ((sai->sin_family != AF_INET) && jail_socket_unixiproute_only) --- > if (!(sa->sa_family == AF_INET || sa->sa_family == AF_INET6) > && jail_socket_unixiproute_only) 383,388c621,652 < else if (sai->sin_family != AF_INET) < ok = 0; < else if (cred->cr_prison->pr_ip != ntohl(sai->sin_addr.s_addr)) < ok = 1; < else < ok = 0; --- > else > { > if (sa->sa_family == AF_INET) > { > int tmp; > struct sockaddr_in *sai = (struct sockaddr_in *)sa; > ok = 1; > for (tmp = 0; tmp < cred->cr_prison->pr_ip4s; ++tmp) > { > if (cred->cr_prison->pr_ip4[tmp].s_addr == sai->sin_addr.s_addr) > { > ok = 0; > break; > } > } > } > else if (sa->sa_family == AF_INET6) > { > struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; > int tmp; > ok = 1; > for (tmp = 0; tmp < cred->cr_prison->pr_ip6s; ++tmp) > { > if (IN6_ARE_ADDR_EQUAL(&(cred->cr_prison->pr_ip6[tmp]), > &(sa6->sin6_addr))) > { > ok = 0; > break; > } > } > } > } 409a674,805 > * assumes that mtx_lock (pr->mtx) is done > */ > static int > prison_add_ip4(struct in_addr *ip, struct prison *pr, void *vpr_new, void **pr_free) > { > struct in_addr *pr_new = vpr_new; > struct in_addr *wrk_new; > > wrk_new = pr_new; > if (pr->pr_ip4s > 0) > { > struct in_addr *pr_old = pr->pr_ip4; > for (;pr_old < &(pr->pr_ip4[pr->pr_ip4s]) ; ++pr_old) > { > if (pr_old->s_addr == ip->s_addr) > { > *pr_free = pr_new; > return 0; > } > *wrk_new++ = *pr_old; > } > } > *wrk_new = *ip; > ++(pr->pr_ip4s); > if (pr->pr_ip4) > *pr_free = pr->pr_ip4; > pr->pr_ip4 = pr_new; > return 0; > } > > static int > prison_add_ip6(struct in6_addr *ip, struct prison *pr, void *vpr_new, void **pr_free) > { > struct in6_addr *pr_new = vpr_new; > struct in6_addr *wrk_new; > > wrk_new = pr_new; > if (pr->pr_ip6s > 0) > { > struct in6_addr *pr_old = pr->pr_ip6; > for (;pr_old < &(pr->pr_ip6[pr->pr_ip6s]) ; ++pr_old) > { > if (IN6_ARE_ADDR_EQUAL(pr_old, ip)) > { > *pr_free = pr_new; > return 0; > } > *wrk_new++ = *pr_old; > } > } > *wrk_new = *ip; > ++(pr->pr_ip6s); > if (pr->pr_ip6) > *pr_free = pr->pr_ip6; > pr->pr_ip6 = pr_new; > return 0; > } > > static int > prison_del_ip4(struct in_addr *ip, struct prison *pr, void *vpr_new, void **pr_free) > { > struct in_addr *pr_new = vpr_new; > struct in_addr *wrk_new; > int errno = ENOENT; > > wrk_new = pr_new; > if (pr->pr_ip4s > 0) > { > struct in_addr *pr_old = pr->pr_ip4; > for (;pr_old < &(pr->pr_ip4[pr->pr_ip4s]) ; ++pr_old) > { > if (pr_old->s_addr != ip->s_addr) > { > if (wrk_new) { /* remove only if one or more elements remaining */ > *wrk_new++ = *pr_old; > } > } > else > { > errno = 0; /* found element to delete */ > } > } > } > if (errno == 0) > { > --(pr->pr_ip4s); > /* attach new array */ > if (pr->pr_ip4) > *pr_free = pr->pr_ip4; > pr->pr_ip4 = pr_new; > } > return errno; > } > > static int > prison_del_ip6(struct in6_addr *ip, struct prison *pr, void *vpr_new, void **pr_free) > { > struct in6_addr *pr_new = vpr_new; > struct in6_addr *wrk_new; > int errno = ENOENT; > > wrk_new = pr_new; > if (pr->pr_ip6s > 0) > { > struct in6_addr *pr_old = pr->pr_ip6; > for (;pr_old < &(pr->pr_ip6[pr->pr_ip6s]) ; ++pr_old) > { > if (!IN6_ARE_ADDR_EQUAL(pr_old, ip)) > { > if (wrk_new) { /* remove only if one or more elements remaining */ > *wrk_new++ = *pr_old; > } > } > else > { > errno = 0; /* found element to delete */ > } > } > } > if (errno == 0) > { > --(pr->pr_ip6s); > /* attach new array */ > if (pr->pr_ip6) > *pr_free = pr->pr_ip6; > pr->pr_ip6 = pr_new; > } > return errno; > } > > > /* 454a851 > int prcount; 461c858,868 < count = prisoncount; --- > count = 0; > prcount = 0; > LIST_FOREACH(pr, &allprison, pr_list) { > ++prcount; > if (pr->pr_ip4s || pr->pr_ip6s) { > count += max(pr->pr_ip4s, pr->pr_ip6s); > } > else { > ++count; > } > } 466a874 > /*printf("jls:count=%d:%d\n", count, prcount);*/ 469c877 < if (count != prisoncount) { --- > if (prcount != prisoncount) { 476,483c884,911 < mtx_lock(&pr->pr_mtx); < xp->pr_version = XPRISON_VERSION; < 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; < mtx_unlock(&pr->pr_mtx); < xp++; --- > int id = 0; > int i; > int maxcnt = max(pr->pr_ip4s, pr->pr_ip6s); > /*printf("jls:maxcnt=%d\n", maxcnt);*/ > for (i = 0; i < (maxcnt ? maxcnt : 1) ; ++i) > { > /*printf("jls:-0-:%d:%d\n", i, maxcnt);*/ > mtx_lock(&pr->pr_mtx); > xp->pr_version = XPRISON_VERSION; > 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)); > if (i < pr->pr_ip4s) { > xp->pr4_id = id; > xp->pr4_num = pr->pr_ip4[i]; > } > else > xp->pr4_id = -1; > if (i < pr->pr_ip6s) { > xp->pr6_id = id; > xp->pr6_num = pr->pr_ip6[i]; > } > else > xp->pr6_id = -1; > ++id; > mtx_unlock(&pr->pr_mtx); > xp++; > } Index: sys/net/rtsock.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/net/rtsock.c,v retrieving revision 1.112 diff -r1.112 rtsock.c 325c325,326 < struct sockaddr_in jail; --- > struct sockaddr_in jail4; > struct sockaddr_in6 jail6; 440,446c441,466 < bzero(&jail, sizeof(jail)); < jail.sin_family = PF_INET; < jail.sin_len = sizeof(jail); < jail.sin_addr.s_addr = < htonl(prison_getip(so->so_cred)); < info.rti_info[RTAX_IFA] = < (struct sockaddr *)&jail; --- > if (rt->rt_ifa->ifa_addr->sa_family == PF_INET) { > bzero(&jail4, sizeof(jail4)); > jail4.sin_family = PF_INET; > jail4.sin_len = sizeof(jail4); > error = prison_first_ip4(so->so_cred, > &jail4.sin_addr); > if (error) > senderr(error); > info.rti_info[RTAX_IFA] = > (struct sockaddr *)&jail4; > } > else if (rt->rt_ifa->ifa_addr->sa_family == PF_INET6) { > bzero(&jail6, sizeof(jail6)); > jail6.sin6_family = PF_INET6; > jail6.sin6_len = sizeof(jail6); > error = prison_first_ip6(so->so_cred, > &jail6.sin6_addr); > if (error) > senderr(error); > info.rti_info[RTAX_IFA] = > (struct sockaddr *)&jail6; > } > else { > info.rti_info[RTAX_IFA] = > rt->rt_ifa->ifa_addr; > } Index: sys/netinet/in_pcb.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/netinet/in_pcb.c,v retrieving revision 1.150 diff -r1.150 in_pcb.c 293c293 < if (prison_ip(cred, 0, &sin->sin_addr.s_addr)) --- > if (prison_redirect_ip4(cred, &sin->sin_addr)) 358c358 < if (prison && prison_ip(cred, 0, &sin->sin_addr.s_addr)) --- > if (prison && prison_redirect_ip4(cred, &sin->sin_addr)) 387c387 < if (prison_ip(cred, 0, &laddr.s_addr)) --- > if (prison_redirect_ip4(cred, &laddr)) 450c450 < if (prison_ip(cred, 0, &laddr.s_addr)) --- > if (prison_redirect_ip4(cred, &laddr)) 557c557,559 < sa.sin_addr.s_addr = htonl(prison_getip(socred)); --- > error = prison_first_ip4(socred, &sa.sin_addr); > if (error) > return (error); Index: sys/netinet/raw_ip.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/netinet/raw_ip.c,v retrieving revision 1.135 diff -r1.135 raw_ip.c 215a216 > 217,218c218 < if (htonl(prison_getip(inp->inp_socket->so_cred)) != < ip->ip_dst.s_addr) --- > if (prison_match_ip4(inp->inp_socket->so_cred, &(ip->ip_dst))) 275,276c275,284 < ip->ip_src.s_addr = < htonl(prison_getip(inp->inp_socket->so_cred)); --- > { > /* fallback to first ip */ > if (prison_match_ip4(inp->inp_socket->so_cred, &inp->inp_laddr)) { > if ((error = prison_first_ip4(inp->inp_socket->so_cred, > &ip->ip_src)) != 0) > return error; > } > else > ip->ip_src = inp->inp_laddr; > } 289,290c297 < if (ip->ip_src.s_addr != < htonl(prison_getip(inp->inp_socket->so_cred))) { --- > if (prison_match_ip4(inp->inp_socket->so_cred, &ip->ip_src)) { 660a668 > int error; 662,664c670,672 < addr->sin_addr.s_addr = < htonl(prison_getip(td->td_ucred)); < if (htonl(prison_getip(td->td_ucred)) != addr->sin_addr.s_addr) --- > if ((error = prison_first_ip4(td->td_ucred, &addr->sin_addr)) != 0) > return error; > if (prison_match_ip4(td->td_ucred, &addr->sin_addr)) Index: sys/netinet/tcp_usrreq.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/netinet/tcp_usrreq.c,v retrieving revision 1.103 diff -r1.103 tcp_usrreq.c 359c359 < prison_remote_ip(td->td_ucred, 0, &sinp->sin_addr.s_addr); --- > prison_remote_ip4(td->td_ucred, &sinp->sin_addr); 386a387,389 > > if (td && jailed(td->td_ucred)) > prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr); Index: sys/netinet/udp_usrreq.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/netinet/udp_usrreq.c,v retrieving revision 1.156 diff -r1.156 udp_usrreq.c 809c809 < prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr); --- > prison_remote_ip4(td->td_ucred, &sin->sin_addr); 1005c1005 < prison_remote_ip(td->td_ucred, 0, &sin->sin_addr.s_addr); --- > prison_remote_ip4(td->td_ucred, &sin->sin_addr); Index: sys/netinet6/in6_pcb.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/netinet6/in6_pcb.c,v retrieving revision 1.52 diff -r1.52 in6_pcb.c 130a131 > int prison = 0; 148a150,153 > if (!IN6_ARE_ADDR_EQUAL(&in6addr_any, &sin6->sin6_addr)) > if (prison_redirect_ip6(cred, &sin6->sin6_addr)) > return (EINVAL); > 191a197 > prison = jailed(cred); 196c202 < INPLOOKUP_WILDCARD); --- > prison ? 0 : INPLOOKUP_WILDCARD); 238a245,246 > if (prison && prison_redirect_ip6(cred, &sin6->sin6_addr)) > return (EADDRNOTAVAIL); 240c248 < lport, wild); --- > lport, prison ? 0 : wild); Index: sys/netinet6/raw_ip6.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/netinet6/raw_ip6.c,v retrieving revision 1.41 diff -r1.41 raw_ip6.c 70a71 > #include <sys/jail.h> 171a173,177 > > if (jailed(in6p->in6p_socket->so_cred)) > if (prison_match_ip6(in6p->in6p_socket->so_cred, &(ip6->ip6_dst))) > continue; > 416c422,435 < ip6->ip6_src = *in6a; --- > if (jailed(in6p->in6p_socket->so_cred)) > { > /* fallback to first ip */ > if (prison_match_ip6(in6p->in6p_socket->so_cred, in6a)) { > if ((error = prison_first_ip6(in6p->in6p_socket->so_cred, > &ip6->ip6_src)) != 0) > return error; > } > else > ip6->ip6_src = *in6a; > } > else > ip6->ip6_src = *in6a; > 555a575,578 > if (td && jailed(td->td_ucred) && !jail_allow_raw_sockets) { > return (EPERM); > } > 620a644,653 > > if (jailed(td->td_ucred)) { > if (IN6_ARE_ADDR_EQUAL(&(addr->sin6_addr), &in6addr_any)) { > int error; > if ((error = prison_first_ip6(td->td_ucred, &addr->sin6_addr)) != 0) > return error; > } > if (prison_match_ip6(td->td_ucred, &addr->sin6_addr)) > return (EADDRNOTAVAIL); > } Index: sys/netinet6/udp6_output.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/netinet6/udp6_output.c,v retrieving revision 1.18 diff -r1.18 udp6_output.c 69a70 > #include <sys/jail.h> 168a170,171 > if (td && jailed(td->td_ucred)) > prison_remote_ip6(td->td_ucred, &sin6->sin6_addr); Index: sys/netinet6/udp6_usrreq.c =================================================================== RCS file: /usr/freebsd.cvs/src/sys/netinet6/udp6_usrreq.c,v retrieving revision 1.48 diff -r1.48 udp6_usrreq.c 69a70 > #include <sys/jail.h> 590a592 > struct sockaddr_in6 *sin6_p; 597,598d598 < struct sockaddr_in6 *sin6_p; < 620a621,624 > sin6_p = (struct sockaddr_in6 *)nam; > if (td && jailed(td->td_ucred)) > prison_remote_ip6(td->td_ucred, &sin6_p->sin6_addr); > Index: sys/sys/jail.h =================================================================== RCS file: /usr/freebsd.cvs/src/sys/sys/jail.h,v retrieving revision 1.21 diff -r1.21 jail.h 9c9 < * $FreeBSD$ --- > * $FreeBSD: src/sys/sys/jail.h,v 1.18 2003/04/09 02:55:18 mike Exp $ 15a16,27 > #include <netinet/in.h> > > /* > * to safe a system call i reuse the jail systemcall to > * to modify a jail. I will enable the ability to add > * and remove ip4/6 numbers to a jail. > * To get rid of it i playing around with version and > * function numbers. > * A jail id is only create on setup path and hostname > * these values are inmutable. The function number is > * CREATEJAIL > */ 17,20c29,61 < u_int32_t version; < char *path; < char *hostname; < u_int32_t ip_number; --- > u_int32_t version; > union { > struct v1_s { > char *path; > char *hostname; > u_int32_t ip_number; > } v1; > struct v2_s { > u_int32_t function; > #define CREATEJAIL 1 > #define ADDIP4 2 > #define DELIP4 3 > #define ADDIP6 4 > #define DELIP6 5 > union > { > struct > { > char *path; > char *hostname; > } createjail; > struct > { > int id; > union > { > struct in_addr ip4_num; > struct in6_addr ip6_num; > } v4_6; > } add_del; > } u; > } v2; > } u; 28c69,72 < u_int32_t pr_ip; --- > int pr4_id; > struct in_addr pr4_num; /* null is empty */ > int pr6_id; > struct in6_addr pr6_num; /* null is empty */ 30c74 < #define XPRISON_VERSION 1 --- > #define XPRISON_VERSION 6 39a84 > #include <sys/_task.h> 42d86 < #include <sys/_task.h> 57a102 > * (d) set only during destruction of jail, no mutex needed 60d104 < * (d) set only during destruction of jail, no mutex needed 61a106,107 > > struct mtx; 69c115,119 < u_int32_t pr_ip; /* (c) ip addr host */ --- > int pr_ip4s; /* (p) ipv4 addr count */ > struct in_addr *pr_ip4; /* (p) ipv4 addr host */ > int pr_ip6s; /* (p) ipv6 addr count */ > struct in6_addr *pr_ip6; /* (p) ipv6 addr host */ > struct task pr_task; /* (d) destroy task */ 72d121 < struct task pr_task; /* (d) destroy task */ 80a130,131 > extern int jail_getfsstat_jailrootonly; > extern int jail_allow_raw_sockets; 84,85d134 < extern int jail_getfsstat_jailrootonly; < extern int jail_allow_raw_sockets; 94d142 < struct mount; 95a144 > struct mount; 98d146 < int prison_check(struct ucred *cred1, struct ucred *cred2); 99a148 > int prison_check(struct ucred *cred1, struct ucred *cred2); 101c150,153 < u_int32_t prison_getip(struct ucred *cred); --- > int prison_first_ip6(struct ucred *cred, struct in6_addr *out); > int prison_first_ip4(struct ucred *cred, struct in_addr *out); > int prison_match_ip4(struct ucred *cred, struct in_addr *in); > int prison_match_ip6(struct ucred *cred, struct in6_addr *in); 104,105c156,160 < 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 prison_redirect_ip4(struct ucred *cred, struct in_addr *ip); > int prison_redirect_ip6(struct ucred *cred, struct in6_addr *ip); > void prison_remote_ip4(struct ucred *cred, struct in_addr *ip); > void prison_remote_ip6(struct ucred *cred, struct in6_addr *ip); > Index: usr.sbin/jail/jail.8 =================================================================== RCS file: /usr/freebsd.cvs/src/usr.sbin/jail/jail.8,v retrieving revision 1.57 diff -r1.57 jail.8 46c46,49 < .Ar path hostname ip-number command ... --- > .Op Fl j Ar jail identifier > .Op Fl a Ar ip4 or ip6 address > .Op Fl d Ar ip4 or ip6 address > .Ar path hostname [ip4|ip6] command ... 55c58 < Output the jail identifier of the newly created jail. --- > Output the jail identifier of the newly created jail. Only valid without -j. 61c64,73 < The user name from jailed environment as whom the --- > The user name from jailed environment as whom the. Only valid without -j. > .It Fl j Ar jail identifier > This options set the jail identifier which is modified with -a oder -d. > The jail identifier could be retrieved with jls. > .It Fl a Ar ip4 or ip6 > This options add the specified ip number to the jail that is give with -j. You > can only have one -a per call. > .It Fl d Ar ip4 or ip6 > This options deletes the specified ip number from the jail that is give with -j. > You can only have one -d per call. 69c81 < IP number assigned to the prison. --- > IP4 or IP6 number assigned to the prison. Index: usr.sbin/jail/jail.c =================================================================== RCS file: /usr/freebsd.cvs/src/usr.sbin/jail/jail.c,v retrieving revision 1.16 diff -r1.16 jail.c 15a16,17 > #include <sys/types.h> > #include <sys/socket.h> 18a21 > 53c56 < struct in_addr in; --- > int jid = 0; 55a59,62 > char *address; > int add = 0; > int del = 0; > 60c67 < while ((ch = getopt(argc, argv, "iu:U:")) != -1) { --- > while ((ch = getopt(argc, argv, "iu:U:j:a:d:")) != -1) { 72a80,91 > case 'j': > jid = atol(optarg); > break; > case 'a': > add = 1; > address = optarg; > break; > case 'd': > del = 1; > address = optarg; > break; > 79c98,101 < if (argc < 4) --- > if ((jid == 0 && argc < 4) || > (jid < 1 && (add || del)) || > (add && del) || > (jid > 0 && !(add || del))) 80a103,122 > if (jid > 0) { > int function; > if (inet_pton(AF_INET, address, &j.u.v2.u.add_del.v4_6.ip4_num) > 0) { > function = add ? ADDIP4 : DELIP4; > } > else if (inet_pton(AF_INET6, address, &j.u.v2.u.add_del.v4_6.ip6_num) > 0) { > function = add ? ADDIP6 : DELIP6; > } > else { > err(1, "inet_pton: %s", address); > } > j.version = XPRISON_VERSION; > j.u.v2.function = function; > j.u.v2.u.add_del.id = jid; > i = jail(&j); > if (i == -1) > err(1, "jail(%d)", function); > exit (0); > } > 90,95c132,148 < j.version = 0; < 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); --- > j.version = XPRISON_VERSION; > j.u.v2.function = CREATEJAIL; > j.u.v2.u.createjail.path = path; > j.u.v2.u.createjail.hostname = argv[1]; > jid = i = jail(&j); > if (i == -1) > err(1, "jail(CREATEJAIL)"); > > j.version = XPRISON_VERSION; > j.u.v2.u.add_del.id = i; > j.u.v2.function = ADDIP4; > if (inet_pton(AF_INET, address, &j.u.v2.u.add_del.v4_6.ip4_num) <= 0) { > j.u.v2.function = ADDIP6; > if (inet_pton(AF_INET6, address, &j.u.v2.u.add_del.v4_6.ip6_num) <= 0) { > errx(1, "Could not make sense of ip-number: %s", argv[2]); > } > } 98c151,152 < err(1, "jail"); --- > err(1, "jail(%d)", j.u.v2.function); > 100c154 < printf("%d\n", i); --- > printf("%d\n", jid); 124,127c178,180 < (void)fprintf(stderr, "%s%s\n", < "usage: jail [-i] [-u username | -U username]", < " path hostname ip-number command ..."); < exit(1); --- > (void)fprintf(stderr, > "usage: jail [-i] [-u username] [-j id] [[-a [ip4|ip6]|[-d [ip4|ip6]] [path hostname [ip4|ip6] command ...]\n"); > exit(1); Index: usr.sbin/jls/jls.8 =================================================================== RCS file: /usr/freebsd.cvs/src/usr.sbin/jls/jls.8,v retrieving revision 1.1 diff -r1.1 jls.8 35a36,37 > .Op Fl a > .Op Fl 6 39a42,52 > .Pp > The options are as follows: > .Bl -tag -width ".Fl a " > .It Fl a > output all ip4 assigments to the jail identifier(JID). Each ip4 gets > one line in output. If no ip4 address is assigned 0.0.0.0 is the output. > .It Fl 6 > output ip6 address also a new column is generated between IP Address > and Hostname. If no ip6 address is assigned :: is the output. > .El > .Pp Index: usr.sbin/jls/jls.c =================================================================== RCS file: /usr/freebsd.cvs/src/usr.sbin/jls/jls.c,v retrieving revision 1.3 diff -r1.3 jls.c 32a33,35 > #include <sys/types.h> > #include <sys/socket.h> > #include <netinet/in.h> 33a37 > 38a43,53 > #include <unistd.h> > > static int > usage(void) > { > fprintf(stderr, "%s\n%s\n%s\n", > "usage: jls [-a] [-6]", > " -a output all jail assigned ip addresses", > " -6 output includes ipv6 addresses"); > exit(1); > } 42c57 < main(void) --- > main(int argc, char **argv) 45d59 < struct in_addr in; 46a61,78 > int allflag = 0; > int ip6flag = 0; > int ch; > > while ((ch = getopt(argc, argv, "a6")) != -1) { > switch (ch) { > case 'a': > allflag = 1; > break; > case '6': > ip6flag = 1; > break; > default: > usage(); > } > } > argc -= optind; > argv += optind; 68c100,103 < printf(" JID IP Address Hostname Path\n"); --- > if (ip6flag) > printf(" JID IP4 Address IP6 Address Hostname Path\n"); > else > printf(" JID IP Address Hostname Path\n"); 70,72c105,119 < 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); --- > if (allflag || xp->pr4_id == 0) { > if (ip6flag) { > char buffer[128]; > printf("%6d %-15.15s %-22.22s %-29.29s %.74s\n", > xp->pr_id, > inet_ntoa(xp->pr4_num), > inet_ntop(AF_INET6, xp->pr6_num.s6_addr, buffer, sizeof(buffer)), > xp->pr_host, > xp->pr_path); > } > else { > printf("%6d %-15.15s %-29.29s %.74s\n", > xp->pr_id, inet_ntoa(xp->pr4_num), xp->pr_host, xp->pr_path); > } > } >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040714192137.A623484040>