kern/69064: No multiple ip4/6's could assigned to a jail.
Meno Abels
abels at adviser.com
Wed Jul 14 12:30:32 PDT 2004
>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 at 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:
More information about the freebsd-bugs
mailing list