The branch main has been updated by kevans:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=1af8d5652a01f79d055436c2ee83219700e7b16c

commit 1af8d5652a01f79d055436c2ee83219700e7b16c
Author:     Kyle Evans <[email protected]>
AuthorDate: 2025-11-27 05:19:39 +0000
Commit:     Kyle Evans <[email protected]>
CommitDate: 2026-01-16 00:23:40 +0000

    libjail: start refactoring struct ioctl support
    
    Instead of ad-hoc comparisons against the struct type in a few places,
    start to abstract out an interface for dealing with struct types.  For
    now, this just means that we have some special jailparam_import and
    jailparam_export handling for the ip addr types, but in the next commit
    we'll extend it further to support MAC labels.
    
    Reviewed by:    jamie
    Differential Revision:  https://reviews.freebsd.org/D53959
---
 lib/libjail/jail.c | 206 ++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 149 insertions(+), 57 deletions(-)

diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c
index ad3348af0d2d..8fbd486d2c96 100644
--- a/lib/libjail/jail.c
+++ b/lib/libjail/jail.c
@@ -35,6 +35,7 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 
+#include <assert.h>
 #include <errno.h>
 #include <inttypes.h>
 #include <stdio.h>
@@ -46,12 +47,45 @@
 
 #define        SJPARAM         "security.jail.param"
 
-#define JPS_IN_ADDR    1
-#define JPS_IN6_ADDR   2
+#define        JPSDEF_OF(jp)   \
+       ((jp)->jp_structtype >= 0 ? &jp_structdefs[(jp)->jp_structtype] : NULL)
+
+typedef int (jps_import_t)(const struct jailparam *, int, const char *);
+typedef char *(jps_export_t)(const struct jailparam *, int);
+
+static jps_import_t    jps_import_in_addr;
+static jps_import_t    jps_import_in6_addr;
+
+static jps_export_t    jps_export_in_addr;
+static jps_export_t    jps_export_in6_addr;
+
+static const struct jp_structdef {
+       const char      *jps_type;              /* sysctl type */
+       size_t           jps_valuelen;          /* value size */
+       jps_import_t    *jps_import;            /* jailparam_import() */
+       jps_export_t    *jps_export;            /* jailparam_export() */
+} jp_structdefs[] = {
+       {
+               .jps_type = "S,in_addr",
+               .jps_valuelen = sizeof(struct in_addr),
+               .jps_import = jps_import_in_addr,
+               .jps_export = jps_export_in_addr,
+       },
+       {
+               .jps_type = "S,in6_addr",
+               .jps_valuelen = sizeof(struct in6_addr),
+               .jps_import = jps_import_in6_addr,
+               .jps_export = jps_export_in6_addr,
+       },
+};
+
+_Static_assert(nitems(jp_structdefs) <= INT_MAX,
+    "Too many struct definitions requires an ABI break in struct jailparam");
 
 #define ARRAY_SANITY   5
 #define ARRAY_SLOP     5
 
+static const struct jp_structdef *jp_structinfo(const char *type, int *);
 
 static int jailparam_import_enum(const char **values, int nvalues,
     const char *valstr, size_t valsize, int *value);
@@ -66,6 +100,23 @@ char jail_errmsg[JAIL_ERRMSGLEN];
 static const char *bool_values[] = { "false", "true" };
 static const char *jailsys_values[] = { "disable", "new", "inherit" };
 
