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
This commit is contained in:
jamie 2010-07-15 19:21:07 +00:00
parent e3a946ddad
commit 9afbdfdebb

View File

@ -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[] = { "disable", "new", "inherit" };
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;
}
}
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) {
va_end(ap);
return (-1);
}
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);
}
/*
@ -793,41 +844,6 @@ jailparam_free(struct jailparam *jp, unsigned njp)
}
}
/*
* 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.
*/