Author: jamie
Date: Thu Jul 15 19:21:07 2010
New Revision: 210133
URL: http://svn.freebsd.org/changeset/base/210133

Log:
  Don't import parameter values in jail_getv, except for the search key.
  Remove the internal jailparam_vlist, in favor of using variants of its
   logic separately in jail_setv and jail_getv.
  Free the temporary parameter list and exported values in jail_setv
   and jail_getv.
  
  Noted by:     Stanislav Uzunchev
  MFC after:    3 days

Modified:
  head/lib/libjail/jail.c

Modified: head/lib/libjail/jail.c
==============================================================================
--- head/lib/libjail/jail.c     Thu Jul 15 18:44:58 2010        (r210132)
+++ head/lib/libjail/jail.c     Thu Jul 15 19:21:07 2010        (r210133)
@@ -56,7 +56,6 @@ __FBSDID("$FreeBSD$");
 
 static int jailparam_import_enum(const char **values, int nvalues,
     const char *valstr, size_t valsize, int *value);
-static int jailparam_vlist(struct jailparam **jpp, va_list ap);
 static int jailparam_type(struct jailparam *jp);
 static char *noname(const char *name);
 static char *nononame(const char *name);
@@ -74,16 +73,31 @@ static const char *jailsys_values[] = { 
 int
 jail_setv(int flags, ...)
 {
-       va_list ap;
+       va_list ap, tap;
        struct jailparam *jp;
-       int njp;
+       const char *name, *value;
+       int njp, jid;
 
+       /* Create the parameter list and import the parameters. */
        va_start(ap, flags);
-       njp = jailparam_vlist(&jp, ap);
+       va_copy(tap, ap);
+       for (njp = 0; va_arg(tap, char *) != NULL; njp++)
+               (void)va_arg(tap, char *);
+       va_end(tap);
+       jp = alloca(njp * sizeof(struct jailparam));
+       for (njp = 0; (name = va_arg(ap, char *)) != NULL; njp++) {
+               value = va_arg(ap, char *);
+               if (jailparam_init(jp + njp, name) < 0 ||
+                   jailparam_import(jp + njp, value) < 0) {
+                       jailparam_free(jp, njp);
+                       va_end(ap);
+                       return (-1);
+               }
+       }
        va_end(ap);
-       if (njp < 0)
-               return (njp);
-       return (jailparam_set(jp, njp, flags));
+       jid = jailparam_set(jp, njp, flags);
+       jailparam_free(jp, njp);
+       return (jid);
 }
 
 /*
@@ -94,48 +108,85 @@ int
 jail_getv(int flags, ...)
 {
        va_list ap, tap;
-       struct jailparam *jp;
-       char *valarg;
-       const char *value;
-       int njp, i, jid, namekey, zero;
+       struct jailparam *jp, *jp_lastjid, *jp_jid, *jp_name, *jp_key;
+       char *valarg, *value;
+       const char *name, *key_value, *lastjid_value, *jid_value, *name_value;
+       int njp, i, jid;
 
+       /* Create the parameter list and find the key. */
        va_start(ap, flags);
        va_copy(tap, ap);
-       njp = jailparam_vlist(&jp, tap);
+       for (njp = 0; va_arg(tap, char *) != NULL; njp++)
+               (void)va_arg(tap, char *);
        va_end(tap);
-       if (njp < 0)
-               return (njp);
-       /*
-        * See if the name is the search key.  If so, we don't want to write
-        * it back in case it's a read-only string.
-        */
-       namekey = 1;
-       zero = 0;
-       for (i = 0; i < njp; i++) {
-               if (!strcmp(jp->jp_name, "lastjid") ||
-                   (!strcmp(jp->jp_name, "jid") &&
-                    memcmp(jp->jp_value, &zero, sizeof(zero))))
-                       namekey = 0;
+
+       jp = alloca(njp * sizeof(struct jailparam));
+       va_copy(tap, ap);
+       jp_lastjid = jp_jid = jp_name = NULL;
+       lastjid_value = jid_value = name_value = NULL;
+       for (njp = 0; (name = va_arg(tap, char *)) != NULL; njp++) {
+               value = va_arg(tap, char *);
+               if (jailparam_init(jp + njp, name) < 0) {
+                       va_end(tap);
+                       goto error;
+               }
+               if (!strcmp(jp[njp].jp_name, "lastjid")) {
+                       jp_lastjid = jp + njp;
+                       lastjid_value = value;
+               } else if (!strcmp(jp[njp].jp_name, "jid")) {
+                       jp_jid = jp + njp;
+                       jid_value = value;
+               } if (!strcmp(jp[njp].jp_name, "name")) {
+                       jp_name = jp + njp;
+                       name_value = value;
+               }
        }
-       jid = jailparam_get(jp, njp, flags);
-       if (jid < 0) {
-               va_end(ap);
-               return (-1);
+       va_end(tap);
+       /* Import the key parameter. */
+       if (jp_lastjid != NULL) {
+               jp_key = jp_lastjid;
+               key_value = lastjid_value;
+       } else if (jp_jid != NULL && strtol(jid_value, NULL, 10) != 0) {
+               jp_key = jp_jid;
+               key_value = jid_value;
+       } else if (jp_name != NULL) {
+               jp_key = jp_name;
+               key_value = name_value;
+       } else {
+               strlcpy(jail_errmsg, "no jail specified", JAIL_ERRMSGLEN);
+               errno = ENOENT;
+               goto error;
        }
+       if (jailparam_import(jp_key, key_value) < 0)
+               goto error;
+       /* Get the jail and export the parameters. */
+       jid = jailparam_get(jp, njp, flags);
+       if (jid < 0)
+               goto error;
        for (i = 0; i < njp; i++) {
                (void)va_arg(ap, char *);
-               value = jailparam_export(jp + i);
-               if (value == NULL) {
-                       va_end(ap);
-                       return (-1);
-               }
                valarg = va_arg(ap, char *);
-               if (!namekey || strcmp(jp[i].jp_name, "name"))
+               if (jp + i != jp_key) {
                        /* It's up to the caller to ensure there's room. */
-                       strcpy(valarg, value);
+                       if ((jp[i].jp_ctltype & CTLTYPE) == CTLTYPE_STRING)
+                               strcpy(valarg, jp[i].jp_value);
+                       else {
+                               value = jailparam_export(jp + i);
+                               if (value == NULL)
+                                       goto error;
+                               strcpy(valarg, value);
+                               free(value);
+                       }
+               }
        }
+       jailparam_free(jp, njp);
        va_end(ap);
        return (jid);
+
+ error:
+       jailparam_free(jp, njp);
+       va_end(ap);
+       return (-1);
 }
 
 /*
@@ -794,41 +845,6 @@ jailparam_free(struct jailparam *jp, uns
 }
 
 /*
- * Create and import an array of jail parameters, given a list of name and
- * value strings, terminated by a null name.
- */
-static int
-jailparam_vlist(struct jailparam **jpp, va_list ap)
-{
-       va_list tap;
-       struct jailparam *jp;
-       char *name, *value;
-       int njp;
-
-       va_copy(tap, ap);
-       for (njp = 0; va_arg(tap, char *) != NULL; njp++)
-               (void)va_arg(tap, char *);
-       va_end(tap);
-       jp = calloc(njp, sizeof(struct jailparam));
-       if (jp == NULL) {
-               strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
-               return (-1);
-       }
-
-       for (njp = 0; (name = va_arg(ap, char *)) != NULL; njp++) {
-               value = va_arg(ap, char *);
-               if (jailparam_init(jp + njp, name) < 0 ||
-                   jailparam_import(jp + njp, value) < 0) {
-                       jailparam_free(jp, njp);
-                       free(jp);
-                       return (-1);
-               }
-       }
-       *jpp = jp;
-       return (njp);
-}
-
-/*
  * Find a parameter's type and size from its MIB.
  */
 static int
_______________________________________________
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