Hi, folks,

I recently became interested in the jail code and have been very
impressed with what I have seen so far.  The one thing I found a
bit surprising was the lack of support for multiple IP addresses
in jail environments.  I did some research into the issue, and I
found the various posts discussing why this decision was made.

While a ``true'' multiple IP address implementation (INADDR_ANY,
loopback, etc.) may be rather involved, getting more than one IP
address into the jailed environment might be much simpler.  Here
is my proposal:

Rather than specifying a single IP address when constructing the
jail, supply an IP address and netmask.  The kernel can then use
the IP address in conjunction with the netmask to determine what
range of addresses are allowed in the jail without having to run
through an actual list of addresses.

This approach is similar to how ISPs assign CIDR blocks to their
customers.  It has various advantages and disadvantages over the
method of providing a list of allowed addresses.  I consider its
primary advantage to be that it is extremely simple to implement
(as can be seen by the attached diff) and does not affect jail's
runtime performance.

Granted, this method does not solve the INADDR_ANY and localhost
issues, but any solution to that side of the jail puzzle is sure
to be an invasive one.

The attached diff is based on 4.6-RELEASE.  To use it, build and
install the jail binary and a new kernel.  By default, this diff
results in a jail binary that acts the same as before.  Adding a
``/ne.tm.as.k'' to the jail call will allow the jail to allocate
any of the IP addresses in the netmask.  For example..

  jail /home/jail myhost 10.20.30.8/255.255.255.248 /bin/sh

..would allow the jail to use all of the following addresses..

  10.20.30.8
  10.20.30.9
  10.20.30.10
  10.20.30.11
  10.20.30.12
  10.20.30.13
  10.20.30.14
  10.20.30.15

INADDR_ANY and 127.0.0.1 still use the first address.  I changed
jail's version number (from 0 to 1) as this affects the syscall.

I look forward to your comments, suggestions, criticisms, etc.

Thank you for your time!

Michael Alyn Miller


-------------------------------
The best kept secret in e-mail.
http://eioMAIL.com/
*** sys/kern/kern_jail.c.orig   Thu Aug 16 18:00:26 2001
--- sys/kern/kern_jail.c        Tue Jun 18 13:52:27 2002
***************
*** 62,68 ****
        error = copyin(uap->jail, &j, sizeof j);
        if (error)
                return (error);
!       if (j.version != 0)
                return (EINVAL);
        MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK);
        bzero((caddr_t)pr, sizeof *pr);
--- 62,68 ----
        error = copyin(uap->jail, &j, sizeof j);
        if (error)
                return (error);
!       if (j.version != 1)
                return (EINVAL);
        MALLOC(pr, struct prison *, sizeof *pr , M_PRISON, M_WAITOK);
        bzero((caddr_t)pr, sizeof *pr);
***************
*** 70,75 ****
--- 70,76 ----
        if (error) 
                goto bail;
        pr->pr_ip = j.ip_number;
+       pr->pr_mask = j.ip_mask;
  
        ca.path = j.path;
        error = chroot(p, &ca);
***************
*** 111,117 ****
                        *ip = htonl(p->p_prison->pr_ip);
                return (0);
        }
!       if (p->p_prison->pr_ip != tmp)
                return (1);
        return (0);
  }
--- 112,119 ----
                        *ip = htonl(p->p_prison->pr_ip);
                return (0);
        }
!       if ((p->p_prison->pr_mask & p->p_prison->pr_ip)
!                       != (p->p_prison->pr_mask & tmp))
                return (1);
        return (0);
  }
*** sys/netinet/in_pcb.c.orig   Wed May  1 19:36:50 2002
--- sys/netinet/in_pcb.c        Tue Jun 18 13:52:15 2002
***************
*** 1028,1034 ****
  {
        if (!p->p_prison)
                return (0);
!       if (ntohl(inp->inp_laddr.s_addr) == p->p_prison->pr_ip)
                return (0);
        return (1);
  }
--- 1028,1035 ----
  {
        if (!p->p_prison)
                return (0);
!       if ((p->p_prison->pr_mask & ntohl(inp->inp_laddr.s_addr))
!                       == (p->p_prison->pr_mask & p->p_prison->pr_ip))
                return (0);
        return (1);
  }
*** sys/sys/jail.h.orig Wed Nov  1 09:58:06 2000
--- sys/sys/jail.h      Tue Jun 18 13:33:28 2002
***************
*** 18,23 ****
--- 18,24 ----
        char            *path;
        char            *hostname;
        u_int32_t       ip_number;
+       u_int32_t       ip_mask;
  };
  
  #ifndef _KERNEL
***************
*** 40,45 ****
--- 41,47 ----
        int             pr_ref;
        char            pr_host[MAXHOSTNAMELEN];
        u_int32_t       pr_ip;
+       u_int32_t       pr_mask;
        void            *pr_linux;
  };
  
*** usr.sbin/jail/jail.c.orig   Mon Jul 30 03:19:54 2001
--- usr.sbin/jail/jail.c        Tue Jun 18 14:28:36 2002
***************
*** 24,40 ****
        struct jail j;
        int i;
        struct in_addr in;
  
        if (argc < 5) 
!               errx(1, "Usage: %s path hostname ip-number command ...\n",
                    argv[0]);
        i = chdir(argv[1]);
        if (i)
                err(1, "chdir %s", argv[1]);
        memset(&j, 0, sizeof(j));
!       j.version = 0;
        j.path = argv[1];
        j.hostname = argv[2];
        i = inet_aton(argv[3], &in);
        if (!i)
                errx(1, "Couldn't make sense of ip-number\n");
--- 24,51 ----
        struct jail j;
        int i;
        struct in_addr in;
+       char *p;
  
        if (argc < 5) 
!               errx(1, "Usage: %s path hostname ip-number[/ip-mask] command ...\n",
                    argv[0]);
        i = chdir(argv[1]);
        if (i)
                err(1, "chdir %s", argv[1]);
        memset(&j, 0, sizeof(j));
!       j.version = 1;
        j.path = argv[1];
        j.hostname = argv[2];
+       p = strchr(argv[3], '/');
+       if (p != NULL) {
+               i = inet_aton(p + 1, &in);
+               if (!i)
+                       errx(1, "Couldn't make sense of ip-mask\n");
+               j.ip_mask = ntohl(in.s_addr);
+               *p = '\0';
+       } else {
+               j.ip_mask = 0xffffffff;
+       }
        i = inet_aton(argv[3], &in);
        if (!i)
                errx(1, "Couldn't make sense of ip-number\n");

Reply via email to