150465Smarcel/*-
250465Smarcel * Copyright (c) 1999 Marcel Moolenaar
350465Smarcel * All rights reserved.
450465Smarcel *
550465Smarcel * Redistribution and use in source and binary forms, with or without
650465Smarcel * modification, are permitted provided that the following conditions
750465Smarcel * are met:
850465Smarcel * 1. Redistributions of source code must retain the above copyright
950465Smarcel *    notice, this list of conditions and the following disclaimer
1050465Smarcel *    in this position and unchanged.
1150465Smarcel * 2. Redistributions in binary form must reproduce the above copyright
1250465Smarcel *    notice, this list of conditions and the following disclaimer in the
1350465Smarcel *    documentation and/or other materials provided with the distribution.
1450465Smarcel * 3. The name of the author may not be used to endorse or promote products
1565067Smarcel *    derived from this software without specific prior written permission.
1650465Smarcel *
1750465Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1850465Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1950465Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2050465Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2150465Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2250465Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2350465Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2450465Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2550465Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2650465Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2750465Smarcel */
2850465Smarcel
29116173Sobrien#include <sys/cdefs.h>
30116173Sobrien__FBSDID("$FreeBSD$");
31116173Sobrien
3250465Smarcel#include <sys/param.h>
3350465Smarcel#include <sys/kernel.h>
34235063Snetchild#include <sys/sdt.h>
3550465Smarcel#include <sys/systm.h>
3650465Smarcel#include <sys/sysctl.h>
3750465Smarcel#include <sys/proc.h>
3850465Smarcel#include <sys/malloc.h>
39191896Sjamie#include <sys/mount.h>
4050465Smarcel#include <sys/jail.h>
4187275Srwatson#include <sys/lock.h>
42191896Sjamie#include <sys/sx.h>
4350465Smarcel
4464907Smarcel#include <compat/linux/linux_mib.h>
45246085Sjhb#include <compat/linux/linux_misc.h>
4650465Smarcel
4750465Smarcelstruct linux_prison {
4850465Smarcel	char	pr_osname[LINUX_MAX_UTSNAME];
4950465Smarcel	char	pr_osrelease[LINUX_MAX_UTSNAME];
5050465Smarcel	int	pr_oss_version;
51191972Sdchagin	int	pr_osrel;
5250465Smarcel};
5350465Smarcel
54192895Sjamiestatic struct linux_prison lprison0 = {
55192895Sjamie	.pr_osname =		"Linux",
56293496Sdchagin	.pr_osrelease =		LINUX_VERSION_STR,
57192895Sjamie	.pr_oss_version =	0x030600,
58293496Sdchagin	.pr_osrel =		LINUX_VERSION_CODE
59192895Sjamie};
60192895Sjamie
61191896Sjamiestatic unsigned linux_osd_jail_slot;
62191896Sjamie
63293527SdchaginSYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0, "Linux mode");
6450465Smarcel
65219668Snetchildstatic int	linux_set_osname(struct thread *td, char *osname);
66219668Snetchildstatic int	linux_set_osrelease(struct thread *td, char *osrelease);
67219668Snetchildstatic int	linux_set_oss_version(struct thread *td, int oss_version);
68219668Snetchild
6950465Smarcelstatic int
7062573Sphklinux_sysctl_osname(SYSCTL_HANDLER_ARGS)
7150465Smarcel{
7250465Smarcel	char osname[LINUX_MAX_UTSNAME];
7350465Smarcel	int error;
7450465Smarcel
75112206Sjhb	linux_get_osname(req->td, osname);
7650465Smarcel	error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req);
77293527Sdchagin	if (error != 0 || req->newptr == NULL)
7850465Smarcel		return (error);
79112206Sjhb	error = linux_set_osname(req->td, osname);
80235063Snetchild
8150465Smarcel	return (error);
8250465Smarcel}
8350465Smarcel
8450465SmarcelSYSCTL_PROC(_compat_linux, OID_AUTO, osname,
85191792Sjamie	    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
8650465Smarcel	    0, 0, linux_sysctl_osname, "A",
8750465Smarcel	    "Linux kernel OS name");
8850465Smarcel
8950465Smarcelstatic int
9062573Sphklinux_sysctl_osrelease(SYSCTL_HANDLER_ARGS)
9150465Smarcel{
9250465Smarcel	char osrelease[LINUX_MAX_UTSNAME];
9350465Smarcel	int error;
9450465Smarcel
95112206Sjhb	linux_get_osrelease(req->td, osrelease);
9650465Smarcel	error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req);
97293527Sdchagin	if (error != 0 || req->newptr == NULL)
9850465Smarcel		return (error);
99112206Sjhb	error = linux_set_osrelease(req->td, osrelease);
100235063Snetchild
10150465Smarcel	return (error);
10250465Smarcel}
10350465Smarcel
10450465SmarcelSYSCTL_PROC(_compat_linux, OID_AUTO, osrelease,
105191792Sjamie	    CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
10650465Smarcel	    0, 0, linux_sysctl_osrelease, "A",
10750465Smarcel	    "Linux kernel OS release");
10850465Smarcel
10950465Smarcelstatic int
11062573Sphklinux_sysctl_oss_version(SYSCTL_HANDLER_ARGS)
11150465Smarcel{
11250465Smarcel	int oss_version;
11350465Smarcel	int error;
11450465Smarcel
115112206Sjhb	oss_version = linux_get_oss_version(req->td);
11650465Smarcel	error = sysctl_handle_int(oidp, &oss_version, 0, req);
117293527Sdchagin	if (error != 0 || req->newptr == NULL)
11850465Smarcel		return (error);
119112206Sjhb	error = linux_set_oss_version(req->td, oss_version);
120235063Snetchild
12150465Smarcel	return (error);
12250465Smarcel}
12350465Smarcel
12450465SmarcelSYSCTL_PROC(_compat_linux, OID_AUTO, oss_version,
125191792Sjamie	    CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE,
12650465Smarcel	    0, 0, linux_sysctl_oss_version, "I",
12750465Smarcel	    "Linux OSS version");
12850465Smarcel
12987275Srwatson/*
130191972Sdchagin * Map the osrelease into integer
131191972Sdchagin */
132191972Sdchaginstatic int
133191972Sdchaginlinux_map_osrel(char *osrelease, int *osrel)
134191972Sdchagin{
135191972Sdchagin	char *sep, *eosrelease;
136191972Sdchagin	int len, v0, v1, v2, v;
137191972Sdchagin
138191972Sdchagin	len = strlen(osrelease);
139191972Sdchagin	eosrelease = osrelease + len;
140191972Sdchagin	v0 = strtol(osrelease, &sep, 10);
141293527Sdchagin	if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.')
142191972Sdchagin		return (EINVAL);
143191972Sdchagin	osrelease = sep + 1;
144191972Sdchagin	v1 = strtol(osrelease, &sep, 10);
145293527Sdchagin	if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.')
146191972Sdchagin		return (EINVAL);
147191972Sdchagin	osrelease = sep + 1;
148191972Sdchagin	v2 = strtol(osrelease, &sep, 10);
149293527Sdchagin	if (osrelease == sep || sep != eosrelease)
150191972Sdchagin		return (EINVAL);
151191972Sdchagin
152191972Sdchagin	v = v0 * 1000000 + v1 * 1000 + v2;
153293527Sdchagin	if (v < 1000000)
154191972Sdchagin		return (EINVAL);
155191972Sdchagin
156191972Sdchagin	*osrel = v;
157235063Snetchild
158191972Sdchagin	return (0);
159191972Sdchagin}
160191972Sdchagin
161191972Sdchagin/*
162192895Sjamie * Find a prison with Linux info.
163192895Sjamie * Return the Linux info and the (locked) prison.
16487275Srwatson */
165191896Sjamiestatic struct linux_prison *
166192895Sjamielinux_find_prison(struct prison *spr, struct prison **prp)
16750465Smarcel{
168191896Sjamie	struct prison *pr;
169191896Sjamie	struct linux_prison *lpr;
17050465Smarcel
171192895Sjamie	if (!linux_osd_jail_slot)
172192895Sjamie		/* In case osd_register failed. */
173192895Sjamie		spr = &prison0;
174192895Sjamie	for (pr = spr;; pr = pr->pr_parent) {
175192895Sjamie		mtx_lock(&pr->pr_mtx);
176192895Sjamie		lpr = (pr == &prison0)
177192895Sjamie		    ? &lprison0
178192895Sjamie		    : osd_jail_get(pr, linux_osd_jail_slot);
179192895Sjamie		if (lpr != NULL)
180192895Sjamie			break;
181191896Sjamie		mtx_unlock(&pr->pr_mtx);
182192895Sjamie	}
183192895Sjamie	*prp = pr;
184235063Snetchild
185191896Sjamie	return (lpr);
186191896Sjamie}
187191896Sjamie
188191896Sjamie/*
189192895Sjamie * Ensure a prison has its own Linux info.  If lprp is non-null, point it to
190192895Sjamie * the Linux info and lock the prison.
191191896Sjamie */
192191896Sjamiestatic int
193191896Sjamielinux_alloc_prison(struct prison *pr, struct linux_prison **lprp)
194191896Sjamie{
195192895Sjamie	struct prison *ppr;
196191896Sjamie	struct linux_prison *lpr, *nlpr;
197191896Sjamie	int error;
198191896Sjamie
199191896Sjamie	/* If this prison already has Linux info, return that. */
200191896Sjamie	error = 0;
201192895Sjamie	lpr = linux_find_prison(pr, &ppr);
202192895Sjamie	if (ppr == pr)
203191896Sjamie		goto done;
204191896Sjamie	/*
205191896Sjamie	 * Allocate a new info record.  Then check again, in case something
206191896Sjamie	 * changed during the allocation.
207191896Sjamie	 */
208192895Sjamie	mtx_unlock(&ppr->pr_mtx);
209191896Sjamie	nlpr = malloc(sizeof(struct linux_prison), M_PRISON, M_WAITOK);
210192895Sjamie	lpr = linux_find_prison(pr, &ppr);
211192895Sjamie	if (ppr == pr) {
212191896Sjamie		free(nlpr, M_PRISON);
213191896Sjamie		goto done;
214191896Sjamie	}
215192895Sjamie	/* Inherit the initial values from the ancestor. */
216192895Sjamie	mtx_lock(&pr->pr_mtx);
217191896Sjamie	error = osd_jail_set(pr, linux_osd_jail_slot, nlpr);
218192895Sjamie	if (error == 0) {
219192895Sjamie		bcopy(lpr, nlpr, sizeof(*lpr));
220192895Sjamie		lpr = nlpr;
221192895Sjamie	} else {
222191896Sjamie		free(nlpr, M_PRISON);
223192895Sjamie		lpr = NULL;
224191896Sjamie	}
225192895Sjamie	mtx_unlock(&ppr->pr_mtx);
226192895Sjamie done:
227191896Sjamie	if (lprp != NULL)
228191896Sjamie		*lprp = lpr;
229192895Sjamie	else
230192895Sjamie		mtx_unlock(&pr->pr_mtx);
231235063Snetchild
232191896Sjamie	return (error);
233191896Sjamie}
234191896Sjamie
235191896Sjamie/*
236191896Sjamie * Jail OSD methods for Linux prison data.
237191896Sjamie */
238191896Sjamiestatic int
239191896Sjamielinux_prison_create(void *obj, void *data)
240191896Sjamie{
241191896Sjamie	struct prison *pr = obj;
242191896Sjamie	struct vfsoptlist *opts = data;
243293527Sdchagin	int jsys;
244191896Sjamie
245293527Sdchagin	if (vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)) == 0 &&
246293527Sdchagin	    jsys == JAIL_SYS_INHERIT)
247191896Sjamie		return (0);
248191896Sjamie	/*
249191896Sjamie	 * Inherit a prison's initial values from its parent
250195870Sjamie	 * (different from JAIL_SYS_INHERIT which also inherits changes).
251191896Sjamie	 */
252293527Sdchagin	return (linux_alloc_prison(pr, NULL));
253191896Sjamie}
254191896Sjamie
255191896Sjamiestatic int
256191896Sjamielinux_prison_check(void *obj __unused, void *data)
257191896Sjamie{
258191896Sjamie	struct vfsoptlist *opts = data;
259191896Sjamie	char *osname, *osrelease;
260195870Sjamie	int error, jsys, len, osrel, oss_version;
261191896Sjamie
262191896Sjamie	/* Check that the parameters are correct. */
263195870Sjamie	error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys));
264195870Sjamie	if (error != ENOENT) {
265293527Sdchagin		if (error != 0)
266195870Sjamie			return (error);
267293527Sdchagin		if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT)
268195870Sjamie			return (EINVAL);
269195870Sjamie	}
270191896Sjamie	error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len);
271191896Sjamie	if (error != ENOENT) {
272293527Sdchagin		if (error != 0)
273191896Sjamie			return (error);
274293527Sdchagin		if (len == 0 || osname[len - 1] != '\0')
275191896Sjamie			return (EINVAL);
276191896Sjamie		if (len > LINUX_MAX_UTSNAME) {
277191896Sjamie			vfs_opterror(opts, "linux.osname too long");
278191896Sjamie			return (ENAMETOOLONG);
279191896Sjamie		}
280191896Sjamie	}
281191896Sjamie	error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len);
282191896Sjamie	if (error != ENOENT) {
283293527Sdchagin		if (error != 0)
284191896Sjamie			return (error);
285293527Sdchagin		if (len == 0 || osrelease[len - 1] != '\0')
286191896Sjamie			return (EINVAL);
287191896Sjamie		if (len > LINUX_MAX_UTSNAME) {
288191896Sjamie			vfs_opterror(opts, "linux.osrelease too long");
289191896Sjamie			return (ENAMETOOLONG);
290191896Sjamie		}
291192895Sjamie		error = linux_map_osrel(osrelease, &osrel);
292192895Sjamie		if (error != 0) {
293192895Sjamie			vfs_opterror(opts, "linux.osrelease format error");
294192895Sjamie			return (error);
295192895Sjamie		}
296191896Sjamie	}
297191896Sjamie	error = vfs_copyopt(opts, "linux.oss_version", &oss_version,
298191896Sjamie	    sizeof(oss_version));
299235063Snetchild
300235063Snetchild	if (error == ENOENT)
301235063Snetchild		error = 0;
302235063Snetchild	return (error);
303191896Sjamie}
304191896Sjamie
305191896Sjamiestatic int
306191896Sjamielinux_prison_set(void *obj, void *data)
307191896Sjamie{
308191896Sjamie	struct linux_prison *lpr;
309191896Sjamie	struct prison *pr = obj;
310191896Sjamie	struct vfsoptlist *opts = data;
311191896Sjamie	char *osname, *osrelease;
312195870Sjamie	int error, gotversion, jsys, len, oss_version;
313191896Sjamie
314191896Sjamie	/* Set the parameters, which should be correct. */
315195870Sjamie	error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys));
316195870Sjamie	if (error == ENOENT)
317195870Sjamie		jsys = -1;
318191896Sjamie	error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len);
319191896Sjamie	if (error == ENOENT)
320191896Sjamie		osname = NULL;
321191896Sjamie	else
322195870Sjamie		jsys = JAIL_SYS_NEW;
323191896Sjamie	error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len);
324191896Sjamie	if (error == ENOENT)
325191896Sjamie		osrelease = NULL;
326191896Sjamie	else
327195870Sjamie		jsys = JAIL_SYS_NEW;
328191896Sjamie	error = vfs_copyopt(opts, "linux.oss_version", &oss_version,
329191896Sjamie	    sizeof(oss_version));
330195870Sjamie	if (error == ENOENT)
331195870Sjamie		gotversion = 0;
332195870Sjamie	else {
333195870Sjamie		gotversion = 1;
334195870Sjamie		jsys = JAIL_SYS_NEW;
335195870Sjamie	}
336195870Sjamie	switch (jsys) {
337195870Sjamie	case JAIL_SYS_INHERIT:
338195870Sjamie		/* "linux=inherit": inherit the parent's Linux info. */
339191896Sjamie		mtx_lock(&pr->pr_mtx);
340191896Sjamie		osd_jail_del(pr, linux_osd_jail_slot);
341191896Sjamie		mtx_unlock(&pr->pr_mtx);
342195870Sjamie		break;
343195870Sjamie	case JAIL_SYS_NEW:
344112206Sjhb		/*
345195870Sjamie		 * "linux=new" or "linux.*":
346191896Sjamie		 * the prison gets its own Linux info.
347112206Sjhb		 */
348191896Sjamie		error = linux_alloc_prison(pr, &lpr);
349191896Sjamie		if (error) {
350191896Sjamie			mtx_unlock(&pr->pr_mtx);
351191896Sjamie			return (error);
352191896Sjamie		}
353191896Sjamie		if (osrelease) {
354191972Sdchagin			error = linux_map_osrel(osrelease, &lpr->pr_osrel);
355191972Sdchagin			if (error) {
356191972Sdchagin				mtx_unlock(&pr->pr_mtx);
357191972Sdchagin				return (error);
358191972Sdchagin			}
359191896Sjamie			strlcpy(lpr->pr_osrelease, osrelease,
360191896Sjamie			    LINUX_MAX_UTSNAME);
361191896Sjamie		}
362191972Sdchagin		if (osname)
363191972Sdchagin			strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME);
364191896Sjamie		if (gotversion)
365191896Sjamie			lpr->pr_oss_version = oss_version;
36687275Srwatson		mtx_unlock(&pr->pr_mtx);
36750465Smarcel	}
368235063Snetchild
369191896Sjamie	return (0);
37050465Smarcel}
37150465Smarcel
372195870SjamieSYSCTL_JAIL_PARAM_SYS_NODE(linux, CTLFLAG_RW, "Jail Linux parameters");
373191896SjamieSYSCTL_JAIL_PARAM_STRING(_linux, osname, CTLFLAG_RW, LINUX_MAX_UTSNAME,
374191896Sjamie    "Jail Linux kernel OS name");
375191896SjamieSYSCTL_JAIL_PARAM_STRING(_linux, osrelease, CTLFLAG_RW, LINUX_MAX_UTSNAME,
376191896Sjamie    "Jail Linux kernel OS release");
377191896SjamieSYSCTL_JAIL_PARAM(_linux, oss_version, CTLTYPE_INT | CTLFLAG_RW,
378191896Sjamie    "I", "Jail Linux OSS version");
379191896Sjamie
380191896Sjamiestatic int
381191896Sjamielinux_prison_get(void *obj, void *data)
382191896Sjamie{
383191896Sjamie	struct linux_prison *lpr;
384192895Sjamie	struct prison *ppr;
385191896Sjamie	struct prison *pr = obj;
386191896Sjamie	struct vfsoptlist *opts = data;
387191896Sjamie	int error, i;
388191896Sjamie
389192895Sjamie	static int version0;
390192895Sjamie
391192895Sjamie	/* See if this prison is the one with the Linux info. */
392192895Sjamie	lpr = linux_find_prison(pr, &ppr);
393195870Sjamie	i = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT;
394191896Sjamie	error = vfs_setopt(opts, "linux", &i, sizeof(i));
395293527Sdchagin	if (error != 0 && error != ENOENT)
396293527Sdchagin		goto done;
397192895Sjamie	if (i) {
398195870Sjamie		error = vfs_setopts(opts, "linux.osname", lpr->pr_osname);
399293527Sdchagin		if (error != 0 && error != ENOENT)
400293527Sdchagin			goto done;
401195870Sjamie		error = vfs_setopts(opts, "linux.osrelease", lpr->pr_osrelease);
402293527Sdchagin		if (error != 0 && error != ENOENT)
403293527Sdchagin			goto done;
404195870Sjamie		error = vfs_setopt(opts, "linux.oss_version",
405195870Sjamie		    &lpr->pr_oss_version, sizeof(lpr->pr_oss_version));
406293527Sdchagin		if (error != 0 && error != ENOENT)
407293527Sdchagin			goto done;
408195870Sjamie	} else {
409192895Sjamie		/*
410192895Sjamie		 * If this prison is inheriting its Linux info, report
411192895Sjamie		 * empty/zero parameters.
412192895Sjamie		 */
413192895Sjamie		error = vfs_setopts(opts, "linux.osname", "");
414293527Sdchagin		if (error != 0 && error != ENOENT)
415293527Sdchagin			goto done;
416192895Sjamie		error = vfs_setopts(opts, "linux.osrelease", "");
417293527Sdchagin		if (error != 0 && error != ENOENT)
418293527Sdchagin			goto done;
419192895Sjamie		error = vfs_setopt(opts, "linux.oss_version", &version0,
420192895Sjamie		    sizeof(lpr->pr_oss_version));
421293527Sdchagin		if (error != 0 && error != ENOENT)
422293527Sdchagin			goto done;
423191896Sjamie	}
424191896Sjamie	error = 0;
425191896Sjamie
426191896Sjamie done:
427192895Sjamie	mtx_unlock(&ppr->pr_mtx);
428235063Snetchild
429191896Sjamie	return (error);
430191896Sjamie}
431191896Sjamie
432191896Sjamiestatic void
433191896Sjamielinux_prison_destructor(void *data)
434191896Sjamie{
435191896Sjamie
436191896Sjamie	free(data, M_PRISON);
437191896Sjamie}
438191896Sjamie
43987275Srwatsonvoid
440191896Sjamielinux_osd_jail_register(void)
44150465Smarcel{
442191896Sjamie	struct prison *pr;
443191896Sjamie	osd_method_t methods[PR_MAXMETHOD] = {
444191896Sjamie	    [PR_METHOD_CREATE] =	linux_prison_create,
445191896Sjamie	    [PR_METHOD_GET] =		linux_prison_get,
446191896Sjamie	    [PR_METHOD_SET] =		linux_prison_set,
447191896Sjamie	    [PR_METHOD_CHECK] =		linux_prison_check
448191896Sjamie	};
44950465Smarcel
450191896Sjamie	linux_osd_jail_slot =
451191896Sjamie	    osd_jail_register(linux_prison_destructor, methods);
452191896Sjamie	if (linux_osd_jail_slot > 0) {
453191896Sjamie		/* Copy the system linux info to any current prisons. */
454191896Sjamie		sx_xlock(&allprison_lock);
455192895Sjamie		TAILQ_FOREACH(pr, &allprison, pr_list)
456191896Sjamie			(void)linux_alloc_prison(pr, NULL);
457191896Sjamie		sx_xunlock(&allprison_lock);
45887275Srwatson	}
459191896Sjamie}
46087275Srwatson
461191896Sjamievoid
462191896Sjamielinux_osd_jail_deregister(void)
463191896Sjamie{
464191896Sjamie
465191896Sjamie	if (linux_osd_jail_slot)
466191896Sjamie		osd_jail_deregister(linux_osd_jail_slot);
46750465Smarcel}
46850465Smarcel
469191896Sjamievoid
470191896Sjamielinux_get_osname(struct thread *td, char *dst)
471191896Sjamie{
472191896Sjamie	struct prison *pr;
473191896Sjamie	struct linux_prison *lpr;
474191896Sjamie
475192895Sjamie	lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
476192895Sjamie	bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME);
477192895Sjamie	mtx_unlock(&pr->pr_mtx);
478191896Sjamie}
479191896Sjamie
480219668Snetchildstatic int
481112206Sjhblinux_set_osname(struct thread *td, char *osname)
48250465Smarcel{
483112206Sjhb	struct prison *pr;
484112206Sjhb	struct linux_prison *lpr;
48550465Smarcel
486192895Sjamie	lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
487192895Sjamie	strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME);
488192895Sjamie	mtx_unlock(&pr->pr_mtx);
489235063Snetchild
49050465Smarcel	return (0);
49150465Smarcel}
49250465Smarcel
49387275Srwatsonvoid
494112206Sjhblinux_get_osrelease(struct thread *td, char *dst)
49550465Smarcel{
496191896Sjamie	struct prison *pr;
49787275Srwatson	struct linux_prison *lpr;
49850465Smarcel
499192895Sjamie	lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
500192895Sjamie	bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME);
501192895Sjamie	mtx_unlock(&pr->pr_mtx);
50250465Smarcel}
50350465Smarcel
50450465Smarcelint
505191972Sdchaginlinux_kernver(struct thread *td)
506165687Snetchild{
507165687Snetchild	struct prison *pr;
508165687Snetchild	struct linux_prison *lpr;
509191972Sdchagin	int osrel;
510165687Snetchild
511192895Sjamie	lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
512192895Sjamie	osrel = lpr->pr_osrel;
513192895Sjamie	mtx_unlock(&pr->pr_mtx);
514235063Snetchild
515191972Sdchagin	return (osrel);
516165687Snetchild}
517165687Snetchild
518219668Snetchildstatic int
519112206Sjhblinux_set_osrelease(struct thread *td, char *osrelease)
52050465Smarcel{
521112206Sjhb	struct prison *pr;
522112206Sjhb	struct linux_prison *lpr;
523191972Sdchagin	int error;
52450465Smarcel
525192895Sjamie	lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
526192895Sjamie	error = linux_map_osrel(osrelease, &lpr->pr_osrel);
527192895Sjamie	if (error == 0)
528191896Sjamie		strlcpy(lpr->pr_osrelease, osrelease, LINUX_MAX_UTSNAME);
529192895Sjamie	mtx_unlock(&pr->pr_mtx);
530235063Snetchild
531192895Sjamie	return (error);
53250465Smarcel}
53350465Smarcel
53450465Smarcelint
535112206Sjhblinux_get_oss_version(struct thread *td)
53650465Smarcel{
537191896Sjamie	struct prison *pr;
538191896Sjamie	struct linux_prison *lpr;
53987275Srwatson	int version;
54050465Smarcel
541192895Sjamie	lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
542192895Sjamie	version = lpr->pr_oss_version;
543192895Sjamie	mtx_unlock(&pr->pr_mtx);
544235063Snetchild
54587275Srwatson	return (version);
54650465Smarcel}
54750465Smarcel
548219668Snetchildstatic int
549112206Sjhblinux_set_oss_version(struct thread *td, int oss_version)
55050465Smarcel{
551112206Sjhb	struct prison *pr;
552112206Sjhb	struct linux_prison *lpr;
55350465Smarcel
554192895Sjamie	lpr = linux_find_prison(td->td_ucred->cr_prison, &pr);
555192895Sjamie	lpr->pr_oss_version = oss_version;
556192895Sjamie	mtx_unlock(&pr->pr_mtx);
557235063Snetchild
55850465Smarcel	return (0);
55950465Smarcel}
560