Author: jamie
Date: Wed Jul 29 16:46:59 2009
New Revision: 195945
URL: http://svn.freebsd.org/changeset/base/195945

Log:
  Don't allow mixing the "vnet" and "ip4/6" jail parameters, since vnet
  jails have their own IP stack and don't have access to the parent IP
  addresses anyway.  Note that a virtual network stack forms a break
  between prisons with regard to the list of allowed IP addresses.
  
  Approved by:  re (kib), bz (mentor)

Modified:
  head/sys/kern/kern_jail.c

Modified: head/sys/kern/kern_jail.c
==============================================================================
--- head/sys/kern/kern_jail.c   Wed Jul 29 16:41:02 2009        (r195944)
+++ head/sys/kern/kern_jail.c   Wed Jul 29 16:46:59 2009        (r195945)
@@ -468,7 +468,7 @@ kern_jail_set(struct thread *td, struct 
 #endif
        struct vfsopt *opt;
        struct vfsoptlist *opts;
-       struct prison *pr, *deadpr, *mypr, *ppr, *tpr;
+       struct prison *pr, *deadpr, *mypr, *ppr, *tpr, *tppr;
        struct vnode *root;
        char *domain, *errmsg, *host, *name, *p, *path, *uuid;
 #if defined(INET) || defined(INET6)
@@ -821,6 +821,15 @@ kern_jail_set(struct thread *td, struct 
        }
 #endif
 
+#if defined(VIMAGE) && (defined(INET) || defined(INET6))
+       if ((ch_flags & PR_VNET) && (ch_flags & (PR_IP4_USER | PR_IP6_USER))) {
+               error = EINVAL;
+               vfs_opterror(opts,
+                   "vnet jails cannot have IP address restrictions");
+               goto done_errmsg;
+       }
+#endif
+
        root = NULL;
        error = vfs_getopt(opts, "path", (void **)&path, &len);
        if (error == ENOENT)
@@ -1137,11 +1146,18 @@ kern_jail_set(struct thread *td, struct 
                }
                strlcpy(pr->pr_hostuuid, DEFAULT_HOSTUUID, HOSTUUIDLEN);
                pr->pr_flags |= PR_HOST;
+#if defined(INET) || defined(INET6)
+#ifdef VIMAGE
+               if (!(pr_flags & PR_VNET))
+#endif
+               {
 #ifdef INET
-               pr->pr_flags |= PR_IP4 | PR_IP4_USER | PR_IP4_DISABLE;
+                       pr->pr_flags |= PR_IP4 | PR_IP4_USER | PR_IP4_DISABLE;
 #endif
 #ifdef INET6
-               pr->pr_flags |= PR_IP6 | PR_IP6_USER | PR_IP6_DISABLE;
+                       pr->pr_flags |= PR_IP6 | PR_IP6_USER | PR_IP6_DISABLE;
+#endif
+               }
 #endif
                pr->pr_securelevel = ppr->pr_securelevel;
                pr->pr_allow = JAIL_DEFAULT_ALLOW & ppr->pr_allow;
@@ -1173,6 +1189,15 @@ kern_jail_set(struct thread *td, struct 
                 */
        } else {
                created = 0;
+#if defined(VIMAGE) && (defined(INET) || defined(INET6))
+               if ((pr->pr_flags & PR_VNET) &&
+                   (ch_flags & (PR_IP4_USER | PR_IP6_USER))) {
+                       error = EINVAL;
+                       vfs_opterror(opts,
+                           "vnet jails cannot have IP address restrictions");
+                       goto done_deref_locked;
+               }
+#endif
                /*
                 * Grab a reference for existing prisons, to ensure they
                 * continue to exist for the duration of the call.
@@ -1299,8 +1324,19 @@ kern_jail_set(struct thread *td, struct 
                         * there is a duplicate on a jail with more than one
                         * IP stop checking and return error.
                         */
-                       FOREACH_PRISON_DESCENDANT(&prison0, tpr, descend) {
-                               if (tpr == pr || tpr->pr_uref == 0) {
+                       tppr = ppr;
+#ifdef VIMAGE
+                       for (; tppr != &prison0; tppr = tppr->pr_parent)
+                               if (tppr->pr_flags & PR_VNET)
+                                       break;
+#endif
+                       FOREACH_PRISON_DESCENDANT(tppr, tpr, descend) {
+                               if (tpr == pr ||
+#ifdef VIMAGE
+                                   (tpr != tppr &&
+                                    (tpr->pr_flags & PR_VNET)) ||
+#endif
+                                   tpr->pr_uref == 0) {
                                        descend = 0;
                                        continue;
                                }
@@ -1407,8 +1443,19 @@ kern_jail_set(struct thread *td, struct 
                }
                if (ip6s > 0) {
                        /* Check for conflicting IP addresses. */
-                       FOREACH_PRISON_DESCENDANT(&prison0, tpr, descend) {
-                               if (tpr == pr || tpr->pr_uref == 0) {
+                       tppr = ppr;
+#ifdef VIMAGE
+                       for (; tppr != &prison0; tppr = tppr->pr_parent)
+                               if (tppr->pr_flags & PR_VNET)
+                                       break;
+#endif
+                       FOREACH_PRISON_DESCENDANT(tppr, tpr, descend) {
+                               if (tpr == pr ||
+#ifdef VIMAGE
+                                   (tpr != tppr &&
+                                    (tpr->pr_flags & PR_VNET)) ||
+#endif
+                                   tpr->pr_uref == 0) {
                                        descend = 0;
                                        continue;
                                }
@@ -1490,6 +1537,12 @@ kern_jail_set(struct thread *td, struct 
                        pr->pr_ip4s = 0;
                }
                FOREACH_PRISON_DESCENDANT_LOCKED(pr, tpr, descend) {
+#ifdef VIMAGE
+                       if (tpr->pr_flags & PR_VNET) {
+                               descend = 0;
+                               continue;
+                       }
+#endif
                        if (prison_restrict_ip4(tpr, NULL)) {
                                redo_ip4 = 1;
                                descend = 0;
@@ -1522,6 +1575,12 @@ kern_jail_set(struct thread *td, struct 
                        pr->pr_ip6s = 0;
                }
                FOREACH_PRISON_DESCENDANT_LOCKED(pr, tpr, descend) {
+#ifdef VIMAGE
+                       if (tpr->pr_flags & PR_VNET) {
+                               descend = 0;
+                               continue;
+                       }
+#endif
                        if (prison_restrict_ip6(tpr, NULL)) {
                                redo_ip6 = 1;
                                descend = 0;
@@ -1655,6 +1714,12 @@ kern_jail_set(struct thread *td, struct 
                mtx_lock(&pr->pr_mtx);
                redo_ip4 = 0;
                FOREACH_PRISON_DESCENDANT_LOCKED(pr, tpr, descend) {
+#ifdef VIMAGE
+                       if (tpr->pr_flags & PR_VNET) {
+                               descend = 0;
+                               continue;
+                       }
+#endif
                        if (prison_restrict_ip4(tpr, ip4)) {
                                if (ip4 != NULL)
                                        ip4 = NULL;
@@ -1672,6 +1737,12 @@ kern_jail_set(struct thread *td, struct 
                mtx_lock(&pr->pr_mtx);
                redo_ip6 = 0;
                FOREACH_PRISON_DESCENDANT_LOCKED(pr, tpr, descend) {
+#ifdef VIMAGE
+                       if (tpr->pr_flags & PR_VNET) {
+                               descend = 0;
+                               continue;
+                       }
+#endif
                        if (prison_restrict_ip6(tpr, ip6)) {
                                if (ip6 != NULL)
                                        ip6 = NULL;
@@ -2697,9 +2768,17 @@ prison_equal_ip4(struct prison *pr1, str
         * proper locking order and end up needing allprison_lock anyway.
         */
        sx_slock(&allprison_lock);
-       while (pr1 != &prison0 && !(pr1->pr_flags & PR_IP4_USER))
+       while (pr1 != &prison0 &&
+#ifdef VIMAGE
+              !(pr1->pr_flags & PR_VNET) &&
+#endif
+              !(pr1->pr_flags & PR_IP4_USER))
                pr1 = pr1->pr_parent;
-       while (pr2 != &prison0 && !(pr2->pr_flags & PR_IP4_USER))
+       while (pr2 != &prison0 &&
+#ifdef VIMAGE
+              !(pr2->pr_flags & PR_VNET) &&
+#endif
+              !(pr2->pr_flags & PR_IP4_USER))
                pr2 = pr2->pr_parent;
        sx_sunlock(&allprison_lock);
        return (pr1 == pr2);
@@ -2995,9 +3074,17 @@ prison_equal_ip6(struct prison *pr1, str
                return (1);
 
        sx_slock(&allprison_lock);
-       while (pr1 != &prison0 && !(pr1->pr_flags & PR_IP6_USER))
+       while (pr1 != &prison0 &&
+#ifdef VIMAGE
+              !(pr1->pr_flags & PR_VNET) &&
+#endif
+              !(pr1->pr_flags & PR_IP6_USER))
                pr1 = pr1->pr_parent;
-       while (pr2 != &prison0 && !(pr2->pr_flags & PR_IP6_USER))
+       while (pr2 != &prison0 &&
+#ifdef VIMAGE
+              !(pr2->pr_flags & PR_VNET) &&
+#endif
+              !(pr2->pr_flags & PR_IP6_USER))
                pr2 = pr2->pr_parent;
        sx_sunlock(&allprison_lock);
        return (pr1 == pr2);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to