summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjamie <jamie@FreeBSD.org>2009-06-24 18:18:35 +0000
committerjamie <jamie@FreeBSD.org>2009-06-24 18:18:35 +0000
commit7c0019fd3084503b16686588e9e052c1a6b6c371 (patch)
treea9cec75f7b2e1076b5455019e71bbc78faac9225
parentbd3587c757355e28ac6abbaf11703661599270bb (diff)
downloadFreeBSD-src-7c0019fd3084503b16686588e9e052c1a6b6c371.zip
FreeBSD-src-7c0019fd3084503b16686588e9e052c1a6b6c371.tar.gz
Add libjail, a (somewhat) simpler interface to the jail_set and jail_get
system calls and the security.jail.param sysctls. Approved by: bz (mentor)
-rw-r--r--gnu/usr.bin/groff/tmac/mdoc.local1
-rw-r--r--lib/Makefile4
-rw-r--r--lib/libjail/Makefile29
-rw-r--r--lib/libjail/jail.3275
-rw-r--r--lib/libjail/jail.c972
-rw-r--r--lib/libjail/jail.h68
-rw-r--r--lib/libjail/jail_getid.c104
-rw-r--r--share/mk/bsd.libnames.mk1
-rw-r--r--usr.bin/killall/Makefile2
-rw-r--r--usr.bin/killall/killall.c17
-rw-r--r--usr.sbin/jail/Makefile4
-rw-r--r--usr.sbin/jail/jail.c205
-rw-r--r--usr.sbin/jexec/Makefile4
-rw-r--r--usr.sbin/jexec/jexec.c20
-rw-r--r--usr.sbin/jls/Makefile3
-rw-r--r--usr.sbin/jls/jls.c577
16 files changed, 1634 insertions, 652 deletions
diff --git a/gnu/usr.bin/groff/tmac/mdoc.local b/gnu/usr.bin/groff/tmac/mdoc.local
index b3d4288..a963b7e 100644
--- a/gnu/usr.bin/groff/tmac/mdoc.local
+++ b/gnu/usr.bin/groff/tmac/mdoc.local
@@ -47,6 +47,7 @@
.ds doc-str-Lb-libfetch File Transfer Library (libfetch, \-lfetch)
.ds doc-str-Lb-libgeom Userland API Library for kernel GEOM subsystem (libgeom, \-lgeom)
.ds doc-str-Lb-libipx IPX Address Conversion Support Library (libipx, \-lipx)
+.ds doc-str-Lb-libjail Jail Library (libjail, \-ljail)
.ds doc-str-Lb-libkiconv Kernel side iconv library (libkiconv, \-lkiconv)
.ds doc-str-Lb-libkse N:M Threading Library (libkse, \-lkse)
.ds doc-str-Lb-libmd Message Digest (MD4, MD5, etc.) Support Library (libmd, \-lmd)
diff --git a/lib/Makefile b/lib/Makefile
index ec866e5..7cacb70 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -35,8 +35,8 @@ SUBDIR= ${_csu} libc libbsm libauditd libcom_err libcrypt libelf libkvm msun \
libcalendar libcam libcompat libdevinfo libdevstat libdisk \
libdwarf libedit libexpat libfetch libftpio libgeom ${_libgpib} \
${_libgssapi} ${_librpcsec_gss} libipsec \
- ${_libipx} libkiconv libmagic libmemstat ${_libmilter} ${_libmp} \
- ${_libncp} ${_libngatm} libopie libpam libpcap \
+ ${_libipx} libjail libkiconv libmagic libmemstat ${_libmilter} \
+ ${_libmp} ${_libncp} ${_libngatm} libopie libpam libpcap \
${_libpmc} libproc librt ${_libsdp} ${_libsm} ${_libsmb} \
${_libsmdb} \
${_libsmutil} libstand ${_libtelnet} ${_libthr} libthread_db libufs \
diff --git a/lib/libjail/Makefile b/lib/libjail/Makefile
new file mode 100644
index 0000000..678d59e
--- /dev/null
+++ b/lib/libjail/Makefile
@@ -0,0 +1,29 @@
+# $FreeBSD$
+
+LIB= jail
+SHLIBDIR?= /lib
+SHLIB_MAJOR= 1
+SRCS= jail.c jail_getid.c
+INCS= jail.h
+
+MAN= jail.3
+
+MLINKS+=jail.3 jail_getid.3
+MLINKS+=jail.3 jail_getname.3
+MLINKS+=jail.3 jail_getv.3
+MLINKS+=jail.3 jail_setv.3
+MLINKS+=jail.3 jailparam.3
+MLINKS+=jail.3 jailparam_all.3
+MLINKS+=jail.3 jailparam_init.3
+MLINKS+=jail.3 jailparam_import.3
+MLINKS+=jail.3 jailparam_import_raw.3
+MLINKS+=jail.3 jailparam_get.3
+MLINKS+=jail.3 jailparam_set.3
+MLINKS+=jail.3 jailparam_export.3
+MLINKS+=jail.3 jailparam_free.3
+
+CFLAGS+=-I${.CURDIR}
+
+WARNS?= 6
+
+.include <bsd.lib.mk>
diff --git a/lib/libjail/jail.3 b/lib/libjail/jail.3
new file mode 100644
index 0000000..7fec585
--- /dev/null
+++ b/lib/libjail/jail.3
@@ -0,0 +1,275 @@
+.\" Copyright (c) 2009 James Gritton.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 24, 2009
+.Dt JAIL 3
+.Os
+.Sh NAME
+.Nm jail_getid ,
+.Nm jail_getname ,
+.Nm jail_setv ,
+.Nm jail_getv ,
+.Nm jailparam_all ,
+.Nm jailparam_init ,
+.Nm jailparam_import ,
+.Nm jailparam_import_raw ,
+.Nm jailparam_set ,
+.Nm jailparam_get ,
+.Nm jailparam_export ,
+.Nm jailparam_free ,
+.Nd create and manage system jails
+.Sh LIBRARY
+.Lb libjail
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/jail.h
+.In jail.h
+.Vt extern char jail_errmsg[] ;
+.Ft int
+.Fn jail_getid "const char *name"
+.Ft char *
+.Fn jail_getname "int jid"
+.Ft int
+.Fn jail_setv "int flags" ...
+.Ft int
+.Fn jail_getv "int flags" ...
+.Ft int
+.Fn jailparam_all "struct jailparam **jpp"
+.Ft int
+.Fn jailparam_init "struct jailparam *jp" "const char *name"
+.Ft int
+.Fn jailparam_import "struct jailparam *jp" "const char *value"
+.Ft int
+.Fn jailparam_import_raw "struct jailparam *jp" "void *value" "size_t valuelen"
+.Ft int
+.Fn jailparam_set "struct jailparam *jp" "unsigned njp" "int flags"
+.Ft int
+.Fn jailparam_get "struct jailparam *jp" "unsigned njp" "int flags"
+.Ft char *
+.Fn jailparam_export "struct jailparam *jp"
+.Ft void
+.Fn jailparam_free "struct jailparam *jp" "unsigned njp"
+.Sh DESCRIPTION
+The
+.Nm jail
+library is an interface to the
+.Xr jail_set 2
+and
+.Xr jail_get 2
+system calls, and the
+.Va security.jail.param
+MIB entries.
+It simplifies the conversion of prison parameters between internal and
+string formats, allowing the setting and querying of prisons without
+knowing the parameter formats.
+.Pp
+The
+.Fn jail_getid
+function returns the JID of the jail identified by
+.Ar name ,
+or \-1 if the jail does not exist.
+.Pp
+The
+.Fn jail_getname
+function returns the name of the jail identified by
+.Ar jid ,
+or NULL if the jail does not exist.
+.Pp
+The
+.Fn jail_setv
+function takes a null-terminated list of name and value strings,
+and passes it to
+.Xr jail_set 2 .
+.Pp
+The
+.Fn jail_getv
+function takes a null-terminated list of name and value strings,
+and passes it to
+.Xr jail_get 2 .
+It is the caller's responsibility to ensure that the value strings point
+to buffers large enough to hold the string representation of the
+returned parameters.
+.Pp
+The
+.Fn jailparam_all
+function sets
+.Ar jpp
+to a list of all known jail parameters, and returns the number of
+parameters.
+The list should later be freed with
+.Fn jailparam_free
+and
+.Xr free 3 .
+.Pp
+The
+.Fn jailparam_init
+function clears a parameter record and copies the
+.Ar name
+to it. After use, it should be freed with
+.Fn jailparam_free .
+.Pp
+The
+.Fn jailparam_import
+function adds a
+.Ar value
+to a parameter record, converting it from a string to its native form.
+The
+.Fn jailparam_import_raw
+function adds a value without performing any conversion.
+.Pp
+The
+.Fn jailparam_set
+function passes a list of parameters to
+.Xr jail_set 2 .
+The parameters are assumed to have been created with
+.Fn jailparam_init
+and
+.Fn jailparam_import .
+.Pp
+The
+.Fn jailparam_get
+function function passes a list of parameters to
+.Xr jail_get 2 .
+The parameters are assumed to have been created with
+.Fn jailparam_init
+or
+.Fn jailparam_list ,
+with one parameter (the key) having been given a value with
+.Fn jailparam_import .
+.Pp
+The
+.Fn jailparam_export
+function returns the string equivalent of a parameter value.
+The returned string should freed after use.
+.Pp
+The
+.Fn jailparam_free
+function frees the stored names and values in a parameter list.
+If the list itself came from
+.Fn jailparam_all ,
+it should be freed as well.
+.Sh EXAMPLES
+Set the hostname of jail
+.Dq foo
+to
+.Dq foo.bar :
+.Bd -literal -offset indent
+jail_setv(JAIL_UPDATE, "name", "foo", "host.hostname", "foo.bar",
+ NULL);
+.Ed
+.Pp
+OR:
+.Bd -literal -offset indent
+struct jailparam params[2];
+jailparam_init(&params[0], "name");
+jailparam_import(&params[0], "foo");
+jailparam_init(&params[1], "host.hostname");
+jailparam_import(&params[1], "foo.bar");
+jailparam_set(params, 2, JAIL_UPDATE);
+jailparam_free(params, 2);
+.Ed
+.Pp
+Retrieve the hostname of jail
+.Dq foo :
+.Bd -literal -offset indent
+char hostname[MAXHOSTNAMELEN];
+jail_getv(0, "name", "foo", "host.hostname", hostname, NULL);
+.Ed
+.Pp
+OR:
+.Bd -literal -offset indent
+struct jailparam params[2];
+jailparam_init(&params[0], "name");
+jailparam_import(&params[0], "foo");
+jailparam_init(&params[1], "host.hostname");
+jailparam_get(params, 2, 0);
+hostname = jailparam_export(&params[1]);
+jailparam_free(params, 2);
+.Ed
+.Sh RETURN VALUES
+The
+.Fn jail_getid ,
+.Fn jail_setv ,
+.Fn jail_getv ,
+.Fn jailparam_set
+and
+.Fn jailparam_get
+functions return a JID on success, or \-1 on error.
+.Pp
+The
+.Fn jail_getname
+and
+.Fn jailparam_export
+functions return a dynamically allocated string on success, or NULL on error.
+.Pp
+The
+.Fn jailparam_all
+function returns the number of parameters on success, or \-1 on error.
+.Pp
+The
+.Fn jailparam_init ,
+.Fn jailparam_import
+and
+.Fn jailparam_import_raw
+functions return 0 on success, or \-1 on error.
+.Pp
+Whenever an error is returned,
+.Va errno
+is set, and the global string
+.Va jail_errmsg
+contains a descrption of the error, possibly from
+.Xr jail_set 2
+or
+.Xr jail_get 2 .
+.Sh ERRORS
+The
+.Nm jail
+functions may return errors from
+.Xr jail_set 2 ,
+.Xr jail_get 2 ,
+.Xr malloc 3
+or
+.Xr sysctl 3 .
+In addition, the following errors are possible:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+A prameter value cannot be convert from the passed string to its
+internal form.
+.It Bq Er ENOENT
+The named parameter does not exist.
+.It Bq Er ENOENT
+A parameter is of an unknown type.
+.Sh SEE ALSO
+.Xr jail 2 ,
+.Xr jail 8 ,
+.Xr sysctl 3
+.Sh HISTORY
+The
+.Nm jail
+library first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An James Gritton
diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c
new file mode 100644
index 0000000..f4a173a
--- /dev/null
+++ b/lib/libjail/jail.c
@@ -0,0 +1,972 @@
+/*-
+ * Copyright (c) 2009 James Gritton.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/jail.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "jail.h"
+
+#define SJPARAM "security.jail.param"
+
+#define JPS_IN_ADDR 1
+#define JPS_IN6_ADDR 2
+
+#define ARRAY_SANITY 5
+#define ARRAY_SLOP 5
+
+
+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);
+
+char jail_errmsg[JAIL_ERRMSGLEN];
+
+
+/*
+ * Import a null-terminated parameter list and set a jail with the flags
+ * and parameters.
+ */
+int
+jail_setv(int flags, ...)
+{
+ va_list ap;
+ struct jailparam *jp;
+ int njp;
+
+ va_start(ap, flags);
+ njp = jailparam_vlist(&jp, ap);
+ va_end(ap);
+ if (njp < 0)
+ return (njp);
+ return (jailparam_set(jp, njp, flags));
+}
+
+/*
+ * Read a null-terminated parameter list, get the referenced jail, and export
+ * the parameters to the list.
+ */
+int
+jail_getv(int flags, ...)
+{
+ va_list ap, tap;
+ struct jailparam *jp;
+ char *valarg;
+ const char *value;
+ int njp, i, jid, namekey, zero;
+
+ va_start(ap, flags);
+ va_copy(tap, ap);
+ njp = jailparam_vlist(&jp, tap);
+ 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;
+ }
+ jid = jailparam_get(jp, njp, flags);
+ if (jid < 0) {
+ va_end(ap);
+ return (-1);
+ }
+ 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"))
+ /* It's up to the caller to ensure there's room. */
+ strcpy(valarg, value);
+ }
+ va_end(ap);
+ return (jid);
+}
+
+/*
+ * Return a list of all known parameters.
+ */
+int
+jailparam_all(struct jailparam **jpp)
+{
+ struct jailparam *jp;
+ char *nname;
+ size_t mlen1, mlen2, buflen;
+ int njp, nlist;
+ int mib1[CTL_MAXNAME], mib2[CTL_MAXNAME - 2];
+ char buf[MAXPATHLEN];
+
+ njp = 0;
+ nlist = 32;
+ jp = malloc(nlist * sizeof(*jp));
+ if (jp == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (-1);
+ }
+ mib1[0] = 0;
+ mib1[1] = 2;
+ mlen1 = CTL_MAXNAME - 2;
+ if (sysctlnametomib(SJPARAM, mib1 + 2, &mlen1) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctlnametomib(" SJPARAM "): %s", strerror(errno));
+ goto error;
+ }
+ for (;; njp++) {
+ /* Get the next parameter. */
+ mlen2 = sizeof(mib2);
+ if (sysctl(mib1, mlen1 + 2, mib2, &mlen2, NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(0.2): %s", strerror(errno));
+ goto error;
+ }
+ if (mib2[0] != mib1[2] || mib2[1] != mib1[3] ||
+ mib2[2] != mib1[4])
+ break;
+ /* Convert it to an ascii name. */
+ memcpy(mib1 + 2, mib2, mlen2);
+ mlen1 = mlen2 / sizeof(int);
+ mib1[1] = 1;
+ buflen = sizeof(buf);
+ if (sysctl(mib1, mlen1 + 2, buf, &buflen, NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(0.1): %s", strerror(errno));
+ goto error;
+ }
+ /* Add the parameter to the list */
+ if (njp >= nlist) {
+ nlist *= 2;
+ jp = realloc(jp, nlist * sizeof(jp));
+ if (jp == NULL) {
+ jailparam_free(jp, njp);
+ return (-1);
+ }
+ }
+ if (jailparam_init(jp + njp, buf + sizeof(SJPARAM)) < 0)
+ goto error;
+ if (jailparam_type(jp + njp) < 0) {
+ njp++;
+ goto error;
+ }
+ /* Convert nobool parameters to bool. */
+ if (jp[njp].jp_flags & JP_NOBOOL) {
+ nname = nononame(jp[njp].jp_name);
+ if (nname == NULL) {
+ njp++;
+ goto error;
+ }
+ free(jp[njp].jp_name);
+ jp[njp].jp_name = nname;
+ jp[njp].jp_flags ^= JP_BOOL | JP_NOBOOL;
+ }
+ mib1[1] = 2;
+ }
+ jp = realloc(jp, njp * sizeof(*jp));
+ *jpp = jp;
+ return (njp);
+
+ error:
+ jailparam_free(jp, njp);
+ free(jp);
+ return (-1);
+}
+
+/*
+ * Clear a jail parameter and copy in its name.
+ */
+int
+jailparam_init(struct jailparam *jp, const char *name)
+{
+
+ memset(jp, 0, sizeof(*jp));
+ jp->jp_name = strdup(name);
+ if (jp->jp_name == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Put a name and value into a jail parameter element, converting the value
+ * to internal form.
+ */
+int
+jailparam_import(struct jailparam *jp, const char *value)
+{
+ char *p, *ep, *tvalue;
+ const char *avalue;
+ int i, nval, fw;
+
+ if (!jp->jp_ctltype && jailparam_type(jp) < 0)
+ goto error;
+ if (value == NULL)
+ return (0);
+ if ((jp->jp_ctltype & CTLTYPE) == CTLTYPE_STRING) {
+ jp->jp_value = strdup(value);
+ if (!jp->jp_value) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ goto error;
+ }
+ return (0);
+ }
+ nval = 1;
+ if (jp->jp_elemlen) {
+ if (value[0] == '\0' || (value[0] == '-' && value[1] == '\0')) {
+ jp->jp_value = strdup("");
+ if (value == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ goto error;
+ }
+ jp->jp_valuelen = 0;
+ return (0);
+ }
+ for (p = strchr(value, ','); p; p = strchr(p + 1, ','))
+ nval++;
+ jp->jp_valuelen = jp->jp_elemlen * nval;
+ }
+ jp->jp_value = malloc(jp->jp_valuelen);
+ if (!jp->jp_value) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ goto error;
+ }
+ avalue = value;
+ for (i = 0; i < nval; i++) {
+ fw = nval == 1 ? strlen(avalue) : strcspn(avalue, ",");
+ switch (jp->jp_ctltype & CTLTYPE) {
+ case CTLTYPE_INT:
+ if (jp->jp_flags & (JP_BOOL | JP_NOBOOL)) {
+ if (!strncasecmp(avalue, "true", 4))
+ ((int *)jp->jp_value)[i] = 1;
+ else if (!strncasecmp(avalue, "false", 5))
+ ((int *)jp->jp_value)[i] = 0;
+ else {
+ snprintf(jail_errmsg,
+ JAIL_ERRMSGLEN,
+ "%s: unknown boolean value \"%.*s\"",
+ jp->jp_name, fw, avalue);
+ errno = EINVAL;
+ goto error;
+ }
+ break;
+ }
+ ((int *)jp->jp_value)[i] = strtol(avalue, &ep, 10);
+ integer_test:
+ if (ep != avalue + fw) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "%s: non-integer value \"%.*s\"",
+ jp->jp_name, fw, avalue);
+ errno = EINVAL;
+ goto error;
+ }
+ break;
+ case CTLTYPE_UINT:
+ ((unsigned *)jp->jp_value)[i] =
+ strtoul(avalue, &ep, 10);
+ goto integer_test;
+ case CTLTYPE_LONG:
+ ((long *)jp->jp_value)[i] = strtol(avalue, &ep, 10);
+ goto integer_test;
+ case CTLTYPE_ULONG:
+ ((unsigned long *)jp->jp_value)[i] =
+ strtoul(avalue, &ep, 10);
+ goto integer_test;
+ case CTLTYPE_QUAD:
+ ((int64_t *)jp->jp_value)[i] =
+ strtoimax(avalue, &ep, 10);
+ goto integer_test;
+ 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:
+ goto unknown_type;
+ }
+ break;
+ default:
+ unknown_type:
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown type for %s", jp->jp_name);
+ errno = ENOENT;
+ goto error;
+ }
+ avalue += fw + 1;
+ }
+ return (0);
+
+ error:
+ free(jp->jp_value);
+ jp->jp_value = NULL;
+ return (-1);
+}
+
+/*
+ * Put a name and value into a jail parameter element, copying the value
+ * but not altering it.
+ */
+int
+jailparam_import_raw(struct jailparam *jp, void *value, size_t valuelen)
+{
+
+ jp->jp_value = value;
+ jp->jp_valuelen = valuelen;
+ jp->jp_flags |= JP_RAWVALUE;
+ return (0);
+}
+
+/*
+ * Run the jail_set and jail_get system calls on a parameter list.
+ */
+int
+jailparam_set(struct jailparam *jp, unsigned njp, int flags)
+{
+ struct iovec *jiov;
+ char *nname;
+ int i, jid;
+ unsigned j;
+
+ jiov = alloca(sizeof(struct iovec) * 2 * (njp + 1));
+ for (i = j = 0; j < njp; j++) {
+ jiov[i].iov_base = jp[j].jp_name;
+ jiov[i].iov_len = strlen(jp[j].jp_name) + 1;
+ i++;
+ if (jp[j].jp_flags & (JP_BOOL | JP_NOBOOL)) {
+ /*
+ * Set booleans without values. If one have a value of
+ * zero, change it to (or from) its "no" counterpart.
+ */
+ jiov[i].iov_base = NULL;
+ jiov[i].iov_len = 0;
+ if (jp[j].jp_value != NULL &&
+ jp[j].jp_valuelen == sizeof(int) &&
+ !*(int *)jp[j].jp_value) {
+ nname = jp[j].jp_flags & JP_BOOL
+ ? noname(jiov[i].iov_base)
+ : nononame(jiov[i].iov_base);
+ if (nname == NULL)
+ return (-1);
+ free(jp[j].jp_name);
+ jiov[i].iov_base = jp[j].jp_name = nname;
+ }
+ } else {
+ jiov[i].iov_base = jp[j].jp_value;
+ jiov[i].iov_len =
+ (jp[j].jp_ctltype & CTLTYPE) == CTLTYPE_STRING
+ ? strlen(jp[j].jp_value) + 1
+ : jp[j].jp_valuelen;
+ }
+ i++;
+ }
+ *(const void **)&jiov[i].iov_base = "errmsg";
+ jiov[i].iov_len = sizeof("errmsg");
+ i++;
+ jiov[i].iov_base = jail_errmsg;
+ jiov[i].iov_len = JAIL_ERRMSGLEN;
+ i++;
+ jail_errmsg[0] = 0;
+ jid = jail_set(jiov, i, flags);
+ if (jid < 0 && !jail_errmsg[0])
+ snprintf(jail_errmsg, sizeof(jail_errmsg), "jail_set: %s",
+ strerror(errno));
+ return (jid);
+}
+
+int
+jailparam_get(struct jailparam *jp, unsigned njp, int flags)
+{
+ struct iovec *jiov;
+ struct jailparam *jp_lastjid, *jp_jid, *jp_name, *jp_key;
+ int i, ai, ki, jid, arrays, sanity;
+ unsigned j;
+
+ /* Find the key and any array parameters. */
+ jiov = alloca(sizeof(struct iovec) * 2 * (njp + 1));
+ jp_lastjid = jp_jid = jp_name = NULL;
+ arrays = 0;
+ for (ai = j = 0; j < njp; j++) {
+ if (!strcmp(jp[j].jp_name, "lastjid"))
+ jp_lastjid = jp + j;
+ else if (!strcmp(jp[j].jp_name, "jid"))
+ jp_jid = jp + j;
+ else if (!strcmp(jp[j].jp_name, "name"))
+ jp_name = jp + j;
+ else if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) {
+ arrays = 1;
+ jiov[ai].iov_base = jp[j].jp_name;
+ jiov[ai].iov_len = strlen(jp[j].jp_name) + 1;
+ ai++;
+ jiov[ai].iov_base = NULL;
+ jiov[ai].iov_len = 0;
+ ai++;
+ }
+ }
+ jp_key = jp_lastjid ? jp_lastjid :
+ jp_jid && jp_jid->jp_valuelen == sizeof(int) &&
+ *(int *)jp_jid->jp_value ? jp_jid : jp_name;
+ if (jp_key == NULL || jp_key->jp_value == NULL) {
+ strlcpy(jail_errmsg, "no jail specified", JAIL_ERRMSGLEN);
+ errno = ENOENT;
+ return (-1);
+ }
+ ki = ai;
+ jiov[ki].iov_base = jp_key->jp_name;
+ jiov[ki].iov_len = strlen(jp_key->jp_name) + 1;
+ ki++;
+ jiov[ki].iov_base = jp_key->jp_value;
+ jiov[ki].iov_len = (jp_key->jp_ctltype & CTLTYPE) == CTLTYPE_STRING
+ ? strlen(jp_key->jp_value) + 1 : jp_key->jp_valuelen;
+ ki++;
+ *(const void **)&jiov[ki].iov_base = "errmsg";
+ jiov[ki].iov_len = sizeof("errmsg");
+ ki++;
+ jiov[ki].iov_base = jail_errmsg;
+ jiov[ki].iov_len = JAIL_ERRMSGLEN;
+ ki++;
+ jail_errmsg[0] = 0;
+ if (arrays && jail_get(jiov, ki, flags) < 0) {
+ if (!jail_errmsg[0])
+ snprintf(jail_errmsg, sizeof(jail_errmsg),
+ "jail_get: %s", strerror(errno));
+ return (-1);
+ }
+ /* Allocate storage for all parameters. */
+ for (ai = j = 0, i = ki; j < njp; j++) {
+ if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) {
+ ai++;
+ jiov[ai].iov_len += jp[j].jp_elemlen * ARRAY_SLOP;
+ jiov[ai].iov_base = jp[j].jp_value =
+ malloc(jiov[ai].iov_len);
+ if (jiov[ai].iov_base == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (-1);
+ }
+ memset(jiov[ai].iov_base, 0, jiov[ai].iov_len);
+ ai++;
+ } else if (jp + j != jp_key) {
+ jiov[i].iov_base = jp[j].jp_name;
+ jiov[i].iov_len = strlen(jp[j].jp_name) + 1;
+ i++;
+ jiov[i].iov_base = jp[j].jp_value =
+ malloc(jp[j].jp_valuelen);
+ if (jiov[i].iov_base == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (-1);
+ }
+ jiov[i].iov_len = jp[j].jp_valuelen;
+ memset(jiov[i].iov_base, 0, jiov[i].iov_len);
+ i++;
+ }
+ }
+ /*
+ * Get the prison. If there are array elements, retry a few times
+ * in case their sizes changed from under us.
+ */
+ for (sanity = 0;; sanity++) {
+ jid = jail_get(jiov, i, flags);
+ if (jid >= 0 || !arrays || sanity == ARRAY_SANITY ||
+ errno != EINVAL || jail_errmsg[0])
+ break;
+ for (ai = j = 0; j < njp; j++) {
+ if (jp[j].jp_elemlen &&
+ !(jp[j].jp_flags & JP_RAWVALUE)) {
+ ai++;
+ free(jiov[ai].iov_base);
+ jiov[ai].iov_base = jp[j].jp_value = NULL;
+ jiov[ai].iov_len = 0;
+ ai++;
+ }
+ }
+ if (jail_get(jiov, ki, flags) < 0)
+ break;
+ for (ai = j = 0; j < njp; j++) {
+ if (jp[j].jp_elemlen &&
+ !(jp[j].jp_flags & JP_RAWVALUE)) {
+ ai++;
+ jiov[ai].iov_len +=
+ jp[j].jp_elemlen * ARRAY_SLOP;
+ jiov[ai].iov_base = jp[j].jp_value =
+ malloc(jiov[ai].iov_len);
+ if (jiov[ai].iov_base == NULL) {
+ strerror_r(errno, jail_errmsg,
+ JAIL_ERRMSGLEN);
+ return (-1);
+ }
+ memset(jiov[ai].iov_base, 0, jiov[ai].iov_len);
+ ai++;
+ }
+ }
+ }
+ if (jid < 0 && !jail_errmsg[0])
+ snprintf(jail_errmsg, sizeof(jail_errmsg),
+ "jail_get: %s", strerror(errno));
+ for (ai = j = 0, i = ki; j < njp; j++) {
+ if (jp[j].jp_elemlen && !(jp[j].jp_flags & JP_RAWVALUE)) {
+ ai++;
+ jp[j].jp_valuelen = jiov[ai].iov_len;
+ ai++;
+ } else if (jp + j != jp_key) {
+ i++;
+ jp[j].jp_valuelen = jiov[i].iov_len;
+ i++;
+ }
+ }
+ return (jid);
+}
+
+/*
+ * Convert a jail parameter's value to external form.
+ */
+char *
+jailparam_export(struct jailparam *jp)
+{
+ char *value, *tvalue, **values;
+ size_t valuelen;
+ int i, nval;
+ char valbuf[INET6_ADDRSTRLEN];
+
+ if (!jp->jp_ctltype && jailparam_type(jp) < 0)
+ return (NULL);
+ if ((jp->jp_ctltype & CTLTYPE) == CTLTYPE_STRING) {
+ value = strdup(jp->jp_value);
+ if (value == NULL)
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (value);
+ }
+ nval = jp->jp_elemlen ? jp->jp_valuelen / jp->jp_elemlen : 1;
+ if (nval == 0) {
+ value = strdup("");
+ if (value == NULL)
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (value);
+ }
+ values = alloca(nval * sizeof(char *));
+ valuelen = 0;
+ for (i = 0; i < nval; i++) {
+ switch (jp->jp_ctltype & CTLTYPE) {
+ case CTLTYPE_INT:
+ if (jp->jp_flags & (JP_BOOL | JP_NOBOOL)) {
+ strlcpy(valbuf,
+ ((int *)jp->jp_value)[i] ? "true" : "false",
+ sizeof(valbuf));
+ break;
+ }
+ snprintf(valbuf, sizeof(valbuf), "%d",
+ ((int *)jp->jp_value)[i]);
+ break;
+ case CTLTYPE_UINT:
+ snprintf(valbuf, sizeof(valbuf), "%u",
+ ((unsigned *)jp->jp_value)[i]);
+ break;
+ case CTLTYPE_LONG:
+ snprintf(valbuf, sizeof(valbuf), "%ld",
+ ((long *)jp->jp_value)[i]);
+ break;
+ case CTLTYPE_ULONG:
+ snprintf(valbuf, sizeof(valbuf), "%lu",
+ ((unsigned long *)jp->jp_value)[i]);
+ break;
+ case CTLTYPE_QUAD:
+ snprintf(valbuf, sizeof(valbuf), "%jd",
+ (intmax_t)((int64_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:
+ goto unknown_type;
+ }
+ break;
+ default:
+ unknown_type:
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown type for %s", jp->jp_name);
+ errno = ENOENT;
+ return (NULL);
+ }
+ valuelen += strlen(valbuf) + 1;
+ values[i] = alloca(valuelen);
+ strcpy(values[i], valbuf);
+ }
+ value = malloc(valuelen + 1);
+ if (value == NULL)
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ else {
+ tvalue = value;
+ for (i = 0; i < nval; i++) {
+ strcpy(tvalue, values[i]);
+ if (i < nval - 1) {
+ tvalue += strlen(values[i]);
+ *tvalue++ = ',';
+ }
+ }
+ }
+ return (value);
+}
+
+/*
+ * Free the contents of a jail parameter list (but not thst list itself).
+ */
+void
+jailparam_free(struct jailparam *jp, unsigned njp)
+{
+ unsigned j;
+
+ for (j = 0; j < njp; j++) {
+ free(jp[j].jp_name);
+ if (!(jp[j].jp_flags & JP_RAWVALUE))
+ free(jp[j].jp_value);
+ }
+}
+
+/*
+ * 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
+jailparam_type(struct jailparam *jp)
+{
+ char *p, *nname;
+ size_t miblen, desclen;
+ int isarray;
+ struct {
+ int i;
+ char s[MAXPATHLEN];
+ } desc;
+ int mib[CTL_MAXNAME];
+
+ /* The "lastjid" parameter isn't real. */
+ if (!strcmp(jp->jp_name, "lastjid")) {
+ jp->jp_valuelen = sizeof(int);
+ jp->jp_ctltype = CTLTYPE_INT | CTLFLAG_WR;
+ return (0);
+ }
+
+ /* Find the sysctl that describes the parameter. */
+ mib[0] = 0;
+ mib[1] = 3;
+ snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", jp->jp_name);
+ miblen = sizeof(mib) - 2 * sizeof(int);
+ if (sysctl(mib, 2, mib + 2, &miblen, desc.s, strlen(desc.s)) < 0) {
+ if (errno != ENOENT) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(0.3.%s): %s", jp->jp_name, strerror(errno));
+ return (-1);
+ }
+ /*
+ * The parameter probably doesn't exist. But it might be
+ * the "no" counterpart to a boolean.
+ */
+ nname = nononame(jp->jp_name);
+ if (nname != NULL) {
+ snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", nname);
+ free(nname);
+ miblen = sizeof(mib) - 2 * sizeof(int);
+ if (sysctl(mib, 2, mib + 2, &miblen, desc.s,
+ strlen(desc.s)) >= 0) {
+ mib[1] = 4;
+ desclen = sizeof(desc);
+ if (sysctl(mib, (miblen / sizeof(int)) + 2,
+ &desc, &desclen, NULL, 0) < 0) {
+ snprintf(jail_errmsg,
+ JAIL_ERRMSGLEN,
+ "sysctl(0.4.%s): %s", desc.s,
+ strerror(errno));
+ return (-1);
+ }
+ if ((desc.i & CTLTYPE) == CTLTYPE_INT &&
+ desc.s[0] == 'B') {
+ jp->jp_ctltype = desc.i;
+ jp->jp_flags |= JP_NOBOOL;
+ jp->jp_valuelen = sizeof(int);
+ return (0);
+ }
+ }
+ }
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown parameter: %s", jp->jp_name);
+ errno = ENOENT;
+ return (-1);
+ }
+ mib[1] = 4;
+ desclen = sizeof(desc);
+ if (sysctl(mib, (miblen / sizeof(int)) + 2, &desc, &desclen,
+ NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(0.4.%s): %s", jp->jp_name, strerror(errno));
+ return (-1);
+ }
+ /* See if this is an array type. */
+ p = strchr(desc.s, '\0');
+ isarray = 0;
+ if (p - 2 < desc.s || strcmp(p - 2, ",a"))
+ isarray = 0;
+ else {
+ isarray = 1;
+ p[-2] = 0;
+ }
+ /* Look for types we understand */
+ jp->jp_ctltype = desc.i;
+ switch (desc.i & CTLTYPE) {
+ case CTLTYPE_INT:
+ if (desc.s[0] == 'B')
+ jp->jp_flags |=
+ (desc.s[1] == 'N') ? JP_NOBOOL : JP_BOOL;
+ case CTLTYPE_UINT:
+ jp->jp_valuelen = sizeof(int);
+ break;
+ case CTLTYPE_LONG:
+ case CTLTYPE_ULONG:
+ jp->jp_valuelen = sizeof(long);
+ break;
+ case CTLTYPE_QUAD:
+ jp->jp_valuelen = sizeof(int64_t);
+ break;
+ case CTLTYPE_STRING:
+ desc.s[0] = 0;
+ desclen = sizeof(desc.s);
+ if (sysctl(mib + 2, miblen / sizeof(int), desc.s, &desclen,
+ NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(" SJPARAM ".%s): %s", jp->jp_name,
+ strerror(errno));
+ return (-1);
+ }
+ 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);
+ } else {
+ desclen = 0;
+ if (sysctl(mib + 2, miblen / sizeof(int),
+ NULL, &jp->jp_valuelen, NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(" SJPARAM ".%s): %s", jp->jp_name,
+ strerror(errno));
+ return (-1);
+ }
+ }
+ break;
+ case CTLTYPE_NODE:
+ /*
+ * A node isn't normally a parameter, but may be a boolean
+ * if its "no" counterpart exists.
+ */
+ nname = noname(jp->jp_name);
+ if (nname == NULL)
+ return (-1);
+ mib[1] = 3;
+ snprintf(desc.s, sizeof(desc.s), SJPARAM ".%s", nname);
+ free(nname);
+ miblen = sizeof(mib) - 2 * sizeof(int);
+ if (sysctl(mib, 2, mib + 2, &miblen, desc.s,
+ strlen(desc.s)) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown parameter: %s", jp->jp_name);
+ return (-1);
+ }
+ mib[1] = 4;
+ desclen = sizeof(desc);
+ if (sysctl(mib, (miblen / sizeof(int)) + 2, &desc, &desclen,
+ NULL, 0) < 0) {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "sysctl(0.4.%s): %s", desc.s, strerror(errno));
+ return (-1);
+ }
+ if ((desc.i & CTLTYPE) != CTLTYPE_INT || desc.s[0] != 'B') {
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown parameter: %s", jp->jp_name);
+ errno = ENOENT;
+ return (-1);
+ }
+ jp->jp_valuelen = sizeof(int);
+ jp->jp_ctltype = desc.i;
+ jp->jp_flags |= JP_BOOL;
+ break;
+ default:
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN,
+ "unknown type for %s", jp->jp_name);
+ errno = ENOENT;
+ return (-1);
+ }
+ if (isarray) {
+ jp->jp_elemlen = jp->jp_valuelen;
+ jp->jp_valuelen = 0;
+ }
+ return (0);
+}
+
+/*
+ * Change a boolean parameter name into its "no" counterpart or vice versa.
+ */
+static char *
+noname(const char *name)
+{
+ char *nname, *p;
+
+ nname = malloc(strlen(name) + 3);
+ if (nname == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (NULL);
+ }
+ p = strrchr(name, '.');
+ if (p != NULL)
+ sprintf(nname, "%.*s.no%s", (int)(p - name), name, p + 1);
+ else
+ sprintf(nname, "no%s", name);
+ return (nname);
+}
+
+static char *
+nononame(const char *name)
+{
+ char *p, *nname;
+
+ p = strrchr(name, '.');
+ if (strncmp(p ? p + 1 : name, "no", 2)) {
+ snprintf(jail_errmsg, sizeof(jail_errmsg),
+ "mismatched boolean: %s", name);
+ errno = EINVAL;
+ return (NULL);
+ }
+ nname = malloc(strlen(name) - 1);
+ if (nname == NULL) {
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return (NULL);
+ }
+ if (p != NULL)
+ sprintf(nname, "%.*s.%s", (int)(p - name), name, p + 3);
+ else
+ strcpy(nname, name + 2);
+ return (nname);
+}
diff --git a/lib/libjail/jail.h b/lib/libjail/jail.h
new file mode 100644
index 0000000..4b38001
--- /dev/null
+++ b/lib/libjail/jail.h
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2009 James Gritton.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _JAIL_H
+#define _JAIL_H
+
+#define JP_RAWVALUE 0x01
+#define JP_BOOL 0x02
+#define JP_NOBOOL 0x04
+
+#define JAIL_ERRMSGLEN 1024
+
+extern char jail_errmsg[];
+
+struct jailparam {
+ char *jp_name;
+ void *jp_value;
+ size_t jp_valuelen;
+ size_t jp_elemlen;
+ int jp_ctltype;
+ int jp_structtype;
+ unsigned jp_flags;
+};
+
+__BEGIN_DECLS
+extern int jail_getid(const char *name);
+extern char *jail_getname(int jid);
+extern int jail_setv(int flags, ...);
+extern int jail_getv(int flags, ...);
+extern int jailparam_all(struct jailparam **jpp);
+extern int jailparam_init(struct jailparam *jp, const char *name);
+extern int jailparam_import(struct jailparam *jp, const char *value);
+extern int jailparam_import_raw(struct jailparam *jp, void *value,
+ size_t valuelen);
+extern int jailparam_set(struct jailparam *jp, unsigned njp, int flags);
+extern int jailparam_get(struct jailparam *jp, unsigned njp, int flags);
+extern char *jailparam_export(struct jailparam *jp);
+extern void jailparam_free(struct jailparam *jp, unsigned njp);
+__END_DECLS
+
+#endif /* _JAIL_H */
+
+
diff --git a/lib/libjail/jail_getid.c b/lib/libjail/jail_getid.c
new file mode 100644
index 0000000..e7601d5
--- /dev/null
+++ b/lib/libjail/jail_getid.c
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 2009 James Gritton.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/jail.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "jail.h"
+
+
+/*
+ * Return the JID corresponding to a jail name.
+ */
+int
+jail_getid(const char *name)
+{
+ char *ep;
+ int jid;
+ struct iovec jiov[4];
+
+ jid = strtoul(name, &ep, 10);
+ if (*name && !*ep)
+ return jid;
+ *(const void **)&jiov[0].iov_base = "name";
+ jiov[0].iov_len = sizeof("name");
+ jiov[1].iov_len = strlen(name) + 1;
+ jiov[1].iov_base = alloca(jiov[1].iov_len);
+ strcpy(jiov[1].iov_base, name);
+ *(const void **)&jiov[2].iov_base = "errmsg";
+ jiov[2].iov_len = sizeof("errmsg");
+ jiov[3].iov_base = jail_errmsg;
+ jiov[3].iov_len = JAIL_ERRMSGLEN;
+ jail_errmsg[0] = 0;
+ jid = jail_get(jiov, 4, 0);
+ if (jid < 0 && !jail_errmsg[0])
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN, "jail_get: %s",
+ strerror(errno));
+ return jid;
+}
+
+/*
+ * Return the name corresponding to a JID.
+ */
+char *
+jail_getname(int jid)
+{
+ struct iovec jiov[6];
+ char *name;
+ char namebuf[MAXHOSTNAMELEN];
+
+ *(const void **)&jiov[0].iov_base = "jid";
+ jiov[0].iov_len = sizeof("jid");
+ jiov[1].iov_base = &jid;
+ jiov[1].iov_len = sizeof(jid);
+ *(const void **)&jiov[2].iov_base = "name";
+ jiov[2].iov_len = sizeof("name");
+ jiov[3].iov_base = namebuf;
+ jiov[3].iov_len = sizeof(namebuf);
+ *(const void **)&jiov[4].iov_base = "errmsg";
+ jiov[4].iov_len = sizeof("errmsg");
+ jiov[5].iov_base = jail_errmsg;
+ jiov[5].iov_len = JAIL_ERRMSGLEN;
+ jail_errmsg[0] = 0;
+ jid = jail_get(jiov, 6, 0);
+ if (jid < 0 && !jail_errmsg[0])
+ snprintf(jail_errmsg, JAIL_ERRMSGLEN, "jail_get: %s",
+ strerror(errno));
+ name = strdup(namebuf);
+ if (name == NULL)
+ strerror_r(errno, jail_errmsg, JAIL_ERRMSGLEN);
+ return name;
+}
diff --git a/share/mk/bsd.libnames.mk b/share/mk/bsd.libnames.mk
index 0a364af..3a3fd86 100644
--- a/share/mk/bsd.libnames.mk
+++ b/share/mk/bsd.libnames.mk
@@ -69,6 +69,7 @@ LIBISC?= ${DESTDIR}${LIBDIR}/libisc.a
LIBISCCC?= ${DESTDIR}${LIBDIR}/libisccc.a
LIBISCCFG?= ${DESTDIR}${LIBDIR}/libisccfg.a
.endif
+LIBJAIL?= ${DESTDIR}${LIBDIR}/libjail.a
LIBKADM5CLNT?= ${DESTDIR}${LIBDIR}/libkadm5clnt.a
LIBKADM5SRV?= ${DESTDIR}${LIBDIR}/libkadm5srv.a
LIBKAFS5?= ${DESTDIR}${LIBDIR}/libkafs5.a
diff --git a/usr.bin/killall/Makefile b/usr.bin/killall/Makefile
index ff772a8..de58c78 100644
--- a/usr.bin/killall/Makefile
+++ b/usr.bin/killall/Makefile
@@ -1,5 +1,7 @@
# $FreeBSD$
PROG= killall
+DPADD= ${LIBJAIL}
+LDADD= -ljail
.include <bsd.prog.mk>
diff --git a/usr.bin/killall/killall.c b/usr.bin/killall/killall.c
index ffb6ee4..0a779fd 100644
--- a/usr.bin/killall/killall.c
+++ b/usr.bin/killall/killall.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
#include <sys/sysctl.h>
#include <fcntl.h>
#include <dirent.h>
+#include <jail.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -101,7 +102,6 @@ nosig(char *name)
int
main(int ac, char **av)
{
- struct iovec jparams[2];
struct kinfo_proc *procs = NULL, *newprocs;
struct stat sb;
struct passwd *pw;
@@ -162,18 +162,9 @@ main(int ac, char **av)
jflag++;
if (*av == NULL)
errx(1, "must specify jail");
- jid = strtoul(*av, &ep, 10);
- if (!**av || *ep) {
- *(const void **)&jparams[0].iov_base =
- "name";
- jparams[0].iov_len = sizeof("name");
- jparams[1].iov_base = *av;
- jparams[1].iov_len = strlen(*av) + 1;
- jid = jail_get(jparams, 2, 0);
- if (jid < 0)
- errx(1, "unknown jail: %s",
- *av);
- }
+ jid = jail_getid(*av);
+ if (jid < 0)
+ errx(1, "%s", jail_errmsg);
if (jail_attach(jid) == -1)
err(1, "jail_attach(%d)", jid);
break;
diff --git a/usr.sbin/jail/Makefile b/usr.sbin/jail/Makefile
index e92ced0..74fd6c4 100644
--- a/usr.sbin/jail/Makefile
+++ b/usr.sbin/jail/Makefile
@@ -4,8 +4,8 @@
PROG= jail
MAN= jail.8
-DPADD= ${LIBUTIL}
-LDADD= -lutil
+DPADD= ${LIBJAIL} ${LIBUTIL}
+LDADD= -ljail -lutil
WARNS?= 6
diff --git a/usr.sbin/jail/jail.c b/usr.sbin/jail/jail.c
index 9d9b979..666d034 100644
--- a/usr.sbin/jail/jail.c
+++ b/usr.sbin/jail/jail.c
@@ -32,7 +32,6 @@ __FBSDID("$FreeBSD$");
#include <sys/jail.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
-#include <sys/uio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
@@ -41,6 +40,7 @@ __FBSDID("$FreeBSD$");
#include <err.h>
#include <errno.h>
#include <grp.h>
+#include <jail.h>
#include <login_cap.h>
#include <netdb.h>
#include <paths.h>
@@ -50,15 +50,7 @@ __FBSDID("$FreeBSD$");
#include <string.h>
#include <unistd.h>
-#define SJPARAM "security.jail.param"
-#define ERRMSG_SIZE 256
-
-struct param {
- struct iovec name;
- struct iovec value;
-};
-
-static struct param *params;
+static struct jailparam *params;
static char **param_values;
static int nparams;
@@ -113,7 +105,6 @@ int
main(int argc, char **argv)
{
login_cap_t *lcap = NULL;
- struct iovec rparams[2];
struct passwd *pwd = NULL;
gid_t *groups;
size_t sysvallen;
@@ -121,8 +112,8 @@ main(int argc, char **argv)
int hflag, iflag, Jflag, lflag, rflag, uflag, Uflag;
long ngroups_max;
unsigned pi;
- char *ep, *jailname, *securelevel, *username, *JidFile;
- char errmsg[ERRMSG_SIZE], enforce_statfs[4];
+ char *jailname, *securelevel, *username, *JidFile;
+ char enforce_statfs[4];
static char *cleanenv;
const char *shell, *p = NULL;
FILE *fp;
@@ -176,16 +167,9 @@ main(int argc, char **argv)
jail_set_flags |= JAIL_UPDATE;
break;
case 'r':
- jid = strtoul(optarg, &ep, 10);
- if (!*optarg || *ep) {
- *(const void **)&rparams[0].iov_base = "name";
- rparams[0].iov_len = sizeof("name");
- rparams[1].iov_base = optarg;
- rparams[1].iov_len = strlen(optarg) + 1;
- jid = jail_get(rparams, 2, 0);
- if (jid < 0)
- errx(1, "unknown jail: %s", optarg);
- }
+ jid = jail_getid(optarg);
+ if (jid < 0)
+ errx(1, "%s", jail_errmsg);
rflag = 1;
break;
default:
@@ -280,21 +264,16 @@ main(int argc, char **argv)
if (ip6_addr != NULL)
set_param("ip6.addr", ip6_addr);
#endif
- errmsg[0] = 0;
- set_param("errmsg", errmsg);
if (Jflag) {
fp = fopen(JidFile, "w");
if (fp == NULL)
errx(1, "Could not create JidFile: %s", JidFile);
}
- jid = jail_set(&params->name, 2 * nparams,
+ jid = jailparam_set(params, nparams,
jail_set_flags ? jail_set_flags : JAIL_CREATE | JAIL_ATTACH);
- if (jid < 0) {
- if (errmsg[0] != '\0')
- errx(1, "%s", errmsg);
- err(1, "jail_set");
- }
+ if (jid < 0)
+ errx(1, "%s", jail_errmsg);
if (iflag) {
printf("%d\n", jid);
fflush(stdout);
@@ -303,10 +282,9 @@ main(int argc, char **argv)
if (jail_set_flags) {
fprintf(fp, "jid=%d", jid);
for (i = 0; i < nparams; i++)
- if (strcmp(params[i].name.iov_base, "jid") &&
- strcmp(params[i].name.iov_base, "errmsg")) {
+ if (strcmp(params[i].jp_name, "jid")) {
fprintf(fp, " %s",
- (char *)params[i].name.iov_base);
+ (char *)params[i].jp_name);
if (param_values[i]) {
putc('=', fp);
quoted_print(fp,
@@ -316,19 +294,19 @@ main(int argc, char **argv)
fprintf(fp, "\n");
} else {
for (i = 0; i < nparams; i++)
- if (!strcmp(params[i].name.iov_base, "path"))
+ if (!strcmp(params[i].jp_name, "path"))
break;
#ifdef INET6
fprintf(fp, "%d\t%s\t%s\t%s%s%s\t%s\n",
jid, i < nparams
- ? (char *)params[i].value.iov_base : argv[0],
+ ? (char *)params[i].jp_value : argv[0],
argv[1], ip4_addr ? ip4_addr : "",
ip4_addr && ip4_addr[0] && ip6_addr && ip6_addr[0]
? "," : "", ip6_addr ? ip6_addr : "", argv[3]);
#else
fprintf(fp, "%d\t%s\t%s\t%s\t%s\n",
jid, i < nparams
- ? (char *)params[i].value.iov_base : argv[0],
+ ? (char *)params[i].jp_value : argv[0],
argv[1], ip4_addr ? ip4_addr : "", argv[3]);
#endif
}
@@ -497,14 +475,8 @@ quoted_print(FILE *fp, char *str)
static void
set_param(const char *name, char *value)
{
- struct param *param;
- char *ep, *p;
- size_t buflen, mlen;
- int i, nval, mib[CTL_MAXNAME];
- struct {
- int i;
- char s[MAXPATHLEN];
- } buf;
+ struct jailparam *param;
+ int i;
static int paramlistsize;
@@ -517,9 +489,10 @@ set_param(const char *name, char *value)
/* Check for repeat parameters */
for (i = 0; i < nparams; i++)
- if (!strcmp(name, params[i].name.iov_base)) {
+ if (!strcmp(name, params[i].jp_name)) {
+ jailparam_free(params + i, 1);
memcpy(params + i, params + i + 1,
- (--nparams - i) * sizeof(struct param));
+ (--nparams - i) * sizeof(struct jailparam));
break;
}
@@ -542,141 +515,9 @@ set_param(const char *name, char *value)
/* Look up the paramter. */
param_values[nparams] = value;
param = params + nparams++;
- *(const void **)&param->name.iov_base = name;
- param->name.iov_len = strlen(name) + 1;
- /* Trivial values - no value or errmsg. */
- if (value == NULL) {
- param->value.iov_base = NULL;
- param->value.iov_len = 0;
- return;
- }
- if (!strcmp(name, "errmsg")) {
- param->value.iov_base = value;
- param->value.iov_len = ERRMSG_SIZE;
- return;
- }
- mib[0] = 0;
- mib[1] = 3;
- snprintf(buf.s, sizeof(buf.s), SJPARAM ".%s", name);
- mlen = sizeof(mib) - 2 * sizeof(int);
- if (sysctl(mib, 2, mib + 2, &mlen, buf.s, strlen(buf.s)) < 0)
- errx(1, "unknown parameter: %s", name);
- mib[1] = 4;
- buflen = sizeof(buf);
- if (sysctl(mib, (mlen / sizeof(int)) + 2, &buf, &buflen, NULL, 0) < 0)
- err(1, "sysctl(0.4.%s)", name);
- /*
- * See if this is an array type.
- * Treat non-arrays as an array of one.
- */
- p = strchr(buf.s, '\0');
- nval = 1;
- if (p - 2 >= buf.s && !strcmp(p - 2, ",a")) {
- if (value[0] == '\0' ||
- (value[0] == '-' && value[1] == '\0')) {
- param->value.iov_base = value;
- param->value.iov_len = 0;
- return;
- }
- p[-2] = 0;
- for (p = strchr(value, ','); p; p = strchr(p + 1, ',')) {
- *p = '\0';
- nval++;
- }
- }
-
- /* Set the values according to the parameter type. */
- switch (buf.i & CTLTYPE) {
- case CTLTYPE_INT:
- case CTLTYPE_UINT:
- param->value.iov_len = nval * sizeof(int);
- break;
- case CTLTYPE_LONG:
- case CTLTYPE_ULONG:
- param->value.iov_len = nval * sizeof(long);
- break;
- case CTLTYPE_STRUCT:
- if (!strcmp(buf.s, "S,in_addr"))
- param->value.iov_len = nval * sizeof(struct in_addr);
-#ifdef INET6
- else if (!strcmp(buf.s, "S,in6_addr"))
- param->value.iov_len = nval * sizeof(struct in6_addr);
-#endif
- else
- errx(1, "%s: unknown parameter structure (%s)",
- name, buf.s);
- break;
- case CTLTYPE_STRING:
- if (!strcmp(name, "path")) {
- param->value.iov_base = malloc(MAXPATHLEN);
- if (param->value.iov_base == NULL)
- err(1, "malloc");
- if (realpath(value, param->value.iov_base) == NULL)
- err(1, "%s: realpath(%s)", name, value);
- if (chdir(param->value.iov_base) != 0)
- err(1, "chdir: %s",
- (char *)param->value.iov_base);
- } else
- param->value.iov_base = value;
- param->value.iov_len = strlen(param->value.iov_base) + 1;
- return;
- default:
- errx(1, "%s: unknown parameter type %d (%s)",
- name, buf.i, buf.s);
- }
- param->value.iov_base = malloc(param->value.iov_len);
- for (i = 0; i < nval; i++) {
- switch (buf.i & CTLTYPE) {
- case CTLTYPE_INT:
- ((int *)param->value.iov_base)[i] =
- strtol(value, &ep, 10);
- if (ep[0] != '\0')
- errx(1, "%s: non-integer value \"%s\"",
- name, value);
- break;
- case CTLTYPE_UINT:
- ((unsigned *)param->value.iov_base)[i] =
- strtoul(value, &ep, 10);
- if (ep[0] != '\0')
- errx(1, "%s: non-integer value \"%s\"",
- name, value);
- break;
- case CTLTYPE_LONG:
- ((long *)param->value.iov_base)[i] =
- strtol(value, &ep, 10);
- if (ep[0] != '\0')
- errx(1, "%s: non-integer value \"%s\"",
- name, value);
- break;
- case CTLTYPE_ULONG:
- ((unsigned long *)param->value.iov_base)[i] =
- strtoul(value, &ep, 10);
- if (ep[0] != '\0')
- errx(1, "%s: non-integer value \"%s\"",
- name, value);
- break;
- case CTLTYPE_STRUCT:
- if (!strcmp(buf.s, "S,in_addr")) {
- if (inet_pton(AF_INET, value,
- &((struct in_addr *)
- param->value.iov_base)[i]) != 1)
- errx(1, "%s: not an IPv4 address: %s",
- name, value);
- }
-#ifdef INET6
- else if (!strcmp(buf.s, "S,in6_addr")) {
- if (inet_pton(AF_INET6, value,
- &((struct in6_addr *)
- param->value.iov_base)[i]) != 1)
- errx(1, "%s: not an IPv6 address: %s",
- name, value);
- }
-#endif
- }
- if (i > 0)
- value[-1] = ',';
- value = strchr(value, '\0') + 1;
- }
+ if (jailparam_init(param, name) < 0 ||
+ jailparam_import(param, value) < 0)
+ errx(1, "%s", jail_errmsg);
}
static void
diff --git a/usr.sbin/jexec/Makefile b/usr.sbin/jexec/Makefile
index 2bf817c..d55ea0fc 100644
--- a/usr.sbin/jexec/Makefile
+++ b/usr.sbin/jexec/Makefile
@@ -2,8 +2,8 @@
PROG= jexec
MAN= jexec.8
-DPADD= ${LIBUTIL}
-LDADD= -lutil
+DPADD= ${LIBJAIL} ${LIBUTIL}
+LDADD= -ljail -lutil
WARNS?= 6
.include <bsd.prog.mk>
diff --git a/usr.sbin/jexec/jexec.c b/usr.sbin/jexec/jexec.c
index 0d82e28..8c15ebe 100644
--- a/usr.sbin/jexec/jexec.c
+++ b/usr.sbin/jexec/jexec.c
@@ -31,13 +31,13 @@
#include <sys/jail.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
-#include <sys/uio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <err.h>
#include <errno.h>
+#include <jail.h>
#include <limits.h>
#include <login_cap.h>
#include <stdio.h>
@@ -67,14 +67,13 @@ static void usage(void);
int
main(int argc, char *argv[])
{
- struct iovec params[2];
int jid;
login_cap_t *lcap = NULL;
struct passwd *pwd = NULL;
gid_t *groups = NULL;
int ch, ngroups, uflag, Uflag;
long ngroups_max;
- char *ep, *username;
+ char *username;
ch = uflag = Uflag = 0;
username = NULL;
@@ -107,18 +106,11 @@ main(int argc, char *argv[])
usage();
if (uflag)
GET_USER_INFO;
- jid = strtoul(argv[0], &ep, 10);
- if (!*argv[0] || *ep) {
- *(const void **)&params[0].iov_base = "name";
- params[0].iov_len = sizeof("name");
- params[1].iov_base = argv[0];
- params[1].iov_len = strlen(argv[0]) + 1;
- jid = jail_get(params, 2, 0);
- if (jid < 0)
- errx(1, "Unknown jail: %s", argv[0]);
- }
+ jid = jail_getid(argv[0]);
+ if (jid < 0)
+ errx(1, "%s", jail_errmsg);
if (jail_attach(jid) == -1)
- err(1, "jail_attach(): %d", jid);
+ err(1, "jail_attach(%d)", jid);
if (chdir("/") == -1)
err(1, "chdir(): /");
if (username != NULL) {
diff --git a/usr.sbin/jls/Makefile b/usr.sbin/jls/Makefile
index 3968946..2d02c56 100644
--- a/usr.sbin/jls/Makefile
+++ b/usr.sbin/jls/Makefile
@@ -2,6 +2,9 @@
PROG= jls
MAN= jls.8
+DPADD= ${LIBJAIL}
+LDADD= -ljail
+
WARNS?= 6
.include <bsd.prog.mk>
diff --git a/usr.sbin/jls/jls.c b/usr.sbin/jls/jls.c
index d5e70d3..443eb8e 100644
--- a/usr.sbin/jls/jls.c
+++ b/usr.sbin/jls/jls.c
@@ -33,32 +33,21 @@ __FBSDID("$FreeBSD$");
#include <sys/jail.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
-#include <sys/uio.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <err.h>
#include <errno.h>
+#include <jail.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#define SJPARAM "security.jail.param"
-#define ARRAY_SLOP 5
-
-#define CTLTYPE_BOOL (CTLTYPE + 1)
-#define CTLTYPE_NOBOOL (CTLTYPE + 2)
-#define CTLTYPE_IPADDR (CTLTYPE + 3)
-#define CTLTYPE_IP6ADDR (CTLTYPE + 4)
-
-#define PARAM_KEY 0x01
-#define PARAM_USER 0x02
-#define PARAM_ARRAY 0x04
-#define PARAM_OPT 0x08
-#define PARAM_WR 0x10
+#define JP_USER 0x01000000
+#define JP_OPT 0x02000000
#define PRINT_DEFAULT 0x01
#define PRINT_HEADER 0x02
@@ -67,31 +56,17 @@ __FBSDID("$FreeBSD$");
#define PRINT_SKIP 0x10
#define PRINT_VERBOSE 0x20
-struct param {
- char *name;
- void *value;
- size_t size;
- int type;
- unsigned flags;
- int noparent;
-};
-
-struct iovec2 {
- struct iovec name;
- struct iovec value;
-};
-
-static struct param *params;
+static struct jailparam *params;
+static int *param_noparent;
static int nparams;
-static char errmsg[256];
-static int add_param(const char *name, void *value, unsigned flags);
-static int get_param(const char *name, struct param *param);
+static int add_param(const char *name, void *value, size_t valuelen,
+ struct jailparam *source, unsigned flags);
static int sort_param(const void *a, const void *b);
static char *noname(const char *name);
static char *nononame(const char *name);
static int print_jail(int pflags, int jflags);
-static void quoted_print(char *str, int len);
+static void quoted_print(char *str);
int
main(int argc, char **argv)
@@ -136,50 +111,54 @@ main(int argc, char **argv)
/* Add the parameters to print. */
if (optind == argc) {
if (pflags & PRINT_VERBOSE) {
- add_param("jid", NULL, PARAM_USER);
- add_param("host.hostname", NULL, PARAM_USER);
- add_param("path", NULL, PARAM_USER);
- add_param("name", NULL, PARAM_USER);
- add_param("dying", NULL, PARAM_USER);
- add_param("cpuset.id", NULL, PARAM_USER);
- add_param("ip4.addr", NULL, PARAM_USER);
- add_param("ip6.addr", NULL, PARAM_USER | PARAM_OPT);
+ add_param("jid", NULL, (size_t)0, NULL, JP_USER);
+ add_param("host.hostname", NULL, (size_t)0, NULL,
+ JP_USER);
+ add_param("path", NULL, (size_t)0, NULL, JP_USER);
+ add_param("name", NULL, (size_t)0, NULL, JP_USER);
+ add_param("dying", NULL, (size_t)0, NULL, JP_USER);
+ add_param("cpuset.id", NULL, (size_t)0, NULL, JP_USER);
+ add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER);
+ add_param("ip6.addr", NULL, (size_t)0, NULL,
+ JP_USER | JP_OPT);
} else {
pflags = (pflags &
~(PRINT_NAMEVAL | PRINT_SKIP | PRINT_VERBOSE)) |
PRINT_DEFAULT;
- add_param("jid", NULL, PARAM_USER);
- add_param("ip4.addr", NULL, PARAM_USER);
- add_param("host.hostname", NULL, PARAM_USER);
- add_param("path", NULL, PARAM_USER);
+ add_param("jid", NULL, (size_t)0, NULL, JP_USER);
+ add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER);
+ add_param("host.hostname", NULL, (size_t)0, NULL,
+ JP_USER);
+ add_param("path", NULL, (size_t)0, NULL, JP_USER);
}
} else
while (optind < argc)
- add_param(argv[optind++], NULL, PARAM_USER);
+ add_param(argv[optind++], NULL, (size_t)0, NULL,
+ JP_USER);
if (pflags & PRINT_SKIP) {
/* Check for parameters with boolean parents. */
for (i = 0; i < nparams; i++) {
- if ((params[i].flags & PARAM_USER) &&
- (dot = strchr(params[i].name, '.'))) {
+ if ((params[i].jp_flags & JP_USER) &&
+ (dot = strchr(params[i].jp_name, '.'))) {
*dot = 0;
- nname = noname(params[i].name);
+ nname = noname(params[i].jp_name);
*dot = '.';
- params[i].noparent =
- add_param(nname, NULL, PARAM_OPT);
+ param_noparent[i] =
+ add_param(nname, NULL, (size_t)0, NULL,
+ JP_OPT);
free(nname);
}
}
}
- /* Add the index key and errmsg parameters. */
+ /* Add the index key parameters. */
if (jid != 0)
- add_param("jid", &jid, PARAM_KEY);
+ add_param("jid", &jid, sizeof(jid), NULL, 0);
else if (jname != NULL)
- add_param("name", jname, PARAM_KEY);
+ add_param("name", jname, strlen(jname), NULL, 0);
else
- add_param("lastjid", &lastjid, PARAM_KEY);
- add_param("errmsg", errmsg, PARAM_KEY);
+ add_param("lastjid", &lastjid, sizeof(lastjid), NULL, 0);
/* Print a header line if requested. */
if (pflags & PRINT_VERBOSE)
@@ -192,105 +171,63 @@ main(int argc, char **argv)
"Hostname Path\n");
else if (pflags & PRINT_HEADER) {
for (i = spc = 0; i < nparams; i++)
- if (params[i].flags & PARAM_USER) {
+ if (params[i].jp_flags & JP_USER) {
if (spc)
putchar(' ');
else
spc = 1;
- fputs(params[i].name, stdout);
+ fputs(params[i].jp_name, stdout);
}
putchar('\n');
}
/* Fetch the jail(s) and print the paramters. */
if (jid != 0 || jname != NULL) {
- if (print_jail(pflags, jflags) < 0) {
- if (errmsg[0])
- errx(1, "%s", errmsg);
- err(1, "jail_get");
- }
+ if (print_jail(pflags, jflags) < 0)
+ errx(1, "%s", jail_errmsg);
} else {
for (lastjid = 0;
(lastjid = print_jail(pflags, jflags)) >= 0; )
;
- if (errno != 0 && errno != ENOENT) {
- if (errmsg[0])
- errx(1, "%s", errmsg);
- err(1, "jail_get");
- }
+ if (errno != 0 && errno != ENOENT)
+ errx(1, "%s", jail_errmsg);
}
return (0);
}
static int
-add_param(const char *name, void *value, unsigned flags)
+add_param(const char *name, void *value, size_t valuelen,
+ struct jailparam *source, unsigned flags)
{
- struct param *param;
- char *nname;
- size_t mlen1, mlen2, buflen;
- int mib1[CTL_MAXNAME], mib2[CTL_MAXNAME - 2];
+ struct jailparam *param, *tparams;
int i, tnparams;
- char buf[MAXPATHLEN];
static int paramlistsize;
/* The pseudo-parameter "all" scans the list of available parameters. */
if (!strcmp(name, "all")) {
- tnparams = nparams;
- mib1[0] = 0;
- mib1[1] = 2;
- mlen1 = CTL_MAXNAME - 2;
- if (sysctlnametomib(SJPARAM, mib1 + 2, &mlen1) < 0)
- err(1, "sysctlnametomib(" SJPARAM ")");
- for (;;) {
- /* Get the next parameter. */
- mlen2 = sizeof(mib2);
- if (sysctl(mib1, mlen1 + 2, mib2, &mlen2, NULL, 0) < 0)
- err(1, "sysctl(0.2)");
- if (mib2[0] != mib1[2] || mib2[1] != mib1[3] ||
- mib2[2] != mib1[4])
- break;
- /* Convert it to an ascii name. */
- memcpy(mib1 + 2, mib2, mlen2);
- mlen1 = mlen2 / sizeof(int);
- mib1[1] = 1;
- buflen = sizeof(buf);
- if (sysctl(mib1, mlen1 + 2, buf, &buflen, NULL, 0) < 0)
- err(1, "sysctl(0.1)");
- add_param(buf + sizeof(SJPARAM), NULL, flags);
- /*
- * Convert nobool parameters to bool if their
- * counterpart is a node, ortherwise discard them.
- */
- param = &params[nparams - 1];
- if (param->type == CTLTYPE_NOBOOL) {
- nname = nononame(param->name);
- if (get_param(nname, param) >= 0 &&
- param->type != CTLTYPE_NODE) {
- free(nname);
- nparams--;
- } else {
- free(param->name);
- param->name = nname;
- param->type = CTLTYPE_BOOL;
- param->size = sizeof(int);
- param->value = NULL;
- }
- }
- mib1[1] = 2;
- }
-
- qsort(params + tnparams, (size_t)(nparams - tnparams),
- sizeof(struct param), sort_param);
+ tnparams = jailparam_all(&tparams);
+ if (tnparams < 0)
+ errx(1, "%s", jail_errmsg);
+ qsort(tparams, (size_t)tnparams, sizeof(struct jailparam),
+ sort_param);
+ for (i = 0; i < tnparams; i++)
+ add_param(tparams[i].jp_name, NULL, (size_t)0,
+ tparams + i, flags);
+ free(tparams);
return -1;
}
/* Check for repeat parameters. */
for (i = 0; i < nparams; i++)
- if (!strcmp(name, params[i].name)) {
- params[i].value = value;
- params[i].flags |= flags;
+ if (!strcmp(name, params[i].jp_name)) {
+ if (value != NULL && jailparam_import_raw(params + i,
+ value, valuelen) < 0)
+ errx(1, "%s", jail_errmsg);
+ params[i].jp_flags |= flags;
+ if (source != NULL)
+ jailparam_free(source, 1);
return i;
}
@@ -298,151 +235,57 @@ add_param(const char *name, void *value, unsigned flags)
if (!nparams) {
paramlistsize = 32;
params = malloc(paramlistsize * sizeof(*params));
- if (params == NULL)
+ param_noparent =
+ malloc(paramlistsize * sizeof(*param_noparent));
+ if (params == NULL || param_noparent == NULL)
err(1, "malloc");
} else if (nparams >= paramlistsize) {
paramlistsize *= 2;
params = realloc(params, paramlistsize * sizeof(*params));
- if (params == NULL)
+ param_noparent = realloc(param_noparent,
+ paramlistsize * sizeof(*param_noparent));
+ if (params == NULL || param_noparent == NULL)
err(1, "realloc");
}
/* Look up the parameter. */
+ param_noparent[nparams] = -1;
param = params + nparams++;
- memset(param, 0, sizeof *param);
- param->name = strdup(name);
- if (param->name == NULL)
- err(1, "strdup");
- param->flags = flags;
- param->noparent = -1;
- /* We have to know about pseudo-parameters without asking. */
- if (!strcmp(param->name, "lastjid")) {
- param->type = CTLTYPE_INT;
- param->size = sizeof(int);
- goto got_type;
+ if (source != NULL) {
+ *param = *source;
+ param->jp_flags |= flags;
+ return param - params;
}
- if (!strcmp(param->name, "errmsg")) {
- param->type = CTLTYPE_STRING;
- param->size = sizeof(errmsg);
- goto got_type;
- }
- if (get_param(name, param) < 0) {
- if (errno != ENOENT)
- err(1, "sysctl(0.3.%s)", name);
- /* See if this the "no" part of an existing boolean. */
- if ((nname = nononame(name))) {
- i = get_param(nname, param);
- free(nname);
- if (i >= 0 && param->type == CTLTYPE_BOOL) {
- param->type = CTLTYPE_NOBOOL;
- goto got_type;
- }
- }
- if (flags & PARAM_OPT) {
+ if (jailparam_init(param, name) < 0)
+ errx(1, "%s", jail_errmsg);
+ param->jp_flags = flags;
+ if ((value != NULL ? jailparam_import_raw(param, value, valuelen)
+ : jailparam_import(param, value)) < 0) {
+ if (flags & JP_OPT) {
nparams--;
- return -1;
- }
- errx(1, "unknown parameter: %s", name);
- }
- if (param->type == CTLTYPE_NODE) {
- /*
- * A node isn't normally a parameter, but may be a boolean
- * if its "no" counterpart exists.
- */
- nname = noname(name);
- i = get_param(nname, param);
- free(nname);
- if (i >= 0 && param->type == CTLTYPE_NOBOOL) {
- param->type = CTLTYPE_BOOL;
- goto got_type;
+ return (-1);
}
- errx(1, "unknown parameter: %s", name);
+ errx(1, "%s", jail_errmsg);
}
-
- got_type:
- param->value = value;
return param - params;
}
static int
-get_param(const char *name, struct param *param)
-{
- char *p;
- size_t buflen, mlen;
- int mib[CTL_MAXNAME];
- struct {
- int i;
- char s[MAXPATHLEN];
- } buf;
-
- /* Look up the MIB. */
- mib[0] = 0;
- mib[1] = 3;
- snprintf(buf.s, sizeof(buf.s), SJPARAM ".%s", name);
- mlen = sizeof(mib) - 2 * sizeof(int);
- if (sysctl(mib, 2, mib + 2, &mlen, buf.s, strlen(buf.s)) < 0)
- return (-1);
- /* Get the type and size. */
- mib[1] = 4;
- buflen = sizeof(buf);
- if (sysctl(mib, (mlen / sizeof(int)) + 2, &buf, &buflen, NULL, 0) < 0)
- err(1, "sysctl(0.4.%s)", name);
- param->type = buf.i & CTLTYPE;
- if (buf.i & (CTLFLAG_WR | CTLFLAG_TUN))
- param->flags |= PARAM_WR;
- p = strchr(buf.s, '\0');
- if (p - 2 >= buf.s && !strcmp(p - 2, ",a")) {
- p[-2] = 0;
- param->flags |= PARAM_ARRAY;
- }
- switch (param->type) {
- case CTLTYPE_INT:
- /* An integer parameter might be a boolean. */
- if (buf.s[0] == 'B')
- param->type = buf.s[1] == 'N'
- ? CTLTYPE_NOBOOL : CTLTYPE_BOOL;
- case CTLTYPE_UINT:
- param->size = sizeof(int);
- break;
- case CTLTYPE_LONG:
- case CTLTYPE_ULONG:
- param->size = sizeof(long);
- break;
- case CTLTYPE_STRUCT:
- if (!strcmp(buf.s, "S,in_addr")) {
- param->type = CTLTYPE_IPADDR;
- param->size = sizeof(struct in_addr);
- } else if (!strcmp(buf.s, "S,in6_addr")) {
- param->type = CTLTYPE_IP6ADDR;
- param->size = sizeof(struct in6_addr);
- }
- break;
- case CTLTYPE_STRING:
- buf.s[0] = 0;
- sysctl(mib + 2, mlen / sizeof(int), buf.s, &buflen, NULL, 0);
- param->size = strtoul(buf.s, NULL, 10);
- if (param->size == 0)
- param->size = BUFSIZ;
- }
- return (0);
-}
-
-static int
sort_param(const void *a, const void *b)
{
- const struct param *parama, *paramb;
+ const struct jailparam *parama, *paramb;
char *ap, *bp;
/* Put top-level parameters first. */
parama = a;
paramb = b;
- ap = strchr(parama->name, '.');
- bp = strchr(paramb->name, '.');
+ ap = strchr(parama->jp_name, '.');
+ bp = strchr(paramb->jp_name, '.');
if (ap && !bp)
return (1);
if (bp && !ap)
return (-1);
- return (strcmp(parama->name, paramb->name));
+ return (strcmp(parama->jp_name, paramb->jp_name));
}
static char *
@@ -483,126 +326,38 @@ static int
print_jail(int pflags, int jflags)
{
char *nname;
- int i, ai, jid, count, sanity, spc;
+ char **param_values;
+ int i, ai, jid, count, spc;
char ipbuf[INET6_ADDRSTRLEN];
- static struct iovec2 *iov, *aiov;
- static int narray, nkey;
-
- /* Set up the parameter list(s) the first time around. */
- if (iov == NULL) {
- iov = malloc(nparams * sizeof(struct iovec2));
- if (iov == NULL)
- err(1, "malloc");
- for (i = narray = 0; i < nparams; i++) {
- iov[i].name.iov_base = params[i].name;
- iov[i].name.iov_len = strlen(params[i].name) + 1;
- iov[i].value.iov_base = params[i].value;
- iov[i].value.iov_len =
- params[i].type == CTLTYPE_STRING &&
- params[i].value != NULL &&
- ((char *)params[i].value)[0] != '\0'
- ? strlen(params[i].value) + 1 : params[i].size;
- if (params[i].flags & (PARAM_KEY | PARAM_ARRAY)) {
- narray++;
- if (params[i].flags & PARAM_KEY)
- nkey++;
- }
- }
- if (narray > nkey) {
- aiov = malloc(narray * sizeof(struct iovec2));
- if (aiov == NULL)
- err(1, "malloc");
- for (i = ai = 0; i < nparams; i++)
- if (params[i].flags &
- (PARAM_KEY | PARAM_ARRAY))
- aiov[ai++] = iov[i];
- }
- }
- /* If there are array parameters, find their sizes. */
- if (aiov != NULL) {
- for (ai = 0; ai < narray; ai++)
- if (aiov[ai].value.iov_base == NULL)
- aiov[ai].value.iov_len = 0;
- if (jail_get((struct iovec *)aiov, 2 * narray, jflags) < 0)
- return (-1);
- }
- /* Allocate storage for all parameters. */
- for (i = ai = 0; i < nparams; i++) {
- if (params[i].flags & (PARAM_KEY | PARAM_ARRAY)) {
- if (params[i].flags & PARAM_ARRAY) {
- iov[i].value.iov_len = aiov[ai].value.iov_len +
- ARRAY_SLOP * params[i].size;
- iov[i].value.iov_base =
- malloc(iov[i].value.iov_len);
- }
- ai++;
- } else
- iov[i].value.iov_base = malloc(params[i].size);
- if (iov[i].value.iov_base == NULL)
- err(1, "malloc");
- if (params[i].value == NULL)
- memset(iov[i].value.iov_base, 0, iov[i].value.iov_len);
- }
- /*
- * Get the actual prison. If there are array elements, retry a few
- * times in case the size changed from under us.
- */
- if ((jid = jail_get((struct iovec *)iov, 2 * nparams, jflags)) < 0) {
- if (errno != EINVAL || aiov == NULL || errmsg[0])
- return (-1);
- for (sanity = 0;; sanity++) {
- if (sanity == 10)
- return (-1);
- for (ai = 0; ai < narray; ai++)
- if (params[i].flags & PARAM_ARRAY)
- aiov[ai].value.iov_len = 0;
- if (jail_get((struct iovec *)iov, 2 * narray, jflags) <
- 0)
- return (-1);
- for (i = ai = 0; i < nparams; i++) {
- if (!(params[i].flags &
- (PARAM_KEY | PARAM_ARRAY)))
- continue;
- if (params[i].flags & PARAM_ARRAY) {
- iov[i].value.iov_len =
- aiov[ai].value.iov_len +
- ARRAY_SLOP * params[i].size;
- iov[i].value.iov_base =
- realloc(iov[i].value.iov_base,
- iov[i].value.iov_len);
- if (iov[i].value.iov_base == NULL)
- err(1, "malloc");
- }
- ai++;
- }
- }
- }
+ jid = jailparam_get(params, nparams, jflags);
+ if (jid < 0)
+ return jid;
if (pflags & PRINT_VERBOSE) {
printf("%6d %-29.29s %.74s\n"
"%6s %-29.29s %.74s\n"
"%6s %-6d\n",
- *(int *)iov[0].value.iov_base,
- (char *)iov[1].value.iov_base,
- (char *)iov[2].value.iov_base,
+ *(int *)params[0].jp_value,
+ (char *)params[1].jp_value,
+ (char *)params[2].jp_value,
"",
- (char *)iov[3].value.iov_base,
- *(int *)iov[4].value.iov_base ? "DYING" : "ACTIVE",
+ (char *)params[3].jp_value,
+ *(int *)params[4].jp_value ? "DYING" : "ACTIVE",
"",
- *(int *)iov[5].value.iov_base);
- count = iov[6].value.iov_len / sizeof(struct in_addr);
+ *(int *)params[5].jp_value);
+ count = params[6].jp_valuelen / sizeof(struct in_addr);
for (ai = 0; ai < count; ai++)
if (inet_ntop(AF_INET,
- &((struct in_addr *)iov[6].value.iov_base)[ai],
+ &((struct in_addr *)params[6].jp_value)[ai],
ipbuf, sizeof(ipbuf)) == NULL)
err(1, "inet_ntop");
else
printf("%6s %-15.15s\n", "", ipbuf);
- if (!strcmp(params[7].name, "ip6.addr")) {
- count = iov[7].value.iov_len / sizeof(struct in6_addr);
+ if (!strcmp(params[7].jp_name, "ip6.addr")) {
+ count = params[7].jp_valuelen / sizeof(struct in6_addr);
for (ai = 0; ai < count; ai++)
- if (inet_ntop(AF_INET6, &((struct in_addr *)
- iov[7].value.iov_base)[ai],
+ if (inet_ntop(AF_INET6,
+ &((struct in_addr *)params[7].jp_value)[ai],
ipbuf, sizeof(ipbuf)) == NULL)
err(1, "inet_ntop");
else
@@ -610,19 +365,28 @@ print_jail(int pflags, int jflags)
}
} else if (pflags & PRINT_DEFAULT)
printf("%6d %-15.15s %-29.29s %.74s\n",
- *(int *)iov[0].value.iov_base,
- iov[1].value.iov_len == 0 ? "-"
- : inet_ntoa(*(struct in_addr *)iov[1].value.iov_base),
- (char *)iov[2].value.iov_base,
- (char *)iov[3].value.iov_base);
+ *(int *)params[0].jp_value,
+ params[1].jp_valuelen == 0 ? "-"
+ : inet_ntoa(*(struct in_addr *)params[1].jp_value),
+ (char *)params[2].jp_value,
+ (char *)params[3].jp_value);
else {
+ param_values = alloca(nparams * sizeof(*param_values));
+ for (i = 0; i < nparams; i++) {
+ if (!(params[i].jp_flags & JP_USER))
+ continue;
+ param_values[i] = jailparam_export(params + i);
+ if (param_values[i] == NULL)
+ errx(1, "%s", jail_errmsg);
+ }
for (i = spc = 0; i < nparams; i++) {
- if (!(params[i].flags & PARAM_USER))
+ if (!(params[i].jp_flags & JP_USER))
continue;
if ((pflags & PRINT_SKIP) &&
- ((!(params[i].flags & PARAM_WR)) ||
- (params[i].noparent >= 0 &&
- *(int *)iov[params[i].noparent].value.iov_base)))
+ ((!(params[i].jp_ctltype &
+ (CTLFLAG_WR | CTLFLAG_TUN))) ||
+ (param_noparent[i] >= 0 &&
+ *(int *)params[param_noparent[i]].jp_value)))
continue;
if (spc)
putchar(' ');
@@ -633,109 +397,48 @@ print_jail(int pflags, int jflags)
* Generally "name=value", but for booleans
* either "name" or "noname".
*/
- switch (params[i].type) {
- case CTLTYPE_BOOL:
- if (*(int *)iov[i].value.iov_base)
- printf("%s", params[i].name);
- else {
- nname = noname(params[i].name);
- printf("%s", nname);
- free(nname);
- }
- break;
- case CTLTYPE_NOBOOL:
- if (*(int *)iov[i].value.iov_base)
- printf("%s", params[i].name);
+ if (params[i].jp_flags &
+ (JP_BOOL | JP_NOBOOL)) {
+ if (*(int *)params[i].jp_value)
+ printf("%s", params[i].jp_name);
else {
- nname =
- nononame(params[i].name);
+ nname = (params[i].jp_flags &
+ JP_NOBOOL) ?
+ nononame(params[i].jp_name)
+ : noname(params[i].jp_name);
printf("%s", nname);
free(nname);
}
- break;
- default:
- printf("%s=", params[i].name);
+ continue;
}
+ printf("%s=", params[i].jp_name);
}
- count = params[i].flags & PARAM_ARRAY
- ? iov[i].value.iov_len / params[i].size : 1;
- if (count == 0) {
+ if (params[i].jp_valuelen == 0) {
if (pflags & PRINT_QUOTED)
printf("\"\"");
else if (!(pflags & PRINT_NAMEVAL))
putchar('-');
- }
- for (ai = 0; ai < count; ai++) {
- if (ai > 0)
- putchar(',');
- switch (params[i].type) {
- case CTLTYPE_INT:
- printf("%d", ((int *)
- iov[i].value.iov_base)[ai]);
- break;
- case CTLTYPE_UINT:
- printf("%u", ((int *)
- iov[i].value.iov_base)[ai]);
- break;
- case CTLTYPE_IPADDR:
- if (inet_ntop(AF_INET,
- &((struct in_addr *)
- iov[i].value.iov_base)[ai],
- ipbuf, sizeof(ipbuf)) == NULL)
- err(1, "inet_ntop");
- else
- printf("%s", ipbuf);
- break;
- case CTLTYPE_IP6ADDR:
- if (inet_ntop(AF_INET6,
- &((struct in6_addr *)
- iov[i].value.iov_base)[ai],
- ipbuf, sizeof(ipbuf)) == NULL)
- err(1, "inet_ntop");
- else
- printf("%s", ipbuf);
- break;
- case CTLTYPE_LONG:
- printf("%ld", ((long *)
- iov[i].value.iov_base)[ai]);
- case CTLTYPE_ULONG:
- printf("%lu", ((long *)
- iov[i].value.iov_base)[ai]);
- break;
- case CTLTYPE_STRING:
- if (pflags & PRINT_QUOTED)
- quoted_print((char *)
- iov[i].value.iov_base,
- params[i].size);
- else
- printf("%.*s",
- (int)params[i].size,
- (char *)
- iov[i].value.iov_base);
- break;
- case CTLTYPE_BOOL:
- case CTLTYPE_NOBOOL:
- if (!(pflags & PRINT_NAMEVAL))
- printf(((int *)
- iov[i].value.iov_base)[ai]
- ? "true" : "false");
- }
- }
+ } else
+ quoted_print(param_values[i]);
}
putchar('\n');
+ for (i = 0; i < nparams; i++)
+ if (params[i].jp_flags & JP_USER)
+ free(param_values[i]);
}
for (i = 0; i < nparams; i++)
- if (params[i].value == NULL)
- free(iov[i].value.iov_base);
+ if (!(params[i].jp_flags & JP_RAWVALUE)) {
+ free(params[i].jp_value);
+ params[i].jp_value = NULL;
+ }
return (jid);
}
static void
-quoted_print(char *str, int len)
+quoted_print(char *str)
{
int c, qc;
char *p = str;
- char *ep = str + len;
/* An empty string needs quoting. */
if (!*p) {
@@ -753,7 +456,7 @@ quoted_print(char *str, int len)
: 0;
if (qc)
putchar(qc);
- while (p < ep && (c = *p++)) {
+ while ((c = *p++)) {
if (c == '\\' || c == qc)
putchar('\\');
putchar(c);
OpenPOWER on IntegriCloud