1c6dfea0eSMarcel Moolenaar /*- 20ba1b365SEd Maste * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 37f2d13d6SPedro 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 110ba1b365SEd Maste * notice, this list of conditions and the following disclaimer. 12c6dfea0eSMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 13c6dfea0eSMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 14c6dfea0eSMarcel Moolenaar * documentation and/or other materials provided with the distribution. 15c6dfea0eSMarcel Moolenaar * 160ba1b365SEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 170ba1b365SEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 180ba1b365SEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 190ba1b365SEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 200ba1b365SEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 210ba1b365SEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 220ba1b365SEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 230ba1b365SEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 240ba1b365SEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 250ba1b365SEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 260ba1b365SEd Maste * SUCH DAMAGE. 27c6dfea0eSMarcel Moolenaar */ 28c6dfea0eSMarcel Moolenaar 2916dbc7f2SDavid E. O'Brien #include <sys/cdefs.h> 3016dbc7f2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3116dbc7f2SDavid E. O'Brien 32c6dfea0eSMarcel Moolenaar #include <sys/param.h> 33c6dfea0eSMarcel Moolenaar #include <sys/kernel.h> 3419e252baSAlexander Leidinger #include <sys/sdt.h> 35c6dfea0eSMarcel Moolenaar #include <sys/systm.h> 36c6dfea0eSMarcel Moolenaar #include <sys/sysctl.h> 37c6dfea0eSMarcel Moolenaar #include <sys/proc.h> 38c6dfea0eSMarcel Moolenaar #include <sys/malloc.h> 397ae27ff4SJamie Gritton #include <sys/mount.h> 40c6dfea0eSMarcel Moolenaar #include <sys/jail.h> 4101137630SRobert Watson #include <sys/lock.h> 427ae27ff4SJamie Gritton #include <sys/sx.h> 43c6dfea0eSMarcel Moolenaar 44607d46efSMarcel Moolenaar #include <compat/linux/linux_mib.h> 45d825ce0aSJohn Baldwin #include <compat/linux/linux_misc.h> 46c6dfea0eSMarcel Moolenaar 47c6dfea0eSMarcel Moolenaar struct linux_prison { 48c6dfea0eSMarcel Moolenaar char pr_osname[LINUX_MAX_UTSNAME]; 49c6dfea0eSMarcel Moolenaar char pr_osrelease[LINUX_MAX_UTSNAME]; 50c6dfea0eSMarcel Moolenaar int pr_oss_version; 51580dd797SDmitry Chagin int pr_osrel; 52c6dfea0eSMarcel Moolenaar }; 53c6dfea0eSMarcel Moolenaar 540304c731SJamie Gritton static struct linux_prison lprison0 = { 550304c731SJamie Gritton .pr_osname = "Linux", 56a6326909SDmitry Chagin .pr_osrelease = LINUX_VERSION_STR, 570304c731SJamie Gritton .pr_oss_version = 0x030600, 58a6326909SDmitry Chagin .pr_osrel = LINUX_VERSION_CODE 590304c731SJamie Gritton }; 600304c731SJamie Gritton 617ae27ff4SJamie Gritton static unsigned linux_osd_jail_slot; 627ae27ff4SJamie Gritton 637029da5cSPawel Biernacki SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 647029da5cSPawel Biernacki "Linux mode"); 65c6dfea0eSMarcel Moolenaar 66da6d8ae6SEdward Tomasz Napierala int linux_ignore_ip_recverr = 1; 67da6d8ae6SEdward Tomasz Napierala SYSCTL_INT(_compat_linux, OID_AUTO, ignore_ip_recverr, CTLFLAG_RWTUN, 68da6d8ae6SEdward Tomasz Napierala &linux_ignore_ip_recverr, 0, "Ignore enabling IP_RECVERR"); 69da6d8ae6SEdward Tomasz Napierala 702cf9eb6cSEdward Tomasz Napierala int linux_preserve_vstatus = 0; 712cf9eb6cSEdward Tomasz Napierala SYSCTL_INT(_compat_linux, OID_AUTO, preserve_vstatus, CTLFLAG_RWTUN, 722cf9eb6cSEdward Tomasz Napierala &linux_preserve_vstatus, 0, "Preserve VSTATUS termios(4) flag"); 732cf9eb6cSEdward Tomasz Napierala 74*b4147bf6STijl Coosemans bool linux_map_sched_prio = true; 75*b4147bf6STijl Coosemans SYSCTL_BOOL(_compat_linux, OID_AUTO, map_sched_prio, CTLFLAG_RDTUN, 76*b4147bf6STijl Coosemans &linux_map_sched_prio, 0, "Map scheduler priorities to Linux priorities " 77*b4147bf6STijl Coosemans "(not POSIX compliant)"); 78*b4147bf6STijl Coosemans 790d7b5e54SAlexander Leidinger static int linux_set_osname(struct thread *td, char *osname); 800d7b5e54SAlexander Leidinger static int linux_set_osrelease(struct thread *td, char *osrelease); 810d7b5e54SAlexander Leidinger static int linux_set_oss_version(struct thread *td, int oss_version); 820d7b5e54SAlexander Leidinger 83c6dfea0eSMarcel Moolenaar static int 8482d9ae4eSPoul-Henning Kamp linux_sysctl_osname(SYSCTL_HANDLER_ARGS) 85c6dfea0eSMarcel Moolenaar { 86c6dfea0eSMarcel Moolenaar char osname[LINUX_MAX_UTSNAME]; 87c6dfea0eSMarcel Moolenaar int error; 88c6dfea0eSMarcel Moolenaar 89b62f75cfSJohn Baldwin linux_get_osname(req->td, osname); 90c6dfea0eSMarcel Moolenaar error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req); 9167d39748SDmitry Chagin if (error != 0 || req->newptr == NULL) 92c6dfea0eSMarcel Moolenaar return (error); 93b62f75cfSJohn Baldwin error = linux_set_osname(req->td, osname); 9419e252baSAlexander Leidinger 95c6dfea0eSMarcel Moolenaar return (error); 96c6dfea0eSMarcel Moolenaar } 97c6dfea0eSMarcel Moolenaar 98c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osname, 9984a8cad0SJamie Gritton CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 100c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_osname, "A", 101c6dfea0eSMarcel Moolenaar "Linux kernel OS name"); 102c6dfea0eSMarcel Moolenaar 103c6dfea0eSMarcel Moolenaar static int 10482d9ae4eSPoul-Henning Kamp linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS) 105c6dfea0eSMarcel Moolenaar { 106c6dfea0eSMarcel Moolenaar char osrelease[LINUX_MAX_UTSNAME]; 107c6dfea0eSMarcel Moolenaar int error; 108c6dfea0eSMarcel Moolenaar 109b62f75cfSJohn Baldwin linux_get_osrelease(req->td, osrelease); 110c6dfea0eSMarcel Moolenaar error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req); 11167d39748SDmitry Chagin if (error != 0 || req->newptr == NULL) 112c6dfea0eSMarcel Moolenaar return (error); 113b62f75cfSJohn Baldwin error = linux_set_osrelease(req->td, osrelease); 11419e252baSAlexander Leidinger 115c6dfea0eSMarcel Moolenaar return (error); 116c6dfea0eSMarcel Moolenaar } 117c6dfea0eSMarcel Moolenaar 118c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease, 11984a8cad0SJamie Gritton CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 120c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_osrelease, "A", 121c6dfea0eSMarcel Moolenaar "Linux kernel OS release"); 122c6dfea0eSMarcel Moolenaar 123c6dfea0eSMarcel Moolenaar static int 12482d9ae4eSPoul-Henning Kamp linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS) 125c6dfea0eSMarcel Moolenaar { 126c6dfea0eSMarcel Moolenaar int oss_version; 127c6dfea0eSMarcel Moolenaar int error; 128c6dfea0eSMarcel Moolenaar 129b62f75cfSJohn Baldwin oss_version = linux_get_oss_version(req->td); 130c6dfea0eSMarcel Moolenaar error = sysctl_handle_int(oidp, &oss_version, 0, req); 13167d39748SDmitry Chagin if (error != 0 || req->newptr == NULL) 132c6dfea0eSMarcel Moolenaar return (error); 133b62f75cfSJohn Baldwin error = linux_set_oss_version(req->td, oss_version); 13419e252baSAlexander Leidinger 135c6dfea0eSMarcel Moolenaar return (error); 136c6dfea0eSMarcel Moolenaar } 137c6dfea0eSMarcel Moolenaar 138c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version, 13984a8cad0SJamie Gritton CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 140c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_oss_version, "I", 141c6dfea0eSMarcel Moolenaar "Linux OSS version"); 142c6dfea0eSMarcel Moolenaar 14301137630SRobert Watson /* 144580dd797SDmitry Chagin * Map the osrelease into integer 145580dd797SDmitry Chagin */ 146580dd797SDmitry Chagin static int 147580dd797SDmitry Chagin linux_map_osrel(char *osrelease, int *osrel) 148580dd797SDmitry Chagin { 149580dd797SDmitry Chagin char *sep, *eosrelease; 150580dd797SDmitry Chagin int len, v0, v1, v2, v; 151580dd797SDmitry Chagin 152580dd797SDmitry Chagin len = strlen(osrelease); 153580dd797SDmitry Chagin eosrelease = osrelease + len; 154580dd797SDmitry Chagin v0 = strtol(osrelease, &sep, 10); 15567d39748SDmitry Chagin if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') 156580dd797SDmitry Chagin return (EINVAL); 157580dd797SDmitry Chagin osrelease = sep + 1; 158580dd797SDmitry Chagin v1 = strtol(osrelease, &sep, 10); 15967d39748SDmitry Chagin if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') 160580dd797SDmitry Chagin return (EINVAL); 161580dd797SDmitry Chagin osrelease = sep + 1; 162580dd797SDmitry Chagin v2 = strtol(osrelease, &sep, 10); 1637a8cbc52SEdward Tomasz Napierala if (osrelease == sep || 1647a8cbc52SEdward Tomasz Napierala (sep != eosrelease && (sep + 1 >= eosrelease || *sep != '-'))) 165580dd797SDmitry Chagin return (EINVAL); 166580dd797SDmitry Chagin 16735755049SChuck Tuffli v = LINUX_KERNVER(v0, v1, v2); 16835755049SChuck Tuffli if (v < LINUX_KERNVER(1, 0, 0)) 169580dd797SDmitry Chagin return (EINVAL); 170580dd797SDmitry Chagin 171d56cf22dSJamie Gritton if (osrel != NULL) 172580dd797SDmitry Chagin *osrel = v; 17319e252baSAlexander Leidinger 174580dd797SDmitry Chagin return (0); 175580dd797SDmitry Chagin } 176580dd797SDmitry Chagin 177580dd797SDmitry Chagin /* 1780304c731SJamie Gritton * Find a prison with Linux info. 1790304c731SJamie Gritton * Return the Linux info and the (locked) prison. 18001137630SRobert Watson */ 1817ae27ff4SJamie Gritton static struct linux_prison * 1820304c731SJamie Gritton linux_find_prison(struct prison *spr, struct prison **prp) 183c6dfea0eSMarcel Moolenaar { 1847ae27ff4SJamie Gritton struct prison *pr; 1857ae27ff4SJamie Gritton struct linux_prison *lpr; 186c6dfea0eSMarcel Moolenaar 1870304c731SJamie Gritton for (pr = spr;; pr = pr->pr_parent) { 188b62f75cfSJohn Baldwin mtx_lock(&pr->pr_mtx); 1890304c731SJamie Gritton lpr = (pr == &prison0) 1900304c731SJamie Gritton ? &lprison0 1910304c731SJamie Gritton : osd_jail_get(pr, linux_osd_jail_slot); 1920304c731SJamie Gritton if (lpr != NULL) 1930304c731SJamie Gritton break; 1947ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 1950304c731SJamie Gritton } 1960304c731SJamie Gritton *prp = pr; 19719e252baSAlexander Leidinger 1987ae27ff4SJamie Gritton return (lpr); 1997ae27ff4SJamie Gritton } 2007ae27ff4SJamie Gritton 20101137630SRobert Watson /* 2020304c731SJamie Gritton * Ensure a prison has its own Linux info. If lprp is non-null, point it to 2030304c731SJamie Gritton * the Linux info and lock the prison. 2047ae27ff4SJamie Gritton */ 2057ab25e3dSJamie Gritton static void 2067ae27ff4SJamie Gritton linux_alloc_prison(struct prison *pr, struct linux_prison **lprp) 2077ae27ff4SJamie Gritton { 2080304c731SJamie Gritton struct prison *ppr; 2097ae27ff4SJamie Gritton struct linux_prison *lpr, *nlpr; 210aa90aec2SConrad Meyer void **rsv; 2117ae27ff4SJamie Gritton 2127ae27ff4SJamie Gritton /* If this prison already has Linux info, return that. */ 2130304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 2140304c731SJamie Gritton if (ppr == pr) 2157ae27ff4SJamie Gritton goto done; 2167ae27ff4SJamie Gritton /* 2177ae27ff4SJamie Gritton * Allocate a new info record. Then check again, in case something 2187ae27ff4SJamie Gritton * changed during the allocation. 21901137630SRobert Watson */ 2200304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 2217ae27ff4SJamie Gritton nlpr = malloc(sizeof(struct linux_prison), M_PRISON, M_WAITOK); 2227ab25e3dSJamie Gritton rsv = osd_reserve(linux_osd_jail_slot); 2230304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 2240304c731SJamie Gritton if (ppr == pr) { 2257ae27ff4SJamie Gritton free(nlpr, M_PRISON); 2267ab25e3dSJamie Gritton osd_free_reserved(rsv); 2277ae27ff4SJamie Gritton goto done; 22801137630SRobert Watson } 2290304c731SJamie Gritton /* Inherit the initial values from the ancestor. */ 2300304c731SJamie Gritton mtx_lock(&pr->pr_mtx); 2317ab25e3dSJamie Gritton (void)osd_jail_set_reserved(pr, linux_osd_jail_slot, rsv, nlpr); 2320304c731SJamie Gritton bcopy(lpr, nlpr, sizeof(*lpr)); 2337ae27ff4SJamie Gritton lpr = nlpr; 2340304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 2357ae27ff4SJamie Gritton done: 2367ae27ff4SJamie Gritton if (lprp != NULL) 2377ae27ff4SJamie Gritton *lprp = lpr; 2380304c731SJamie Gritton else 2390304c731SJamie Gritton mtx_unlock(&pr->pr_mtx); 2407ae27ff4SJamie Gritton } 2417ae27ff4SJamie Gritton 2427ae27ff4SJamie Gritton /* 2437ae27ff4SJamie Gritton * Jail OSD methods for Linux prison data. 2447ae27ff4SJamie Gritton */ 2457ae27ff4SJamie Gritton static int 2467ae27ff4SJamie Gritton linux_prison_create(void *obj, void *data) 2477ae27ff4SJamie Gritton { 2487ae27ff4SJamie Gritton struct prison *pr = obj; 2497ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 25067d39748SDmitry Chagin int jsys; 2517ae27ff4SJamie Gritton 25267d39748SDmitry Chagin if (vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)) == 0 && 25367d39748SDmitry Chagin jsys == JAIL_SYS_INHERIT) 2547ae27ff4SJamie Gritton return (0); 2557ae27ff4SJamie Gritton /* 2567ae27ff4SJamie Gritton * Inherit a prison's initial values from its parent 2577cbf7213SJamie Gritton * (different from JAIL_SYS_INHERIT which also inherits changes). 2587ae27ff4SJamie Gritton */ 2597ab25e3dSJamie Gritton linux_alloc_prison(pr, NULL); 2607ab25e3dSJamie Gritton return (0); 2617ae27ff4SJamie Gritton } 2627ae27ff4SJamie Gritton 2637ae27ff4SJamie Gritton static int 2647ae27ff4SJamie Gritton linux_prison_check(void *obj __unused, void *data) 2657ae27ff4SJamie Gritton { 2667ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 2677ae27ff4SJamie Gritton char *osname, *osrelease; 268d56cf22dSJamie Gritton int error, jsys, len, oss_version; 2697ae27ff4SJamie Gritton 2707ae27ff4SJamie Gritton /* Check that the parameters are correct. */ 2717cbf7213SJamie Gritton error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 2727cbf7213SJamie Gritton if (error != ENOENT) { 27367d39748SDmitry Chagin if (error != 0) 2747cbf7213SJamie Gritton return (error); 27567d39748SDmitry Chagin if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT) 2767cbf7213SJamie Gritton return (EINVAL); 2777cbf7213SJamie Gritton } 2787ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len); 2797ae27ff4SJamie Gritton if (error != ENOENT) { 28067d39748SDmitry Chagin if (error != 0) 2817ae27ff4SJamie Gritton return (error); 28267d39748SDmitry Chagin if (len == 0 || osname[len - 1] != '\0') 2837ae27ff4SJamie Gritton return (EINVAL); 2847ae27ff4SJamie Gritton if (len > LINUX_MAX_UTSNAME) { 2857ae27ff4SJamie Gritton vfs_opterror(opts, "linux.osname too long"); 2867ae27ff4SJamie Gritton return (ENAMETOOLONG); 2877ae27ff4SJamie Gritton } 2887ae27ff4SJamie Gritton } 2897ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len); 2907ae27ff4SJamie Gritton if (error != ENOENT) { 29167d39748SDmitry Chagin if (error != 0) 2927ae27ff4SJamie Gritton return (error); 29367d39748SDmitry Chagin if (len == 0 || osrelease[len - 1] != '\0') 2947ae27ff4SJamie Gritton return (EINVAL); 2957ae27ff4SJamie Gritton if (len > LINUX_MAX_UTSNAME) { 2967ae27ff4SJamie Gritton vfs_opterror(opts, "linux.osrelease too long"); 2977ae27ff4SJamie Gritton return (ENAMETOOLONG); 2987ae27ff4SJamie Gritton } 299d56cf22dSJamie Gritton error = linux_map_osrel(osrelease, NULL); 3000304c731SJamie Gritton if (error != 0) { 3010304c731SJamie Gritton vfs_opterror(opts, "linux.osrelease format error"); 3020304c731SJamie Gritton return (error); 3030304c731SJamie Gritton } 3047ae27ff4SJamie Gritton } 3057ae27ff4SJamie Gritton error = vfs_copyopt(opts, "linux.oss_version", &oss_version, 3067ae27ff4SJamie Gritton sizeof(oss_version)); 30719e252baSAlexander Leidinger 30819e252baSAlexander Leidinger if (error == ENOENT) 30919e252baSAlexander Leidinger error = 0; 31019e252baSAlexander Leidinger return (error); 3117ae27ff4SJamie Gritton } 3127ae27ff4SJamie Gritton 3137ae27ff4SJamie Gritton static int 3147ae27ff4SJamie Gritton linux_prison_set(void *obj, void *data) 3157ae27ff4SJamie Gritton { 3167ae27ff4SJamie Gritton struct linux_prison *lpr; 3177ae27ff4SJamie Gritton struct prison *pr = obj; 3187ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 3197ae27ff4SJamie Gritton char *osname, *osrelease; 3207cbf7213SJamie Gritton int error, gotversion, jsys, len, oss_version; 3217ae27ff4SJamie Gritton 3227ae27ff4SJamie Gritton /* Set the parameters, which should be correct. */ 3237cbf7213SJamie Gritton error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 3247cbf7213SJamie Gritton if (error == ENOENT) 3257cbf7213SJamie Gritton jsys = -1; 3267ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len); 3277ae27ff4SJamie Gritton if (error == ENOENT) 3287ae27ff4SJamie Gritton osname = NULL; 3297ae27ff4SJamie Gritton else 3307cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 3317ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len); 3327ae27ff4SJamie Gritton if (error == ENOENT) 3337ae27ff4SJamie Gritton osrelease = NULL; 3347ae27ff4SJamie Gritton else 3357cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 3367ae27ff4SJamie Gritton error = vfs_copyopt(opts, "linux.oss_version", &oss_version, 3377ae27ff4SJamie Gritton sizeof(oss_version)); 3387cbf7213SJamie Gritton if (error == ENOENT) 3397cbf7213SJamie Gritton gotversion = 0; 3407cbf7213SJamie Gritton else { 3417cbf7213SJamie Gritton gotversion = 1; 3427cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 3437cbf7213SJamie Gritton } 3447cbf7213SJamie Gritton switch (jsys) { 3457cbf7213SJamie Gritton case JAIL_SYS_INHERIT: 3467cbf7213SJamie Gritton /* "linux=inherit": inherit the parent's Linux info. */ 3477ae27ff4SJamie Gritton mtx_lock(&pr->pr_mtx); 3487ae27ff4SJamie Gritton osd_jail_del(pr, linux_osd_jail_slot); 3497ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 3507cbf7213SJamie Gritton break; 3517cbf7213SJamie Gritton case JAIL_SYS_NEW: 3527ae27ff4SJamie Gritton /* 3537cbf7213SJamie Gritton * "linux=new" or "linux.*": 3547ae27ff4SJamie Gritton * the prison gets its own Linux info. 3557ae27ff4SJamie Gritton */ 3567ab25e3dSJamie Gritton linux_alloc_prison(pr, &lpr); 3577ae27ff4SJamie Gritton if (osrelease) { 358d56cf22dSJamie Gritton (void)linux_map_osrel(osrelease, &lpr->pr_osrel); 3597ae27ff4SJamie Gritton strlcpy(lpr->pr_osrelease, osrelease, 3607ae27ff4SJamie Gritton LINUX_MAX_UTSNAME); 3617ae27ff4SJamie Gritton } 362580dd797SDmitry Chagin if (osname) 363580dd797SDmitry Chagin strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME); 3647ae27ff4SJamie Gritton if (gotversion) 3657ae27ff4SJamie Gritton lpr->pr_oss_version = oss_version; 3667ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 3677ae27ff4SJamie Gritton } 36819e252baSAlexander Leidinger 3697ae27ff4SJamie Gritton return (0); 3707ae27ff4SJamie Gritton } 3717ae27ff4SJamie Gritton 3727cbf7213SJamie Gritton SYSCTL_JAIL_PARAM_SYS_NODE(linux, CTLFLAG_RW, "Jail Linux parameters"); 3737ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM_STRING(_linux, osname, CTLFLAG_RW, LINUX_MAX_UTSNAME, 3747ae27ff4SJamie Gritton "Jail Linux kernel OS name"); 3757ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM_STRING(_linux, osrelease, CTLFLAG_RW, LINUX_MAX_UTSNAME, 3767ae27ff4SJamie Gritton "Jail Linux kernel OS release"); 3777ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM(_linux, oss_version, CTLTYPE_INT | CTLFLAG_RW, 3787ae27ff4SJamie Gritton "I", "Jail Linux OSS version"); 3797ae27ff4SJamie Gritton 3807ae27ff4SJamie Gritton static int 3817ae27ff4SJamie Gritton linux_prison_get(void *obj, void *data) 3827ae27ff4SJamie Gritton { 3837ae27ff4SJamie Gritton struct linux_prison *lpr; 3840304c731SJamie Gritton struct prison *ppr; 3857ae27ff4SJamie Gritton struct prison *pr = obj; 3867ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 3877ae27ff4SJamie Gritton int error, i; 3887ae27ff4SJamie Gritton 3890304c731SJamie Gritton static int version0; 3900304c731SJamie Gritton 3910304c731SJamie Gritton /* See if this prison is the one with the Linux info. */ 3920304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 3937cbf7213SJamie Gritton i = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT; 3947ae27ff4SJamie Gritton error = vfs_setopt(opts, "linux", &i, sizeof(i)); 39567d39748SDmitry Chagin if (error != 0 && error != ENOENT) 3967ae27ff4SJamie Gritton goto done; 3977cbf7213SJamie Gritton if (i) { 3987cbf7213SJamie Gritton error = vfs_setopts(opts, "linux.osname", lpr->pr_osname); 39967d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4007ae27ff4SJamie Gritton goto done; 4017cbf7213SJamie Gritton error = vfs_setopts(opts, "linux.osrelease", lpr->pr_osrelease); 40267d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4037cbf7213SJamie Gritton goto done; 4047cbf7213SJamie Gritton error = vfs_setopt(opts, "linux.oss_version", 4057cbf7213SJamie Gritton &lpr->pr_oss_version, sizeof(lpr->pr_oss_version)); 40667d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4077cbf7213SJamie Gritton goto done; 4087cbf7213SJamie Gritton } else { 4097ae27ff4SJamie Gritton /* 4100304c731SJamie Gritton * If this prison is inheriting its Linux info, report 4110304c731SJamie Gritton * empty/zero parameters. 4127ae27ff4SJamie Gritton */ 4130304c731SJamie Gritton error = vfs_setopts(opts, "linux.osname", ""); 41467d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4150304c731SJamie Gritton goto done; 4160304c731SJamie Gritton error = vfs_setopts(opts, "linux.osrelease", ""); 41767d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4180304c731SJamie Gritton goto done; 4190304c731SJamie Gritton error = vfs_setopt(opts, "linux.oss_version", &version0, 4200304c731SJamie Gritton sizeof(lpr->pr_oss_version)); 42167d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4220304c731SJamie Gritton goto done; 4237ae27ff4SJamie Gritton } 4247ae27ff4SJamie Gritton error = 0; 4257ae27ff4SJamie Gritton 4267ae27ff4SJamie Gritton done: 4270304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 42819e252baSAlexander Leidinger 4297ae27ff4SJamie Gritton return (error); 4307ae27ff4SJamie Gritton } 4317ae27ff4SJamie Gritton 4327ae27ff4SJamie Gritton static void 4337ae27ff4SJamie Gritton linux_prison_destructor(void *data) 4347ae27ff4SJamie Gritton { 4357ae27ff4SJamie Gritton 4367ae27ff4SJamie Gritton free(data, M_PRISON); 4377ae27ff4SJamie Gritton } 4387ae27ff4SJamie Gritton 4397ae27ff4SJamie Gritton void 4407ae27ff4SJamie Gritton linux_osd_jail_register(void) 4417ae27ff4SJamie Gritton { 4427ae27ff4SJamie Gritton struct prison *pr; 4437ae27ff4SJamie Gritton osd_method_t methods[PR_MAXMETHOD] = { 4447ae27ff4SJamie Gritton [PR_METHOD_CREATE] = linux_prison_create, 4457ae27ff4SJamie Gritton [PR_METHOD_GET] = linux_prison_get, 4467ae27ff4SJamie Gritton [PR_METHOD_SET] = linux_prison_set, 4477ae27ff4SJamie Gritton [PR_METHOD_CHECK] = linux_prison_check 4487ae27ff4SJamie Gritton }; 4497ae27ff4SJamie Gritton 4507ae27ff4SJamie Gritton linux_osd_jail_slot = 4517ae27ff4SJamie Gritton osd_jail_register(linux_prison_destructor, methods); 452eae594f7SEd Maste /* Copy the system Linux info to any current prisons. */ 4537ab25e3dSJamie Gritton sx_slock(&allprison_lock); 4540304c731SJamie Gritton TAILQ_FOREACH(pr, &allprison, pr_list) 4557ab25e3dSJamie Gritton linux_alloc_prison(pr, NULL); 4567ab25e3dSJamie Gritton sx_sunlock(&allprison_lock); 4577ae27ff4SJamie Gritton } 4587ae27ff4SJamie Gritton 4597ae27ff4SJamie Gritton void 4607ae27ff4SJamie Gritton linux_osd_jail_deregister(void) 4617ae27ff4SJamie Gritton { 4627ae27ff4SJamie Gritton 4637ae27ff4SJamie Gritton osd_jail_deregister(linux_osd_jail_slot); 464c6dfea0eSMarcel Moolenaar } 465c6dfea0eSMarcel Moolenaar 46601137630SRobert Watson void 467b62f75cfSJohn Baldwin linux_get_osname(struct thread *td, char *dst) 468c6dfea0eSMarcel Moolenaar { 4697ae27ff4SJamie Gritton struct prison *pr; 4707ae27ff4SJamie Gritton struct linux_prison *lpr; 471c6dfea0eSMarcel Moolenaar 4720304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 47301137630SRobert Watson bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME); 47401137630SRobert Watson mtx_unlock(&pr->pr_mtx); 4757ae27ff4SJamie Gritton } 476c6dfea0eSMarcel Moolenaar 4770d7b5e54SAlexander Leidinger static int 478b62f75cfSJohn Baldwin linux_set_osname(struct thread *td, char *osname) 479c6dfea0eSMarcel Moolenaar { 480b62f75cfSJohn Baldwin struct prison *pr; 481b62f75cfSJohn Baldwin struct linux_prison *lpr; 482c6dfea0eSMarcel Moolenaar 4830304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 4847ae27ff4SJamie Gritton strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME); 485b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 48619e252baSAlexander Leidinger 487c6dfea0eSMarcel Moolenaar return (0); 488c6dfea0eSMarcel Moolenaar } 489c6dfea0eSMarcel Moolenaar 49001137630SRobert Watson void 491b62f75cfSJohn Baldwin linux_get_osrelease(struct thread *td, char *dst) 492c6dfea0eSMarcel Moolenaar { 4937ae27ff4SJamie Gritton struct prison *pr; 49401137630SRobert Watson struct linux_prison *lpr; 495c6dfea0eSMarcel Moolenaar 4960304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 4977ae27ff4SJamie Gritton bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME); 49801137630SRobert Watson mtx_unlock(&pr->pr_mtx); 4997ae27ff4SJamie Gritton } 500c6dfea0eSMarcel Moolenaar 501c6dfea0eSMarcel Moolenaar int 502580dd797SDmitry Chagin linux_kernver(struct thread *td) 5039ce8f9bcSAlexander Leidinger { 5049ce8f9bcSAlexander Leidinger struct prison *pr; 5059ce8f9bcSAlexander Leidinger struct linux_prison *lpr; 506580dd797SDmitry Chagin int osrel; 5079ce8f9bcSAlexander Leidinger 5080304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 509580dd797SDmitry Chagin osrel = lpr->pr_osrel; 5107ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 51119e252baSAlexander Leidinger 512580dd797SDmitry Chagin return (osrel); 5139ce8f9bcSAlexander Leidinger } 5149ce8f9bcSAlexander Leidinger 5150d7b5e54SAlexander Leidinger static int 516b62f75cfSJohn Baldwin linux_set_osrelease(struct thread *td, char *osrelease) 517c6dfea0eSMarcel Moolenaar { 518b62f75cfSJohn Baldwin struct prison *pr; 519b62f75cfSJohn Baldwin struct linux_prison *lpr; 520580dd797SDmitry Chagin int error; 5219ce8f9bcSAlexander Leidinger 5220304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 523580dd797SDmitry Chagin error = linux_map_osrel(osrelease, &lpr->pr_osrel); 5240304c731SJamie Gritton if (error == 0) 5257ae27ff4SJamie Gritton strlcpy(lpr->pr_osrelease, osrelease, LINUX_MAX_UTSNAME); 526b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 52719e252baSAlexander Leidinger 528580dd797SDmitry Chagin return (error); 529580dd797SDmitry Chagin } 530c6dfea0eSMarcel Moolenaar 531c6dfea0eSMarcel Moolenaar int 532b62f75cfSJohn Baldwin linux_get_oss_version(struct thread *td) 533c6dfea0eSMarcel Moolenaar { 5347ae27ff4SJamie Gritton struct prison *pr; 5357ae27ff4SJamie Gritton struct linux_prison *lpr; 53601137630SRobert Watson int version; 53701137630SRobert Watson 5380304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 53901137630SRobert Watson version = lpr->pr_oss_version; 540b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 54119e252baSAlexander Leidinger 54201137630SRobert Watson return (version); 543c6dfea0eSMarcel Moolenaar } 544c6dfea0eSMarcel Moolenaar 5450d7b5e54SAlexander Leidinger static int 546b62f75cfSJohn Baldwin linux_set_oss_version(struct thread *td, int oss_version) 547c6dfea0eSMarcel Moolenaar { 548b62f75cfSJohn Baldwin struct prison *pr; 549b62f75cfSJohn Baldwin struct linux_prison *lpr; 550c6dfea0eSMarcel Moolenaar 5510304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 552c6dfea0eSMarcel Moolenaar lpr->pr_oss_version = oss_version; 553b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 55419e252baSAlexander Leidinger 555c6dfea0eSMarcel Moolenaar return (0); 556c6dfea0eSMarcel Moolenaar } 557