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> 33*d8e53d94SDmitry Chagin #include <sys/lock.h> 34c6dfea0eSMarcel Moolenaar #include <sys/malloc.h> 357ae27ff4SJamie Gritton #include <sys/mount.h> 36c6dfea0eSMarcel Moolenaar #include <sys/jail.h> 37*d8e53d94SDmitry Chagin #include <sys/proc.h> 387ae27ff4SJamie Gritton #include <sys/sx.h> 39c6dfea0eSMarcel Moolenaar 40607d46efSMarcel Moolenaar #include <compat/linux/linux_mib.h> 41d825ce0aSJohn Baldwin #include <compat/linux/linux_misc.h> 42c6dfea0eSMarcel Moolenaar 43c6dfea0eSMarcel Moolenaar struct linux_prison { 44c6dfea0eSMarcel Moolenaar char pr_osname[LINUX_MAX_UTSNAME]; 45c6dfea0eSMarcel Moolenaar char pr_osrelease[LINUX_MAX_UTSNAME]; 46c6dfea0eSMarcel Moolenaar int pr_oss_version; 47580dd797SDmitry Chagin int pr_osrel; 48c6dfea0eSMarcel Moolenaar }; 49c6dfea0eSMarcel Moolenaar 500304c731SJamie Gritton static struct linux_prison lprison0 = { 510304c731SJamie Gritton .pr_osname = "Linux", 52a6326909SDmitry Chagin .pr_osrelease = LINUX_VERSION_STR, 530304c731SJamie Gritton .pr_oss_version = 0x030600, 54a6326909SDmitry Chagin .pr_osrel = LINUX_VERSION_CODE 550304c731SJamie Gritton }; 560304c731SJamie Gritton 577ae27ff4SJamie Gritton static unsigned linux_osd_jail_slot; 587ae27ff4SJamie Gritton 597029da5cSPawel Biernacki SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 607029da5cSPawel Biernacki "Linux mode"); 61c6dfea0eSMarcel Moolenaar 628ec6c4a3SAlexander Leidinger int linux_debug = 3; 63462171d9SEdward Tomasz Napierala SYSCTL_INT(_compat_linux, OID_AUTO, debug, CTLFLAG_RWTUN, 64462171d9SEdward Tomasz Napierala &linux_debug, 0, "Log warnings from linux(4); or 0 to disable"); 65462171d9SEdward Tomasz Napierala 668c5059e9SEdward Tomasz Napierala int linux_default_openfiles = 1024; 678c5059e9SEdward Tomasz Napierala SYSCTL_INT(_compat_linux, OID_AUTO, default_openfiles, CTLFLAG_RWTUN, 688c5059e9SEdward Tomasz Napierala &linux_default_openfiles, 0, 698c5059e9SEdward Tomasz Napierala "Default soft openfiles resource limit, or -1 for unlimited"); 708c5059e9SEdward Tomasz Napierala 711c34dcb5SEdward Tomasz Napierala int linux_default_stacksize = 8 * 1024 * 1024; 721c34dcb5SEdward Tomasz Napierala SYSCTL_INT(_compat_linux, OID_AUTO, default_stacksize, CTLFLAG_RWTUN, 731c34dcb5SEdward Tomasz Napierala &linux_default_stacksize, 0, 741c34dcb5SEdward Tomasz Napierala "Default soft stack size resource limit, or -1 for unlimited"); 751c34dcb5SEdward Tomasz Napierala 7654669eb7SEdward Tomasz Napierala int linux_dummy_rlimits = 0; 7754669eb7SEdward Tomasz Napierala SYSCTL_INT(_compat_linux, OID_AUTO, dummy_rlimits, CTLFLAG_RWTUN, 7854669eb7SEdward Tomasz Napierala &linux_dummy_rlimits, 0, 7954669eb7SEdward Tomasz Napierala "Return dummy values for unsupported Linux-specific rlimits"); 8054669eb7SEdward Tomasz Napierala 81da6d8ae6SEdward Tomasz Napierala int linux_ignore_ip_recverr = 1; 82da6d8ae6SEdward Tomasz Napierala SYSCTL_INT(_compat_linux, OID_AUTO, ignore_ip_recverr, CTLFLAG_RWTUN, 83da6d8ae6SEdward Tomasz Napierala &linux_ignore_ip_recverr, 0, "Ignore enabling IP_RECVERR"); 84da6d8ae6SEdward Tomasz Napierala 85b896bdb8SEdward Tomasz Napierala int linux_preserve_vstatus = 1; 862cf9eb6cSEdward Tomasz Napierala SYSCTL_INT(_compat_linux, OID_AUTO, preserve_vstatus, CTLFLAG_RWTUN, 872cf9eb6cSEdward Tomasz Napierala &linux_preserve_vstatus, 0, "Preserve VSTATUS termios(4) flag"); 882cf9eb6cSEdward Tomasz Napierala 89b4147bf6STijl Coosemans bool linux_map_sched_prio = true; 90b4147bf6STijl Coosemans SYSCTL_BOOL(_compat_linux, OID_AUTO, map_sched_prio, CTLFLAG_RDTUN, 91b4147bf6STijl Coosemans &linux_map_sched_prio, 0, "Map scheduler priorities to Linux priorities " 92b4147bf6STijl Coosemans "(not POSIX compliant)"); 93b4147bf6STijl Coosemans 94a125ed50SMateusz Guzik int linux_use_emul_path = 1; 95a125ed50SMateusz Guzik SYSCTL_INT(_compat_linux, OID_AUTO, use_emul_path, CTLFLAG_RWTUN, 96a125ed50SMateusz Guzik &linux_use_emul_path, 0, "Use linux.compat.emul_path"); 97a125ed50SMateusz Guzik 98598f6fb4SKonstantin Belousov static bool linux_setid_allowed = true; 99598f6fb4SKonstantin Belousov SYSCTL_BOOL(_compat_linux, OID_AUTO, setid_allowed, CTLFLAG_RWTUN, 100598f6fb4SKonstantin Belousov &linux_setid_allowed, 0, 101598f6fb4SKonstantin Belousov "Allow setuid/setgid on execve of Linux binary"); 102598f6fb4SKonstantin Belousov 10362b8258aSKonstantin Belousov int 104598f6fb4SKonstantin Belousov linux_setid_allowed_query(struct thread *td __unused, 105598f6fb4SKonstantin Belousov struct image_params *imgp __unused) 106598f6fb4SKonstantin Belousov { 107598f6fb4SKonstantin Belousov return (linux_setid_allowed); 108598f6fb4SKonstantin Belousov } 109598f6fb4SKonstantin Belousov 1100d7b5e54SAlexander Leidinger static int linux_set_osname(struct thread *td, char *osname); 1110d7b5e54SAlexander Leidinger static int linux_set_osrelease(struct thread *td, char *osrelease); 1120d7b5e54SAlexander Leidinger static int linux_set_oss_version(struct thread *td, int oss_version); 1130d7b5e54SAlexander Leidinger 114c6dfea0eSMarcel Moolenaar static int 11582d9ae4eSPoul-Henning Kamp linux_sysctl_osname(SYSCTL_HANDLER_ARGS) 116c6dfea0eSMarcel Moolenaar { 117c6dfea0eSMarcel Moolenaar char osname[LINUX_MAX_UTSNAME]; 118c6dfea0eSMarcel Moolenaar int error; 119c6dfea0eSMarcel Moolenaar 120b62f75cfSJohn Baldwin linux_get_osname(req->td, osname); 121c6dfea0eSMarcel Moolenaar error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req); 12267d39748SDmitry Chagin if (error != 0 || req->newptr == NULL) 123c6dfea0eSMarcel Moolenaar return (error); 124b62f75cfSJohn Baldwin error = linux_set_osname(req->td, osname); 12519e252baSAlexander Leidinger 126c6dfea0eSMarcel Moolenaar return (error); 127c6dfea0eSMarcel Moolenaar } 128c6dfea0eSMarcel Moolenaar 129c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osname, 13084a8cad0SJamie Gritton CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 131c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_osname, "A", 132c6dfea0eSMarcel Moolenaar "Linux kernel OS name"); 133c6dfea0eSMarcel Moolenaar 134c6dfea0eSMarcel Moolenaar static int 13582d9ae4eSPoul-Henning Kamp linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS) 136c6dfea0eSMarcel Moolenaar { 137c6dfea0eSMarcel Moolenaar char osrelease[LINUX_MAX_UTSNAME]; 138c6dfea0eSMarcel Moolenaar int error; 139c6dfea0eSMarcel Moolenaar 140b62f75cfSJohn Baldwin linux_get_osrelease(req->td, osrelease); 141c6dfea0eSMarcel Moolenaar error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req); 14267d39748SDmitry Chagin if (error != 0 || req->newptr == NULL) 143c6dfea0eSMarcel Moolenaar return (error); 144b62f75cfSJohn Baldwin error = linux_set_osrelease(req->td, osrelease); 14519e252baSAlexander Leidinger 146c6dfea0eSMarcel Moolenaar return (error); 147c6dfea0eSMarcel Moolenaar } 148c6dfea0eSMarcel Moolenaar 149c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease, 15084a8cad0SJamie Gritton CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 151c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_osrelease, "A", 152c6dfea0eSMarcel Moolenaar "Linux kernel OS release"); 153c6dfea0eSMarcel Moolenaar 154c6dfea0eSMarcel Moolenaar static int 15582d9ae4eSPoul-Henning Kamp linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS) 156c6dfea0eSMarcel Moolenaar { 157c6dfea0eSMarcel Moolenaar int oss_version; 158c6dfea0eSMarcel Moolenaar int error; 159c6dfea0eSMarcel Moolenaar 160b62f75cfSJohn Baldwin oss_version = linux_get_oss_version(req->td); 161c6dfea0eSMarcel Moolenaar error = sysctl_handle_int(oidp, &oss_version, 0, req); 16267d39748SDmitry Chagin if (error != 0 || req->newptr == NULL) 163c6dfea0eSMarcel Moolenaar return (error); 164b62f75cfSJohn Baldwin error = linux_set_oss_version(req->td, oss_version); 16519e252baSAlexander Leidinger 166c6dfea0eSMarcel Moolenaar return (error); 167c6dfea0eSMarcel Moolenaar } 168c6dfea0eSMarcel Moolenaar 169c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version, 17084a8cad0SJamie Gritton CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 171c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_oss_version, "I", 172c6dfea0eSMarcel Moolenaar "Linux OSS version"); 173c6dfea0eSMarcel Moolenaar 17401137630SRobert Watson /* 175580dd797SDmitry Chagin * Map the osrelease into integer 176580dd797SDmitry Chagin */ 177580dd797SDmitry Chagin static int 178580dd797SDmitry Chagin linux_map_osrel(char *osrelease, int *osrel) 179580dd797SDmitry Chagin { 180580dd797SDmitry Chagin char *sep, *eosrelease; 181580dd797SDmitry Chagin int len, v0, v1, v2, v; 182580dd797SDmitry Chagin 183580dd797SDmitry Chagin len = strlen(osrelease); 184580dd797SDmitry Chagin eosrelease = osrelease + len; 185580dd797SDmitry Chagin v0 = strtol(osrelease, &sep, 10); 18667d39748SDmitry Chagin if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') 187580dd797SDmitry Chagin return (EINVAL); 188580dd797SDmitry Chagin osrelease = sep + 1; 189580dd797SDmitry Chagin v1 = strtol(osrelease, &sep, 10); 19067d39748SDmitry Chagin if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') 191580dd797SDmitry Chagin return (EINVAL); 192580dd797SDmitry Chagin osrelease = sep + 1; 193580dd797SDmitry Chagin v2 = strtol(osrelease, &sep, 10); 1947a8cbc52SEdward Tomasz Napierala if (osrelease == sep || 1957a8cbc52SEdward Tomasz Napierala (sep != eosrelease && (sep + 1 >= eosrelease || *sep != '-'))) 196580dd797SDmitry Chagin return (EINVAL); 197580dd797SDmitry Chagin 19835755049SChuck Tuffli v = LINUX_KERNVER(v0, v1, v2); 19935755049SChuck Tuffli if (v < LINUX_KERNVER(1, 0, 0)) 200580dd797SDmitry Chagin return (EINVAL); 201580dd797SDmitry Chagin 202d56cf22dSJamie Gritton if (osrel != NULL) 203580dd797SDmitry Chagin *osrel = v; 20419e252baSAlexander Leidinger 205580dd797SDmitry Chagin return (0); 206580dd797SDmitry Chagin } 207580dd797SDmitry Chagin 208580dd797SDmitry Chagin /* 2090304c731SJamie Gritton * Find a prison with Linux info. 2100304c731SJamie Gritton * Return the Linux info and the (locked) prison. 21101137630SRobert Watson */ 2127ae27ff4SJamie Gritton static struct linux_prison * 2130304c731SJamie Gritton linux_find_prison(struct prison *spr, struct prison **prp) 214c6dfea0eSMarcel Moolenaar { 2157ae27ff4SJamie Gritton struct prison *pr; 2167ae27ff4SJamie Gritton struct linux_prison *lpr; 217c6dfea0eSMarcel Moolenaar 2180304c731SJamie Gritton for (pr = spr;; pr = pr->pr_parent) { 219b62f75cfSJohn Baldwin mtx_lock(&pr->pr_mtx); 2200304c731SJamie Gritton lpr = (pr == &prison0) 2210304c731SJamie Gritton ? &lprison0 2220304c731SJamie Gritton : osd_jail_get(pr, linux_osd_jail_slot); 2230304c731SJamie Gritton if (lpr != NULL) 2240304c731SJamie Gritton break; 2257ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 2260304c731SJamie Gritton } 2270304c731SJamie Gritton *prp = pr; 22819e252baSAlexander Leidinger 2297ae27ff4SJamie Gritton return (lpr); 2307ae27ff4SJamie Gritton } 2317ae27ff4SJamie Gritton 23201137630SRobert Watson /* 2330304c731SJamie Gritton * Ensure a prison has its own Linux info. If lprp is non-null, point it to 2340304c731SJamie Gritton * the Linux info and lock the prison. 2357ae27ff4SJamie Gritton */ 2367ab25e3dSJamie Gritton static void 2377ae27ff4SJamie Gritton linux_alloc_prison(struct prison *pr, struct linux_prison **lprp) 2387ae27ff4SJamie Gritton { 2390304c731SJamie Gritton struct prison *ppr; 2407ae27ff4SJamie Gritton struct linux_prison *lpr, *nlpr; 241aa90aec2SConrad Meyer void **rsv; 2427ae27ff4SJamie Gritton 2437ae27ff4SJamie Gritton /* If this prison already has Linux info, return that. */ 2440304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 2450304c731SJamie Gritton if (ppr == pr) 2467ae27ff4SJamie Gritton goto done; 2477ae27ff4SJamie Gritton /* 2487ae27ff4SJamie Gritton * Allocate a new info record. Then check again, in case something 2497ae27ff4SJamie Gritton * changed during the allocation. 25001137630SRobert Watson */ 2510304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 2527ae27ff4SJamie Gritton nlpr = malloc(sizeof(struct linux_prison), M_PRISON, M_WAITOK); 2537ab25e3dSJamie Gritton rsv = osd_reserve(linux_osd_jail_slot); 2540304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 2550304c731SJamie Gritton if (ppr == pr) { 2567ae27ff4SJamie Gritton free(nlpr, M_PRISON); 2577ab25e3dSJamie Gritton osd_free_reserved(rsv); 2587ae27ff4SJamie Gritton goto done; 25901137630SRobert Watson } 2600304c731SJamie Gritton /* Inherit the initial values from the ancestor. */ 2610304c731SJamie Gritton mtx_lock(&pr->pr_mtx); 2627ab25e3dSJamie Gritton (void)osd_jail_set_reserved(pr, linux_osd_jail_slot, rsv, nlpr); 2630304c731SJamie Gritton bcopy(lpr, nlpr, sizeof(*lpr)); 2647ae27ff4SJamie Gritton lpr = nlpr; 2650304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 2667ae27ff4SJamie Gritton done: 2677ae27ff4SJamie Gritton if (lprp != NULL) 2687ae27ff4SJamie Gritton *lprp = lpr; 2690304c731SJamie Gritton else 2700304c731SJamie Gritton mtx_unlock(&pr->pr_mtx); 2717ae27ff4SJamie Gritton } 2727ae27ff4SJamie Gritton 2737ae27ff4SJamie Gritton /* 2747ae27ff4SJamie Gritton * Jail OSD methods for Linux prison data. 2757ae27ff4SJamie Gritton */ 2767ae27ff4SJamie Gritton static int 2777ae27ff4SJamie Gritton linux_prison_create(void *obj, void *data) 2787ae27ff4SJamie Gritton { 2797ae27ff4SJamie Gritton struct prison *pr = obj; 2807ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 28167d39748SDmitry Chagin int jsys; 2827ae27ff4SJamie Gritton 28367d39748SDmitry Chagin if (vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)) == 0 && 28467d39748SDmitry Chagin jsys == JAIL_SYS_INHERIT) 2857ae27ff4SJamie Gritton return (0); 2867ae27ff4SJamie Gritton /* 2877ae27ff4SJamie Gritton * Inherit a prison's initial values from its parent 2887cbf7213SJamie Gritton * (different from JAIL_SYS_INHERIT which also inherits changes). 2897ae27ff4SJamie Gritton */ 2907ab25e3dSJamie Gritton linux_alloc_prison(pr, NULL); 2917ab25e3dSJamie Gritton return (0); 2927ae27ff4SJamie Gritton } 2937ae27ff4SJamie Gritton 2947ae27ff4SJamie Gritton static int 2957ae27ff4SJamie Gritton linux_prison_check(void *obj __unused, void *data) 2967ae27ff4SJamie Gritton { 2977ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 2987ae27ff4SJamie Gritton char *osname, *osrelease; 299d56cf22dSJamie Gritton int error, jsys, len, oss_version; 3007ae27ff4SJamie Gritton 3017ae27ff4SJamie Gritton /* Check that the parameters are correct. */ 3027cbf7213SJamie Gritton error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 3037cbf7213SJamie Gritton if (error != ENOENT) { 30467d39748SDmitry Chagin if (error != 0) 3057cbf7213SJamie Gritton return (error); 30667d39748SDmitry Chagin if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT) 3077cbf7213SJamie Gritton return (EINVAL); 3087cbf7213SJamie Gritton } 3097ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len); 3107ae27ff4SJamie Gritton if (error != ENOENT) { 31167d39748SDmitry Chagin if (error != 0) 3127ae27ff4SJamie Gritton return (error); 31367d39748SDmitry Chagin if (len == 0 || osname[len - 1] != '\0') 3147ae27ff4SJamie Gritton return (EINVAL); 3157ae27ff4SJamie Gritton if (len > LINUX_MAX_UTSNAME) { 3167ae27ff4SJamie Gritton vfs_opterror(opts, "linux.osname too long"); 3177ae27ff4SJamie Gritton return (ENAMETOOLONG); 3187ae27ff4SJamie Gritton } 3197ae27ff4SJamie Gritton } 3207ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len); 3217ae27ff4SJamie Gritton if (error != ENOENT) { 32267d39748SDmitry Chagin if (error != 0) 3237ae27ff4SJamie Gritton return (error); 32467d39748SDmitry Chagin if (len == 0 || osrelease[len - 1] != '\0') 3257ae27ff4SJamie Gritton return (EINVAL); 3267ae27ff4SJamie Gritton if (len > LINUX_MAX_UTSNAME) { 3277ae27ff4SJamie Gritton vfs_opterror(opts, "linux.osrelease too long"); 3287ae27ff4SJamie Gritton return (ENAMETOOLONG); 3297ae27ff4SJamie Gritton } 330d56cf22dSJamie Gritton error = linux_map_osrel(osrelease, NULL); 3310304c731SJamie Gritton if (error != 0) { 3320304c731SJamie Gritton vfs_opterror(opts, "linux.osrelease format error"); 3330304c731SJamie Gritton return (error); 3340304c731SJamie Gritton } 3357ae27ff4SJamie Gritton } 3367ae27ff4SJamie Gritton error = vfs_copyopt(opts, "linux.oss_version", &oss_version, 3377ae27ff4SJamie Gritton sizeof(oss_version)); 33819e252baSAlexander Leidinger 33919e252baSAlexander Leidinger if (error == ENOENT) 34019e252baSAlexander Leidinger error = 0; 34119e252baSAlexander Leidinger return (error); 3427ae27ff4SJamie Gritton } 3437ae27ff4SJamie Gritton 3447ae27ff4SJamie Gritton static int 3457ae27ff4SJamie Gritton linux_prison_set(void *obj, void *data) 3467ae27ff4SJamie Gritton { 3477ae27ff4SJamie Gritton struct linux_prison *lpr; 3487ae27ff4SJamie Gritton struct prison *pr = obj; 3497ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 3507ae27ff4SJamie Gritton char *osname, *osrelease; 3517cbf7213SJamie Gritton int error, gotversion, jsys, len, oss_version; 3527ae27ff4SJamie Gritton 3537ae27ff4SJamie Gritton /* Set the parameters, which should be correct. */ 3547cbf7213SJamie Gritton error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 3557cbf7213SJamie Gritton if (error == ENOENT) 3567cbf7213SJamie Gritton jsys = -1; 3577ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len); 3587ae27ff4SJamie Gritton if (error == ENOENT) 3597ae27ff4SJamie Gritton osname = NULL; 3607ae27ff4SJamie Gritton else 3617cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 3627ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len); 3637ae27ff4SJamie Gritton if (error == ENOENT) 3647ae27ff4SJamie Gritton osrelease = NULL; 3657ae27ff4SJamie Gritton else 3667cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 3677ae27ff4SJamie Gritton error = vfs_copyopt(opts, "linux.oss_version", &oss_version, 3687ae27ff4SJamie Gritton sizeof(oss_version)); 3697cbf7213SJamie Gritton if (error == ENOENT) 3707cbf7213SJamie Gritton gotversion = 0; 3717cbf7213SJamie Gritton else { 3727cbf7213SJamie Gritton gotversion = 1; 3737cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 3747cbf7213SJamie Gritton } 3757cbf7213SJamie Gritton switch (jsys) { 3767cbf7213SJamie Gritton case JAIL_SYS_INHERIT: 3777cbf7213SJamie Gritton /* "linux=inherit": inherit the parent's Linux info. */ 3787ae27ff4SJamie Gritton mtx_lock(&pr->pr_mtx); 3797ae27ff4SJamie Gritton osd_jail_del(pr, linux_osd_jail_slot); 3807ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 3817cbf7213SJamie Gritton break; 3827cbf7213SJamie Gritton case JAIL_SYS_NEW: 3837ae27ff4SJamie Gritton /* 3847cbf7213SJamie Gritton * "linux=new" or "linux.*": 3857ae27ff4SJamie Gritton * the prison gets its own Linux info. 3867ae27ff4SJamie Gritton */ 3877ab25e3dSJamie Gritton linux_alloc_prison(pr, &lpr); 3887ae27ff4SJamie Gritton if (osrelease) { 389d56cf22dSJamie Gritton (void)linux_map_osrel(osrelease, &lpr->pr_osrel); 3907ae27ff4SJamie Gritton strlcpy(lpr->pr_osrelease, osrelease, 3917ae27ff4SJamie Gritton LINUX_MAX_UTSNAME); 3927ae27ff4SJamie Gritton } 393580dd797SDmitry Chagin if (osname) 394580dd797SDmitry Chagin strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME); 3957ae27ff4SJamie Gritton if (gotversion) 3967ae27ff4SJamie Gritton lpr->pr_oss_version = oss_version; 3977ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 3987ae27ff4SJamie Gritton } 39919e252baSAlexander Leidinger 4007ae27ff4SJamie Gritton return (0); 4017ae27ff4SJamie Gritton } 4027ae27ff4SJamie Gritton 4037cbf7213SJamie Gritton SYSCTL_JAIL_PARAM_SYS_NODE(linux, CTLFLAG_RW, "Jail Linux parameters"); 4047ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM_STRING(_linux, osname, CTLFLAG_RW, LINUX_MAX_UTSNAME, 4057ae27ff4SJamie Gritton "Jail Linux kernel OS name"); 4067ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM_STRING(_linux, osrelease, CTLFLAG_RW, LINUX_MAX_UTSNAME, 4077ae27ff4SJamie Gritton "Jail Linux kernel OS release"); 4087ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM(_linux, oss_version, CTLTYPE_INT | CTLFLAG_RW, 4097ae27ff4SJamie Gritton "I", "Jail Linux OSS version"); 4107ae27ff4SJamie Gritton 4117ae27ff4SJamie Gritton static int 4127ae27ff4SJamie Gritton linux_prison_get(void *obj, void *data) 4137ae27ff4SJamie Gritton { 4147ae27ff4SJamie Gritton struct linux_prison *lpr; 4150304c731SJamie Gritton struct prison *ppr; 4167ae27ff4SJamie Gritton struct prison *pr = obj; 4177ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 4187ae27ff4SJamie Gritton int error, i; 4197ae27ff4SJamie Gritton 4200304c731SJamie Gritton static int version0; 4210304c731SJamie Gritton 4220304c731SJamie Gritton /* See if this prison is the one with the Linux info. */ 4230304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 4247cbf7213SJamie Gritton i = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT; 4257ae27ff4SJamie Gritton error = vfs_setopt(opts, "linux", &i, sizeof(i)); 42667d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4277ae27ff4SJamie Gritton goto done; 4287cbf7213SJamie Gritton if (i) { 4297cbf7213SJamie Gritton error = vfs_setopts(opts, "linux.osname", lpr->pr_osname); 43067d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4317ae27ff4SJamie Gritton goto done; 4327cbf7213SJamie Gritton error = vfs_setopts(opts, "linux.osrelease", lpr->pr_osrelease); 43367d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4347cbf7213SJamie Gritton goto done; 4357cbf7213SJamie Gritton error = vfs_setopt(opts, "linux.oss_version", 4367cbf7213SJamie Gritton &lpr->pr_oss_version, sizeof(lpr->pr_oss_version)); 43767d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4387cbf7213SJamie Gritton goto done; 4397cbf7213SJamie Gritton } else { 4407ae27ff4SJamie Gritton /* 4410304c731SJamie Gritton * If this prison is inheriting its Linux info, report 4420304c731SJamie Gritton * empty/zero parameters. 4437ae27ff4SJamie Gritton */ 4440304c731SJamie Gritton error = vfs_setopts(opts, "linux.osname", ""); 44567d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4460304c731SJamie Gritton goto done; 4470304c731SJamie Gritton error = vfs_setopts(opts, "linux.osrelease", ""); 44867d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4490304c731SJamie Gritton goto done; 4500304c731SJamie Gritton error = vfs_setopt(opts, "linux.oss_version", &version0, 4510304c731SJamie Gritton sizeof(lpr->pr_oss_version)); 45267d39748SDmitry Chagin if (error != 0 && error != ENOENT) 4530304c731SJamie Gritton goto done; 4547ae27ff4SJamie Gritton } 4557ae27ff4SJamie Gritton error = 0; 4567ae27ff4SJamie Gritton 4577ae27ff4SJamie Gritton done: 4580304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 45919e252baSAlexander Leidinger 4607ae27ff4SJamie Gritton return (error); 4617ae27ff4SJamie Gritton } 4627ae27ff4SJamie Gritton 4637ae27ff4SJamie Gritton static void 4647ae27ff4SJamie Gritton linux_prison_destructor(void *data) 4657ae27ff4SJamie Gritton { 4667ae27ff4SJamie Gritton 4677ae27ff4SJamie Gritton free(data, M_PRISON); 4687ae27ff4SJamie Gritton } 4697ae27ff4SJamie Gritton 4707ae27ff4SJamie Gritton void 4717ae27ff4SJamie Gritton linux_osd_jail_register(void) 4727ae27ff4SJamie Gritton { 4737ae27ff4SJamie Gritton struct prison *pr; 4747ae27ff4SJamie Gritton osd_method_t methods[PR_MAXMETHOD] = { 4757ae27ff4SJamie Gritton [PR_METHOD_CREATE] = linux_prison_create, 4767ae27ff4SJamie Gritton [PR_METHOD_GET] = linux_prison_get, 4777ae27ff4SJamie Gritton [PR_METHOD_SET] = linux_prison_set, 4787ae27ff4SJamie Gritton [PR_METHOD_CHECK] = linux_prison_check 4797ae27ff4SJamie Gritton }; 4807ae27ff4SJamie Gritton 4817ae27ff4SJamie Gritton linux_osd_jail_slot = 4827ae27ff4SJamie Gritton osd_jail_register(linux_prison_destructor, methods); 483eae594f7SEd Maste /* Copy the system Linux info to any current prisons. */ 4847ab25e3dSJamie Gritton sx_slock(&allprison_lock); 4850304c731SJamie Gritton TAILQ_FOREACH(pr, &allprison, pr_list) 4867ab25e3dSJamie Gritton linux_alloc_prison(pr, NULL); 4877ab25e3dSJamie Gritton sx_sunlock(&allprison_lock); 4887ae27ff4SJamie Gritton } 4897ae27ff4SJamie Gritton 4907ae27ff4SJamie Gritton void 4917ae27ff4SJamie Gritton linux_osd_jail_deregister(void) 4927ae27ff4SJamie Gritton { 4937ae27ff4SJamie Gritton 4947ae27ff4SJamie Gritton osd_jail_deregister(linux_osd_jail_slot); 495c6dfea0eSMarcel Moolenaar } 496c6dfea0eSMarcel Moolenaar 49701137630SRobert Watson void 498b62f75cfSJohn Baldwin linux_get_osname(struct thread *td, char *dst) 499c6dfea0eSMarcel Moolenaar { 5007ae27ff4SJamie Gritton struct prison *pr; 5017ae27ff4SJamie Gritton struct linux_prison *lpr; 502c6dfea0eSMarcel Moolenaar 5030304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 50401137630SRobert Watson bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME); 50501137630SRobert Watson mtx_unlock(&pr->pr_mtx); 5067ae27ff4SJamie Gritton } 507c6dfea0eSMarcel Moolenaar 5080d7b5e54SAlexander Leidinger static int 509b62f75cfSJohn Baldwin linux_set_osname(struct thread *td, char *osname) 510c6dfea0eSMarcel Moolenaar { 511b62f75cfSJohn Baldwin struct prison *pr; 512b62f75cfSJohn Baldwin struct linux_prison *lpr; 513c6dfea0eSMarcel Moolenaar 5140304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 5157ae27ff4SJamie Gritton strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME); 516b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 51719e252baSAlexander Leidinger 518c6dfea0eSMarcel Moolenaar return (0); 519c6dfea0eSMarcel Moolenaar } 520c6dfea0eSMarcel Moolenaar 52101137630SRobert Watson void 522b62f75cfSJohn Baldwin linux_get_osrelease(struct thread *td, char *dst) 523c6dfea0eSMarcel Moolenaar { 5247ae27ff4SJamie Gritton struct prison *pr; 52501137630SRobert Watson struct linux_prison *lpr; 526c6dfea0eSMarcel Moolenaar 5270304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 5287ae27ff4SJamie Gritton bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME); 52901137630SRobert Watson mtx_unlock(&pr->pr_mtx); 5307ae27ff4SJamie Gritton } 531c6dfea0eSMarcel Moolenaar 532c6dfea0eSMarcel Moolenaar int 533580dd797SDmitry Chagin linux_kernver(struct thread *td) 5349ce8f9bcSAlexander Leidinger { 5359ce8f9bcSAlexander Leidinger struct prison *pr; 5369ce8f9bcSAlexander Leidinger struct linux_prison *lpr; 537580dd797SDmitry Chagin int osrel; 5389ce8f9bcSAlexander Leidinger 5390304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 540580dd797SDmitry Chagin osrel = lpr->pr_osrel; 5417ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 54219e252baSAlexander Leidinger 543580dd797SDmitry Chagin return (osrel); 5449ce8f9bcSAlexander Leidinger } 5459ce8f9bcSAlexander Leidinger 5460d7b5e54SAlexander Leidinger static int 547b62f75cfSJohn Baldwin linux_set_osrelease(struct thread *td, char *osrelease) 548c6dfea0eSMarcel Moolenaar { 549b62f75cfSJohn Baldwin struct prison *pr; 550b62f75cfSJohn Baldwin struct linux_prison *lpr; 551580dd797SDmitry Chagin int error; 5529ce8f9bcSAlexander Leidinger 5530304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 554580dd797SDmitry Chagin error = linux_map_osrel(osrelease, &lpr->pr_osrel); 5550304c731SJamie Gritton if (error == 0) 5567ae27ff4SJamie Gritton strlcpy(lpr->pr_osrelease, osrelease, LINUX_MAX_UTSNAME); 557b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 55819e252baSAlexander Leidinger 559580dd797SDmitry Chagin return (error); 560580dd797SDmitry Chagin } 561c6dfea0eSMarcel Moolenaar 562c6dfea0eSMarcel Moolenaar int 563b62f75cfSJohn Baldwin linux_get_oss_version(struct thread *td) 564c6dfea0eSMarcel Moolenaar { 5657ae27ff4SJamie Gritton struct prison *pr; 5667ae27ff4SJamie Gritton struct linux_prison *lpr; 56701137630SRobert Watson int version; 56801137630SRobert Watson 5690304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 57001137630SRobert Watson version = lpr->pr_oss_version; 571b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 57219e252baSAlexander Leidinger 57301137630SRobert Watson return (version); 574c6dfea0eSMarcel Moolenaar } 575c6dfea0eSMarcel Moolenaar 5760d7b5e54SAlexander Leidinger static int 577b62f75cfSJohn Baldwin linux_set_oss_version(struct thread *td, int oss_version) 578c6dfea0eSMarcel Moolenaar { 579b62f75cfSJohn Baldwin struct prison *pr; 580b62f75cfSJohn Baldwin struct linux_prison *lpr; 581c6dfea0eSMarcel Moolenaar 5820304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 583c6dfea0eSMarcel Moolenaar lpr->pr_oss_version = oss_version; 584b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 58519e252baSAlexander Leidinger 586c6dfea0eSMarcel Moolenaar return (0); 587c6dfea0eSMarcel Moolenaar } 588