Index: sys/kern/imgact_elf.c =================================================================== --- sys/kern/imgact_elf.c +++ sys/kern/imgact_elf.c @@ -1007,7 +1007,8 @@ 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); Index: sys/kern/kern_jail.c =================================================================== --- sys/kern/kern_jail.c +++ sys/kern/kern_jail.c @@ -239,6 +239,19 @@ static unsigned jail_max_af_ips = 255; #endif +/* + * Copy the global osreldate and osrelease into prison0 early in kernel init so + * that they get inherited by jails that don't change the value at creation. + */ +static void +prison0_init(void *dummy __unused) +{ + + prison0.pr_osreldate = osreldate; + strlcpy(prison0.pr_osrelease, osrelease, sizeof(prison0.pr_osrelease)); +} +SYSINIT(prison0init, SI_SUB_INTRINSIC, SI_ORDER_ANY, prison0_init, NULL); + #ifdef INET static int qcmp_v4(const void *ip1, const void *ip2) @@ -538,7 +551,7 @@ 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; @@ -548,7 +561,7 @@ 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; @@ -959,6 +972,45 @@ } } + 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-31 bytes long"); + 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 @@ -1285,6 +1337,12 @@ 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); @@ -4309,6 +4367,10 @@ 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_RD, "I", + "Jail value for kern.osreldate and uname -K"); +SYSCTL_JAIL_PARAM_STRING(, osrelease, CTLFLAG_RDTUN, MAXPATHLEN, + "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, Index: sys/kern/kern_mib.c =================================================================== --- sys/kern/kern_mib.c +++ sys/kern/kern_mib.c @@ -90,9 +90,6 @@ 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, 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 | CTLFLAG_NOFETCH, &maxproc, 0, "Maximum number of processes"); @@ -429,6 +419,48 @@ 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 Index: sys/sys/jail.h =================================================================== --- sys/sys/jail.h +++ sys/sys/jail.h @@ -134,6 +134,7 @@ #include #define HOSTUUIDLEN 64 +#define OSRELEASELEN 32 struct racct; struct prison_racct; @@ -177,13 +178,15 @@ 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 { Index: usr.sbin/jail/jail.8 =================================================================== --- usr.sbin/jail/jail.8 +++ 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 @@ .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 @@ .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.