1c6dfea0eSMarcel Moolenaar /*- 2c6dfea0eSMarcel Moolenaar * Copyright (c) 1999 Marcel Moolenaar 3c6dfea0eSMarcel Moolenaar * All rights reserved. 4c6dfea0eSMarcel Moolenaar * 5c6dfea0eSMarcel Moolenaar * Redistribution and use in source and binary forms, with or without 6c6dfea0eSMarcel Moolenaar * modification, are permitted provided that the following conditions 7c6dfea0eSMarcel Moolenaar * are met: 8c6dfea0eSMarcel Moolenaar * 1. Redistributions of source code must retain the above copyright 9c6dfea0eSMarcel Moolenaar * notice, this list of conditions and the following disclaimer 10c6dfea0eSMarcel Moolenaar * in this position and unchanged. 11c6dfea0eSMarcel Moolenaar * 2. Redistributions in binary form must reproduce the above copyright 12c6dfea0eSMarcel Moolenaar * notice, this list of conditions and the following disclaimer in the 13c6dfea0eSMarcel Moolenaar * documentation and/or other materials provided with the distribution. 14c6dfea0eSMarcel Moolenaar * 3. The name of the author may not be used to endorse or promote products 15bc34729cSMarcel Moolenaar * derived from this software without specific prior written permission. 16c6dfea0eSMarcel Moolenaar * 17c6dfea0eSMarcel Moolenaar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18c6dfea0eSMarcel Moolenaar * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19c6dfea0eSMarcel Moolenaar * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20c6dfea0eSMarcel Moolenaar * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21c6dfea0eSMarcel Moolenaar * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22c6dfea0eSMarcel Moolenaar * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23c6dfea0eSMarcel Moolenaar * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24c6dfea0eSMarcel Moolenaar * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25c6dfea0eSMarcel Moolenaar * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26c6dfea0eSMarcel Moolenaar * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27c6dfea0eSMarcel Moolenaar */ 28c6dfea0eSMarcel Moolenaar 2916dbc7f2SDavid E. O'Brien #include <sys/cdefs.h> 3016dbc7f2SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3116dbc7f2SDavid E. O'Brien 32*19e252baSAlexander Leidinger #include "opt_compat.h" 33*19e252baSAlexander Leidinger #include "opt_kdtrace.h" 34*19e252baSAlexander Leidinger 35c6dfea0eSMarcel Moolenaar #include <sys/param.h> 36c6dfea0eSMarcel Moolenaar #include <sys/kernel.h> 37*19e252baSAlexander Leidinger #include <sys/sdt.h> 38c6dfea0eSMarcel Moolenaar #include <sys/systm.h> 39c6dfea0eSMarcel Moolenaar #include <sys/sysctl.h> 40c6dfea0eSMarcel Moolenaar #include <sys/proc.h> 41c6dfea0eSMarcel Moolenaar #include <sys/malloc.h> 427ae27ff4SJamie Gritton #include <sys/mount.h> 43c6dfea0eSMarcel Moolenaar #include <sys/jail.h> 4401137630SRobert Watson #include <sys/lock.h> 4501137630SRobert Watson #include <sys/mutex.h> 467ae27ff4SJamie Gritton #include <sys/sx.h> 47c6dfea0eSMarcel Moolenaar 481997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32 494af27623STim J. Robbins #include <machine/../linux32/linux.h> 501997c537SDavid E. O'Brien #else 511997c537SDavid E. O'Brien #include <machine/../linux/linux.h> 524af27623STim J. Robbins #endif 53*19e252baSAlexander Leidinger #include <compat/linux/linux_dtrace.h> 54607d46efSMarcel Moolenaar #include <compat/linux/linux_mib.h> 55c6dfea0eSMarcel Moolenaar 56*19e252baSAlexander Leidinger /* DTrace init */ 57*19e252baSAlexander Leidinger LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); 58*19e252baSAlexander Leidinger 59*19e252baSAlexander Leidinger /** 60*19e252baSAlexander Leidinger * DTrace probes in this module. 61*19e252baSAlexander Leidinger */ 62*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(mib, linux_sysctl_osname, entry); 63*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_osname, sysctl_string_error, "int"); 64*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_osname, return, "int"); 65*19e252baSAlexander Leidinger 66*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(mib, linux_sysctl_osrelease, entry); 67*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_osrelease, sysctl_string_error, "int"); 68*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_osrelease, return, "int"); 69*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(mib, linux_sysctl_oss_version, entry); 70*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_oss_version, sysctl_string_error, 71*19e252baSAlexander Leidinger "int"); 72*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_sysctl_oss_version, return, "int"); 73*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_map_osrel, entry, "char *", "int *"); 74*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_map_osrel, return, "int"); 75*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_get_prison, entry, "struct prison *", 76*19e252baSAlexander Leidinger "struct prison **"); 77*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_get_prison, return, "struct linux_prison *"); 78*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_alloc_prison, entry, "struct prison *", 79*19e252baSAlexander Leidinger "struct linux_prison **"); 80*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_alloc_prison, return, "int"); 81*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_prison_create, entry, "void *", "void *"); 82*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_create, vfs_copyopt_error, "int"); 83*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_create, return, "int"); 84*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_prison_check, entry, "void *", "void *"); 85*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_check, vfs_copyopt_error, "int"); 86*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_check, vfs_getopt_error, "int"); 87*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_check, return, "int"); 88*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_prison_set, entry, "void *", "void *"); 89*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_set, vfs_copyopt_error, "int"); 90*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_set, vfs_getopt_error, "int"); 91*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_set, return, "int"); 92*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_prison_get, entry, "void *", "void *"); 93*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_get, vfs_setopt_error, "int"); 94*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_get, vfs_setopts_error, "int"); 95*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_get, return, "int"); 96*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_prison_destructor, entry, "void *"); 97*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(mib, linux_prison_destructor, return); 98*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(mib, linux_osd_jail_register, entry); 99*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(mib, linux_osd_jail_register, return); 100*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(mib, linux_osd_jail_deregister, entry); 101*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(mib, linux_osd_jail_deregister, return); 102*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_get_osname, entry, "struct thread *", 103*19e252baSAlexander Leidinger "char *"); 104*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(mib, linux_get_osname, return); 105*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_set_osname, entry, "struct thread *", 106*19e252baSAlexander Leidinger "char *"); 107*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_set_osname, return, "int"); 108*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_get_osrelease, entry, "struct thread *", 109*19e252baSAlexander Leidinger "char *"); 110*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(mib, linux_get_osrelease, return); 111*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_kernver, entry, "struct thread *"); 112*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_kernver, return, "int"); 113*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_set_osrelease, entry, "struct thread *", 114*19e252baSAlexander Leidinger "char *"); 115*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_set_osrelease, return, "int"); 116*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_get_oss_version, entry, "struct thread *"); 117*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_get_oss_version, return, "int"); 118*19e252baSAlexander Leidinger 119*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(mib, linux_set_oss_version, entry, "struct thread *", 120*19e252baSAlexander Leidinger "int"); 121*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(mib, linux_set_oss_version, return, "int"); 122*19e252baSAlexander Leidinger 123c6dfea0eSMarcel Moolenaar struct linux_prison { 124c6dfea0eSMarcel Moolenaar char pr_osname[LINUX_MAX_UTSNAME]; 125c6dfea0eSMarcel Moolenaar char pr_osrelease[LINUX_MAX_UTSNAME]; 126c6dfea0eSMarcel Moolenaar int pr_oss_version; 127580dd797SDmitry Chagin int pr_osrel; 128c6dfea0eSMarcel Moolenaar }; 129c6dfea0eSMarcel Moolenaar 1300304c731SJamie Gritton static struct linux_prison lprison0 = { 1310304c731SJamie Gritton .pr_osname = "Linux", 1320304c731SJamie Gritton .pr_osrelease = "2.6.16", 1330304c731SJamie Gritton .pr_oss_version = 0x030600, 1340304c731SJamie Gritton .pr_osrel = 2006016 1350304c731SJamie Gritton }; 1360304c731SJamie Gritton 1377ae27ff4SJamie Gritton static unsigned linux_osd_jail_slot; 1387ae27ff4SJamie Gritton 1396472ac3dSEd Schouten static SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0, 140c6dfea0eSMarcel Moolenaar "Linux mode"); 141c6dfea0eSMarcel Moolenaar 1420d7b5e54SAlexander Leidinger static int linux_set_osname(struct thread *td, char *osname); 1430d7b5e54SAlexander Leidinger static int linux_set_osrelease(struct thread *td, char *osrelease); 1440d7b5e54SAlexander Leidinger static int linux_set_oss_version(struct thread *td, int oss_version); 1450d7b5e54SAlexander Leidinger 146c6dfea0eSMarcel Moolenaar static int 14782d9ae4eSPoul-Henning Kamp linux_sysctl_osname(SYSCTL_HANDLER_ARGS) 148c6dfea0eSMarcel Moolenaar { 149c6dfea0eSMarcel Moolenaar char osname[LINUX_MAX_UTSNAME]; 150c6dfea0eSMarcel Moolenaar int error; 151c6dfea0eSMarcel Moolenaar 152*19e252baSAlexander Leidinger LIN_SDT_PROBE0(mib, linux_sysctl_osname, entry); 153*19e252baSAlexander Leidinger 154b62f75cfSJohn Baldwin linux_get_osname(req->td, osname); 155c6dfea0eSMarcel Moolenaar error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req); 156*19e252baSAlexander Leidinger if (error != 0 || req->newptr == NULL) { 157*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_sysctl_osname, sysctl_string_error, 158*19e252baSAlexander Leidinger error); 159*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_sysctl_osname, return, error); 160c6dfea0eSMarcel Moolenaar return (error); 161*19e252baSAlexander Leidinger } 162b62f75cfSJohn Baldwin error = linux_set_osname(req->td, osname); 163*19e252baSAlexander Leidinger 164*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_sysctl_osname, return, error); 165c6dfea0eSMarcel Moolenaar return (error); 166c6dfea0eSMarcel Moolenaar } 167c6dfea0eSMarcel Moolenaar 168c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osname, 16984a8cad0SJamie Gritton CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 170c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_osname, "A", 171c6dfea0eSMarcel Moolenaar "Linux kernel OS name"); 172c6dfea0eSMarcel Moolenaar 173c6dfea0eSMarcel Moolenaar static int 17482d9ae4eSPoul-Henning Kamp linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS) 175c6dfea0eSMarcel Moolenaar { 176c6dfea0eSMarcel Moolenaar char osrelease[LINUX_MAX_UTSNAME]; 177c6dfea0eSMarcel Moolenaar int error; 178c6dfea0eSMarcel Moolenaar 179*19e252baSAlexander Leidinger LIN_SDT_PROBE0(mib, linux_sysctl_osrelease, entry); 180*19e252baSAlexander Leidinger 181b62f75cfSJohn Baldwin linux_get_osrelease(req->td, osrelease); 182c6dfea0eSMarcel Moolenaar error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req); 183*19e252baSAlexander Leidinger if (error != 0 || req->newptr == NULL) { 184*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_sysctl_osrelease, sysctl_string_error, 185*19e252baSAlexander Leidinger error); 186*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_sysctl_osrelease, return, error); 187c6dfea0eSMarcel Moolenaar return (error); 188*19e252baSAlexander Leidinger } 189b62f75cfSJohn Baldwin error = linux_set_osrelease(req->td, osrelease); 190*19e252baSAlexander Leidinger 191*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_sysctl_osrelease, return, error); 192c6dfea0eSMarcel Moolenaar return (error); 193c6dfea0eSMarcel Moolenaar } 194c6dfea0eSMarcel Moolenaar 195c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease, 19684a8cad0SJamie Gritton CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 197c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_osrelease, "A", 198c6dfea0eSMarcel Moolenaar "Linux kernel OS release"); 199c6dfea0eSMarcel Moolenaar 200c6dfea0eSMarcel Moolenaar static int 20182d9ae4eSPoul-Henning Kamp linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS) 202c6dfea0eSMarcel Moolenaar { 203c6dfea0eSMarcel Moolenaar int oss_version; 204c6dfea0eSMarcel Moolenaar int error; 205c6dfea0eSMarcel Moolenaar 206*19e252baSAlexander Leidinger LIN_SDT_PROBE0(mib, linux_sysctl_oss_version, entry); 207*19e252baSAlexander Leidinger 208b62f75cfSJohn Baldwin oss_version = linux_get_oss_version(req->td); 209c6dfea0eSMarcel Moolenaar error = sysctl_handle_int(oidp, &oss_version, 0, req); 210*19e252baSAlexander Leidinger if (error != 0 || req->newptr == NULL) { 211*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_sysctl_oss_version, 212*19e252baSAlexander Leidinger sysctl_string_error, error); 213*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_sysctl_oss_version, return, error); 214c6dfea0eSMarcel Moolenaar return (error); 215*19e252baSAlexander Leidinger } 216b62f75cfSJohn Baldwin error = linux_set_oss_version(req->td, oss_version); 217*19e252baSAlexander Leidinger 218*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_sysctl_oss_version, return, error); 219c6dfea0eSMarcel Moolenaar return (error); 220c6dfea0eSMarcel Moolenaar } 221c6dfea0eSMarcel Moolenaar 222c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version, 22384a8cad0SJamie Gritton CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 224c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_oss_version, "I", 225c6dfea0eSMarcel Moolenaar "Linux OSS version"); 226c6dfea0eSMarcel Moolenaar 22701137630SRobert Watson /* 228580dd797SDmitry Chagin * Map the osrelease into integer 229580dd797SDmitry Chagin */ 230580dd797SDmitry Chagin static int 231580dd797SDmitry Chagin linux_map_osrel(char *osrelease, int *osrel) 232580dd797SDmitry Chagin { 233580dd797SDmitry Chagin char *sep, *eosrelease; 234580dd797SDmitry Chagin int len, v0, v1, v2, v; 235580dd797SDmitry Chagin 236*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_map_osrel, entry, osrelease, osrel); 237*19e252baSAlexander Leidinger 238580dd797SDmitry Chagin len = strlen(osrelease); 239580dd797SDmitry Chagin eosrelease = osrelease + len; 240580dd797SDmitry Chagin v0 = strtol(osrelease, &sep, 10); 241*19e252baSAlexander Leidinger if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') { 242*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_map_osrel, return, EINVAL); 243580dd797SDmitry Chagin return (EINVAL); 244*19e252baSAlexander Leidinger } 245580dd797SDmitry Chagin osrelease = sep + 1; 246580dd797SDmitry Chagin v1 = strtol(osrelease, &sep, 10); 247*19e252baSAlexander Leidinger if (osrelease == sep || sep + 1 >= eosrelease || *sep != '.') { 248*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_map_osrel, return, EINVAL); 249580dd797SDmitry Chagin return (EINVAL); 250*19e252baSAlexander Leidinger } 251580dd797SDmitry Chagin osrelease = sep + 1; 252580dd797SDmitry Chagin v2 = strtol(osrelease, &sep, 10); 253*19e252baSAlexander Leidinger if (osrelease == sep || sep != eosrelease) { 254*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_map_osrel, return, EINVAL); 255580dd797SDmitry Chagin return (EINVAL); 256*19e252baSAlexander Leidinger } 257580dd797SDmitry Chagin 258580dd797SDmitry Chagin v = v0 * 1000000 + v1 * 1000 + v2; 259*19e252baSAlexander Leidinger if (v < 1000000) { 260*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_map_osrel, return, EINVAL); 261580dd797SDmitry Chagin return (EINVAL); 262*19e252baSAlexander Leidinger } 263580dd797SDmitry Chagin 264580dd797SDmitry Chagin *osrel = v; 265*19e252baSAlexander Leidinger 266*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_map_osrel, return, 0); 267580dd797SDmitry Chagin return (0); 268580dd797SDmitry Chagin } 269580dd797SDmitry Chagin 270580dd797SDmitry Chagin /* 2710304c731SJamie Gritton * Find a prison with Linux info. 2720304c731SJamie Gritton * Return the Linux info and the (locked) prison. 27301137630SRobert Watson */ 2747ae27ff4SJamie Gritton static struct linux_prison * 2750304c731SJamie Gritton linux_find_prison(struct prison *spr, struct prison **prp) 276c6dfea0eSMarcel Moolenaar { 2777ae27ff4SJamie Gritton struct prison *pr; 2787ae27ff4SJamie Gritton struct linux_prison *lpr; 279c6dfea0eSMarcel Moolenaar 280*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_get_prison, entry, spr, prp); 281*19e252baSAlexander Leidinger 2820304c731SJamie Gritton if (!linux_osd_jail_slot) 2830304c731SJamie Gritton /* In case osd_register failed. */ 2840304c731SJamie Gritton spr = &prison0; 2850304c731SJamie Gritton for (pr = spr;; pr = pr->pr_parent) { 286b62f75cfSJohn Baldwin mtx_lock(&pr->pr_mtx); 2870304c731SJamie Gritton lpr = (pr == &prison0) 2880304c731SJamie Gritton ? &lprison0 2890304c731SJamie Gritton : osd_jail_get(pr, linux_osd_jail_slot); 2900304c731SJamie Gritton if (lpr != NULL) 2910304c731SJamie Gritton break; 2927ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 2930304c731SJamie Gritton } 2940304c731SJamie Gritton *prp = pr; 295*19e252baSAlexander Leidinger 296*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_get_prison, return, lpr); 2977ae27ff4SJamie Gritton return (lpr); 2987ae27ff4SJamie Gritton } 2997ae27ff4SJamie Gritton 30001137630SRobert Watson /* 3010304c731SJamie Gritton * Ensure a prison has its own Linux info. If lprp is non-null, point it to 3020304c731SJamie Gritton * the Linux info and lock the prison. 3037ae27ff4SJamie Gritton */ 3047ae27ff4SJamie Gritton static int 3057ae27ff4SJamie Gritton linux_alloc_prison(struct prison *pr, struct linux_prison **lprp) 3067ae27ff4SJamie Gritton { 3070304c731SJamie Gritton struct prison *ppr; 3087ae27ff4SJamie Gritton struct linux_prison *lpr, *nlpr; 3097ae27ff4SJamie Gritton int error; 3107ae27ff4SJamie Gritton 311*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_alloc_prison, entry, pr, lprp); 312*19e252baSAlexander Leidinger 3137ae27ff4SJamie Gritton /* If this prison already has Linux info, return that. */ 3147ae27ff4SJamie Gritton error = 0; 3150304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 3160304c731SJamie Gritton if (ppr == pr) 3177ae27ff4SJamie Gritton goto done; 3187ae27ff4SJamie Gritton /* 3197ae27ff4SJamie Gritton * Allocate a new info record. Then check again, in case something 3207ae27ff4SJamie Gritton * changed during the allocation. 32101137630SRobert Watson */ 3220304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 3237ae27ff4SJamie Gritton nlpr = malloc(sizeof(struct linux_prison), M_PRISON, M_WAITOK); 3240304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 3250304c731SJamie Gritton if (ppr == pr) { 3267ae27ff4SJamie Gritton free(nlpr, M_PRISON); 3277ae27ff4SJamie Gritton goto done; 32801137630SRobert Watson } 3290304c731SJamie Gritton /* Inherit the initial values from the ancestor. */ 3300304c731SJamie Gritton mtx_lock(&pr->pr_mtx); 3317ae27ff4SJamie Gritton error = osd_jail_set(pr, linux_osd_jail_slot, nlpr); 3320304c731SJamie Gritton if (error == 0) { 3330304c731SJamie Gritton bcopy(lpr, nlpr, sizeof(*lpr)); 3347ae27ff4SJamie Gritton lpr = nlpr; 3350304c731SJamie Gritton } else { 3360304c731SJamie Gritton free(nlpr, M_PRISON); 3370304c731SJamie Gritton lpr = NULL; 3387ae27ff4SJamie Gritton } 3390304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 3407ae27ff4SJamie Gritton done: 3417ae27ff4SJamie Gritton if (lprp != NULL) 3427ae27ff4SJamie Gritton *lprp = lpr; 3430304c731SJamie Gritton else 3440304c731SJamie Gritton mtx_unlock(&pr->pr_mtx); 345*19e252baSAlexander Leidinger 346*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_alloc_prison, return, error); 3477ae27ff4SJamie Gritton return (error); 3487ae27ff4SJamie Gritton } 3497ae27ff4SJamie Gritton 3507ae27ff4SJamie Gritton /* 3517ae27ff4SJamie Gritton * Jail OSD methods for Linux prison data. 3527ae27ff4SJamie Gritton */ 3537ae27ff4SJamie Gritton static int 3547ae27ff4SJamie Gritton linux_prison_create(void *obj, void *data) 3557ae27ff4SJamie Gritton { 3567ae27ff4SJamie Gritton struct prison *pr = obj; 3577ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 358*19e252baSAlexander Leidinger int jsys, error; 3597ae27ff4SJamie Gritton 360*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_prison_create, entry, obj, data); 361*19e252baSAlexander Leidinger 362*19e252baSAlexander Leidinger error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 363*19e252baSAlexander Leidinger if (error != 0) { 364*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_create, vfs_copyopt_error, 365*19e252baSAlexander Leidinger error); 366*19e252baSAlexander Leidinger } else if (jsys == JAIL_SYS_INHERIT) { 367*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_create, return, 0); 3687ae27ff4SJamie Gritton return (0); 369*19e252baSAlexander Leidinger } 3707ae27ff4SJamie Gritton /* 3717ae27ff4SJamie Gritton * Inherit a prison's initial values from its parent 3727cbf7213SJamie Gritton * (different from JAIL_SYS_INHERIT which also inherits changes). 3737ae27ff4SJamie Gritton */ 374*19e252baSAlexander Leidinger error = linux_alloc_prison(pr, NULL); 375*19e252baSAlexander Leidinger 376*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_create, return, error); 377*19e252baSAlexander Leidinger return (error); 3787ae27ff4SJamie Gritton } 3797ae27ff4SJamie Gritton 3807ae27ff4SJamie Gritton static int 3817ae27ff4SJamie Gritton linux_prison_check(void *obj __unused, void *data) 3827ae27ff4SJamie Gritton { 3837ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 3847ae27ff4SJamie Gritton char *osname, *osrelease; 3857cbf7213SJamie Gritton int error, jsys, len, osrel, oss_version; 3867ae27ff4SJamie Gritton 387*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_prison_check, entry, obj, data); 388*19e252baSAlexander Leidinger 3897ae27ff4SJamie Gritton /* Check that the parameters are correct. */ 3907cbf7213SJamie Gritton error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 391*19e252baSAlexander Leidinger if (error != 0) { 392*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, vfs_copyopt_error, 393*19e252baSAlexander Leidinger error); 394*19e252baSAlexander Leidinger } 3957cbf7213SJamie Gritton if (error != ENOENT) { 396*19e252baSAlexander Leidinger if (error != 0) { 397*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, return, error); 3987cbf7213SJamie Gritton return (error); 399*19e252baSAlexander Leidinger } 400*19e252baSAlexander Leidinger if (jsys != JAIL_SYS_NEW && jsys != JAIL_SYS_INHERIT) { 401*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, return, EINVAL); 4027cbf7213SJamie Gritton return (EINVAL); 4037cbf7213SJamie Gritton } 404*19e252baSAlexander Leidinger } 4057ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len); 406*19e252baSAlexander Leidinger if (error != 0) { 407*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, vfs_getopt_error, 408*19e252baSAlexander Leidinger error); 409*19e252baSAlexander Leidinger } 4107ae27ff4SJamie Gritton if (error != ENOENT) { 411*19e252baSAlexander Leidinger if (error != 0) { 412*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, return, error); 4137ae27ff4SJamie Gritton return (error); 414*19e252baSAlexander Leidinger } 415*19e252baSAlexander Leidinger if (len == 0 || osname[len - 1] != '\0') { 416*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, return, EINVAL); 4177ae27ff4SJamie Gritton return (EINVAL); 418*19e252baSAlexander Leidinger } 4197ae27ff4SJamie Gritton if (len > LINUX_MAX_UTSNAME) { 4207ae27ff4SJamie Gritton vfs_opterror(opts, "linux.osname too long"); 421*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, return, 422*19e252baSAlexander Leidinger ENAMETOOLONG); 4237ae27ff4SJamie Gritton return (ENAMETOOLONG); 4247ae27ff4SJamie Gritton } 4257ae27ff4SJamie Gritton } 4267ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len); 427*19e252baSAlexander Leidinger if (error != 0) { 428*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, vfs_getopt_error, 429*19e252baSAlexander Leidinger error); 430*19e252baSAlexander Leidinger } 4317ae27ff4SJamie Gritton if (error != ENOENT) { 432*19e252baSAlexander Leidinger if (error != 0) { 433*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, return, error); 4347ae27ff4SJamie Gritton return (error); 435*19e252baSAlexander Leidinger } 436*19e252baSAlexander Leidinger if (len == 0 || osrelease[len - 1] != '\0') { 437*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, return, EINVAL); 4387ae27ff4SJamie Gritton return (EINVAL); 439*19e252baSAlexander Leidinger } 4407ae27ff4SJamie Gritton if (len > LINUX_MAX_UTSNAME) { 4417ae27ff4SJamie Gritton vfs_opterror(opts, "linux.osrelease too long"); 442*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, return, 443*19e252baSAlexander Leidinger ENAMETOOLONG); 4447ae27ff4SJamie Gritton return (ENAMETOOLONG); 4457ae27ff4SJamie Gritton } 4460304c731SJamie Gritton error = linux_map_osrel(osrelease, &osrel); 4470304c731SJamie Gritton if (error != 0) { 4480304c731SJamie Gritton vfs_opterror(opts, "linux.osrelease format error"); 449*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, return, error); 4500304c731SJamie Gritton return (error); 4510304c731SJamie Gritton } 4527ae27ff4SJamie Gritton } 4537ae27ff4SJamie Gritton error = vfs_copyopt(opts, "linux.oss_version", &oss_version, 4547ae27ff4SJamie Gritton sizeof(oss_version)); 455*19e252baSAlexander Leidinger if (error != 0) 456*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, vfs_copyopt_error, error); 457*19e252baSAlexander Leidinger 458*19e252baSAlexander Leidinger if (error == ENOENT) 459*19e252baSAlexander Leidinger error = 0; 460*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_check, return, error); 461*19e252baSAlexander Leidinger return (error); 4627ae27ff4SJamie Gritton } 4637ae27ff4SJamie Gritton 4647ae27ff4SJamie Gritton static int 4657ae27ff4SJamie Gritton linux_prison_set(void *obj, void *data) 4667ae27ff4SJamie Gritton { 4677ae27ff4SJamie Gritton struct linux_prison *lpr; 4687ae27ff4SJamie Gritton struct prison *pr = obj; 4697ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 4707ae27ff4SJamie Gritton char *osname, *osrelease; 4717cbf7213SJamie Gritton int error, gotversion, jsys, len, oss_version; 4727ae27ff4SJamie Gritton 473*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_prison_set, entry, obj, data); 474*19e252baSAlexander Leidinger 4757ae27ff4SJamie Gritton /* Set the parameters, which should be correct. */ 4767cbf7213SJamie Gritton error = vfs_copyopt(opts, "linux", &jsys, sizeof(jsys)); 477*19e252baSAlexander Leidinger if (error != 0) 478*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_set, vfs_copyopt_error, error); 4797cbf7213SJamie Gritton if (error == ENOENT) 4807cbf7213SJamie Gritton jsys = -1; 4817ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osname", (void **)&osname, &len); 482*19e252baSAlexander Leidinger if (error != 0) 483*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_set, vfs_getopt_error, error); 4847ae27ff4SJamie Gritton if (error == ENOENT) 4857ae27ff4SJamie Gritton osname = NULL; 4867ae27ff4SJamie Gritton else 4877cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 4887ae27ff4SJamie Gritton error = vfs_getopt(opts, "linux.osrelease", (void **)&osrelease, &len); 489*19e252baSAlexander Leidinger if (error != 0) 490*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_set, vfs_getopt_error, error); 4917ae27ff4SJamie Gritton if (error == ENOENT) 4927ae27ff4SJamie Gritton osrelease = NULL; 4937ae27ff4SJamie Gritton else 4947cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 4957ae27ff4SJamie Gritton error = vfs_copyopt(opts, "linux.oss_version", &oss_version, 4967ae27ff4SJamie Gritton sizeof(oss_version)); 497*19e252baSAlexander Leidinger if (error != 0) 498*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_set, vfs_copyopt_error, error); 4997cbf7213SJamie Gritton if (error == ENOENT) 5007cbf7213SJamie Gritton gotversion = 0; 5017cbf7213SJamie Gritton else { 5027cbf7213SJamie Gritton gotversion = 1; 5037cbf7213SJamie Gritton jsys = JAIL_SYS_NEW; 5047cbf7213SJamie Gritton } 5057cbf7213SJamie Gritton switch (jsys) { 5067cbf7213SJamie Gritton case JAIL_SYS_INHERIT: 5077cbf7213SJamie Gritton /* "linux=inherit": inherit the parent's Linux info. */ 5087ae27ff4SJamie Gritton mtx_lock(&pr->pr_mtx); 5097ae27ff4SJamie Gritton osd_jail_del(pr, linux_osd_jail_slot); 5107ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 5117cbf7213SJamie Gritton break; 5127cbf7213SJamie Gritton case JAIL_SYS_NEW: 5137ae27ff4SJamie Gritton /* 5147cbf7213SJamie Gritton * "linux=new" or "linux.*": 5157ae27ff4SJamie Gritton * the prison gets its own Linux info. 5167ae27ff4SJamie Gritton */ 5177ae27ff4SJamie Gritton error = linux_alloc_prison(pr, &lpr); 5187ae27ff4SJamie Gritton if (error) { 5197ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 520*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_set, return, error); 5217ae27ff4SJamie Gritton return (error); 5227ae27ff4SJamie Gritton } 5237ae27ff4SJamie Gritton if (osrelease) { 524580dd797SDmitry Chagin error = linux_map_osrel(osrelease, &lpr->pr_osrel); 525580dd797SDmitry Chagin if (error) { 526580dd797SDmitry Chagin mtx_unlock(&pr->pr_mtx); 527*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_set, return, 528*19e252baSAlexander Leidinger error); 529580dd797SDmitry Chagin return (error); 530580dd797SDmitry Chagin } 5317ae27ff4SJamie Gritton strlcpy(lpr->pr_osrelease, osrelease, 5327ae27ff4SJamie Gritton LINUX_MAX_UTSNAME); 5337ae27ff4SJamie Gritton } 534580dd797SDmitry Chagin if (osname) 535580dd797SDmitry Chagin strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME); 5367ae27ff4SJamie Gritton if (gotversion) 5377ae27ff4SJamie Gritton lpr->pr_oss_version = oss_version; 5387ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 5397ae27ff4SJamie Gritton } 540*19e252baSAlexander Leidinger 541*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_set, return, 0); 5427ae27ff4SJamie Gritton return (0); 5437ae27ff4SJamie Gritton } 5447ae27ff4SJamie Gritton 5457cbf7213SJamie Gritton SYSCTL_JAIL_PARAM_SYS_NODE(linux, CTLFLAG_RW, "Jail Linux parameters"); 5467ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM_STRING(_linux, osname, CTLFLAG_RW, LINUX_MAX_UTSNAME, 5477ae27ff4SJamie Gritton "Jail Linux kernel OS name"); 5487ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM_STRING(_linux, osrelease, CTLFLAG_RW, LINUX_MAX_UTSNAME, 5497ae27ff4SJamie Gritton "Jail Linux kernel OS release"); 5507ae27ff4SJamie Gritton SYSCTL_JAIL_PARAM(_linux, oss_version, CTLTYPE_INT | CTLFLAG_RW, 5517ae27ff4SJamie Gritton "I", "Jail Linux OSS version"); 5527ae27ff4SJamie Gritton 5537ae27ff4SJamie Gritton static int 5547ae27ff4SJamie Gritton linux_prison_get(void *obj, void *data) 5557ae27ff4SJamie Gritton { 5567ae27ff4SJamie Gritton struct linux_prison *lpr; 5570304c731SJamie Gritton struct prison *ppr; 5587ae27ff4SJamie Gritton struct prison *pr = obj; 5597ae27ff4SJamie Gritton struct vfsoptlist *opts = data; 5607ae27ff4SJamie Gritton int error, i; 5617ae27ff4SJamie Gritton 5620304c731SJamie Gritton static int version0; 5630304c731SJamie Gritton 564*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_prison_get, entry, obj, data); 565*19e252baSAlexander Leidinger 5660304c731SJamie Gritton /* See if this prison is the one with the Linux info. */ 5670304c731SJamie Gritton lpr = linux_find_prison(pr, &ppr); 5687cbf7213SJamie Gritton i = (ppr == pr) ? JAIL_SYS_NEW : JAIL_SYS_INHERIT; 5697ae27ff4SJamie Gritton error = vfs_setopt(opts, "linux", &i, sizeof(i)); 570*19e252baSAlexander Leidinger if (error != 0) { 571*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopt_error, error); 572*19e252baSAlexander Leidinger if (error != ENOENT) 5737ae27ff4SJamie Gritton goto done; 574*19e252baSAlexander Leidinger } 5757cbf7213SJamie Gritton if (i) { 5767cbf7213SJamie Gritton error = vfs_setopts(opts, "linux.osname", lpr->pr_osname); 577*19e252baSAlexander Leidinger if (error != 0) { 578*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopts_error, 579*19e252baSAlexander Leidinger error); 580*19e252baSAlexander Leidinger if (error != ENOENT) 5817ae27ff4SJamie Gritton goto done; 582*19e252baSAlexander Leidinger } 5837cbf7213SJamie Gritton error = vfs_setopts(opts, "linux.osrelease", lpr->pr_osrelease); 584*19e252baSAlexander Leidinger if (error != 0) { 585*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopts_error, 586*19e252baSAlexander Leidinger error); 587*19e252baSAlexander Leidinger if (error != ENOENT) 5887cbf7213SJamie Gritton goto done; 589*19e252baSAlexander Leidinger } 5907cbf7213SJamie Gritton error = vfs_setopt(opts, "linux.oss_version", 5917cbf7213SJamie Gritton &lpr->pr_oss_version, sizeof(lpr->pr_oss_version)); 592*19e252baSAlexander Leidinger if (error != 0) { 593*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopt_error, 594*19e252baSAlexander Leidinger error); 595*19e252baSAlexander Leidinger if(error != ENOENT) 5967cbf7213SJamie Gritton goto done; 597*19e252baSAlexander Leidinger } 5987cbf7213SJamie Gritton } else { 5997ae27ff4SJamie Gritton /* 6000304c731SJamie Gritton * If this prison is inheriting its Linux info, report 6010304c731SJamie Gritton * empty/zero parameters. 6027ae27ff4SJamie Gritton */ 6030304c731SJamie Gritton error = vfs_setopts(opts, "linux.osname", ""); 604*19e252baSAlexander Leidinger if (error != 0) { 605*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopts_error, 606*19e252baSAlexander Leidinger error); 607*19e252baSAlexander Leidinger if(error != ENOENT) 6080304c731SJamie Gritton goto done; 609*19e252baSAlexander Leidinger } 6100304c731SJamie Gritton error = vfs_setopts(opts, "linux.osrelease", ""); 611*19e252baSAlexander Leidinger if (error != 0) { 612*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopts_error, 613*19e252baSAlexander Leidinger error); 614*19e252baSAlexander Leidinger if(error != ENOENT) 6150304c731SJamie Gritton goto done; 616*19e252baSAlexander Leidinger } 6170304c731SJamie Gritton error = vfs_setopt(opts, "linux.oss_version", &version0, 6180304c731SJamie Gritton sizeof(lpr->pr_oss_version)); 619*19e252baSAlexander Leidinger if (error != 0) { 620*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_get, vfs_setopt_error, 621*19e252baSAlexander Leidinger error); 622*19e252baSAlexander Leidinger if(error != ENOENT) 6230304c731SJamie Gritton goto done; 6247ae27ff4SJamie Gritton } 625*19e252baSAlexander Leidinger } 6267ae27ff4SJamie Gritton error = 0; 6277ae27ff4SJamie Gritton 6287ae27ff4SJamie Gritton done: 6290304c731SJamie Gritton mtx_unlock(&ppr->pr_mtx); 630*19e252baSAlexander Leidinger 631*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_get, return, error); 6327ae27ff4SJamie Gritton return (error); 6337ae27ff4SJamie Gritton } 6347ae27ff4SJamie Gritton 6357ae27ff4SJamie Gritton static void 6367ae27ff4SJamie Gritton linux_prison_destructor(void *data) 6377ae27ff4SJamie Gritton { 6387ae27ff4SJamie Gritton 639*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_prison_destructor, entry, data); 6407ae27ff4SJamie Gritton free(data, M_PRISON); 641*19e252baSAlexander Leidinger LIN_SDT_PROBE0(mib, linux_prison_destructor, return); 6427ae27ff4SJamie Gritton } 6437ae27ff4SJamie Gritton 6447ae27ff4SJamie Gritton void 6457ae27ff4SJamie Gritton linux_osd_jail_register(void) 6467ae27ff4SJamie Gritton { 6477ae27ff4SJamie Gritton struct prison *pr; 6487ae27ff4SJamie Gritton osd_method_t methods[PR_MAXMETHOD] = { 6497ae27ff4SJamie Gritton [PR_METHOD_CREATE] = linux_prison_create, 6507ae27ff4SJamie Gritton [PR_METHOD_GET] = linux_prison_get, 6517ae27ff4SJamie Gritton [PR_METHOD_SET] = linux_prison_set, 6527ae27ff4SJamie Gritton [PR_METHOD_CHECK] = linux_prison_check 6537ae27ff4SJamie Gritton }; 6547ae27ff4SJamie Gritton 655*19e252baSAlexander Leidinger LIN_SDT_PROBE0(mib, linux_osd_jail_register, entry); 656*19e252baSAlexander Leidinger 6577ae27ff4SJamie Gritton linux_osd_jail_slot = 6587ae27ff4SJamie Gritton osd_jail_register(linux_prison_destructor, methods); 6597ae27ff4SJamie Gritton if (linux_osd_jail_slot > 0) { 6607ae27ff4SJamie Gritton /* Copy the system linux info to any current prisons. */ 6617ae27ff4SJamie Gritton sx_xlock(&allprison_lock); 6620304c731SJamie Gritton TAILQ_FOREACH(pr, &allprison, pr_list) 6637ae27ff4SJamie Gritton (void)linux_alloc_prison(pr, NULL); 6647ae27ff4SJamie Gritton sx_xunlock(&allprison_lock); 6657ae27ff4SJamie Gritton } 666*19e252baSAlexander Leidinger 667*19e252baSAlexander Leidinger LIN_SDT_PROBE0(mib, linux_osd_jail_register, return); 6687ae27ff4SJamie Gritton } 6697ae27ff4SJamie Gritton 6707ae27ff4SJamie Gritton void 6717ae27ff4SJamie Gritton linux_osd_jail_deregister(void) 6727ae27ff4SJamie Gritton { 6737ae27ff4SJamie Gritton 674*19e252baSAlexander Leidinger LIN_SDT_PROBE0(mib, linux_osd_jail_register, entry); 675*19e252baSAlexander Leidinger 6767ae27ff4SJamie Gritton if (linux_osd_jail_slot) 6777ae27ff4SJamie Gritton osd_jail_deregister(linux_osd_jail_slot); 678*19e252baSAlexander Leidinger 679*19e252baSAlexander Leidinger LIN_SDT_PROBE0(mib, linux_osd_jail_register, return); 680c6dfea0eSMarcel Moolenaar } 681c6dfea0eSMarcel Moolenaar 68201137630SRobert Watson void 683b62f75cfSJohn Baldwin linux_get_osname(struct thread *td, char *dst) 684c6dfea0eSMarcel Moolenaar { 6857ae27ff4SJamie Gritton struct prison *pr; 6867ae27ff4SJamie Gritton struct linux_prison *lpr; 687c6dfea0eSMarcel Moolenaar 688*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_get_osname, entry, td, dst); 689*19e252baSAlexander Leidinger 6900304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 69101137630SRobert Watson bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME); 69201137630SRobert Watson mtx_unlock(&pr->pr_mtx); 693*19e252baSAlexander Leidinger 694*19e252baSAlexander Leidinger LIN_SDT_PROBE0(mib, linux_get_osname, return); 6957ae27ff4SJamie Gritton } 696c6dfea0eSMarcel Moolenaar 6970d7b5e54SAlexander Leidinger static int 698b62f75cfSJohn Baldwin linux_set_osname(struct thread *td, char *osname) 699c6dfea0eSMarcel Moolenaar { 700b62f75cfSJohn Baldwin struct prison *pr; 701b62f75cfSJohn Baldwin struct linux_prison *lpr; 702c6dfea0eSMarcel Moolenaar 703*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_set_osname, entry, td, osname); 704*19e252baSAlexander Leidinger 7050304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 7067ae27ff4SJamie Gritton strlcpy(lpr->pr_osname, osname, LINUX_MAX_UTSNAME); 707b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 708*19e252baSAlexander Leidinger 709*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_set_osname, return, 0); 710c6dfea0eSMarcel Moolenaar return (0); 711c6dfea0eSMarcel Moolenaar } 712c6dfea0eSMarcel Moolenaar 71301137630SRobert Watson void 714b62f75cfSJohn Baldwin linux_get_osrelease(struct thread *td, char *dst) 715c6dfea0eSMarcel Moolenaar { 7167ae27ff4SJamie Gritton struct prison *pr; 71701137630SRobert Watson struct linux_prison *lpr; 718c6dfea0eSMarcel Moolenaar 719*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_get_osrelease, entry, td, dst); 720*19e252baSAlexander Leidinger 7210304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 7227ae27ff4SJamie Gritton bcopy(lpr->pr_osrelease, dst, LINUX_MAX_UTSNAME); 72301137630SRobert Watson mtx_unlock(&pr->pr_mtx); 724*19e252baSAlexander Leidinger 725*19e252baSAlexander Leidinger LIN_SDT_PROBE0(mib, linux_get_osrelease, return); 7267ae27ff4SJamie Gritton } 727c6dfea0eSMarcel Moolenaar 728c6dfea0eSMarcel Moolenaar int 729580dd797SDmitry Chagin linux_kernver(struct thread *td) 7309ce8f9bcSAlexander Leidinger { 7319ce8f9bcSAlexander Leidinger struct prison *pr; 7329ce8f9bcSAlexander Leidinger struct linux_prison *lpr; 733580dd797SDmitry Chagin int osrel; 7349ce8f9bcSAlexander Leidinger 735*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_kernver, entry, td); 736*19e252baSAlexander Leidinger 7370304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 738580dd797SDmitry Chagin osrel = lpr->pr_osrel; 7397ae27ff4SJamie Gritton mtx_unlock(&pr->pr_mtx); 740*19e252baSAlexander Leidinger 741*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_kernver, return, osrel); 742580dd797SDmitry Chagin return (osrel); 7439ce8f9bcSAlexander Leidinger } 7449ce8f9bcSAlexander Leidinger 7450d7b5e54SAlexander Leidinger static int 746b62f75cfSJohn Baldwin linux_set_osrelease(struct thread *td, char *osrelease) 747c6dfea0eSMarcel Moolenaar { 748b62f75cfSJohn Baldwin struct prison *pr; 749b62f75cfSJohn Baldwin struct linux_prison *lpr; 750580dd797SDmitry Chagin int error; 7519ce8f9bcSAlexander Leidinger 752*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_set_osrelease, entry, td, osrelease); 753*19e252baSAlexander Leidinger 7540304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 755580dd797SDmitry Chagin error = linux_map_osrel(osrelease, &lpr->pr_osrel); 7560304c731SJamie Gritton if (error == 0) 7577ae27ff4SJamie Gritton strlcpy(lpr->pr_osrelease, osrelease, LINUX_MAX_UTSNAME); 758b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 759*19e252baSAlexander Leidinger 760*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_set_osrelease, return, error); 761580dd797SDmitry Chagin return (error); 762580dd797SDmitry Chagin } 763c6dfea0eSMarcel Moolenaar 764c6dfea0eSMarcel Moolenaar int 765b62f75cfSJohn Baldwin linux_get_oss_version(struct thread *td) 766c6dfea0eSMarcel Moolenaar { 7677ae27ff4SJamie Gritton struct prison *pr; 7687ae27ff4SJamie Gritton struct linux_prison *lpr; 76901137630SRobert Watson int version; 77001137630SRobert Watson 771*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_get_oss_version, entry, td); 772*19e252baSAlexander Leidinger 7730304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 77401137630SRobert Watson version = lpr->pr_oss_version; 775b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 776*19e252baSAlexander Leidinger 777*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_get_oss_version, return, version); 77801137630SRobert Watson return (version); 779c6dfea0eSMarcel Moolenaar } 780c6dfea0eSMarcel Moolenaar 7810d7b5e54SAlexander Leidinger static int 782b62f75cfSJohn Baldwin linux_set_oss_version(struct thread *td, int oss_version) 783c6dfea0eSMarcel Moolenaar { 784b62f75cfSJohn Baldwin struct prison *pr; 785b62f75cfSJohn Baldwin struct linux_prison *lpr; 786c6dfea0eSMarcel Moolenaar 787*19e252baSAlexander Leidinger LIN_SDT_PROBE2(mib, linux_set_oss_version, entry, td, oss_version); 788*19e252baSAlexander Leidinger 7890304c731SJamie Gritton lpr = linux_find_prison(td->td_ucred->cr_prison, &pr); 790c6dfea0eSMarcel Moolenaar lpr->pr_oss_version = oss_version; 791b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 792*19e252baSAlexander Leidinger 793*19e252baSAlexander Leidinger LIN_SDT_PROBE1(mib, linux_set_oss_version, return, 0); 794c6dfea0eSMarcel Moolenaar return (0); 795c6dfea0eSMarcel Moolenaar } 79624593369SJonathan Lemon 7974ec3ea90SDmitry Chagin #if defined(DEBUG) || defined(KTR) 798*19e252baSAlexander Leidinger /* XXX: can be removed when every ldebug(...) and KTR stuff are removed. */ 79924593369SJonathan Lemon 80067b60513SPeter Wemm u_char linux_debug_map[howmany(LINUX_SYS_MAXSYSCALL, sizeof(u_char))]; 80124593369SJonathan Lemon 802ec0b1e67SPeter Wemm static int 80324593369SJonathan Lemon linux_debug(int syscall, int toggle, int global) 80424593369SJonathan Lemon { 80524593369SJonathan Lemon 80624593369SJonathan Lemon if (global) { 80724593369SJonathan Lemon char c = toggle ? 0 : 0xff; 80824593369SJonathan Lemon 80924593369SJonathan Lemon memset(linux_debug_map, c, sizeof(linux_debug_map)); 81024593369SJonathan Lemon return (0); 81124593369SJonathan Lemon } 81224593369SJonathan Lemon if (syscall < 0 || syscall >= LINUX_SYS_MAXSYSCALL) 81324593369SJonathan Lemon return (EINVAL); 81424593369SJonathan Lemon if (toggle) 81524593369SJonathan Lemon clrbit(linux_debug_map, syscall); 81624593369SJonathan Lemon else 81724593369SJonathan Lemon setbit(linux_debug_map, syscall); 81824593369SJonathan Lemon return (0); 81924593369SJonathan Lemon } 82024593369SJonathan Lemon 82124593369SJonathan Lemon /* 822b90faaf3SDima Dorfman * Usage: sysctl linux.debug=<syscall_nr>.<0/1> 82324593369SJonathan Lemon * 824b90faaf3SDima Dorfman * E.g.: sysctl linux.debug=21.0 82524593369SJonathan Lemon * 82624593369SJonathan Lemon * As a special case, syscall "all" will apply to all syscalls globally. 82724593369SJonathan Lemon */ 82824593369SJonathan Lemon #define LINUX_MAX_DEBUGSTR 16 82924593369SJonathan Lemon static int 83024593369SJonathan Lemon linux_sysctl_debug(SYSCTL_HANDLER_ARGS) 83124593369SJonathan Lemon { 83224593369SJonathan Lemon char value[LINUX_MAX_DEBUGSTR], *p; 83324593369SJonathan Lemon int error, sysc, toggle; 83424593369SJonathan Lemon int global = 0; 83524593369SJonathan Lemon 83624593369SJonathan Lemon value[0] = '\0'; 83724593369SJonathan Lemon error = sysctl_handle_string(oidp, value, LINUX_MAX_DEBUGSTR, req); 83824593369SJonathan Lemon if (error || req->newptr == NULL) 83924593369SJonathan Lemon return (error); 84024593369SJonathan Lemon for (p = value; *p != '\0' && *p != '.'; p++); 84124593369SJonathan Lemon if (*p == '\0') 84224593369SJonathan Lemon return (EINVAL); 84324593369SJonathan Lemon *p++ = '\0'; 84424593369SJonathan Lemon sysc = strtol(value, NULL, 0); 84524593369SJonathan Lemon toggle = strtol(p, NULL, 0); 84624593369SJonathan Lemon if (strcmp(value, "all") == 0) 84724593369SJonathan Lemon global = 1; 84824593369SJonathan Lemon error = linux_debug(sysc, toggle, global); 84924593369SJonathan Lemon return (error); 85024593369SJonathan Lemon } 85124593369SJonathan Lemon 85224593369SJonathan Lemon SYSCTL_PROC(_compat_linux, OID_AUTO, debug, 85324593369SJonathan Lemon CTLTYPE_STRING | CTLFLAG_RW, 85424593369SJonathan Lemon 0, 0, linux_sysctl_debug, "A", 85524593369SJonathan Lemon "Linux debugging control"); 85624593369SJonathan Lemon 8574ec3ea90SDmitry Chagin #endif /* DEBUG || KTR */ 858