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 32c6dfea0eSMarcel Moolenaar #include <sys/param.h> 33c6dfea0eSMarcel Moolenaar #include <sys/kernel.h> 34c6dfea0eSMarcel Moolenaar #include <sys/systm.h> 35c6dfea0eSMarcel Moolenaar #include <sys/sysctl.h> 36c6dfea0eSMarcel Moolenaar #include <sys/proc.h> 37c6dfea0eSMarcel Moolenaar #include <sys/malloc.h> 38c6dfea0eSMarcel Moolenaar #include <sys/jail.h> 3901137630SRobert Watson #include <sys/lock.h> 4001137630SRobert Watson #include <sys/mutex.h> 41c6dfea0eSMarcel Moolenaar 42aefce619SRuslan Ermilov #include "opt_compat.h" 43aefce619SRuslan Ermilov 441997c537SDavid E. O'Brien #ifdef COMPAT_LINUX32 454af27623STim J. Robbins #include <machine/../linux32/linux.h> 461997c537SDavid E. O'Brien #else 471997c537SDavid E. O'Brien #include <machine/../linux/linux.h> 484af27623STim J. Robbins #endif 49607d46efSMarcel Moolenaar #include <compat/linux/linux_mib.h> 50c6dfea0eSMarcel Moolenaar 51c6dfea0eSMarcel Moolenaar struct linux_prison { 52c6dfea0eSMarcel Moolenaar char pr_osname[LINUX_MAX_UTSNAME]; 53c6dfea0eSMarcel Moolenaar char pr_osrelease[LINUX_MAX_UTSNAME]; 54c6dfea0eSMarcel Moolenaar int pr_oss_version; 559ce8f9bcSAlexander Leidinger int pr_use_linux26; /* flag to determine whether to use 2.6 emulation */ 56c6dfea0eSMarcel Moolenaar }; 57c6dfea0eSMarcel Moolenaar 58c6dfea0eSMarcel Moolenaar SYSCTL_NODE(_compat, OID_AUTO, linux, CTLFLAG_RW, 0, 59c6dfea0eSMarcel Moolenaar "Linux mode"); 60c6dfea0eSMarcel Moolenaar 61b62f75cfSJohn Baldwin static struct mtx osname_lock; 62b62f75cfSJohn Baldwin MTX_SYSINIT(linux_osname, &osname_lock, "linux osname", MTX_DEF); 63b62f75cfSJohn Baldwin 64c6dfea0eSMarcel Moolenaar static char linux_osname[LINUX_MAX_UTSNAME] = "Linux"; 65c6dfea0eSMarcel Moolenaar 66c6dfea0eSMarcel Moolenaar static int 6782d9ae4eSPoul-Henning Kamp linux_sysctl_osname(SYSCTL_HANDLER_ARGS) 68c6dfea0eSMarcel Moolenaar { 69c6dfea0eSMarcel Moolenaar char osname[LINUX_MAX_UTSNAME]; 70c6dfea0eSMarcel Moolenaar int error; 71c6dfea0eSMarcel Moolenaar 72b62f75cfSJohn Baldwin linux_get_osname(req->td, osname); 73c6dfea0eSMarcel Moolenaar error = sysctl_handle_string(oidp, osname, LINUX_MAX_UTSNAME, req); 74c6dfea0eSMarcel Moolenaar if (error || req->newptr == NULL) 75c6dfea0eSMarcel Moolenaar return (error); 76b62f75cfSJohn Baldwin error = linux_set_osname(req->td, osname); 77c6dfea0eSMarcel Moolenaar return (error); 78c6dfea0eSMarcel Moolenaar } 79c6dfea0eSMarcel Moolenaar 80c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osname, 8184a8cad0SJamie Gritton CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 82c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_osname, "A", 83c6dfea0eSMarcel Moolenaar "Linux kernel OS name"); 84c6dfea0eSMarcel Moolenaar 85a47444d5SRoman Divacky static char linux_osrelease[LINUX_MAX_UTSNAME] = "2.6.16"; 86a47444d5SRoman Divacky static int linux_use_linux26 = 1; 87c6dfea0eSMarcel Moolenaar 88c6dfea0eSMarcel Moolenaar static int 8982d9ae4eSPoul-Henning Kamp linux_sysctl_osrelease(SYSCTL_HANDLER_ARGS) 90c6dfea0eSMarcel Moolenaar { 91c6dfea0eSMarcel Moolenaar char osrelease[LINUX_MAX_UTSNAME]; 92c6dfea0eSMarcel Moolenaar int error; 93c6dfea0eSMarcel Moolenaar 94b62f75cfSJohn Baldwin linux_get_osrelease(req->td, osrelease); 95c6dfea0eSMarcel Moolenaar error = sysctl_handle_string(oidp, osrelease, LINUX_MAX_UTSNAME, req); 96c6dfea0eSMarcel Moolenaar if (error || req->newptr == NULL) 97c6dfea0eSMarcel Moolenaar return (error); 98b62f75cfSJohn Baldwin error = linux_set_osrelease(req->td, osrelease); 99c6dfea0eSMarcel Moolenaar return (error); 100c6dfea0eSMarcel Moolenaar } 101c6dfea0eSMarcel Moolenaar 102c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, osrelease, 10384a8cad0SJamie Gritton CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 104c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_osrelease, "A", 105c6dfea0eSMarcel Moolenaar "Linux kernel OS release"); 106c6dfea0eSMarcel Moolenaar 107c6dfea0eSMarcel Moolenaar static int linux_oss_version = 0x030600; 108c6dfea0eSMarcel Moolenaar 109c6dfea0eSMarcel Moolenaar static int 11082d9ae4eSPoul-Henning Kamp linux_sysctl_oss_version(SYSCTL_HANDLER_ARGS) 111c6dfea0eSMarcel Moolenaar { 112c6dfea0eSMarcel Moolenaar int oss_version; 113c6dfea0eSMarcel Moolenaar int error; 114c6dfea0eSMarcel Moolenaar 115b62f75cfSJohn Baldwin oss_version = linux_get_oss_version(req->td); 116c6dfea0eSMarcel Moolenaar error = sysctl_handle_int(oidp, &oss_version, 0, req); 117c6dfea0eSMarcel Moolenaar if (error || req->newptr == NULL) 118c6dfea0eSMarcel Moolenaar return (error); 119b62f75cfSJohn Baldwin error = linux_set_oss_version(req->td, oss_version); 120c6dfea0eSMarcel Moolenaar return (error); 121c6dfea0eSMarcel Moolenaar } 122c6dfea0eSMarcel Moolenaar 123c6dfea0eSMarcel Moolenaar SYSCTL_PROC(_compat_linux, OID_AUTO, oss_version, 12484a8cad0SJamie Gritton CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_PRISON | CTLFLAG_MPSAFE, 125c6dfea0eSMarcel Moolenaar 0, 0, linux_sysctl_oss_version, "I", 126c6dfea0eSMarcel Moolenaar "Linux OSS version"); 127c6dfea0eSMarcel Moolenaar 12801137630SRobert Watson /* 12901137630SRobert Watson * Returns holding the prison mutex if return non-NULL. 13001137630SRobert Watson */ 131b62f75cfSJohn Baldwin static struct prison * 132b62f75cfSJohn Baldwin linux_get_prison(struct thread *td) 133c6dfea0eSMarcel Moolenaar { 134c6dfea0eSMarcel Moolenaar register struct prison *pr; 135c6dfea0eSMarcel Moolenaar register struct linux_prison *lpr; 136c6dfea0eSMarcel Moolenaar 137b62f75cfSJohn Baldwin KASSERT(td == curthread, ("linux_get_prison() called on !curthread")); 138b62f75cfSJohn Baldwin if (!jailed(td->td_ucred)) 139c6dfea0eSMarcel Moolenaar return (NULL); 140b62f75cfSJohn Baldwin pr = td->td_ucred->cr_prison; 141b62f75cfSJohn Baldwin mtx_lock(&pr->pr_mtx); 142b62f75cfSJohn Baldwin if (pr->pr_linux == NULL) { 14301137630SRobert Watson /* 144b62f75cfSJohn Baldwin * If we don't have a linux prison structure yet, allocate 145b62f75cfSJohn Baldwin * one. We have to handle the race where another thread 146b62f75cfSJohn Baldwin * could be adding a linux prison to this process already. 14701137630SRobert Watson */ 14801137630SRobert Watson mtx_unlock(&pr->pr_mtx); 149b62f75cfSJohn Baldwin lpr = malloc(sizeof(struct linux_prison), M_PRISON, 150b62f75cfSJohn Baldwin M_WAITOK | M_ZERO); 15101137630SRobert Watson mtx_lock(&pr->pr_mtx); 152b62f75cfSJohn Baldwin if (pr->pr_linux == NULL) 153c6dfea0eSMarcel Moolenaar pr->pr_linux = lpr; 154b62f75cfSJohn Baldwin else 155b62f75cfSJohn Baldwin free(lpr, M_PRISON); 15601137630SRobert Watson } 157b62f75cfSJohn Baldwin return (pr); 158c6dfea0eSMarcel Moolenaar } 159c6dfea0eSMarcel Moolenaar 16001137630SRobert Watson void 161b62f75cfSJohn Baldwin linux_get_osname(struct thread *td, char *dst) 162c6dfea0eSMarcel Moolenaar { 163c6dfea0eSMarcel Moolenaar register struct prison *pr; 164c6dfea0eSMarcel Moolenaar register struct linux_prison *lpr; 165c6dfea0eSMarcel Moolenaar 166b62f75cfSJohn Baldwin pr = td->td_ucred->cr_prison; 167b62f75cfSJohn Baldwin if (pr != NULL) { 16801137630SRobert Watson mtx_lock(&pr->pr_mtx); 16901137630SRobert Watson if (pr->pr_linux != NULL) { 17001137630SRobert Watson lpr = (struct linux_prison *)pr->pr_linux; 17101137630SRobert Watson if (lpr->pr_osname[0]) { 17201137630SRobert Watson bcopy(lpr->pr_osname, dst, LINUX_MAX_UTSNAME); 17301137630SRobert Watson mtx_unlock(&pr->pr_mtx); 17401137630SRobert Watson return; 17501137630SRobert Watson } 17601137630SRobert Watson } 17701137630SRobert Watson mtx_unlock(&pr->pr_mtx); 178b62f75cfSJohn Baldwin } 179b62f75cfSJohn Baldwin 180b62f75cfSJohn Baldwin mtx_lock(&osname_lock); 18101137630SRobert Watson bcopy(linux_osname, dst, LINUX_MAX_UTSNAME); 182b62f75cfSJohn Baldwin mtx_unlock(&osname_lock); 183c6dfea0eSMarcel Moolenaar } 184c6dfea0eSMarcel Moolenaar 185c6dfea0eSMarcel Moolenaar int 186b62f75cfSJohn Baldwin linux_set_osname(struct thread *td, char *osname) 187c6dfea0eSMarcel Moolenaar { 188b62f75cfSJohn Baldwin struct prison *pr; 189b62f75cfSJohn Baldwin struct linux_prison *lpr; 190c6dfea0eSMarcel Moolenaar 191b62f75cfSJohn Baldwin pr = linux_get_prison(td); 192b62f75cfSJohn Baldwin if (pr != NULL) { 193b62f75cfSJohn Baldwin lpr = (struct linux_prison *)pr->pr_linux; 194c6dfea0eSMarcel Moolenaar strcpy(lpr->pr_osname, osname); 195b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 19601137630SRobert Watson } else { 197b62f75cfSJohn Baldwin mtx_lock(&osname_lock); 198c6dfea0eSMarcel Moolenaar strcpy(linux_osname, osname); 199b62f75cfSJohn Baldwin mtx_unlock(&osname_lock); 20001137630SRobert Watson } 201c6dfea0eSMarcel Moolenaar 202c6dfea0eSMarcel Moolenaar return (0); 203c6dfea0eSMarcel Moolenaar } 204c6dfea0eSMarcel Moolenaar 20501137630SRobert Watson void 206b62f75cfSJohn Baldwin linux_get_osrelease(struct thread *td, char *dst) 207c6dfea0eSMarcel Moolenaar { 208c6dfea0eSMarcel Moolenaar register struct prison *pr; 20901137630SRobert Watson struct linux_prison *lpr; 210c6dfea0eSMarcel Moolenaar 211b62f75cfSJohn Baldwin pr = td->td_ucred->cr_prison; 212b62f75cfSJohn Baldwin if (pr != NULL) { 21301137630SRobert Watson mtx_lock(&pr->pr_mtx); 21401137630SRobert Watson if (pr->pr_linux != NULL) { 21501137630SRobert Watson lpr = (struct linux_prison *)pr->pr_linux; 21601137630SRobert Watson if (lpr->pr_osrelease[0]) { 217b62f75cfSJohn Baldwin bcopy(lpr->pr_osrelease, dst, 218b62f75cfSJohn Baldwin LINUX_MAX_UTSNAME); 21901137630SRobert Watson mtx_unlock(&pr->pr_mtx); 22001137630SRobert Watson return; 22101137630SRobert Watson } 22201137630SRobert Watson } 22301137630SRobert Watson mtx_unlock(&pr->pr_mtx); 224b62f75cfSJohn Baldwin } 225b62f75cfSJohn Baldwin 226b62f75cfSJohn Baldwin mtx_lock(&osname_lock); 22701137630SRobert Watson bcopy(linux_osrelease, dst, LINUX_MAX_UTSNAME); 228b62f75cfSJohn Baldwin mtx_unlock(&osname_lock); 229c6dfea0eSMarcel Moolenaar } 230c6dfea0eSMarcel Moolenaar 231c6dfea0eSMarcel Moolenaar int 2329ce8f9bcSAlexander Leidinger linux_use26(struct thread *td) 2339ce8f9bcSAlexander Leidinger { 2349ce8f9bcSAlexander Leidinger struct prison *pr; 2359ce8f9bcSAlexander Leidinger struct linux_prison *lpr; 23631becc76SAlexander Leidinger int use26 = linux_use_linux26; 2379ce8f9bcSAlexander Leidinger 2389ce8f9bcSAlexander Leidinger pr = td->td_ucred->cr_prison; 2399ce8f9bcSAlexander Leidinger if (pr != NULL) { 2409ce8f9bcSAlexander Leidinger if (pr->pr_linux != NULL) { 2419ce8f9bcSAlexander Leidinger lpr = (struct linux_prison *)pr->pr_linux; 2429ce8f9bcSAlexander Leidinger use26 = lpr->pr_use_linux26; 2439ce8f9bcSAlexander Leidinger } 24431becc76SAlexander Leidinger } 2459ce8f9bcSAlexander Leidinger 2469ce8f9bcSAlexander Leidinger return (use26); 2479ce8f9bcSAlexander Leidinger } 2489ce8f9bcSAlexander Leidinger 2499ce8f9bcSAlexander Leidinger int 250b62f75cfSJohn Baldwin linux_set_osrelease(struct thread *td, char *osrelease) 251c6dfea0eSMarcel Moolenaar { 252b62f75cfSJohn Baldwin struct prison *pr; 253b62f75cfSJohn Baldwin struct linux_prison *lpr; 2549ce8f9bcSAlexander Leidinger int use26; 2559ce8f9bcSAlexander Leidinger 2569ce8f9bcSAlexander Leidinger use26 = (strlen(osrelease) >= 3 && osrelease[2] == '6'); 257c6dfea0eSMarcel Moolenaar 258b62f75cfSJohn Baldwin pr = linux_get_prison(td); 259b62f75cfSJohn Baldwin if (pr != NULL) { 260b62f75cfSJohn Baldwin lpr = (struct linux_prison *)pr->pr_linux; 261c6dfea0eSMarcel Moolenaar strcpy(lpr->pr_osrelease, osrelease); 2629ce8f9bcSAlexander Leidinger lpr->pr_use_linux26 = use26; 263b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 26401137630SRobert Watson } else { 265b62f75cfSJohn Baldwin mtx_lock(&osname_lock); 266c6dfea0eSMarcel Moolenaar strcpy(linux_osrelease, osrelease); 2679ce8f9bcSAlexander Leidinger linux_use_linux26 = use26; 268b62f75cfSJohn Baldwin mtx_unlock(&osname_lock); 26901137630SRobert Watson } 270c6dfea0eSMarcel Moolenaar 271c6dfea0eSMarcel Moolenaar return (0); 272c6dfea0eSMarcel Moolenaar } 273c6dfea0eSMarcel Moolenaar 274c6dfea0eSMarcel Moolenaar int 275b62f75cfSJohn Baldwin linux_get_oss_version(struct thread *td) 276c6dfea0eSMarcel Moolenaar { 277c6dfea0eSMarcel Moolenaar register struct prison *pr; 278c6dfea0eSMarcel Moolenaar register struct linux_prison *lpr; 27901137630SRobert Watson int version; 28001137630SRobert Watson 281b62f75cfSJohn Baldwin pr = td->td_ucred->cr_prison; 282b62f75cfSJohn Baldwin if (pr != NULL) { 28301137630SRobert Watson mtx_lock(&pr->pr_mtx); 28401137630SRobert Watson if (pr->pr_linux != NULL) { 28501137630SRobert Watson lpr = (struct linux_prison *)pr->pr_linux; 28601137630SRobert Watson if (lpr->pr_oss_version) { 28701137630SRobert Watson version = lpr->pr_oss_version; 288b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 289b62f75cfSJohn Baldwin return (version); 29001137630SRobert Watson } 29101137630SRobert Watson } 29201137630SRobert Watson mtx_unlock(&pr->pr_mtx); 293b62f75cfSJohn Baldwin } 29401137630SRobert Watson 295b62f75cfSJohn Baldwin mtx_lock(&osname_lock); 296b62f75cfSJohn Baldwin version = linux_oss_version; 297b62f75cfSJohn Baldwin mtx_unlock(&osname_lock); 29801137630SRobert Watson return (version); 299c6dfea0eSMarcel Moolenaar } 300c6dfea0eSMarcel Moolenaar 301c6dfea0eSMarcel Moolenaar int 302b62f75cfSJohn Baldwin linux_set_oss_version(struct thread *td, int oss_version) 303c6dfea0eSMarcel Moolenaar { 304b62f75cfSJohn Baldwin struct prison *pr; 305b62f75cfSJohn Baldwin struct linux_prison *lpr; 306c6dfea0eSMarcel Moolenaar 307b62f75cfSJohn Baldwin pr = linux_get_prison(td); 308b62f75cfSJohn Baldwin if (pr != NULL) { 309b62f75cfSJohn Baldwin lpr = (struct linux_prison *)pr->pr_linux; 310c6dfea0eSMarcel Moolenaar lpr->pr_oss_version = oss_version; 311b62f75cfSJohn Baldwin mtx_unlock(&pr->pr_mtx); 31201137630SRobert Watson } else { 313b62f75cfSJohn Baldwin mtx_lock(&osname_lock); 314c6dfea0eSMarcel Moolenaar linux_oss_version = oss_version; 315b62f75cfSJohn Baldwin mtx_unlock(&osname_lock); 31601137630SRobert Watson } 317c6dfea0eSMarcel Moolenaar 318c6dfea0eSMarcel Moolenaar return (0); 319c6dfea0eSMarcel Moolenaar } 32024593369SJonathan Lemon 32124593369SJonathan Lemon #ifdef DEBUG 32224593369SJonathan Lemon 32367b60513SPeter Wemm u_char linux_debug_map[howmany(LINUX_SYS_MAXSYSCALL, sizeof(u_char))]; 32424593369SJonathan Lemon 325ec0b1e67SPeter Wemm static int 32624593369SJonathan Lemon linux_debug(int syscall, int toggle, int global) 32724593369SJonathan Lemon { 32824593369SJonathan Lemon 32924593369SJonathan Lemon if (global) { 33024593369SJonathan Lemon char c = toggle ? 0 : 0xff; 33124593369SJonathan Lemon 33224593369SJonathan Lemon memset(linux_debug_map, c, sizeof(linux_debug_map)); 33324593369SJonathan Lemon return (0); 33424593369SJonathan Lemon } 33524593369SJonathan Lemon if (syscall < 0 || syscall >= LINUX_SYS_MAXSYSCALL) 33624593369SJonathan Lemon return (EINVAL); 33724593369SJonathan Lemon if (toggle) 33824593369SJonathan Lemon clrbit(linux_debug_map, syscall); 33924593369SJonathan Lemon else 34024593369SJonathan Lemon setbit(linux_debug_map, syscall); 34124593369SJonathan Lemon return (0); 34224593369SJonathan Lemon } 34324593369SJonathan Lemon 34424593369SJonathan Lemon /* 345b90faaf3SDima Dorfman * Usage: sysctl linux.debug=<syscall_nr>.<0/1> 34624593369SJonathan Lemon * 347b90faaf3SDima Dorfman * E.g.: sysctl linux.debug=21.0 34824593369SJonathan Lemon * 34924593369SJonathan Lemon * As a special case, syscall "all" will apply to all syscalls globally. 35024593369SJonathan Lemon */ 35124593369SJonathan Lemon #define LINUX_MAX_DEBUGSTR 16 35224593369SJonathan Lemon static int 35324593369SJonathan Lemon linux_sysctl_debug(SYSCTL_HANDLER_ARGS) 35424593369SJonathan Lemon { 35524593369SJonathan Lemon char value[LINUX_MAX_DEBUGSTR], *p; 35624593369SJonathan Lemon int error, sysc, toggle; 35724593369SJonathan Lemon int global = 0; 35824593369SJonathan Lemon 35924593369SJonathan Lemon value[0] = '\0'; 36024593369SJonathan Lemon error = sysctl_handle_string(oidp, value, LINUX_MAX_DEBUGSTR, req); 36124593369SJonathan Lemon if (error || req->newptr == NULL) 36224593369SJonathan Lemon return (error); 36324593369SJonathan Lemon for (p = value; *p != '\0' && *p != '.'; p++); 36424593369SJonathan Lemon if (*p == '\0') 36524593369SJonathan Lemon return (EINVAL); 36624593369SJonathan Lemon *p++ = '\0'; 36724593369SJonathan Lemon sysc = strtol(value, NULL, 0); 36824593369SJonathan Lemon toggle = strtol(p, NULL, 0); 36924593369SJonathan Lemon if (strcmp(value, "all") == 0) 37024593369SJonathan Lemon global = 1; 37124593369SJonathan Lemon error = linux_debug(sysc, toggle, global); 37224593369SJonathan Lemon return (error); 37324593369SJonathan Lemon } 37424593369SJonathan Lemon 37524593369SJonathan Lemon SYSCTL_PROC(_compat_linux, OID_AUTO, debug, 37624593369SJonathan Lemon CTLTYPE_STRING | CTLFLAG_RW, 37724593369SJonathan Lemon 0, 0, linux_sysctl_debug, "A", 37824593369SJonathan Lemon "Linux debugging control"); 37924593369SJonathan Lemon 38024593369SJonathan Lemon #endif /* DEBUG */ 381