Index: lib/libc/gen/sysctlbyname.c =================================================================== --- lib/libc/gen/sysctlbyname.c +++ lib/libc/gen/sysctlbyname.c @@ -1,11 +1,29 @@ -/* - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright 2019 Pawel Biernacki, Mysterious Code Ltd. * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include @@ -13,16 +31,17 @@ #include #include +#include +extern int __sysctlbyname(const char *name, size_t namelen, void *oldp, + size_t *oldlenp, const void *newp, size_t newlen); + int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, const void *newp, size_t newlen) { - int real_oid[CTL_MAXNAME+2]; - size_t oidlen; + size_t namelen; - oidlen = sizeof(real_oid) / sizeof(int); - if (sysctlnametomib(name, real_oid, &oidlen) < 0) - return (-1); - return (sysctl(real_oid, oidlen, oldp, oldlenp, newp, newlen)); + namelen = strlen(name); + return (__sysctlbyname(name, namelen, oldp, oldlenp, newp, newlen)); } Index: sys/compat/freebsd32/freebsd32_misc.c =================================================================== --- sys/compat/freebsd32/freebsd32_misc.c +++ sys/compat/freebsd32/freebsd32_misc.c @@ -121,6 +121,8 @@ FEATURE(compat_freebsd_32bit, "Compatible with 32-bit FreeBSD"); +MALLOC_DECLARE(M_SYSCTL); + #ifdef __amd64__ CTASSERT(sizeof(struct timeval32) == 8); CTASSERT(sizeof(struct timespec32) == 8); @@ -2256,6 +2258,59 @@ } int +freebsd32___sysctlbyname(struct thread *td, struct + freebsd32___sysctlbyname_args *uap) +{ + int oid[CTL_MAXNAME]; +#define NAMEBUFLEN 16 + char namebuf[NAMEBUFLEN]; + char *name; + size_t namelen, oidlen, oldlen, rv; + int error; + uint32_t tmp; + + namelen = uap->namelen; + if (namelen > MAXPATHLEN || namelen == 0) + return (EINVAL); + + name = namebuf; + if (namelen > NAMEBUFLEN) + name = malloc(namelen, M_SYSCTL, M_WAITOK); + error = copyin(uap->name, name, namelen); + if (error != 0) + goto out; + + oid[0] = 0; + oid[1] = 3; + oidlen = sizeof(oid); + error = kernel_sysctl(td, oid, 2, oid, &oidlen, (void *)name, namelen, + &rv, 0); + if (error != 0) + goto out; + + if (uap->oldlenp != NULL) { + error = fueword32(uap->oldlenp, &tmp); + oldlen = tmp; + } else { + oldlen = 0; + } + if (error != 0) + goto out; + error = userland_sysctl(td, oid, rv / sizeof(int), uap->old, + &oldlen, 1, (void *)uap->new, uap->newlen, &rv, 0); + if (error != 0) + goto out; + if (uap->oldlenp != NULL) + suword32(uap->oldlenp, rv); + +out: + if (namelen > NAMEBUFLEN) + free(name, M_SYSCTL); + return (error); +#undef NAMEBUF +} + +int freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap) { uint32_t version; Index: sys/compat/freebsd32/syscalls.master =================================================================== --- sys/compat/freebsd32/syscalls.master +++ sys/compat/freebsd32/syscalls.master @@ -1150,5 +1150,8 @@ 569 AUE_NULL NOPROTO { ssize_t copy_file_range(int infd, \ off_t *inoffp, int outfd, off_t *outoffp, \ size_t len, unsigned int flags); } +570 AUE_SYSCTL STD { int freebsd32___sysctlbyname(const char *name, \ + size_t namelen, void *old, uint32_t *oldlenp, \ + void *new, size_t newlen); } ; vim: syntax=off Index: sys/kern/kern_sysctl.c =================================================================== --- sys/kern/kern_sysctl.c +++ sys/kern/kern_sysctl.c @@ -79,7 +79,8 @@ #include #include -static MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic"); +/* Can't be static, used by freebsd32 compat. */ +MALLOC_DEFINE(M_SYSCTL, "sysctl", "sysctl internal magic"); static MALLOC_DEFINE(M_SYSCTLOID, "sysctloid", "sysctl dynamic oids"); static MALLOC_DEFINE(M_SYSCTLTMP, "sysctltmp", "sysctl temp output buffer"); @@ -2145,6 +2146,59 @@ return (error); } +#ifndef _SYS_SYSPROTO_H_ +struct __sysctlbyname_args { + const char *name; + size_t namelen; + void *old; + size_t *oldlenp; + void *new; + size_t newlen; +}; +#endif +int +sys___sysctlbyname(struct thread *td, struct __sysctlbyname_args *uap) +{ + int oid[CTL_MAXNAME]; +#define NAMEBUFLEN 16 + char namebuf[NAMEBUFLEN]; + char *name; + size_t namelen, oidlen, rv; + int error; + + namelen = uap->namelen; + if (namelen > MAXPATHLEN || namelen == 0) + return (EINVAL); + + name = namebuf; + if (namelen > NAMEBUFLEN) + name = malloc(namelen, M_SYSCTL, M_WAITOK); + error = copyin(uap->name, name, namelen); + if (error != 0) + goto out; + + oid[0] = 0; + oid[1] = 3; + oidlen = sizeof(oid); + error = kernel_sysctl(td, oid, 2, oid, &oidlen, (void *)name, namelen, + &rv, 0); + if (error != 0) + goto out; + + error = userland_sysctl(td, oid, rv / sizeof(int), uap->old, uap->oldlenp, + 0, (void *)uap->new, uap->newlen, &rv, 0); + if (error != 0) + goto out; + if (uap->oldlenp != NULL) + error = copyout(&rv, uap->oldlenp, sizeof(rv)); + +out: + if (namelen > NAMEBUFLEN) + free(name, M_SYSCTL); + return (error); +#undef NAMEBUFLEN +} + /* * This is used from various compatibility syscalls too. That's why name * must be in kernel space. Index: sys/kern/syscalls.master =================================================================== --- sys/kern/syscalls.master +++ sys/kern/syscalls.master @@ -3185,6 +3185,15 @@ unsigned int flags ); } +570 AUE_SYSCTL STD { + int __sysctlbyname( + _In_reads_(namelen) const char *name, + size_t namelen, + _Out_writes_bytes_opt_(*oldlenp) void *old, + _Inout_opt_ size_t *oldlenp, + _In_reads_bytes_opt_(newlen) void *new, + size_t newlen); + } ; Please copy any additions and changes to the following compatability tables: ; sys/compat/freebsd32/syscalls.master