Cider Isn't Darwin Emulation, Really
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340#include "sysctl_kern.h"#include "sysctl_proc.h"#include "getrlimit.h"#include "../ext/sysinfo.h"#include "../ext/syslog.h"#include "../ext/sys/utsname.h"#include <linux-syscalls/linux.h>#include "../base.h"#include "../time/gettimeofday.h"#include "darling-config.h"#include "../errno.h"#include "../simple.h"#include "../fcntl/open.h"#include "../unistd/read.h"#include "../unistd/close.h"#include <sys/errno.h>
enum { _KERN_MSGBUF = 1000, _KERN_OSPRODUCTVERSION,
_KERN_SEMMNS = 1000,};
static sysctl_handler(handle_msgbuf);static sysctl_handler(handle_proc);static sysctl_handler(handle_procargs32);static sysctl_handler(handle_argmax);static sysctl_handler(handle_boottime);static sysctl_handler(handle_ostype);static sysctl_handler(handle_hostname);static sysctl_handler(handle_domainname);static sysctl_handler(handle_osrelease);static sysctl_handler(handle_version);static sysctl_handler(handle_osversion);static sysctl_handler(handle_maxproc);static sysctl_handler(handle_netboot);static sysctl_handler(handle_safeboot);static sysctl_handler(handle_usrstack32);static sysctl_handler(handle_usrstack64);static sysctl_handler(handle_sysv_semmns);static sysctl_handler(handle_osproductversion);
extern int _sysctl_proc(int what, int flag, struct kinfo_proc* out, unsigned long* buflen);extern int _sysctl_procargs(int pid, char* buf, unsigned long* buflen);extern int strlcpy(char* dst, const char* src, __SIZE_TYPE__ dst_size);extern __SIZE_TYPE__ strlen(const char* str);
const struct known_sysctl sysctls_kern_sysv[] = { { .oid = _KERN_SEMMNS, .type = CTLTYPE_INT, .exttype = "I", .name = "semmns", .handler = handle_sysv_semmns }, { .oid = -1 }};
const struct known_sysctl sysctls_kern[] = { { .oid = _KERN_MSGBUF, .type = CTLTYPE_STRING, .exttype = "S", .name = "msgbuf", .handler = handle_msgbuf }, { .oid = KERN_PROC, .type = CTLTYPE_STRUCT, .exttype = "", .name = "proc", .handler = handle_proc }, { .oid = KERN_PROCARGS2, .type = CTLTYPE_STRUCT, .exttype = "", .name = "procargs2", .handler = handle_procargs32 }, { .oid = KERN_ARGMAX, .type = CTLTYPE_INT, .exttype = "I", .name = "argmax", .handler = handle_argmax }, { .oid = KERN_MAXPROC, .type = CTLTYPE_INT, .exttype = "I", .name = "maxproc", .handler = handle_maxproc }, { .oid = KERN_NETBOOT, .type = CTLTYPE_INT, .exttype = "I", .name = "netboot", .handler = handle_netboot }, { .oid = KERN_SAFEBOOT, .type = CTLTYPE_INT, .exttype = "I", .name = "safeboot", .handler = handle_safeboot }, { .oid = KERN_BOOTTIME, .type = CTLTYPE_STRUCT, .exttype = "S,timeval", .name = "boottime", .handler = handle_boottime }, { .oid = KERN_OSTYPE, .type = CTLTYPE_STRING, .exttype = "S", .name = "ostype", .handler = handle_ostype }, { .oid = KERN_HOSTNAME, .type = CTLTYPE_STRING, .exttype = "S", .name = "hostname", .handler = handle_hostname }, { .oid = KERN_DOMAINNAME, .type = CTLTYPE_STRING, .exttype = "S", .name = "domainname", .handler = handle_domainname }, { .oid = KERN_OSRELEASE, .type = CTLTYPE_STRING, .exttype = "S", .name = "osrelease", .handler = handle_osrelease }, { .oid = KERN_VERSION, .type = CTLTYPE_STRING, .exttype = "S", .name = "version", .handler = handle_version }, { .oid = KERN_OSVERSION, .type = CTLTYPE_STRING, .exttype = "S", .name = "osversion", .handler = handle_osversion }, { .oid = KERN_USRSTACK32, .type = CTLTYPE_INT, .exttype = "I", .name = "usrstack", .handler = handle_usrstack32 }, { .oid = KERN_USRSTACK64, .type = CTLTYPE_QUAD, .exttype = "Q", .name = "usrstack64", .handler = handle_usrstack64 }, { .oid = _KERN_OSPRODUCTVERSION, .type = CTLTYPE_STRING, .exttype = "S", .name = "osproductversion", .handler = handle_osproductversion }, { .oid = KERN_SYSV, .type = CTLTYPE_NODE, .exttype = "", .name = "sysv", .subctls = sysctls_kern_sysv }, { .oid = -1 }};
sysctl_handler(handle_msgbuf){ if (*oldlen <= 8) { // Caller is asking for buffer size if (*oldlen < sizeof(int)) return -EINVAL;
*((int*) old) = __linux_syslog(SYSLOG_ACTION_SIZE_BUFFER, NULL, 0); } else { // Caller is asking for buffer contents int ret;
ret = __linux_syslog(SYSLOG_ACTION_READ_ALL, (char*) old, *oldlen); if (ret < 0) return errno_linux_to_bsd(ret);
*oldlen = ret; } return 0;}
sysctl_handler(handle_proc){ if (nlen < 4) return -ENOENT; return _sysctl_proc(name[2], name[3], (struct kinfo_proc*) old, oldlen);}
sysctl_handler(handle_procargs32){ if (nlen < 3) return -ENOENT; return _sysctl_procargs(name[2], (char*) old, oldlen);}
sysctl_handler(handle_argmax){ struct rlimit lim; int r; int* ovalue = (int*) old;
r = sys_getrlimit(BSD_RLIMIT_STACK, &lim); if (r < 0) return r;
if (ovalue != NULL) *ovalue = lim.rlim_cur / 4; *oldlen = sizeof(int); return 0;}
sysctl_handler(handle_boottime){ // Fill in struct timeval { tv_sec, tv_usec } struct sysinfo info; struct bsd_timeval* tv;
if (__linux_sysinfo(&info) == -1) return -errno;
tv = (struct bsd_timeval*) old; if (tv != NULL) { if (*oldlen < sizeof(*tv)) return -EINVAL; sys_gettimeofday(tv, NULL);
tv->tv_sec -= info.uptime;
// we don't want the microseconds to be constantly jumping around // (that actually causes an infinite loop in `_mach_boottime_usec` in libc) // but Linux doesn't give us microseconds, so just settle for 0 tv->tv_usec = 0; } *oldlen = sizeof(*tv); return 0;}
sysctl_handler(handle_ostype){ const char* s = EMULATED_SYSNAME;
copyout_string(s, (char*) old, oldlen); return 0;}
sysctl_handler(handle_osrelease){ const char* s = EMULATED_RELEASE;
copyout_string(s, (char*) old, oldlen); return 0;}
sysctl_handler(handle_version){ const char* s = EMULATED_VERSION;
copyout_string(s, (char*) old, oldlen); return 0;}
sysctl_handler(handle_osversion){ const char* s = EMULATED_OSVERSION;
copyout_string(s, (char*) old, oldlen); return 0;}
static struct linux_utsname lu;struct linux_utsname* need_uname(void){#ifndef VARIANT_DYLD // Cache __linux_uname results if (!lu.sysname[0]) { __linux_uname(&lu); }#endif return &lu;}
sysctl_handler(handle_hostname){ int rv = 0; need_uname(); copyout_string(lu.nodename, (char*) old, oldlen); if (_new && newlen > 0) { rv = LINUX_SYSCALL(__NR_sethostname, _new, newlen); if (rv < 0) rv = errno_linux_to_bsd(rv); } return rv;}
sysctl_handler(handle_domainname){ int rv = 0; need_uname(); copyout_string(lu.domainname, (char*) old, oldlen); if (_new && newlen > 0) { rv = LINUX_SYSCALL(__NR_setdomainname, _new, newlen); if (rv < 0) rv = errno_linux_to_bsd(rv); } return rv;}
sysctl_handler(handle_maxproc){ char buf[16]; int fd = sys_open("/proc/sys/kernel/pid_max", BSD_O_RDONLY, 0); int value = 1024; int* ovalue = (int*) old; if (!oldlen) return -EINVAL; if (fd >= 0) { int rd = sys_read(fd, buf, sizeof(buf) - 1); close_internal(fd); if (rd > 0) { buf[rd] = '\0'; value = __simple_atoi(buf, NULL); } } if (ovalue != NULL) *ovalue = value; *oldlen = sizeof(int); return 0;}
sysctl_handler(handle_netboot){ int* ovalue = (int*) old; if (!oldlen) return -EINVAL;
if (*oldlen >= sizeof(int)) *ovalue = 0; *oldlen = sizeof(int);
return 0;}
sysctl_handler(handle_safeboot){ int* ovalue = (int*) old; if (!oldlen) return -EINVAL;
if (*oldlen >= sizeof(int)) *ovalue = 0; *oldlen = sizeof(int);
return 0;}
sysctl_handler(handle_sysv_semmns){ int* ovalue = (int*) old; if (!oldlen) return -EINVAL; if (*oldlen >= sizeof(int)) *ovalue = -1; *oldlen = sizeof(int); return 0;}
static void* mystack(void){ char buf[400]; char* ptr = buf;
if (!read_string("/proc/self/stat", buf, sizeof(buf))) return NULL;
skip_stat_elems(&ptr, 27);
const char* stack = next_stat_elem(&ptr); return (void*) __simple_atoi(stack, NULL);}
sysctl_handler(handle_usrstack32){ unsigned int* ovalue = (unsigned int*) old; if (ovalue) *ovalue = mystack(); *oldlen = sizeof(*ovalue); return 0;}
sysctl_handler(handle_usrstack64){ unsigned long long* ovalue = (unsigned long long*) old; if (ovalue) *ovalue = mystack(); *oldlen = sizeof(*ovalue); return 0;}
static sysctl_handler(handle_osproductversion) { copyout_string(EMULATED_OSPRODUCTVERSION, (char*)old, oldlen); return 0;};