1c6dfea0eSMarcel Moolenaar /*- 2*7f2d13d6SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 3*7f2d13d6SPedro F. Giffuni * 4c6dfea0eSMarcel Moolenaar * Copyright (c) 1999 Marcel Moolenaar 5c6dfea0eSMarcel Moolenaar * All rights reserved. 6c6dfea0eSMarcel Moolenaar * 7c6dfea0eSMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 8c6dfea0eSMarcel Moolenaar * modification, are permitted provided that the following conditions 9c6dfea0eSMarcel Moolenaar * are met: 10c6dfea0eSMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 11c6dfea0eSMarcel Moolenaar * notice, this list of conditions and the following disclaimer 12c6dfea0eSMarcel Moolenaar * in this position and unchanged. 13c6dfea0eSMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 14c6dfea0eSMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 15c6dfea0eSMarcel Moolenaar * documentation and/or other materials provided with the distribution. 16c6dfea0eSMarcel Moolenaar * 3. The name of the author may not be used to endorse or promote products 17bc34729cSMarcel Moolenaar * derived from this software without specific prior written permission. 18c6dfea0eSMarcel Moolenaar * 19c6dfea0eSMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20c6dfea0eSMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21c6dfea0eSMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22c6dfea0eSMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23c6dfea0eSMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24c6dfea0eSMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25c6dfea0eSMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26c6dfea0eSMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27c6dfea0eSMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28c6dfea0eSMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29c6dfea0eSMarcel Moolenaar */ 30c6dfea0eSMarcel Moolenaar 3116dbc7f2SDavid E. O'Brien #include <sys/cdefs.h> 3216dbc7f2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3316dbc7f2SDavid E. O'Brien 34c6dfea0eSMarcel Moolenaar #include <sys/param.h> 35c6dfea0eSMarcel Moolenaar #include <sys/kernel.h> 3619e252baSAlexander Leidinger #include <sys/sdt.h> 37c6dfea0eSMarcel Moolenaar #include <sys/systm.h> 38c6dfea0eSMarcel Moolenaar #include <sys/sysctl.h> 39c6dfea0eSMarcel Moolenaar #include <sys/proc.h> 40c6dfea0eSMarcel Moolenaar #include <sys/malloc.h> 417ae27ff4SJamie Gritton #include <sys/mount.h> 42c6dfea0eSMarcel Moolenaar #include <sys/jail.h> 4301137630SRobert Watson #include <sys/lock.h> 447ae27ff4SJamie Gritton #include <sys/sx.h> 45c6dfea0eSMarcel Moolenaar 46607d46efSMarcel Moolenaar #include <compat/linux/linux_mib.h> 47d825ce0aSJohn Baldwin #include <compat/linux/linux_misc.h> 48c6dfea0eSMarcel Moolenaar 49c6dfea0eSMarcel Moolenaar struct linux_prison { 50c6dfea0eSMarcel Moolenaar char pr_osname[LINUX_MAX_UTSNAME]; 51c6dfea0eSMarcel Moolenaar char pr_osrelease[LINUX_MAX_UTSNAME]; 52c6dfea0eSMarcel Moolenaar int pr_oss_version; 53580dd797SDmitry Chagin int pr_osrel; 54c6dfea0eSMarcel Moolenaar }; 55c6dfea0eSMarcel Moolenaar 560304c731SJamie Gritton static struct linux_prison lprison0 = { 570304c731SJamie Gritton .pr_osname = "Linux", 58a6326909SDmitry Chagin .pr_osrelease = LINUX_VERSION_STR, 590304c731SJamie Gritton .pr_oss_version = 0x030600, 60a6326909SDmitry Chagin .pr_osrel = LINUX_VERSION_CODE 610304c731SJamie Gritton }; 620304c731SJamie Gritton 637ae27ff4SJamie Gritton static unsigned linux_osd_jail_slot; 647ae27ff4SJamie Gritton 6567d39748SDmitry Chagin SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0, "Linux mode"); 66c6dfea0eSMarcel Moolenaar 670d7b5e54SAlexander Leidinger static int linux_set_osname(struct thread *td, char *osname); 680d7b5e54SAlexander Leidinger static int linux_set_osrelease(struct thread *td, char *osrelease); 690d7b5e54SAlexander Leidinger static int linux_set_oss_version(struct thread *td, int oss_version); 700d7b5e54SAlexander Leidinger 71c6dfea0eSMarcel Moolenaar static int 7282d9ae4eSPoul-Henning Kamp linux_sysctl_osname(SYSCTL_HANDLER_ARGS) 73c6dfea0eSMarcel Moolenaar { 74c6dfea0eSMarcel Moolenaar char osname[LINUX_MAX_UTSNAME]; 75c6dfea0eSMarcel Moolenaar int error; 76c6dfea0eSMarcel Moolenaar 77b62f75cfSJohn Baldwin linux_get_osname(req->td, osname); 78c6dfea0eSMarcel Moolenaar error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req); 7967d39748SDmitry Chagin if (error != 0 || req->newptr == NULL) 80c6dfea0eSMarcel Moolenaar return (error); 81b62f75cfSJohn Baldwin error = linux_set_osname(req->td, osname); 8219e252baSAlexander Leidinger 83c6dfea0eSMarcel Moolenaar return (error); 84c6dfea0eSMarcel Moolenaar } 85c6dfea0eSMarcel Moolenaar 86c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osname, 8784a8cad0SJamie Gritton CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 88c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_osname, "A", 89c6dfea0eSMarcel Moolenaar "Linux kernel OS name"); 90c6dfea0eSMarcel Moolenaar 91c6dfea0eSMarcel Moolenaar static int 9282d9ae4eSPoul-Henning Kamp linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS) 93c6dfea0eSMarcel Moolenaar { 94c6dfea0eSMarcel Moolenaar char osrelease[LINUX_MAX_UTSNAME]; 95c6dfea0eSMarcel Moolenaar int error; 96c6dfea0eSMarcel Moolenaar 97b62f75cfSJohn Baldwin linux_get_osrelease(req->td, osrelease); 98c6dfea0eSMarcel Moolenaar error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req); 9967d39748SDmitry Chagin if (error != 0 || req->newptr == NULL) 100c6dfea0eSMarcel Moolenaar return (error); 101b62f75cfSJohn Baldwin error = linux_set_osrelease(req->td, osrelease); 10219e252baSAlexander Leidinger 103c6dfea0eSMarcel Moolenaar return (error); 104c6dfea0eSMarcel Moolenaar } 105c6dfea0eSMarcel Moolenaar 106c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease, 10784a8cad0SJamie Gritton CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 108c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_osrelease, "A", 109c6dfea0eSMarcel Moolenaar "Linux kernel OS release"); 110c6dfea0eSMarcel Moolenaar 111c6dfea0eSMarcel Moolenaar static int 11282d9ae4eSPoul-Henning Kamp linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS) 113c6dfea0eSMarcel Moolenaar { 114c6dfea0eSMarcel Moolenaar int oss_version; 115c6dfea0eSMarcel Moolenaar int error; 116c6dfea0eSMarcel Moolenaar 117b62f75cfSJohn Baldwin oss_version = linux_get_oss_version(req->td); 118c6dfea0eSMarcel Moolenaar error = sysctl_handle_int(oidp, &oss_version, 0, req); 11967d39748SDmitry Chagin if (error != 0 || req->newptr == NULL) 120c6dfea0eSMarcel Moolenaar return (error); 121b62f75cfSJohn Baldwin error = linux_set_oss_version(req->td, oss_version); 12219e252baSAlexander Leidinger 123c6dfea0eSMarcel Moolenaar return (error); 124c6dfea0eSMarcel Moolenaar } 125c6dfea0eSMarcel Moolenaar 126c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version, 12784a8cad0SJamie Gritton CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 128c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_oss_version, "I", 129c6dfea0eSMarcel Moolenaar "Linux OSS version"); 130c6dfea0eSMarcel Moolenaar 13101137630SRobert Watson /* 132580dd797SDmitry Chagin * Map the osrelease into integer 133580dd797SDmitry Chagin */ 134580dd797SDmitry Chagin static int 135580dd797SDmitry Chagin linux_map_osrel(char *osrelease, int *osrel) 136580dd797SDmitry Chagin { 137580dd797SDmitry Chagin char *sep, *eosrelease; 138580dd797SDmitry Chagin int len, v0, v1, v2, v; 139580dd797SDmitry Chagin 140580dd797SDmitry Chagin len = strlen(osrelease); 141580dd797SDmitry Chagin eosrelease = osrelease + len; 142580dd797SDmitry Chagin v0 = strtol(osrelease, &sep, 10); 14367d39748SDmitry Chagin if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') 144580dd797SDmitry Chagin return (EINVAL); 145580dd797SDmitry Chagin osrelease = sep + 1; 146580dd797SDmitry Chagin v1 = strtol(osrelease, &sep, 10); 14767d39748SDmitry Chagin if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') 148580dd797SDmitry Chagin return (EINVAL); 149580dd797SDmitry Chagin osrelease = sep + 1; 150580dd797SDmitry Chagin v2 = strtol(osrelease, &sep, 10); 15167d39748SDmitry Chagin if (osrelease == sep || sep != eosrelease) 152580dd797SDmitry Chagin return (EINVAL); 153580dd797SDmitry Chagin 154580dd797SDmitry Chagin v = v0 * 1000000 + v1 * 1000 + v2; 15567d39748SDmitry Chagin if (v < 1000000) 156580dd797SDmitry Chagin return (EINVAL); 157580dd797SDmitry Chagin 158d56cf22dSJamie Gritton if (osrel != NULL) 159580dd797SDmitry Chagin *osrel = v; 16019e252baSAlexander Leidinger 161580dd797SDmitry Chagin return (0); 162580dd797SDmitry Chagin } 163580dd797SDmitry Chagin 164580dd797SDmitry Chagin /* 1650304c731SJamie Gritton * Find a prison with Linux info. 1660304c731SJamie Gritton * Return the Linux info and the (locked) prison. 16701137630SRobert Watson */ 1687ae27ff4SJamie Gritton static struct linux_prison * 1690304c731SJamie Gritton linux_find_prison(struct prison *spr, struct prison **prp) 170c6dfea0eSMarcel Moolenaar { 1717ae27ff4SJamie Gritton struct prison *pr; 1727ae27ff4SJamie Gritton struct linux_prison *lpr; 173c6dfea0eSMarcel Moolenaar 1740304c731SJamie Gritton for (pr = spr;; pr = pr->pr_parent) { 175b62f75cfSJohn Baldwin mtx_lock(&pr->pr_mtx); 1760304c731SJamie Gritton lpr = (pr == &prison0) 1770304c731SJamie Gritton ? &lprison0 1780304c731SJamie Gritton : osd_jail_get(pr, linux_osd_jail_slot); 1790304c731SJamie Gritton if (lpr != NULL) 1800304c731SJamie Gritton break; 1817ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 1820304c731SJamie Gritton } 1830304c731SJamie Gritton *prp = pr; 18419e252baSAlexander Leidinger 1857ae27ff4SJamie Gritton return (lpr); 1867ae27ff4SJamie Gritton } 1877ae27ff4SJamie Gritton 18801137630SRobert Watson /* 1890304c731SJamie Gritton * Ensure a prison has its own Linux info. If lprp is non-null, point it to 1900304c731SJamie Gritton * the Linux info and lock the prison. 1917ae27ff4SJamie Gritton */ 1927ab25e3dSJamie Gritton static void 1937ae27ff4SJamie Gritton linux_alloc_prison(struct prison *pr, struct linux_prison **lprp) 1947ae27ff4SJamie Gritton { 1950304c731SJamie Gritton struct prison *ppr; 1967ae27ff4SJamie Gritton struct linux_prison *lpr, *nlpr; 197aa90aec2SConrad Meyer void **rsv; 1987ae27ff4SJamie Gritton 1997ae27ff4SJamie Gritton /* If this prison already has Linux info, return that. */ 2000304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 2010304c731SJamie Gritton if (ppr == pr) 2027ae27ff4SJamie Gritton goto done; 2037ae27ff4SJamie Gritton /* 2047ae27ff4SJamie Gritton * Allocate a new info record. Then check again, in case something 2057ae27ff4SJamie Gritton * changed during the allocation. 20601137630SRobert Watson */ 2070304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 2087ae27ff4SJamie Gritton nlpr = malloc(sizeof(struct linux_prison), M_PRISON, M_WAITOK); 2097ab25e3dSJamie Gritton rsv = osd_reserve(linux_osd_jail_slot); 2100304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 2110304c731SJamie Gritton if (ppr == pr) { 2127ae27ff4SJamie Gritton free(nlpr, M_PRISON); 2137ab25e3dSJamie Gritton osd_free_reserved(rsv); 2147ae27ff4SJamie Gritton goto done; 21501137630SRobert Watson } 2160304c731SJamie Gritton /* Inherit the initial values from the ancestor. */ 2170304c731SJamie Gritton mtx_lock(&pr->pr_mtx); 2187ab25e3dSJamie Gritton (void)osd_jail_set_reserved(pr, linux_osd_jail_slot, rsv, nlpr); 2190304c731SJamie Gritton bcopy(lpr, nlpr, sizeof(*lpr)); 2207ae27ff4SJamie Gritton lpr = nlpr; 2210304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 2227ae27ff4SJamie Gritton done: 2237ae27ff4SJamie Gritton if (lprp != NULL) 2247ae27ff4SJamie Gritton *lprp = lpr; 2250304c731SJamie Gritton else 2260304c731SJamie Gritton mtx_unlock(&pr->pr_mtx); 2277ae27ff4SJamie Gritton } 2287ae27ff4SJamie Gritton 2297ae27ff4SJamie Gritton /* 2307ae27ff4SJamie Gritton * Jail OSD methods for Linux prison data. 2317ae27ff4SJamie Gritton */ 2327ae27ff4SJamie Gritton static int 2337ae27ff4SJamie Gritton linux_prison_create(void *obj, void *data) 2347ae27ff4SJamie Gritton { 2357ae27ff4SJamie Gritton struct prison *pr = obj; 2367ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 23767d39748SDmitry Chagin int jsys; 2387ae27ff4SJamie Gritton 23967d39748SDmitry Chagin if (vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)) == 0 && 24067d39748SDmitry Chagin jsys == JAIL_SYS_INHERIT) 2417ae27ff4SJamie Gritton return (0); 2427ae27ff4SJamie Gritton /* 2437ae27ff4SJamie Gritton * Inherit a prison's initial values from its parent 2447cbf7213SJamie Gritton * (different from JAIL_SYS_INHERIT which also inherits changes). 2457ae27ff4SJamie Gritton */ 2467ab25e3dSJamie Gritton linux_alloc_prison(pr, NULL); 2477ab25e3dSJamie Gritton return (0); 2487ae27ff4SJamie Gritton } 2497ae27ff4SJamie Gritton 2507ae27ff4SJamie Gritton static int 2517ae27ff4SJamie Gritton linux_prison_check(void *obj __unused, void *data) 2527ae27ff4SJamie Gritton { 2537ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 2547ae27ff4SJamie Gritton char *osname, *osrelease; 255d56cf22dSJamie Gritton int error, jsys, len, oss_version; 2567ae27ff4SJamie Gritton 2577ae27ff4SJamie Gritton /* Check that the parameters are correct. */ 2587cbf7213SJamie Gritton error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 2597cbf7213SJamie Gritton if (error != ENOENT) { 26067d39748SDmitry Chagin if (error != 0) 2617cbf7213SJamie Gritton return (error); 26267d39748SDmitry Chagin if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT) 2637cbf7213SJamie Gritton return (EINVAL); 2647cbf7213SJamie Gritton } 2657ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len); 2667ae27ff4SJamie Gritton if (error != ENOENT) { 26767d39748SDmitry Chagin if (error != 0) 2687ae27ff4SJamie Gritton return (error); 26967d39748SDmitry Chagin if (len == 0 || osname[len - 1] != '\0') 2707ae27ff4SJamie Gritton return (EINVAL); 2717ae27ff4SJamie Gritton if (len > LINUX_MAX_UTSNAME) { 2727ae27ff4SJamie Gritton vfs_opterror(opts, "linux.osname too long"); 2737ae27ff4SJamie Gritton return (ENAMETOOLONG); 2747ae27ff4SJamie Gritton } 2757ae27ff4SJamie Gritton } 2767ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len); 2777ae27ff4SJamie Gritton if (error != ENOENT) { 27867d39748SDmitry Chagin if (error != 0) 2797ae27ff4SJamie Gritton return (error); 28067d39748SDmitry Chagin if (len == 0 || osrelease[len - 1] != '\0') 2817ae27ff4SJamie Gritton return (EINVAL); 2827ae27ff4SJamie Gritton if (len > LINUX_MAX_UTSNAME) { 2837ae27ff4SJamie Gritton vfs_opterror(opts, "linux.osrelease too long"); 2847ae27ff4SJamie Gritton return (ENAMETOOLONG); 2857ae27ff4SJamie Gritton } 286d56cf22dSJamie Gritton error = linux_map_osrel(osrelease, NULL); 2870304c731SJamie Gritton if (error != 0) { 2880304c731SJamie Gritton vfs_opterror(opts, "linux.osrelease format error"); 2890304c731SJamie Gritton return (error); 2900304c731SJamie Gritton } 2917ae27ff4SJamie Gritton } 2927ae27ff4SJamie Gritton error = vfs_copyopt(opts, "linux.oss_version", &oss_version, 2937ae27ff4SJamie Gritton sizeof(oss_version)); 29419e252baSAlexander Leidinger 29519e252baSAlexander Leidinger if (error == ENOENT) 29619e252baSAlexander Leidinger error = 0; 29719e252baSAlexander Leidinger return (error); 2987ae27ff4SJamie Gritton } 2997ae27ff4SJamie Gritton 3007ae27ff4SJamie Gritton static int 3017ae27ff4SJamie Gritton linux_prison_set(void *obj, void *data) 3027ae27ff4SJamie Gritton { 3037ae27ff4SJamie Gritton struct linux_prison *lpr; 3047ae27ff4SJamie Gritton struct prison *pr = obj; 3057ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 3067ae27ff4SJamie Gritton char *osname, *osrelease; 3077cbf7213SJamie Gritton int error, gotversion, jsys, len, oss_version; 3087ae27ff4SJamie Gritton 3097ae27ff4SJamie Gritton /* Set the parameters, which should be correct. */ 3107cbf7213SJamie Gritton error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 3117cbf7213SJamie Gritton if (error == ENOENT) 3127cbf7213SJamie Gritton jsys = -1; 3137ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len); 3147ae27ff4SJamie Gritton if (error == ENOENT) 3157ae27ff4SJamie Gritton osname = NULL; 3167ae27ff4SJamie Gritton else 3177cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 3187ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len); 3197ae27ff4SJamie Gritton if (error == ENOENT) 3207ae27ff4SJamie Gritton osrelease = NULL; 3217ae27ff4SJamie Gritton else 3227cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 3237ae27ff4SJamie Gritton error = vfs_copyopt(opts, "linux.oss_version", &oss_version, 3247ae27ff4SJamie Gritton sizeof(oss_version)); 3257cbf7213SJamie Gritton if (error == ENOENT) 3267cbf7213SJamie Gritton gotversion = 0; 3277cbf7213SJamie Gritton else { 3287cbf7213SJamie Gritton gotversion = 1; 3297cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 3307cbf7213SJamie Gritton } 3317cbf7213SJamie Gritton switch (jsys) { 3327cbf7213SJamie Gritton case JAIL_SYS_INHERIT: 3337cbf7213SJamie Gritton /* "linux=inherit": inherit the parent's Linux info. */ 3347ae27ff4SJamie Gritton mtx_lock(&pr->pr_mtx); 3357ae27ff4SJamie Gritton osd_jail_del(pr, linux_osd_jail_slot); 3367ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 3377cbf7213SJamie Gritton break; 3387cbf7213SJamie Gritton case JAIL_SYS_NEW: 3397ae27ff4SJamie Gritton /* 3407cbf7213SJamie Gritton * "linux=new" or "linux.*": 3417ae27ff4SJamie Gritton * the prison gets its own Linux info. 3427ae27ff4SJamie Gritton */ 3437ab25e3dSJamie Gritton linux_alloc_prison(pr, &lpr); 3447ae27ff4SJamie Gritton if (osrelease) { 345d56cf22dSJamie Gritton (void)linux_map_osrel(osrelease, &lpr->pr_osrel); 3467ae27ff4SJamie Gritton strlcpy(lpr->pr_osrelease, osrelease, 3477ae27ff4SJamie Gritton LINUX_MAX_UTSNAME); 3487ae27ff4SJamie Gritton } 349580dd797SDmitry Chagin if (osname) 350580dd797SDmitry Chagin strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME); 3517ae27ff4SJamie Gritton if (gotversion) 3527ae27ff4SJamie Gritton lpr->pr_oss_version = oss_version; 3537ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 3547ae27ff4SJamie Gritton } 35519e252baSAlexander Leidinger 3567ae27ff4SJamie Gritton return (0); 3577ae27ff4SJamie Gritton } 3587ae27ff4SJamie Gritton 3597cbf7213SJamie Gritton SYSCTL_JAIL_PARAM_SYS_NODE(linux, CTLFLAG_RW, "Jail Linux parameters"); 3607ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM_STRING(_linux, osname, CTLFLAG_RW, LINUX_MAX_UTSNAME, 3617ae27ff4SJamie Gritton "Jail Linux kernel OS name"); 3627ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM_STRING(_linux, osrelease, CTLFLAG_RW, LINUX_MAX_UTSNAME, 3637ae27ff4SJamie Gritton "Jail Linux kernel OS release"); 3647ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM(_linux, oss_version, CTLTYPE_INT | CTLFLAG_RW, 3657ae27ff4SJamie Gritton "I", "Jail Linux OSS version"); 3667ae27ff4SJamie Gritton 3677ae27ff4SJamie Gritton static int 3687ae27ff4SJamie Gritton linux_prison_get(void *obj, void *data) 3697ae27ff4SJamie Gritton { 3707ae27ff4SJamie Gritton struct linux_prison *lpr; 3710304c731SJamie Gritton struct prison *ppr; 3727ae27ff4SJamie Gritton struct prison *pr = obj; 3737ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 3747ae27ff4SJamie Gritton int error, i; 3757ae27ff4SJamie Gritton 3760304c731SJamie Gritton static int version0; 3770304c731SJamie Gritton 3780304c731SJamie Gritton /* See if this prison is the one with the Linux info. */ 3790304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 3807cbf7213SJamie Gritton i = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT; 3817ae27ff4SJamie Gritton error = vfs_setopt(opts, "linux", &i, sizeof(i)); 38267d39748SDmitry Chagin if (error != 0 && error != ENOENT) 3837ae27ff4SJamie Gritton goto done; 3847cbf7213SJamie Gritton if (i) { 3857cbf7213SJamie Gritton error = vfs_setopts(opts, "linux.osname", lpr->pr_osname); 38667d39748SDmitry Chagin if (error != 0 && error != ENOENT) 3877ae27ff4SJamie Gritton goto done; 3887cbf7213SJamie Gritton error = vfs_setopts(opts, "linux.osrelease", lpr->pr_osrelease); 38967d39748SDmitry Chagin if (error != 0 && error != ENOENT) 3907cbf7213SJamie Gritton goto done; 3917cbf7213SJamie Gritton error = vfs_setopt(opts, "linux.oss_version", 3927cbf7213SJamie Gritton &lpr->pr_oss_version, sizeof(lpr->pr_oss_version)); 39367d39748SDmitry Chagin if (error != 0 && error != ENOENT) 3947cbf7213SJamie Gritton goto done; 3957cbf7213SJamie Gritton } else { 3967ae27ff4SJamie Gritton /* 3970304c731SJamie Gritton * If this prison is inheriting its Linux info, report 3980304c731SJamie Gritton * empty/zero parameters. 3997ae27ff4SJamie Gritton */ 4000304c731SJamie Gritton error = vfs_setopts(opts, "linux.osname", ""); 40167d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4020304c731SJamie Gritton goto done; 4030304c731SJamie Gritton error = vfs_setopts(opts, "linux.osrelease", ""); 40467d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4050304c731SJamie Gritton goto done; 4060304c731SJamie Gritton error = vfs_setopt(opts, "linux.oss_version", &version0, 4070304c731SJamie Gritton sizeof(lpr->pr_oss_version)); 40867d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4090304c731SJamie Gritton goto done; 4107ae27ff4SJamie Gritton } 4117ae27ff4SJamie Gritton error = 0; 4127ae27ff4SJamie Gritton 4137ae27ff4SJamie Gritton done: 4140304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 41519e252baSAlexander Leidinger 4167ae27ff4SJamie Gritton return (error); 4177ae27ff4SJamie Gritton } 4187ae27ff4SJamie Gritton 4197ae27ff4SJamie Gritton static void 4207ae27ff4SJamie Gritton linux_prison_destructor(void *data) 4217ae27ff4SJamie Gritton { 4227ae27ff4SJamie Gritton 4237ae27ff4SJamie Gritton free(data, M_PRISON); 4247ae27ff4SJamie Gritton } 4257ae27ff4SJamie Gritton 4267ae27ff4SJamie Gritton void 4277ae27ff4SJamie Gritton linux_osd_jail_register(void) 4287ae27ff4SJamie Gritton { 4297ae27ff4SJamie Gritton struct prison *pr; 4307ae27ff4SJamie Gritton osd_method_t methods[PR_MAXMETHOD] = { 4317ae27ff4SJamie Gritton [PR_METHOD_CREATE] = linux_prison_create, 4327ae27ff4SJamie Gritton [PR_METHOD_GET] = linux_prison_get, 4337ae27ff4SJamie Gritton [PR_METHOD_SET] = linux_prison_set, 4347ae27ff4SJamie Gritton [PR_METHOD_CHECK] = linux_prison_check 4357ae27ff4SJamie Gritton }; 4367ae27ff4SJamie Gritton 4377ae27ff4SJamie Gritton linux_osd_jail_slot = 4387ae27ff4SJamie Gritton osd_jail_register(linux_prison_destructor, methods); 4397ae27ff4SJamie Gritton /* Copy the system linux info to any current prisons. */ 4407ab25e3dSJamie Gritton sx_slock(&allprison_lock); 4410304c731SJamie Gritton TAILQ_FOREACH(pr, &allprison, pr_list) 4427ab25e3dSJamie Gritton linux_alloc_prison(pr, NULL); 4437ab25e3dSJamie Gritton sx_sunlock(&allprison_lock); 4447ae27ff4SJamie Gritton } 4457ae27ff4SJamie Gritton 4467ae27ff4SJamie Gritton void 4477ae27ff4SJamie Gritton linux_osd_jail_deregister(void) 4487ae27ff4SJamie Gritton { 4497ae27ff4SJamie Gritton 4507ae27ff4SJamie Gritton osd_jail_deregister(linux_osd_jail_slot); 451c6dfea0eSMarcel Moolenaar } 452c6dfea0eSMarcel Moolenaar 45301137630SRobert Watson void 454b62f75cfSJohn Baldwin linux_get_osname(struct thread *td, char *dst) 455c6dfea0eSMarcel Moolenaar { 4567ae27ff4SJamie Gritton struct prison *pr; 4577ae27ff4SJamie Gritton struct linux_prison *lpr; 458c6dfea0eSMarcel Moolenaar 4590304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 46001137630SRobert Watson bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME); 46101137630SRobert Watson mtx_unlock(&pr->pr_mtx); 4627ae27ff4SJamie Gritton } 463c6dfea0eSMarcel Moolenaar 4640d7b5e54SAlexander Leidinger static int 465b62f75cfSJohn Baldwin linux_set_osname(struct thread *td, char *osname) 466c6dfea0eSMarcel Moolenaar { 467b62f75cfSJohn Baldwin struct prison *pr; 468b62f75cfSJohn Baldwin struct linux_prison *lpr; 469c6dfea0eSMarcel Moolenaar 4700304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 4717ae27ff4SJamie Gritton strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME); 472b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 47319e252baSAlexander Leidinger 474c6dfea0eSMarcel Moolenaar return (0); 475c6dfea0eSMarcel Moolenaar } 476c6dfea0eSMarcel Moolenaar 47701137630SRobert Watson void 478b62f75cfSJohn Baldwin linux_get_osrelease(struct thread *td, char *dst) 479c6dfea0eSMarcel Moolenaar { 4807ae27ff4SJamie Gritton struct prison *pr; 48101137630SRobert Watson struct linux_prison *lpr; 482c6dfea0eSMarcel Moolenaar 4830304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 4847ae27ff4SJamie Gritton bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME); 48501137630SRobert Watson mtx_unlock(&pr->pr_mtx); 4867ae27ff4SJamie Gritton } 487c6dfea0eSMarcel Moolenaar 488c6dfea0eSMarcel Moolenaar int 489580dd797SDmitry Chagin linux_kernver(struct thread *td) 4909ce8f9bcSAlexander Leidinger { 4919ce8f9bcSAlexander Leidinger struct prison *pr; 4929ce8f9bcSAlexander Leidinger struct linux_prison *lpr; 493580dd797SDmitry Chagin int osrel; 4949ce8f9bcSAlexander Leidinger 4950304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 496580dd797SDmitry Chagin osrel = lpr->pr_osrel; 4977ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 49819e252baSAlexander Leidinger 499580dd797SDmitry Chagin return (osrel); 5009ce8f9bcSAlexander Leidinger } 5019ce8f9bcSAlexander Leidinger 5020d7b5e54SAlexander Leidinger static int 503b62f75cfSJohn Baldwin linux_set_osrelease(struct thread *td, char *osrelease) 504c6dfea0eSMarcel Moolenaar { 505b62f75cfSJohn Baldwin struct prison *pr; 506b62f75cfSJohn Baldwin struct linux_prison *lpr; 507580dd797SDmitry Chagin int error; 5089ce8f9bcSAlexander Leidinger 5090304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 510580dd797SDmitry Chagin error = linux_map_osrel(osrelease, &lpr->pr_osrel); 5110304c731SJamie Gritton if (error == 0) 5127ae27ff4SJamie Gritton strlcpy(lpr->pr_osrelease, osrelease, LINUX_MAX_UTSNAME); 513b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 51419e252baSAlexander Leidinger 515580dd797SDmitry Chagin return (error); 516580dd797SDmitry Chagin } 517c6dfea0eSMarcel Moolenaar 518c6dfea0eSMarcel Moolenaar int 519b62f75cfSJohn Baldwin linux_get_oss_version(struct thread *td) 520c6dfea0eSMarcel Moolenaar { 5217ae27ff4SJamie Gritton struct prison *pr; 5227ae27ff4SJamie Gritton struct linux_prison *lpr; 52301137630SRobert Watson int version; 52401137630SRobert Watson 5250304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 52601137630SRobert Watson version = lpr->pr_oss_version; 527b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 52819e252baSAlexander Leidinger 52901137630SRobert Watson return (version); 530c6dfea0eSMarcel Moolenaar } 531c6dfea0eSMarcel Moolenaar 5320d7b5e54SAlexander Leidinger static int 533b62f75cfSJohn Baldwin linux_set_oss_version(struct thread *td, int oss_version) 534c6dfea0eSMarcel Moolenaar { 535b62f75cfSJohn Baldwin struct prison *pr; 536b62f75cfSJohn Baldwin struct linux_prison *lpr; 537c6dfea0eSMarcel Moolenaar 5380304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 539c6dfea0eSMarcel Moolenaar lpr->pr_oss_version = oss_version; 540b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 54119e252baSAlexander Leidinger 542c6dfea0eSMarcel Moolenaar return (0); 543c6dfea0eSMarcel Moolenaar } 544