MFC r279361, r279395, r279396:
Allow the kern.osrelease and kern.osreldate sysctl values to be set in a jail's creation parameters. This allows the kernel version to be reliably spoofed within the jail whether examined directly with sysctl or indirectly with the uname -r and -K options. Export the new osreldate and osrelease jail parms in jail_get(2). Fix line wrap.
This commit is contained in:
parent
024d3d32c2
commit
17ca262c02
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
@ -2124,6 +2183,13 @@ kern_jail_get(struct thread *td, struct uio *optuio, int flags)
|
||||
goto done_deref;
|
||||
i = !i;
|
||||
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;
|
||||
|
||||
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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 *);
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user