-/*
- * ----------------------------------------------------------------------------
- * "THE BEER-WARE LICENSE" (Revision 42):
- * <phk@FreeBSD.org> 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
-#include <sys/types.h>
+#include <sys/param.h>
#include <sys/sysctl.h>
+#include <string.h>
+
+#include "libc_private.h"
+
+#define SYSCTLBYNAME_OSREL 1300045
+
+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;
+ int oid[CTL_MAXNAME];
+ size_t len;
- oidlen = sizeof(real_oid) / sizeof(int);
- if (sysctlnametomib(name, real_oid, &oidlen) < 0)
+ if (__getosreldate() >= SYSCTLBYNAME_OSREL) {
+ len = strlen(name);
+ return (__sysctlbyname(name, len, oldp, oldlenp, newp,
+ newlen));
+ }
+ len = nitems(oid);
+ if (sysctlnametomib(name, oid, &len) == -1)
return (-1);
- return (sysctl(real_oid, oidlen, oldp, oldlenp, newp, newlen));
+ return (sysctl(oid, len, oldp, oldlenp, newp, newlen));
}
};
FBSD_1.6 {
+ __sysctlbyname;
copy_file_range;
fhlink;
fhlinkat;
return (0);
}
+int
+freebsd32___sysctlbyname(struct thread *td,
+ struct freebsd32___sysctlbyname_args *uap)
+{
+ size_t oldlen, rv;
+ int error;
+ uint32_t tmp;
+
+ if (uap->oldlenp != NULL) {
+ error = fueword32(uap->oldlenp, &tmp);
+ oldlen = tmp;
+ } else {
+ error = oldlen = 0;
+ }
+ if (error != 0)
+ return (EFAULT);
+ error = kern___sysctlbyname(td, uap->name, uap->namelen, uap->old,
+ &oldlen, uap->new, uap->newlen, &rv, SCTL_MASK32, 1);
+ if (error != 0)
+ return (error);
+ if (uap->oldlenp != NULL)
+ error = suword32(uap->oldlenp, rv);
+
+ return (error);
+}
+
int
freebsd32_jail(struct thread *td, struct freebsd32_jail_args *uap)
{
char mask_l_[PADL_(domainset_t *)]; domainset_t * mask; char mask_r_[PADR_(domainset_t *)];
char policy_l_[PADL_(int)]; int policy; char policy_r_[PADR_(int)];
};
+struct freebsd32___sysctlbyname_args {
+ char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)];
+ char namelen_l_[PADL_(size_t)]; size_t namelen; char namelen_r_[PADR_(size_t)];
+ char old_l_[PADL_(void *)]; void * old; char old_r_[PADR_(void *)];
+ char oldlenp_l_[PADL_(uint32_t *)]; uint32_t * oldlenp; char oldlenp_r_[PADR_(uint32_t *)];
+ char new_l_[PADL_(void *)]; void * new; char new_r_[PADR_(void *)];
+ char newlen_l_[PADL_(size_t)]; size_t newlen; char newlen_r_[PADR_(size_t)];
+};
#if !defined(PAD64_REQUIRED) && !defined(__amd64__)
#define PAD64_REQUIRED
#endif
int freebsd32_kevent(struct thread *, struct freebsd32_kevent_args *);
int freebsd32_cpuset_getdomain(struct thread *, struct freebsd32_cpuset_getdomain_args *);
int freebsd32_cpuset_setdomain(struct thread *, struct freebsd32_cpuset_setdomain_args *);
+int freebsd32___sysctlbyname(struct thread *, struct freebsd32___sysctlbyname_args *);
#ifdef COMPAT_43
#define FREEBSD32_SYS_AUE_freebsd32_kevent AUE_KEVENT
#define FREEBSD32_SYS_AUE_freebsd32_cpuset_getdomain AUE_NULL
#define FREEBSD32_SYS_AUE_freebsd32_cpuset_setdomain AUE_NULL
+#define FREEBSD32_SYS_AUE_freebsd32___sysctlbyname AUE_SYSCTL
#undef PAD_
#undef PADL_
#define FREEBSD32_SYS_fhreadlink 567
#define FREEBSD32_SYS_funlinkat 568
#define FREEBSD32_SYS_copy_file_range 569
-#define FREEBSD32_SYS_MAXSYSCALL 570
+#define FREEBSD32_SYS_freebsd32___sysctlbyname 570
+#define FREEBSD32_SYS_MAXSYSCALL 571
"fhreadlink", /* 567 = fhreadlink */
"funlinkat", /* 568 = funlinkat */
"copy_file_range", /* 569 = copy_file_range */
+ "freebsd32___sysctlbyname", /* 570 = freebsd32___sysctlbyname */
};
{ AS(fhreadlink_args), (sy_call_t *)sys_fhreadlink, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 567 = fhreadlink */
{ AS(funlinkat_args), (sy_call_t *)sys_funlinkat, AUE_UNLINKAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 568 = funlinkat */
{ AS(copy_file_range_args), (sy_call_t *)sys_copy_file_range, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 569 = copy_file_range */
+ { AS(freebsd32___sysctlbyname_args), (sy_call_t *)freebsd32___sysctlbyname, AUE_SYSCTL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 570 = freebsd32___sysctlbyname */
};
*n_args = 6;
break;
}
+ /* freebsd32___sysctlbyname */
+ case 570: {
+ struct freebsd32___sysctlbyname_args *p = params;
+ uarg[0] = (intptr_t) p->name; /* const char * */
+ uarg[1] = p->namelen; /* size_t */
+ uarg[2] = (intptr_t) p->old; /* void * */
+ uarg[3] = (intptr_t) p->oldlenp; /* uint32_t * */
+ uarg[4] = (intptr_t) p->new; /* void * */
+ uarg[5] = p->newlen; /* size_t */
+ *n_args = 6;
+ break;
+ }
default:
*n_args = 0;
break;
break;
};
break;
+ /* freebsd32___sysctlbyname */
+ case 570:
+ switch(ndx) {
+ case 0:
+ p = "userland const char *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "userland void *";
+ break;
+ case 3:
+ p = "userland uint32_t *";
+ break;
+ case 4:
+ p = "userland void *";
+ break;
+ case 5:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
if (ndx == 0 || ndx == 1)
p = "ssize_t";
break;
+ /* freebsd32___sysctlbyname */
+ case 570:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
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
## proxying daemon in userspace.
##
__sysctl
+__sysctlbyname
##
## Allow umtx operations as these are scoped by address space.
{ AS(fhreadlink_args), (sy_call_t *)sys_fhreadlink, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 567 = fhreadlink */
{ AS(funlinkat_args), (sy_call_t *)sys_funlinkat, AUE_UNLINKAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 568 = funlinkat */
{ AS(copy_file_range_args), (sy_call_t *)sys_copy_file_range, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 569 = copy_file_range */
+ { AS(__sysctlbyname_args), (sy_call_t *)sys___sysctlbyname, AUE_SYSCTL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 570 = __sysctlbyname */
};
return (error);
}
+int
+kern___sysctlbyname(struct thread *td, const char *oname, size_t namelen,
+ void *old, size_t *oldlenp, void *new, size_t newlen, size_t *retval,
+ int flags, bool inkernel)
+{
+ int oid[CTL_MAXNAME];
+ char namebuf[16];
+ char *name;
+ size_t oidlen;
+ int error;
+
+ if (namelen > MAXPATHLEN || namelen == 0)
+ return (EINVAL);
+ name = namebuf;
+ if (namelen > sizeof(namebuf))
+ name = malloc(namelen, M_SYSCTL, M_WAITOK);
+ error = copyin(oname, 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,
+ retval, flags);
+ if (error != 0)
+ goto out;
+ error = userland_sysctl(td, oid, *retval / sizeof(int), old, oldlenp,
+ inkernel, new, newlen, retval, flags);
+
+out:
+ if (namelen > sizeof(namebuf))
+ free(name, M_SYSCTL);
+ 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)
+{
+ size_t rv;
+ int error;
+
+ error = kern___sysctlbyname(td, uap->name, uap->namelen, uap->old,
+ uap->oldlenp, uap->new, uap->newlen, &rv, 0, 0);
+ if (error != 0)
+ return (error);
+ if (uap->oldlenp != NULL)
+ error = copyout(&rv, uap->oldlenp, sizeof(rv));
+
+ return (error);
+}
+
/*
* This is used from various compatibility syscalls too. That's why name
* must be in kernel space.
"fhreadlink", /* 567 = fhreadlink */
"funlinkat", /* 568 = funlinkat */
"copy_file_range", /* 569 = copy_file_range */
+ "__sysctlbyname", /* 570 = __sysctlbyname */
};
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
*n_args = 6;
break;
}
+ /* __sysctlbyname */
+ case 570: {
+ struct __sysctlbyname_args *p = params;
+ uarg[0] = (intptr_t) p->name; /* const char * */
+ uarg[1] = p->namelen; /* size_t */
+ uarg[2] = (intptr_t) p->old; /* void * */
+ uarg[3] = (intptr_t) p->oldlenp; /* size_t * */
+ uarg[4] = (intptr_t) p->new; /* void * */
+ uarg[5] = p->newlen; /* size_t */
+ *n_args = 6;
+ break;
+ }
default:
*n_args = 0;
break;
break;
};
break;
+ /* __sysctlbyname */
+ case 570:
+ switch(ndx) {
+ case 0:
+ p = "userland const char *";
+ break;
+ case 1:
+ p = "size_t";
+ break;
+ case 2:
+ p = "userland void *";
+ break;
+ case 3:
+ p = "userland size_t *";
+ break;
+ case 4:
+ p = "userland void *";
+ break;
+ case 5:
+ p = "size_t";
+ break;
+ default:
+ break;
+ };
+ break;
default:
break;
};
if (ndx == 0 || ndx == 1)
p = "ssize_t";
break;
+ /* __sysctlbyname */
+ case 570:
+ if (ndx == 0 || ndx == 1)
+ p = "int";
+ break;
default:
break;
};
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1300044 /* Master, propagated to newvers */
+#define __FreeBSD_version 1300045 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
#define SYS_fhreadlink 567
#define SYS_funlinkat 568
#define SYS_copy_file_range 569
-#define SYS_MAXSYSCALL 570
+#define SYS___sysctlbyname 570
+#define SYS_MAXSYSCALL 571
fhlinkat.o \
fhreadlink.o \
funlinkat.o \
- copy_file_range.o
+ copy_file_range.o \
+ __sysctlbyname.o
void sysctl_wlock(void);
void sysctl_wunlock(void);
int sysctl_wire_old_buffer(struct sysctl_req *req, size_t len);
+int kern___sysctlbyname(struct thread *td, const char *name,
+ size_t namelen, void *old, size_t *oldlenp, void *new,
+ size_t newlen, size_t *retval, int flags, bool inkernel);
struct sbuf;
struct sbuf *sbuf_new_for_sysctl(struct sbuf *, char *, int,
char len_l_[PADL_(size_t)]; size_t len; char len_r_[PADR_(size_t)];
char flags_l_[PADL_(unsigned int)]; unsigned int flags; char flags_r_[PADR_(unsigned int)];
};
+struct __sysctlbyname_args {
+ char name_l_[PADL_(const char *)]; const char * name; char name_r_[PADR_(const char *)];
+ char namelen_l_[PADL_(size_t)]; size_t namelen; char namelen_r_[PADR_(size_t)];
+ char old_l_[PADL_(void *)]; void * old; char old_r_[PADR_(void *)];
+ char oldlenp_l_[PADL_(size_t *)]; size_t * oldlenp; char oldlenp_r_[PADR_(size_t *)];
+ char new_l_[PADL_(void *)]; void * new; char new_r_[PADR_(void *)];
+ char newlen_l_[PADL_(size_t)]; size_t newlen; char newlen_r_[PADR_(size_t)];
+};
int nosys(struct thread *, struct nosys_args *);
void sys_sys_exit(struct thread *, struct sys_exit_args *);
int sys_fork(struct thread *, struct fork_args *);
int sys_fhreadlink(struct thread *, struct fhreadlink_args *);
int sys_funlinkat(struct thread *, struct funlinkat_args *);
int sys_copy_file_range(struct thread *, struct copy_file_range_args *);
+int sys___sysctlbyname(struct thread *, struct __sysctlbyname_args *);
#ifdef COMPAT_43
#define SYS_AUE_fhreadlink AUE_NULL
#define SYS_AUE_funlinkat AUE_UNLINKAT
#define SYS_AUE_copy_file_range AUE_NULL
+#define SYS_AUE___sysctlbyname AUE_SYSCTL
#undef PAD_
#undef PADL_