+static const struct jp_structdef *
+jp_structinfo(const char *type, int *oidx)
+{
+       const struct jp_structdef *jpsdef;
+
+       for (size_t idx = 0; idx < nitems(jp_structdefs); idx++) {
+               jpsdef = &jp_structdefs[idx];
+
+               if (strcmp(jpsdef->jps_type, type) == 0) {
+                       *oidx = (int)idx;
+                       return (jpsdef);
+               }
+       }
+
+       *oidx = -1;
+       return (NULL);
+}
 
 /*
  * Import a null-terminated parameter list and set a jail with the flags
@@ -325,6 +376,7 @@ jailparam_import(struct jailparam *jp, const char *value)
 {
        char *p, *ep, *tvalue;
        const char *avalue;
+       const struct jp_structdef *jpsdef;
        int i, nval, fw;
 
        if (value == NULL)
@@ -426,34 +478,13 @@ jailparam_import(struct jailparam *jp, const char *value)
                case CTLTYPE_STRUCT:
                        tvalue = alloca(fw + 1);
                        strlcpy(tvalue, avalue, fw + 1);
-                       switch (jp->jp_structtype) {
-                       case JPS_IN_ADDR:
-                               if (inet_pton(AF_INET, tvalue,
-                                   &((struct in_addr *)jp->jp_value)[i]) != 1)
-                               {
-                                       snprintf(jail_errmsg,
-                                           JAIL_ERRMSGLEN,
-                                           "%s: not an IPv4 address: %s",
-                                           jp->jp_name, tvalue);
-                                       errno = EINVAL;
-                                       goto error;
-                               }
-                               break;
-                       case JPS_IN6_ADDR:
-                               if (inet_pton(AF_INET6, tvalue,
-                                   &((struct in6_addr *)jp->jp_value)[i]) != 1)
-                               {
-                                       snprintf(jail_errmsg,
-                                           JAIL_ERRMSGLEN,
-                                           "%s: not an IPv6 address: %s",
-                                           jp->jp_name, tvalue);
-                                       errno = EINVAL;
-                                       goto error;
-                               }
-                               break;
-                       default:
+
+                       if (jp->jp_structtype == -1)
                                goto unknown_type;
-                       }
+
+                       jpsdef = &jp_structdefs[jp->jp_structtype];
+                       if ((*jpsdef->jps_import)(jp, i, tvalue) != 0)
+                               goto error;
                        break;
                default:
                unknown_type:
@@ -773,6 +804,7 @@ jailparam_export(struct jailparam *jp)
 {
        size_t *valuelens;
        char *value, *tvalue, **values;
+       const struct jp_structdef *jpsdef;
        size_t valuelen;
        int i, nval, ival;
        char valbuf[INET6_ADDRSTRLEN];
@@ -839,29 +871,25 @@ jailparam_export(struct jailparam *jp)
                            (uintmax_t)((uint64_t *)jp->jp_value)[i]);
                        break;
                case CTLTYPE_STRUCT:
-                       switch (jp->jp_structtype) {
-                       case JPS_IN_ADDR:
-                               if (inet_ntop(AF_INET,
-                                   &((struct in_addr *)jp->jp_value)[i],
-                                   valbuf, sizeof(valbuf)) == NULL) {
-                                       strerror_r(errno, jail_errmsg,
-                                           JAIL_ERRMSGLEN);
-                                       return (NULL);
-                               }
-                               break;
-                       case JPS_IN6_ADDR:
-                               if (inet_ntop(AF_INET6,
-                                   &((struct in6_addr *)jp->jp_value)[i],
-                                   valbuf, sizeof(valbuf)) == NULL) {
-                                       strerror_r(errno, jail_errmsg,
-                                           JAIL_ERRMSGLEN);
-                                       return (NULL);
-                               }
-                               break;
-                       default:
+                       if (jp->jp_structtype == -1)
                                goto unknown_type;
+
+                       jpsdef = &jp_structdefs[jp->jp_structtype];
+                       value = (*jpsdef->jps_export)(jp, i);
+                       if (value == NULL) {
+                               strerror_r(errno, jail_errmsg,
+                                   JAIL_ERRMSGLEN);
+                               return (NULL);
                        }
-                       break;
+
+                       valuelens[i] = strlen(value) + 1;
+                       valuelen += valuelens[i];
+                       values[i] = alloca(valuelens[i]);
+                       strcpy(values[i], value);
+
+                       free(value);
+                       value = NULL;
+                       continue;       /* Value already added to values[] */
                default:
                unknown_type:
                        snprintf(jail_errmsg, JAIL_ERRMSGLEN,
@@ -1055,14 +1083,17 @@ unknown_parameter:
                }
                jp->jp_valuelen = strtoul(desc.s, NULL, 10);
                break;
-       case CTLTYPE_STRUCT:
-               if (!strcmp(desc.s, "S,in_addr")) {
-                       jp->jp_structtype = JPS_IN_ADDR;
-                       jp->jp_valuelen = sizeof(struct in_addr);
-               } else if (!strcmp(desc.s, "S,in6_addr")) {
-                       jp->jp_structtype = JPS_IN6_ADDR;
-                       jp->jp_valuelen = sizeof(struct in6_addr);
+       case CTLTYPE_STRUCT: {
+               const struct jp_structdef *jpsdef;
+
+               jpsdef = jp_structinfo(desc.s, &jp->jp_structtype);
+               if (jpsdef != NULL) {
+                       assert(jp->jp_structtype >= 0);
+
+                       jp->jp_valuelen = jpsdef->jps_valuelen;
                } else {
+                       assert(jp->jp_structtype == -1);
+
                        desclen = 0;
                        if (sysctl(mib + 2, miblen / sizeof(int),
                            NULL, &jp->jp_valuelen, NULL, 0) < 0) {
@@ -1073,6 +1104,7 @@ unknown_parameter:
                        }
                }
                break;
+       }
        case CTLTYPE_NODE:
                /*
                 * A node might be described by an empty-named child,
@@ -1215,3 +1247,63 @@ kvname(const char *name)
 
        return (kvname);
 }
+
+static int
+jps_import_in_addr(const struct jailparam *jp, int i, const char *value)
+{
+       struct in_addr *addr;
+
+       addr = &((struct in_addr *)jp->jp_value)[i];
+       if (inet_pton(AF_INET, value, addr) != 1) {
+               snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+                   "%s: not an IPv4 address: %s", jp->jp_name, value);
+               errno = EINVAL;
+               return (-1);
+       }
+
+       return (0);
+}
+
+static int
+jps_import_in6_addr(const struct jailparam *jp, int i, const char *value)
+{
+       struct in6_addr *addr6;
+
+       addr6 = &((struct in6_addr *)jp->jp_value)[i];
+       if (inet_pton(AF_INET6, value, addr6) != 1) {
+               snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+                   "%s: not an IPv6 address: %s", jp->jp_name, value);
+               errno = EINVAL;
+               return (-1);
+       }
+
+       return (0);
+}
+
+static char *
+jps_export_in_addr(const struct jailparam *jp, int i)
+{
+       struct in_addr *addr;
+       char valbuf[INET_ADDRSTRLEN];
+
+       addr = &((struct in_addr *)jp->jp_value)[i];
+       if (inet_ntop(AF_INET, addr, valbuf, sizeof(valbuf)) == NULL)
+               return (NULL);
+
+       /* Error checked by caller. */
+       return (strdup(valbuf));
+}
+
+static char *
+jps_export_in6_addr(const struct jailparam *jp, int i)
+{
+       struct in6_addr *addr6;
+       char valbuf[INET6_ADDRSTRLEN];
+
+       addr6 = &((struct in6_addr *)jp->jp_value)[i];
+       if (inet_ntop(AF_INET6, addr6, valbuf, sizeof(valbuf)) == NULL)
+               return (NULL);
+
+       /* Error checked by caller. */
+       return (strdup(valbuf));
+}

Reply via email to