Some jail parameters (in particular, "ip4" and "ip6" for IP address
restrictions) were found to be inadequately described by a boolean. Define a new parameter type with three values (disable, new, inherit) to handle these and future cases. Approved by: re (kib), bz (mentor) Discussed with: rwatson
This commit is contained in:
parent
0888b985ac
commit
274ea197bb
@ -54,6 +54,8 @@ __FBSDID("$FreeBSD$");
|
||||
#define ARRAY_SLOP 5
|
||||
|
||||
|
||||
static int jailparam_import_enum(const char **values, int nvalues,
|
||||
const char *valstr, size_t valsize, int *value);
|
||||
static int jailparam_vlist(struct jailparam **jpp, va_list ap);
|
||||
static int jailparam_type(struct jailparam *jp);
|
||||
static char *noname(const char *name);
|
||||
@ -61,6 +63,9 @@ static char *nononame(const char *name);
|
||||
|
||||
char jail_errmsg[JAIL_ERRMSGLEN];
|
||||
|
||||
static const char *bool_values[] = { "false", "true" };
|
||||
static const char *jailsys_values[] = { "disable", "new", "inherit" };
|
||||
|
||||
|
||||
/*
|
||||
* Import a null-terminated parameter list and set a jail with the flags
|
||||
@ -140,7 +145,6 @@ 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];
|
||||
@ -182,6 +186,8 @@ jailparam_all(struct jailparam **jpp)
|
||||
"sysctl(0.1): %s", strerror(errno));
|
||||
goto error;
|
||||
}
|
||||
if (buf[buflen - 2] == '.')
|
||||
buf[buflen - 2] = '\0';
|
||||
/* Add the parameter to the list */
|
||||
if (njp >= nlist) {
|
||||
nlist *= 2;
|
||||
@ -197,17 +203,6 @@ jailparam_all(struct jailparam **jpp)
|
||||
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));
|
||||
@ -285,14 +280,31 @@ jailparam_import(struct jailparam *jp, const char *value)
|
||||
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 {
|
||||
if (!jailparam_import_enum(bool_values, 2,
|
||||
avalue, fw, &((int *)jp->jp_value)[i])) {
|
||||
snprintf(jail_errmsg,
|
||||
JAIL_ERRMSGLEN,
|
||||
"%s: unknown boolean value \"%.*s\"",
|
||||
JAIL_ERRMSGLEN, "%s: "
|
||||
"unknown boolean value \"%.*s\"",
|
||||
jp->jp_name, fw, avalue);
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (jp->jp_flags & JP_JAILSYS) {
|
||||
/*
|
||||
* Allow setting a jailsys parameter to "new"
|
||||
* in a booleanesque fashion.
|
||||
*/
|
||||
if (value[0] == '\0')
|
||||
((int *)jp->jp_value)[i] = JAIL_SYS_NEW;
|
||||
else if (!jailparam_import_enum(jailsys_values,
|
||||
sizeof(jailsys_values) /
|
||||
sizeof(jailsys_values[0]), avalue, fw,
|
||||
&((int *)jp->jp_value)[i])) {
|
||||
snprintf(jail_errmsg,
|
||||
JAIL_ERRMSGLEN, "%s: "
|
||||
"unknown jailsys value \"%.*s\"",
|
||||
jp->jp_name, fw, avalue);
|
||||
errno = EINVAL;
|
||||
goto error;
|
||||
@ -373,6 +385,23 @@ jailparam_import(struct jailparam *jp, const char *value)
|
||||
return (-1);
|
||||
}
|
||||
|
||||
static int
|
||||
jailparam_import_enum(const char **values, int nvalues, const char *valstr,
|
||||
size_t valsize, int *value)
|
||||
{
|
||||
char *ep;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nvalues; i++)
|
||||
if (valsize == strlen(values[i]) &&
|
||||
!strncasecmp(valstr, values[i], valsize)) {
|
||||
*value = i;
|
||||
return 1;
|
||||
}
|
||||
*value = strtol(valstr, &ep, 10);
|
||||
return (ep == valstr + valsize);
|
||||
}
|
||||
|
||||
/*
|
||||
* Put a name and value into a jail parameter element, copying the value
|
||||
* but not altering it.
|
||||
@ -428,6 +457,15 @@ jailparam_set(struct jailparam *jp, unsigned njp, int flags)
|
||||
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Try to fill in missing values with an empty string.
|
||||
*/
|
||||
if (jp[j].jp_value == NULL && jp[j].jp_valuelen > 0 &&
|
||||
jailparam_import(jp + j, "") < 0) {
|
||||
njp = j;
|
||||
jid = -1;
|
||||
goto done;
|
||||
}
|
||||
jiov[i].iov_base = jp[j].jp_value;
|
||||
jiov[i].iov_len =
|
||||
(jp[j].jp_ctltype & CTLTYPE) == CTLTYPE_STRING
|
||||
@ -632,7 +670,7 @@ jailparam_export(struct jailparam *jp)
|
||||
{
|
||||
char *value, *tvalue, **values;
|
||||
size_t valuelen;
|
||||
int i, nval;
|
||||
int i, nval, ival;
|
||||
char valbuf[INET6_ADDRSTRLEN];
|
||||
|
||||
if (!jp->jp_ctltype && jailparam_type(jp) < 0)
|
||||
@ -655,14 +693,21 @@ jailparam_export(struct jailparam *jp)
|
||||
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",
|
||||
ival = ((int *)jp->jp_value)[i];
|
||||
if ((jp->jp_flags & (JP_BOOL | JP_NOBOOL)) &&
|
||||
(unsigned)ival < 2) {
|
||||
strlcpy(valbuf, bool_values[ival],
|
||||
sizeof(valbuf));
|
||||
break;
|
||||
}
|
||||
snprintf(valbuf, sizeof(valbuf), "%d",
|
||||
((int *)jp->jp_value)[i]);
|
||||
if ((jp->jp_flags & JP_JAILSYS) &&
|
||||
(unsigned)ival < sizeof(jailsys_values) /
|
||||
sizeof(jailsys_values[0])) {
|
||||
strlcpy(valbuf, jailsys_values[ival],
|
||||
sizeof(valbuf));
|
||||
break;
|
||||
}
|
||||
snprintf(valbuf, sizeof(valbuf), "%d", ival);
|
||||
break;
|
||||
case CTLTYPE_UINT:
|
||||
snprintf(valbuf, sizeof(valbuf), "%u",
|
||||
@ -688,7 +733,7 @@ jailparam_export(struct jailparam *jp)
|
||||
valbuf, sizeof(valbuf)) == NULL) {
|
||||
strerror_r(errno, jail_errmsg,
|
||||
JAIL_ERRMSGLEN);
|
||||
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
@ -698,7 +743,7 @@ jailparam_export(struct jailparam *jp)
|
||||
valbuf, sizeof(valbuf)) == NULL) {
|
||||
strerror_r(errno, jail_errmsg,
|
||||
JAIL_ERRMSGLEN);
|
||||
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
break;
|
||||
@ -846,11 +891,13 @@ jailparam_type(struct jailparam *jp)
|
||||
}
|
||||
}
|
||||
}
|
||||
unknown_parameter:
|
||||
snprintf(jail_errmsg, JAIL_ERRMSGLEN,
|
||||
"unknown parameter: %s", jp->jp_name);
|
||||
errno = ENOENT;
|
||||
return (-1);
|
||||
}
|
||||
mib_desc:
|
||||
mib[1] = 4;
|
||||
desclen = sizeof(desc);
|
||||
if (sysctl(mib, (miblen / sizeof(int)) + 2, &desc, &desclen,
|
||||
@ -873,8 +920,9 @@ jailparam_type(struct jailparam *jp)
|
||||
switch (desc.i & CTLTYPE) {
|
||||
case CTLTYPE_INT:
|
||||
if (desc.s[0] == 'B')
|
||||
jp->jp_flags |=
|
||||
(desc.s[1] == 'N') ? JP_NOBOOL : JP_BOOL;
|
||||
jp->jp_flags |= JP_BOOL;
|
||||
else if (!strcmp(desc.s, "E,jailsys"))
|
||||
jp->jp_flags |= JP_JAILSYS;
|
||||
case CTLTYPE_UINT:
|
||||
jp->jp_valuelen = sizeof(int);
|
||||
break;
|
||||
@ -916,41 +964,21 @@ jailparam_type(struct jailparam *jp)
|
||||
}
|
||||
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,
|
||||
/* A node might be described by an empty-named child. */
|
||||
mib[1] = 1;
|
||||
mib[(miblen / sizeof(int)) + 2] =
|
||||
mib[(miblen / sizeof(int)) + 1] - 1;
|
||||
miblen += sizeof(int);
|
||||
desclen = sizeof(desc.s);
|
||||
if (sysctl(mib, (miblen / sizeof(int)) + 2, desc.s, &desclen,
|
||||
NULL, 0) < 0) {
|
||||
snprintf(jail_errmsg, JAIL_ERRMSGLEN,
|
||||
"sysctl(0.4.%s): %s", desc.s, strerror(errno));
|
||||
"sysctl(0.1): %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;
|
||||
if (desc.s[desclen - 2] != '.')
|
||||
goto unknown_parameter;
|
||||
goto mib_desc;
|
||||
default:
|
||||
snprintf(jail_errmsg, JAIL_ERRMSGLEN,
|
||||
"unknown type for %s", jp->jp_name);
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define JP_RAWVALUE 0x01
|
||||
#define JP_BOOL 0x02
|
||||
#define JP_NOBOOL 0x04
|
||||
#define JP_JAILSYS 0x08
|
||||
|
||||
#define JAIL_ERRMSGLEN 1024
|
||||
|
||||
|
@ -237,12 +237,14 @@ linux_prison_create(void *obj, void *data)
|
||||
{
|
||||
struct prison *pr = obj;
|
||||
struct vfsoptlist *opts = data;
|
||||
int jsys;
|
||||
|
||||
if (vfs_flagopt(opts, "nolinux", NULL, 0))
|
||||
if (vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)) == 0 &&
|
||||
jsys == JAIL_SYS_INHERIT)
|
||||
return (0);
|
||||
/*
|
||||
* Inherit a prison's initial values from its parent
|
||||
* (different from NULL which also inherits changes).
|
||||
* (different from JAIL_SYS_INHERIT which also inherits changes).
|
||||
*/
|
||||
return linux_alloc_prison(pr, NULL);
|
||||
}
|
||||
@ -252,11 +254,16 @@ linux_prison_check(void *obj __unused, void *data)
|
||||
{
|
||||
struct vfsoptlist *opts = data;
|
||||
char *osname, *osrelease;
|
||||
int error, len, osrel, oss_version;
|
||||
int error, jsys, len, osrel, oss_version;
|
||||
|
||||
/* Check that the parameters are correct. */
|
||||
(void)vfs_flagopt(opts, "linux", NULL, 0);
|
||||
(void)vfs_flagopt(opts, "nolinux", NULL, 0);
|
||||
error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys));
|
||||
if (error != ENOENT) {
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT)
|
||||
return (EINVAL);
|
||||
}
|
||||
error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len);
|
||||
if (error != ENOENT) {
|
||||
if (error != 0)
|
||||
@ -296,33 +303,40 @@ linux_prison_set(void *obj, void *data)
|
||||
struct prison *pr = obj;
|
||||
struct vfsoptlist *opts = data;
|
||||
char *osname, *osrelease;
|
||||
int error, gotversion, len, nolinux, oss_version, yeslinux;
|
||||
int error, gotversion, jsys, len, oss_version;
|
||||
|
||||
/* Set the parameters, which should be correct. */
|
||||
yeslinux = vfs_flagopt(opts, "linux", NULL, 0);
|
||||
nolinux = vfs_flagopt(opts, "nolinux", NULL, 0);
|
||||
error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys));
|
||||
if (error == ENOENT)
|
||||
jsys = -1;
|
||||
error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len);
|
||||
if (error == ENOENT)
|
||||
osname = NULL;
|
||||
else
|
||||
yeslinux = 1;
|
||||
jsys = JAIL_SYS_NEW;
|
||||
error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len);
|
||||
if (error == ENOENT)
|
||||
osrelease = NULL;
|
||||
else
|
||||
yeslinux = 1;
|
||||
jsys = JAIL_SYS_NEW;
|
||||
error = vfs_copyopt(opts, "linux.oss_version", &oss_version,
|
||||
sizeof(oss_version));
|
||||
gotversion = (error == 0);
|
||||
yeslinux |= gotversion;
|
||||
if (nolinux) {
|
||||
/* "nolinux": inherit the parent's Linux info. */
|
||||
if (error == ENOENT)
|
||||
gotversion = 0;
|
||||
else {
|
||||
gotversion = 1;
|
||||
jsys = JAIL_SYS_NEW;
|
||||
}
|
||||
switch (jsys) {
|
||||
case JAIL_SYS_INHERIT:
|
||||
/* "linux=inherit": inherit the parent's Linux info. */
|
||||
mtx_lock(&pr->pr_mtx);
|
||||
osd_jail_del(pr, linux_osd_jail_slot);
|
||||
mtx_unlock(&pr->pr_mtx);
|
||||
} else if (yeslinux) {
|
||||
break;
|
||||
case JAIL_SYS_NEW:
|
||||
/*
|
||||
* "linux" or "linux.*":
|
||||
* "linux=new" or "linux.*":
|
||||
* the prison gets its own Linux info.
|
||||
*/
|
||||
error = linux_alloc_prison(pr, &lpr);
|
||||
@ -348,9 +362,7 @@ linux_prison_set(void *obj, void *data)
|
||||
return (0);
|
||||
}
|
||||
|
||||
SYSCTL_JAIL_PARAM_NODE(linux, "Jail Linux parameters");
|
||||
SYSCTL_JAIL_PARAM(, nolinux, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"BN", "Jail w/ no Linux parameters");
|
||||
SYSCTL_JAIL_PARAM_SYS_NODE(linux, CTLFLAG_RW, "Jail Linux parameters");
|
||||
SYSCTL_JAIL_PARAM_STRING(_linux, osname, CTLFLAG_RW, LINUX_MAX_UTSNAME,
|
||||
"Jail Linux kernel OS name");
|
||||
SYSCTL_JAIL_PARAM_STRING(_linux, osrelease, CTLFLAG_RW, LINUX_MAX_UTSNAME,
|
||||
@ -371,15 +383,22 @@ linux_prison_get(void *obj, void *data)
|
||||
|
||||
/* See if this prison is the one with the Linux info. */
|
||||
lpr = linux_find_prison(pr, &ppr);
|
||||
i = (ppr == pr);
|
||||
i = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT;
|
||||
error = vfs_setopt(opts, "linux", &i, sizeof(i));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
i = !i;
|
||||
error = vfs_setopt(opts, "nolinux", &i, sizeof(i));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
if (i) {
|
||||
error = vfs_setopts(opts, "linux.osname", lpr->pr_osname);
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
error = vfs_setopts(opts, "linux.osrelease", lpr->pr_osrelease);
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
error = vfs_setopt(opts, "linux.oss_version",
|
||||
&lpr->pr_oss_version, sizeof(lpr->pr_oss_version));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
} else {
|
||||
/*
|
||||
* If this prison is inheriting its Linux info, report
|
||||
* empty/zero parameters.
|
||||
@ -394,17 +413,6 @@ linux_prison_get(void *obj, void *data)
|
||||
sizeof(lpr->pr_oss_version));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
} else {
|
||||
error = vfs_setopts(opts, "linux.osname", lpr->pr_osname);
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
error = vfs_setopts(opts, "linux.osrelease", lpr->pr_osrelease);
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
error = vfs_setopt(opts, "linux.oss_version",
|
||||
&lpr->pr_oss_version, sizeof(lpr->pr_oss_version));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done;
|
||||
}
|
||||
error = 0;
|
||||
|
||||
|
@ -120,29 +120,26 @@ static int prison_restrict_ip6(struct prison *pr, struct in6_addr *newip6);
|
||||
*/
|
||||
static char *pr_flag_names[] = {
|
||||
[0] = "persist",
|
||||
"host",
|
||||
#ifdef INET
|
||||
"ip4",
|
||||
#endif
|
||||
#ifdef INET6
|
||||
[3] = "ip6",
|
||||
#endif
|
||||
#ifdef VIMAGE
|
||||
[4] = "vnet",
|
||||
#endif
|
||||
};
|
||||
|
||||
static char *pr_flag_nonames[] = {
|
||||
[0] = "nopersist",
|
||||
"nohost",
|
||||
};
|
||||
|
||||
struct jailsys_flags {
|
||||
const char *name;
|
||||
unsigned disable;
|
||||
unsigned new;
|
||||
} pr_flag_jailsys[] = {
|
||||
{ "host", 0, PR_HOST },
|
||||
#ifdef VIMAGE
|
||||
{ "vnet", 0, PR_VNET },
|
||||
#endif
|
||||
#ifdef INET
|
||||
"noip4",
|
||||
{ "ip4", PR_IP4_USER | PR_IP4_DISABLE, PR_IP4_USER },
|
||||
#endif
|
||||
#ifdef INET6
|
||||
[3] = "noip6",
|
||||
#endif
|
||||
#ifdef VIMAGE
|
||||
[4] = "novnet",
|
||||
{ "ip6", PR_IP6_USER | PR_IP6_DISABLE, PR_IP6_USER },
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -478,7 +475,8 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
unsigned long hid;
|
||||
size_t namelen, onamelen;
|
||||
int created, cuflags, descend, enforce, error, errmsg_len, errmsg_pos;
|
||||
int gotchildmax, gotenforce, gothid, gotslevel, fi, jid, len, level;
|
||||
int gotchildmax, gotenforce, gothid, gotslevel;
|
||||
int fi, jid, jsys, len, level;
|
||||
int childmax, slevel, vfslocked;
|
||||
#if defined(INET) || defined(INET6)
|
||||
int ii, ij;
|
||||
@ -569,6 +567,34 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
vfs_flagopt(opts, pr_flag_nonames[fi], &ch_flags, 1 << fi);
|
||||
}
|
||||
ch_flags |= pr_flags;
|
||||
for (fi = 0; fi < sizeof(pr_flag_jailsys) / sizeof(pr_flag_jailsys[0]);
|
||||
fi++) {
|
||||
error = vfs_copyopt(opts, pr_flag_jailsys[fi].name, &jsys,
|
||||
sizeof(jsys));
|
||||
if (error == ENOENT)
|
||||
continue;
|
||||
if (error != 0)
|
||||
goto done_free;
|
||||
switch (jsys) {
|
||||
case JAIL_SYS_DISABLE:
|
||||
if (!pr_flag_jailsys[fi].disable) {
|
||||
error = EINVAL;
|
||||
goto done_free;
|
||||
}
|
||||
pr_flags |= pr_flag_jailsys[fi].disable;
|
||||
break;
|
||||
case JAIL_SYS_NEW:
|
||||
pr_flags |= pr_flag_jailsys[fi].new;
|
||||
break;
|
||||
case JAIL_SYS_INHERIT:
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
goto done_free;
|
||||
}
|
||||
ch_flags |=
|
||||
pr_flag_jailsys[fi].new | pr_flag_jailsys[fi].disable;
|
||||
}
|
||||
if ((flags & (JAIL_CREATE | JAIL_UPDATE | JAIL_ATTACH)) == JAIL_CREATE
|
||||
&& !(pr_flags & PR_PERSIST)) {
|
||||
error = EINVAL;
|
||||
@ -684,16 +710,18 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
#ifdef INET
|
||||
error = vfs_getopt(opts, "ip4.addr", &op, &ip4s);
|
||||
if (error == ENOENT)
|
||||
ip4s = -1;
|
||||
ip4s = (pr_flags & PR_IP4_DISABLE) ? 0 : -1;
|
||||
else if (error != 0)
|
||||
goto done_free;
|
||||
else if (ip4s & (sizeof(*ip4) - 1)) {
|
||||
error = EINVAL;
|
||||
goto done_free;
|
||||
} else {
|
||||
ch_flags |= PR_IP4_USER;
|
||||
pr_flags |= PR_IP4_USER;
|
||||
if (ip4s > 0) {
|
||||
ch_flags |= PR_IP4_USER | PR_IP4_DISABLE;
|
||||
if (ip4s == 0)
|
||||
pr_flags |= PR_IP4_USER | PR_IP4_DISABLE;
|
||||
else {
|
||||
pr_flags = (pr_flags & ~PR_IP4_DISABLE) | PR_IP4_USER;
|
||||
ip4s /= sizeof(*ip4);
|
||||
if (ip4s > jail_max_af_ips) {
|
||||
error = EINVAL;
|
||||
@ -745,16 +773,18 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
|
||||
#ifdef INET6
|
||||
error = vfs_getopt(opts, "ip6.addr", &op, &ip6s);
|
||||
if (error == ENOENT)
|
||||
ip6s = -1;
|
||||
ip6s = (pr_flags & PR_IP6_DISABLE) ? 0 : -1;
|
||||
else if (error != 0)
|
||||
goto done_free;
|
||||
else if (ip6s & (sizeof(*ip6) - 1)) {
|
||||
error = EINVAL;
|
||||
goto done_free;
|
||||
} else {
|
||||
ch_flags |= PR_IP6_USER;
|
||||
pr_flags |= PR_IP6_USER;
|
||||
if (ip6s > 0) {
|
||||
ch_flags |= PR_IP6_USER | PR_IP6_DISABLE;
|
||||
if (ip6s == 0)
|
||||
pr_flags |= PR_IP6_USER | PR_IP6_DISABLE;
|
||||
else {
|
||||
pr_flags = (pr_flags & ~PR_IP6_DISABLE) | PR_IP6_USER;
|
||||
ip6s /= sizeof(*ip6);
|
||||
if (ip6s > jail_max_af_ips) {
|
||||
error = EINVAL;
|
||||
@ -1968,6 +1998,19 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done_deref;
|
||||
}
|
||||
for (fi = 0; fi < sizeof(pr_flag_jailsys) / sizeof(pr_flag_jailsys[0]);
|
||||
fi++) {
|
||||
i = pr->pr_flags &
|
||||
(pr_flag_jailsys[fi].disable | pr_flag_jailsys[fi].new);
|
||||
i = pr_flag_jailsys[fi].disable &&
|
||||
(i == pr_flag_jailsys[fi].disable) ? JAIL_SYS_DISABLE
|
||||
: (i == pr_flag_jailsys[fi].new) ? JAIL_SYS_NEW
|
||||
: JAIL_SYS_INHERIT;
|
||||
error =
|
||||
vfs_setopt(opts, pr_flag_jailsys[fi].name, &i, sizeof(i));
|
||||
if (error != 0 && error != ENOENT)
|
||||
goto done_deref;
|
||||
}
|
||||
for (fi = 0; fi < sizeof(pr_allow_names) / sizeof(pr_allow_names[0]);
|
||||
fi++) {
|
||||
if (pr_allow_names[fi] == NULL)
|
||||
@ -2614,6 +2657,7 @@ prison_restrict_ip4(struct prison *pr, struct in_addr *newip4)
|
||||
}
|
||||
}
|
||||
if (pr->pr_ip4s == 0) {
|
||||
pr->pr_flags |= PR_IP4_DISABLE;
|
||||
free(pr->pr_ip4, M_PRISON);
|
||||
pr->pr_ip4 = NULL;
|
||||
}
|
||||
@ -2918,6 +2962,7 @@ prison_restrict_ip6(struct prison *pr, struct in6_addr *newip6)
|
||||
}
|
||||
}
|
||||
if (pr->pr_ip6s == 0) {
|
||||
pr->pr_flags |= PR_IP6_DISABLE;
|
||||
free(pr->pr_ip6, M_PRISON);
|
||||
pr->pr_ip6 = NULL;
|
||||
}
|
||||
@ -4035,7 +4080,7 @@ SYSCTL_JAIL_PARAM(, persist, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"B", "Jail persistence");
|
||||
#ifdef VIMAGE
|
||||
SYSCTL_JAIL_PARAM(, vnet, CTLTYPE_INT | CTLFLAG_RDTUN,
|
||||
"B", "Virtual network stack");
|
||||
"E,jailsys", "Virtual network stack");
|
||||
#endif
|
||||
SYSCTL_JAIL_PARAM(, dying, CTLTYPE_INT | CTLFLAG_RD,
|
||||
"B", "Jail is in the process of shutting down");
|
||||
@ -4046,9 +4091,7 @@ SYSCTL_JAIL_PARAM(_children, cur, CTLTYPE_INT | CTLFLAG_RD,
|
||||
SYSCTL_JAIL_PARAM(_children, max, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"I", "Maximum number of child jails");
|
||||
|
||||
SYSCTL_JAIL_PARAM_NODE(host, "Jail host info");
|
||||
SYSCTL_JAIL_PARAM(, nohost, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"BN", "Jail w/ no host info");
|
||||
SYSCTL_JAIL_PARAM_SYS_NODE(host, CTLFLAG_RW, "Jail host info");
|
||||
SYSCTL_JAIL_PARAM_STRING(_host, hostname, CTLFLAG_RW, MAXHOSTNAMELEN,
|
||||
"Jail hostname");
|
||||
SYSCTL_JAIL_PARAM_STRING(_host, domainname, CTLFLAG_RW, MAXHOSTNAMELEN,
|
||||
@ -4062,16 +4105,12 @@ SYSCTL_JAIL_PARAM_NODE(cpuset, "Jail cpuset");
|
||||
SYSCTL_JAIL_PARAM(_cpuset, id, CTLTYPE_INT | CTLFLAG_RD, "I", "Jail cpuset ID");
|
||||
|
||||
#ifdef INET
|
||||
SYSCTL_JAIL_PARAM_NODE(ip4, "Jail IPv4 address virtualization");
|
||||
SYSCTL_JAIL_PARAM(, noip4, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"BN", "Jail w/ no IP address virtualization");
|
||||
SYSCTL_JAIL_PARAM_SYS_NODE(ip4, CTLFLAG_RW, "Jail IPv4 address virtualization");
|
||||
SYSCTL_JAIL_PARAM_STRUCT(_ip4, addr, CTLFLAG_RW, sizeof(struct in_addr),
|
||||
"S,in_addr,a", "Jail IPv4 addresses");
|
||||
#endif
|
||||
#ifdef INET6
|
||||
SYSCTL_JAIL_PARAM_NODE(ip6, "Jail IPv6 address virtualization");
|
||||
SYSCTL_JAIL_PARAM(, noip6, CTLTYPE_INT | CTLFLAG_RW,
|
||||
"BN", "Jail w/ no IP address virtualization");
|
||||
SYSCTL_JAIL_PARAM_SYS_NODE(ip6, CTLFLAG_RW, "Jail IPv6 address virtualization");
|
||||
SYSCTL_JAIL_PARAM_STRUCT(_ip6, addr, CTLFLAG_RW, sizeof(struct in6_addr),
|
||||
"S,in6_addr,a", "Jail IPv6 addresses");
|
||||
#endif
|
||||
@ -4102,6 +4141,7 @@ db_show_prison(struct prison *pr)
|
||||
#if defined(INET) || defined(INET6)
|
||||
int ii;
|
||||
#endif
|
||||
unsigned jsf;
|
||||
#ifdef INET6
|
||||
char ip6buf[INET6_ADDRSTRLEN];
|
||||
#endif
|
||||
@ -4128,6 +4168,16 @@ db_show_prison(struct prison *pr)
|
||||
fi++)
|
||||
if (pr_flag_names[fi] != NULL && (pr->pr_flags & (1 << fi)))
|
||||
db_printf(" %s", pr_flag_names[fi]);
|
||||
for (fi = 0; fi < sizeof(pr_flag_jailsys) / sizeof(pr_flag_jailsys[0]);
|
||||
fi++) {
|
||||
jsf = pr->pr_flags &
|
||||
(pr_flag_jailsys[fi].disable | pr_flag_jailsys[fi].new);
|
||||
db_printf(" %-16s= %s\n", pr_flag_jailsys[fi].name,
|
||||
pr_flag_jailsys[fi].disable &&
|
||||
(jsf == pr_flag_jailsys[fi].disable) ? "disable"
|
||||
: (jsf == pr_flag_jailsys[fi].new) ? "new"
|
||||
: "inherit");
|
||||
}
|
||||
db_printf(" allow = %x", pr->pr_allow);
|
||||
for (fi = 0; fi < sizeof(pr_allow_names) / sizeof(pr_allow_names[0]);
|
||||
fi++)
|
||||
|
@ -100,6 +100,10 @@ struct xprison {
|
||||
#define JAIL_SET_MASK 0x0f
|
||||
#define JAIL_GET_MASK 0x08
|
||||
|
||||
#define JAIL_SYS_DISABLE 0
|
||||
#define JAIL_SYS_NEW 1
|
||||
#define JAIL_SYS_INHERIT 2
|
||||
|
||||
#ifndef _KERNEL
|
||||
|
||||
struct iovec;
|
||||
@ -182,16 +186,18 @@ struct prison {
|
||||
/* Flag bits set via options */
|
||||
#define PR_PERSIST 0x00000001 /* Can exist without processes */
|
||||
#define PR_HOST 0x00000002 /* Virtualize hostname et al */
|
||||
#define PR_IP4_USER 0x00000004 /* Virtualize IPv4 addresses */
|
||||
#define PR_IP6_USER 0x00000008 /* Virtualize IPv6 addresses */
|
||||
#define PR_IP4_USER 0x00000004 /* Restrict IPv4 addresses */
|
||||
#define PR_IP6_USER 0x00000008 /* Restrict IPv6 addresses */
|
||||
#define PR_VNET 0x00000010 /* Virtual network stack */
|
||||
#define PR_IP4_DISABLE 0x00000020 /* Disable IPv4 */
|
||||
#define PR_IP6_DISABLE 0x00000040 /* Disable IPv6 */
|
||||
|
||||
/* Internal flag bits */
|
||||
#define PR_REMOVE 0x01000000 /* In process of being removed */
|
||||
#define PR_IP4 0x02000000 /* IPv4 virtualized by this jail or */
|
||||
/* an ancestor */
|
||||
#define PR_IP6 0x04000000 /* IPv6 virtualized by this jail or */
|
||||
/* an ancestor */
|
||||
#define PR_IP4 0x02000000 /* IPv4 restricted or disabled */
|
||||
/* by this jail or an ancestor */
|
||||
#define PR_IP6 0x04000000 /* IPv6 restricted or disabled */
|
||||
/* by this jail or an ancestor */
|
||||
|
||||
/* Flags for pr_allow */
|
||||
#define PR_ALLOW_SET_HOSTNAME 0x0001
|
||||
@ -315,7 +321,11 @@ SYSCTL_DECL(_security_jail_param);
|
||||
CTLTYPE_STRUCT | CTLFLAG_MPSAFE | (access), NULL, len, \
|
||||
sysctl_jail_param, fmt, descr)
|
||||
#define SYSCTL_JAIL_PARAM_NODE(module, descr) \
|
||||
SYSCTL_NODE(_security_jail_param, OID_AUTO, module, CTLFLAG_RW, 0, descr)
|
||||
SYSCTL_NODE(_security_jail_param, OID_AUTO, module, 0, 0, descr)
|
||||
#define SYSCTL_JAIL_PARAM_SYS_NODE(module, access, descr) \
|
||||
SYSCTL_JAIL_PARAM_NODE(module, descr); \
|
||||
SYSCTL_JAIL_PARAM(_##module, , CTLTYPE_INT | (access), "E,jailsys", \
|
||||
descr)
|
||||
|
||||
/*
|
||||
* Kernel support functions for jail().
|
||||
|
@ -34,7 +34,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 8, 2009
|
||||
.Dd July 25, 2009
|
||||
.Dt JAIL 8
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -252,14 +252,26 @@ match.
|
||||
It is only possible to start multiple jails with the same IP address,
|
||||
if none of the jails has more than this single overlapping IP address
|
||||
assigned to itself.
|
||||
.Pp
|
||||
A list of zero elements (an empty string) will stop the jail from using IPv4
|
||||
entirely; setting the boolean parameter
|
||||
.Ar noip4
|
||||
will not restrict the jail at all.
|
||||
.It Va ip6.addr
|
||||
.It Va ip4
|
||||
Control the availablity of IPv4 addresses.
|
||||
Possible values are
|
||||
.Dq inherit
|
||||
to allow unrestricted access to all system addresses,
|
||||
.Dq new
|
||||
to restrict addresses via
|
||||
.Va ip4.addr
|
||||
above, and
|
||||
.Dq disable
|
||||
to stop the jail from using IPv4 entirely.
|
||||
Setting the
|
||||
.Va ip4.addr
|
||||
parameter implies a value of
|
||||
.Dq new .
|
||||
.It Va ip6.addr , Va ip6
|
||||
A list of IPv6 addresses assigned to the prison, the counterpart to
|
||||
.Ar ip4.addr
|
||||
.Va ip4.addr
|
||||
and
|
||||
.Va ip4
|
||||
above.
|
||||
.It Va host.hostname
|
||||
Hostname of the prison.
|
||||
@ -268,9 +280,15 @@ Other similar parameters are
|
||||
.Va host.hostuuid
|
||||
and
|
||||
.Va host.hostid .
|
||||
Setting the boolean parameter
|
||||
.Va nohost
|
||||
will retain the system values of these settings.
|
||||
.It Va host
|
||||
Set the origin of hostname and related information.
|
||||
Possible values are
|
||||
.Dq inherit
|
||||
to use the system information and
|
||||
.Dq new
|
||||
for the jail to use the information from the above fields.
|
||||
Setting any of the above fields implies a value of
|
||||
.Dq new .
|
||||
.It Va securelevel
|
||||
The value of the jail's
|
||||
.Va kern.securelevel
|
||||
|
@ -57,7 +57,7 @@ __FBSDID("$FreeBSD$");
|
||||
#define PRINT_VERBOSE 0x20
|
||||
|
||||
static struct jailparam *params;
|
||||
static int *param_noparent;
|
||||
static int *param_parent;
|
||||
static int nparams;
|
||||
|
||||
static int add_param(const char *name, void *value, size_t valuelen,
|
||||
@ -71,7 +71,7 @@ static void quoted_print(char *str);
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *dot, *ep, *jname, *nname;
|
||||
char *dot, *ep, *jname;
|
||||
int c, i, jflags, jid, lastjid, pflags, spc;
|
||||
|
||||
jname = NULL;
|
||||
@ -139,17 +139,14 @@ main(int argc, char **argv)
|
||||
JP_USER);
|
||||
|
||||
if (pflags & PRINT_SKIP) {
|
||||
/* Check for parameters with boolean parents. */
|
||||
/* Check for parameters with jailsys parents. */
|
||||
for (i = 0; i < nparams; i++) {
|
||||
if ((params[i].jp_flags & JP_USER) &&
|
||||
(dot = strchr(params[i].jp_name, '.'))) {
|
||||
*dot = 0;
|
||||
nname = noname(params[i].jp_name);
|
||||
param_parent[i] = add_param(params[i].jp_name,
|
||||
NULL, (size_t)0, NULL, JP_OPT);
|
||||
*dot = '.';
|
||||
param_noparent[i] =
|
||||
add_param(nname, NULL, (size_t)0, NULL,
|
||||
JP_OPT);
|
||||
free(nname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -237,21 +234,20 @@ add_param(const char *name, void *value, size_t valuelen,
|
||||
if (!nparams) {
|
||||
paramlistsize = 32;
|
||||
params = malloc(paramlistsize * sizeof(*params));
|
||||
param_noparent =
|
||||
malloc(paramlistsize * sizeof(*param_noparent));
|
||||
if (params == NULL || param_noparent == NULL)
|
||||
param_parent = malloc(paramlistsize * sizeof(*param_parent));
|
||||
if (params == NULL || param_parent == NULL)
|
||||
err(1, "malloc");
|
||||
} else if (nparams >= paramlistsize) {
|
||||
paramlistsize *= 2;
|
||||
params = realloc(params, paramlistsize * sizeof(*params));
|
||||
param_noparent = realloc(param_noparent,
|
||||
paramlistsize * sizeof(*param_noparent));
|
||||
if (params == NULL || param_noparent == NULL)
|
||||
param_parent = realloc(param_parent,
|
||||
paramlistsize * sizeof(*param_parent));
|
||||
if (params == NULL || param_parent == NULL)
|
||||
err(1, "realloc");
|
||||
}
|
||||
|
||||
/* Look up the parameter. */
|
||||
param_noparent[nparams] = -1;
|
||||
param_parent[nparams] = -1;
|
||||
param = params + nparams++;
|
||||
if (source != NULL) {
|
||||
*param = *source;
|
||||
@ -387,8 +383,9 @@ print_jail(int pflags, int jflags)
|
||||
if ((pflags & PRINT_SKIP) &&
|
||||
((!(params[i].jp_ctltype &
|
||||
(CTLFLAG_WR | CTLFLAG_TUN))) ||
|
||||
(param_noparent[i] >= 0 &&
|
||||
*(int *)params[param_noparent[i]].jp_value)))
|
||||
(param_parent[i] >= 0 &&
|
||||
*(int *)params[param_parent[i]].jp_value !=
|
||||
JAIL_SYS_NEW)))
|
||||
continue;
|
||||
if (spc)
|
||||
putchar(' ');
|
||||
|
Loading…
Reference in New Issue
Block a user