summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjamie <jamie@FreeBSD.org>2009-07-25 14:48:57 +0000
committerjamie <jamie@FreeBSD.org>2009-07-25 14:48:57 +0000
commit274ea197bb2f446e42dd6f17d5046b348d26d82d (patch)
treee2f5557445f7151dc18cefe88f9b884b83f55993
parent0888b985acf99a673549ca79a753e47d3e98fe9a (diff)
downloadFreeBSD-src-274ea197bb2f446e42dd6f17d5046b348d26d82d.zip
FreeBSD-src-274ea197bb2f446e42dd6f17d5046b348d26d82d.tar.gz
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
-rw-r--r--lib/libjail/jail.c148
-rw-r--r--lib/libjail/jail.h1
-rw-r--r--sys/compat/linux/linux_mib.c78
-rw-r--r--sys/kern/kern_jail.c120
-rw-r--r--sys/sys/jail.h24
-rw-r--r--usr.sbin/jail/jail.840
-rw-r--r--usr.sbin/jls/jls.c31
7 files changed, 277 insertions, 165 deletions
diff --git a/lib/libjail/jail.c b/lib/libjail/jail.c
index 621b5b5..9411b88 100644
--- a/lib/libjail/jail.c
+++ b/lib/libjail/jail.c
@@ -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;
+ }
+ 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",
- ((int *)jp->jp_value)[i]);
+ 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));
- 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;
+ "sysctl(0.1): %s", strerror(errno));
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);
diff --git a/lib/libjail/jail.h b/lib/libjail/jail.h
index 4b38001..2801dbc 100644
--- a/lib/libjail/jail.h
+++ b/lib/libjail/jail.h
@@ -32,6 +32,7 @@
#define JP_RAWVALUE 0x01
#define JP_BOOL 0x02
#define JP_NOBOOL 0x04
+#define JP_JAILSYS 0x08
#define JAIL_ERRMSGLEN 1024
diff --git a/sys/compat/linux/linux_mib.c b/sys/compat/linux/linux_mib.c
index 58af9c5..5e770f6 100644
--- a/sys/compat/linux/linux_mib.c
+++ b/sys/compat/linux/linux_mib.c
@@ -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;
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 5c36758..6f6ae28 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -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++)
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
index 117e134..d7457bf 100644
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -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().
diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8
index 7189001..f3340bd 100644
--- a/usr.sbin/jail/jail.8
+++ b/usr.sbin/jail/jail.8
@@ -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
diff --git a/usr.sbin/jls/jls.c b/usr.sbin/jls/jls.c
index 40019f1..8c8b981 100644
--- a/usr.sbin/jls/jls.c
+++ b/usr.sbin/jls/jls.c
@@ -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(' ');
OpenPOWER on IntegriCloud