summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/imgact_elf.c4
-rw-r--r--sys/kern/init_main.c2
-rw-r--r--sys/kern/kern_jail.c78
-rw-r--r--sys/kern/kern_mib.c52
-rw-r--r--sys/sys/jail.h6
-rw-r--r--usr.sbin/jail/jail.812
6 files changed, 137 insertions, 17 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 940b38f..e41ad76 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/fcntl.h>
#include <sys/imgact.h>
#include <sys/imgact_elf.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/malloc.h>
@@ -996,7 +997,8 @@ __elfN(freebsd_fixup)(register_t **stack_base, struct image_params *imgp)
AUXARGS_ENTRY(pos, AT_BASE, args->base);
if (imgp->execpathp != 0)
AUXARGS_ENTRY(pos, AT_EXECPATH, imgp->execpathp);
- AUXARGS_ENTRY(pos, AT_OSRELDATE, osreldate);
+ AUXARGS_ENTRY(pos, AT_OSRELDATE,
+ imgp->proc->p_ucred->cr_prison->pr_osreldate);
if (imgp->canary != 0) {
AUXARGS_ENTRY(pos, AT_CANARY, imgp->canary);
AUXARGS_ENTRY(pos, AT_CANARYLEN, imgp->canarylen);
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 16235bc..1c5f77c 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -493,7 +493,7 @@ proc0_init(void *dummy __unused)
td->td_flags = TDF_INMEM;
td->td_pflags = TDP_KTHREAD;
td->td_cpuset = cpuset_thread0();
- prison0.pr_cpuset = cpuset_ref(td->td_cpuset);
+ prison0_init();
p->p_peers = 0;
p->p_leader = p;
p->p_reaper = p;
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 54ca3ff..e9c71ca 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -238,6 +238,19 @@ static int jail_default_devfs_rsnum = JAIL_DEFAULT_DEVFS_RSNUM;
static unsigned jail_max_af_ips = 255;
#endif
+/*
+ * Initialize the parts of prison0 that can't be static-initialized with
+ * constants. This is called from proc0_init() after creating thread0 cpuset.
+ */
+void
+prison0_init(void)
+{
+
+ prison0.pr_cpuset = cpuset_ref(thread0.td_cpuset);
+ prison0.pr_osreldate = osreldate;
+ strlcpy(prison0.pr_osrelease, osrelease, sizeof(prison0.pr_osrelease));
+}
+
#ifdef INET
static int
qcmp_v4(const void *ip1, const void *ip2)
@@ -537,7 +550,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
struct prison *pr, *deadpr, *mypr, *ppr, *tpr;
struct vnode *root;
char *domain, *errmsg, *host, *name, *namelc, *p, *path, *uuid;
- char *g_path;
+ char *g_path, *osrelstr;
#if defined(INET) || defined(INET6)
struct prison *tppr;
void *op;
@@ -547,7 +560,7 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
int created, cuflags, descend, enforce, error, errmsg_len, errmsg_pos;
int gotchildmax, gotenforce, gothid, gotrsnum, gotslevel;
int fi, jid, jsys, len, level;
- int childmax, rsnum, slevel;
+ int childmax, osreldt, rsnum, slevel;
int fullpath_disabled;
#if defined(INET) || defined(INET6)
int ii, ij;
@@ -962,6 +975,46 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
}
}
+ error = vfs_getopt(opts, "osrelease", (void **)&osrelstr, &len);
+ if (error == ENOENT)
+ osrelstr = NULL;
+ else if (error != 0)
+ goto done_free;
+ else {
+ if (flags & JAIL_UPDATE) {
+ error = EINVAL;
+ vfs_opterror(opts,
+ "osrelease cannot be changed after creation");
+ goto done_errmsg;
+ }
+ if (len == 0 || len >= OSRELEASELEN) {
+ error = EINVAL;
+ vfs_opterror(opts,
+ "osrelease string must be 1-%d bytes long",
+ OSRELEASELEN - 1);
+ goto done_errmsg;
+ }
+ }
+
+ error = vfs_copyopt(opts, "osreldate", &osreldt, sizeof(osreldt));
+ if (error == ENOENT)
+ osreldt = 0;
+ else if (error != 0)
+ goto done_free;
+ else {
+ if (flags & JAIL_UPDATE) {
+ error = EINVAL;
+ vfs_opterror(opts,
+ "osreldate cannot be changed after creation");
+ goto done_errmsg;
+ }
+ if (osreldt == 0) {
+ error = EINVAL;
+ vfs_opterror(opts, "osreldate cannot be 0");
+ goto done_errmsg;
+ }
+ }
+
/*
* Grab the allprison lock before letting modules check their
* parameters. Once we have it, do not let go so we'll have a
@@ -1290,6 +1343,12 @@ kern_jail_set(struct thread *td, struct uio *optuio, int flags)
pr->pr_enforce_statfs = JAIL_DEFAULT_ENFORCE_STATFS;
pr->pr_devfs_rsnum = ppr->pr_devfs_rsnum;
+ pr->pr_osreldate = osreldt ? osreldt : ppr->pr_osreldate;
+ if (osrelstr == NULL)
+ strcpy(pr->pr_osrelease, ppr->pr_osrelease);
+ else
+ strcpy(pr->pr_osrelease, osrelstr);
+
LIST_INIT(&pr->pr_children);
mtx_init(&pr->pr_mtx, "jail mutex", NULL, MTX_DEF | MTX_DUPOK);
@@ -2126,6 +2185,13 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
error = vfs_setopt(opts, "nodying", &i, sizeof(i));
if (error != 0 && error != ENOENT)
goto done_deref;
+ error = vfs_setopt(opts, "osreldate", &pr->pr_osreldate,
+ sizeof(pr->pr_osreldate));
+ if (error != 0 && error != ENOENT)
+ goto done_deref;
+ error = vfs_setopts(opts, "osrelease", pr->pr_osrelease);
+ if (error != 0 && error != ENOENT)
+ goto done_deref;
/* Get the module parameters. */
mtx_unlock(&pr->pr_mtx);
@@ -4321,12 +4387,20 @@ sysctl_jail_param(SYSCTL_HANDLER_ARGS)
return (0);
}
+/*
+ * CTLFLAG_RDTUN in the following indicates jail parameters that can be set at
+ * jail creation time but cannot be changed in an existing jail.
+ */
SYSCTL_JAIL_PARAM(, jid, CTLTYPE_INT | CTLFLAG_RDTUN, "I", "Jail ID");
SYSCTL_JAIL_PARAM(, parent, CTLTYPE_INT | CTLFLAG_RD, "I", "Jail parent ID");
SYSCTL_JAIL_PARAM_STRING(, name, CTLFLAG_RW, MAXHOSTNAMELEN, "Jail name");
SYSCTL_JAIL_PARAM_STRING(, path, CTLFLAG_RDTUN, MAXPATHLEN, "Jail root path");
SYSCTL_JAIL_PARAM(, securelevel, CTLTYPE_INT | CTLFLAG_RW,
"I", "Jail secure level");
+SYSCTL_JAIL_PARAM(, osreldate, CTLTYPE_INT | CTLFLAG_RDTUN, "I",
+ "Jail value for kern.osreldate and uname -K");
+SYSCTL_JAIL_PARAM_STRING(, osrelease, CTLFLAG_RDTUN, OSRELEASELEN,
+ "Jail value for kern.osrelease and uname -r");
SYSCTL_JAIL_PARAM(, enforce_statfs, CTLTYPE_INT | CTLFLAG_RW,
"I", "Jail cannot see all mounted file systems");
SYSCTL_JAIL_PARAM(, devfs_ruleset, CTLTYPE_INT | CTLFLAG_RW,
diff --git a/sys/kern/kern_mib.c b/sys/kern/kern_mib.c
index 6f7d046..0307791 100644
--- a/sys/kern/kern_mib.c
+++ b/sys/kern/kern_mib.c
@@ -90,9 +90,6 @@ SYSCTL_ROOT_NODE(OID_AUTO, regression, CTLFLAG_RW, 0,
SYSCTL_STRING(_kern, OID_AUTO, ident, CTLFLAG_RD|CTLFLAG_MPSAFE,
kern_ident, 0, "Kernel identifier");
-SYSCTL_STRING(_kern, KERN_OSRELEASE, osrelease, CTLFLAG_RD|CTLFLAG_MPSAFE|
- CTLFLAG_CAPRD, osrelease, 0, "Operating system release");
-
SYSCTL_INT(_kern, KERN_OSREV, osrevision, CTLFLAG_RD|CTLFLAG_CAPRD,
SYSCTL_NULL_INT_PTR, BSD, "Operating system revision");
@@ -105,13 +102,6 @@ SYSCTL_STRING(_kern, OID_AUTO, compiler_version, CTLFLAG_RD|CTLFLAG_MPSAFE,
SYSCTL_STRING(_kern, KERN_OSTYPE, ostype, CTLFLAG_RD|CTLFLAG_MPSAFE|
CTLFLAG_CAPRD, ostype, 0, "Operating system type");
-/*
- * NOTICE: The *userland* release date is available in
- * /usr/include/osreldate.h
- */
-SYSCTL_INT(_kern, KERN_OSRELDATE, osreldate, CTLFLAG_RD|CTLFLAG_CAPRD,
- &osreldate, 0, "Kernel release date");
-
SYSCTL_INT(_kern, KERN_MAXPROC, maxproc, CTLFLAG_RDTUN,
&maxproc, 0, "Maximum number of processes");
@@ -429,6 +419,48 @@ SYSCTL_PROC(_kern, KERN_HOSTID, hostid,
CTLTYPE_ULONG | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
NULL, 0, sysctl_hostid, "LU", "Host ID");
+/*
+ * The osrelease string is copied from the global (osrelease in vers.c) into
+ * prison0 by a sysinit and is inherited by child jails if not changed at jail
+ * creation, so we always return the copy from the current prison data.
+ */
+static int
+sysctl_osrelease(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+
+ pr = req->td->td_ucred->cr_prison;
+ return (SYSCTL_OUT(req, pr->pr_osrelease, strlen(pr->pr_osrelease) + 1));
+
+}
+
+SYSCTL_PROC(_kern, KERN_OSRELEASE, osrelease,
+ CTLTYPE_STRING | CTLFLAG_CAPRD | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ NULL, 0, sysctl_osrelease, "A", "Operating system release");
+
+/*
+ * The osreldate number is copied from the global (osreldate in vers.c) into
+ * prison0 by a sysinit and is inherited by child jails if not changed at jail
+ * creation, so we always return the value from the current prison data.
+ */
+static int
+sysctl_osreldate(SYSCTL_HANDLER_ARGS)
+{
+ struct prison *pr;
+
+ pr = req->td->td_ucred->cr_prison;
+ return (SYSCTL_OUT(req, &pr->pr_osreldate, sizeof(pr->pr_osreldate)));
+
+}
+
+/*
+ * NOTICE: The *userland* release date is available in
+ * /usr/include/osreldate.h
+ */
+SYSCTL_PROC(_kern, KERN_OSRELDATE, osreldate,
+ CTLTYPE_INT | CTLFLAG_CAPRD | CTLFLAG_RD | CTLFLAG_MPSAFE,
+ NULL, 0, sysctl_osreldate, "I", "Kernel release date");
+
SYSCTL_NODE(_kern, OID_AUTO, features, CTLFLAG_RD, 0, "Kernel Features");
#ifdef COMPAT_FREEBSD4
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
index 08b5f4b..cfe71d8 100644
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -134,6 +134,7 @@ MALLOC_DECLARE(M_PRISON);
#include <sys/osd.h>
#define HOSTUUIDLEN 64
+#define OSRELEASELEN 32
struct racct;
struct prison_racct;
@@ -177,13 +178,15 @@ struct prison {
int pr_securelevel; /* (p) securelevel */
int pr_enforce_statfs; /* (p) statfs permission */
int pr_devfs_rsnum; /* (p) devfs ruleset */
- int pr_spare[4];
+ int pr_spare[3];
+ int pr_osreldate; /* (c) kern.osreldate value */
unsigned long pr_hostid; /* (p) jail hostid */
char pr_name[MAXHOSTNAMELEN]; /* (p) admin jail name */
char pr_path[MAXPATHLEN]; /* (c) chroot path */
char pr_hostname[MAXHOSTNAMELEN]; /* (p) jail hostname */
char pr_domainname[MAXHOSTNAMELEN]; /* (p) jail domainname */
char pr_hostuuid[HOSTUUIDLEN]; /* (p) jail hostuuid */
+ char pr_osrelease[OSRELEASELEN]; /* (c) kern.osrelease value */
};
struct prison_racct {
@@ -364,6 +367,7 @@ void getcredhostname(struct ucred *, char *, size_t);
void getcreddomainname(struct ucred *, char *, size_t);
void getcredhostuuid(struct ucred *, char *, size_t);
void getcredhostid(struct ucred *, unsigned long *);
+void prison0_init(void);
int prison_allow(struct ucred *, unsigned);
int prison_check(struct ucred *cred1, struct ucred *cred2);
int prison_owns_vnet(struct ucred *);
diff --git a/usr.sbin/jail/jail.8 b/usr.sbin/jail/jail.8
index b270a15..83666ab 100644
--- a/usr.sbin/jail/jail.8
+++ b/usr.sbin/jail/jail.8
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd February 6, 2015
+.Dd February 25, 2015
.Dt JAIL 8
.Os
.Sh NAME
@@ -276,7 +276,7 @@ Then there are pseudo-parameters that are only used by
.Nm
itself.
.Pp
-Jails have a set a core parameters, and kernel modules can add their own
+Jails have a set of core parameters, and kernel modules can add their own
jail parameters.
The current set of available parameters can be retrieved via
.Dq Nm sysctl Fl d Va security.jail.param .
@@ -471,6 +471,14 @@ The
.Va jid
of the parent of this jail, or zero if this is a top-level jail
(read-only).
+.It Va osrelease
+The string for the jail's
+.Va kern.osrelease
+sysctl and uname -r.
+.It Va osreldate
+The number for the jail's
+.Va kern.osreldate
+and uname -K.
.It Va allow.*
Some restrictions of the jail environment may be set on a per-jail
basis.
OpenPOWER on IntegriCloud