mirror of
https://git.FreeBSD.org/src.git
synced 2024-10-18 02:19:39 +00:00
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)
This commit is contained in:
parent
9d81738f8f
commit
de6f37045c
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=194869
@ -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)
|
||||
|
@ -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 \
|
||||
|
29
lib/libjail/Makefile
Normal file
29
lib/libjail/Makefile
Normal file
@ -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>
|
275
lib/libjail/jail.3
Normal file
275
lib/libjail/jail.3
Normal file
@ -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(¶ms[0], "name");
|
||||
jailparam_import(¶ms[0], "foo");
|
||||
jailparam_init(¶ms[1], "host.hostname");
|
||||
jailparam_import(¶ms[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(¶ms[0], "name");
|
||||
jailparam_import(¶ms[0], "foo");
|
||||
jailparam_init(¶ms[1], "host.hostname");
|
||||
jailparam_get(params, 2, 0);
|
||||
hostname = jailparam_export(¶ms[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
|
972
lib/libjail/jail.c
Normal file
972
lib/libjail/jail.c
Normal file
@ -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);
|
||||
}
|
68
lib/libjail/jail.h
Normal file
68
lib/libjail/jail.h
Normal file
@ -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 */
|
||||
|
||||
|
104
lib/libjail/jail_getid.c
Normal file
104
lib/libjail/jail_getid.c
Normal file
@ -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;
|
||||
}
|
@ -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
|
||||
|
@ -1,5 +1,7 @@
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= killall
|
||||
DPADD= ${LIBJAIL}
|
||||
LDADD= -ljail
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -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;
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
PROG= jail
|
||||
MAN= jail.8
|
||||
DPADD= ${LIBUTIL}
|
||||
LDADD= -lutil
|
||||
DPADD= ${LIBJAIL} ${LIBUTIL}
|
||||
LDADD= -ljail -lutil
|
||||
|
||||
WARNS?= 6
|
||||
|
||||
|
@ -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(¶ms->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 **)¶m->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
|
||||
|
@ -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>
|
||||
|
@ -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 **)¶ms[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) {
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
PROG= jls
|
||||
MAN= jls.8
|
||||
DPADD= ${LIBJAIL}
|
||||
LDADD= -ljail
|
||||
|
||||
WARNS?= 6
|
||||
|
||||
.include <bsd.prog.mk>
|
||||
|
@ -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 = ¶ms[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;
|
||||
return (-1);
|
||||
}
|
||||
errx(1, "unknown parameter: %s", name);
|
||||
errx(1, "%s", jail_errmsg);
|
||||
}
|
||||
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;
|
||||
}
|
||||
errx(1, "unknown parameter: %s", name);
|
||||
}
|
||||
|
||||
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);
|
||||
if (params[i].jp_flags &
|
||||
(JP_BOOL | JP_NOBOOL)) {
|
||||
if (*(int *)params[i].jp_value)
|
||||
printf("%s", params[i].jp_name);
|
||||
else {
|
||||
nname = noname(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;
|
||||
case CTLTYPE_NOBOOL:
|
||||
if (*(int *)iov[i].value.iov_base)
|
||||
printf("%s", params[i].name);
|
||||
else {
|
||||
nname =
|
||||
nononame(params[i].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);
|
||||
|
Loading…
Reference in New Issue
Block a user