From 96e4217c433fcef2e4ffeef1ade7ce0c2f920d25 Mon Sep 17 00:00:00 2001 From: Lubos Dolezel Date: Sat, 8 Feb 2020 22:47:49 +0100 Subject: [PATCH] Add missing SysV Semaphore syscalls + some other improvements in submodules --- src/external/darling-dmg | 2 +- src/external/foundation | 2 +- src/kernel/emulation/linux/CMakeLists.txt | 3 ++ src/kernel/emulation/linux/syscalls.c | 6 +++ src/kernel/emulation/linux/sysv_sem/semctl.c | 47 +++++++++++++++++ src/kernel/emulation/linux/sysv_sem/semctl.h | 52 +++++++++++++++++++ src/kernel/emulation/linux/sysv_sem/semget.c | 21 ++++++++ src/kernel/emulation/linux/sysv_sem/semget.h | 7 +++ src/kernel/emulation/linux/sysv_sem/semop.c | 21 ++++++++ src/kernel/emulation/linux/sysv_sem/semop.h | 8 +++ .../emulation/linux/vchroot_userspace.c | 18 +++++++ 11 files changed, 185 insertions(+), 2 deletions(-) create mode 100644 src/kernel/emulation/linux/sysv_sem/semctl.c create mode 100644 src/kernel/emulation/linux/sysv_sem/semctl.h create mode 100644 src/kernel/emulation/linux/sysv_sem/semget.c create mode 100644 src/kernel/emulation/linux/sysv_sem/semget.h create mode 100644 src/kernel/emulation/linux/sysv_sem/semop.c create mode 100644 src/kernel/emulation/linux/sysv_sem/semop.h diff --git a/src/external/darling-dmg b/src/external/darling-dmg index 9d19ebaa7..98d843d96 160000 --- a/src/external/darling-dmg +++ b/src/external/darling-dmg @@ -1 +1 @@ -Subproject commit 9d19ebaa7f1be38e9c274351b620ebde5d91dd0c +Subproject commit 98d843d96a13f37a5590892a3084951444b7d7d3 diff --git a/src/external/foundation b/src/external/foundation index d584712b0..5326c3d84 160000 --- a/src/external/foundation +++ b/src/external/foundation @@ -1 +1 @@ -Subproject commit d584712b0bf56c8536d440e079b75991946e8a46 +Subproject commit 5326c3d84bd27c1f08689d8f04ad2940380da057 diff --git a/src/kernel/emulation/linux/CMakeLists.txt b/src/kernel/emulation/linux/CMakeLists.txt index c32ca439f..8efd41e4a 100644 --- a/src/kernel/emulation/linux/CMakeLists.txt +++ b/src/kernel/emulation/linux/CMakeLists.txt @@ -275,6 +275,9 @@ set(emulation_sources psynch/psynch_cvsignal.c psynch/ulock_wait.c psynch/ulock_wake.c + sysv_sem/semget.c + sysv_sem/semctl.c + sysv_sem/semop.c conf/pathconf.c conf/fpathconf.c vchroot_userspace.c diff --git a/src/kernel/emulation/linux/syscalls.c b/src/kernel/emulation/linux/syscalls.c index efa0d76b3..8f727163f 100644 --- a/src/kernel/emulation/linux/syscalls.c +++ b/src/kernel/emulation/linux/syscalls.c @@ -198,6 +198,9 @@ #include "bsdthread/pthread_kill.h" #include "conf/pathconf.h" #include "conf/fpathconf.h" +#include "sysv_sem/semctl.h" +#include "sysv_sem/semget.h" +#include "sysv_sem/semop.h" void* __bsd_syscall_table[600] = { [0] = sys_syscall, @@ -342,6 +345,9 @@ void* __bsd_syscall_table[600] = { [241] = sys_flistxattr, [243] = sys_initgroups, [244] = sys_posix_spawn, + [254] = sys_semctl, + [255] = sys_semget, + [256] = sys_semop, [266] = sys_shm_open, [267] = sys_shm_unlink, [268] = sys_sem_open, diff --git a/src/kernel/emulation/linux/sysv_sem/semctl.c b/src/kernel/emulation/linux/sysv_sem/semctl.c new file mode 100644 index 000000000..6dc78b2b2 --- /dev/null +++ b/src/kernel/emulation/linux/sysv_sem/semctl.c @@ -0,0 +1,47 @@ +#include "semctl.h" +#include "../base.h" +#include "../errno.h" +#include +#include + +#define LINUX_IPC_64 0x100 +#define IPCOP_semop 1 +#define IPCOP_semget 2 +#define IPCOP_semctl 3 + +#define IPC_SET 1 +#define IPC_STAT 2 + +extern void *memcpy(void *dest, const void *src, __SIZE_TYPE__ n); + +long sys_semctl(int semid, int semnum, int cmd, semun_t arg) +{ +#ifdef __NR_semctl + int ret = LINUX_SYSCALL(__NR_semctl, semid, semnum, cmd | LINUX_IPC_64, arg.buf); +#else + int ret = LINUX_SYSCALL(__NR_ipc, IPCOP_semctl, semid, semnum, cmd | LINUX_IPC_64, &arg.buf); +#endif + + if (ret < 0) + return errno_linux_to_bsd(ret); + + if (cmd == IPC_SET || cmd == IPC_STAT) + { + struct linux_semid_ds orig; + + memcpy(&orig, arg.buf, sizeof(orig)); + + arg.buf->sem_perm.uid = orig.sem_perm.uid; + arg.buf->sem_perm.gid = orig.sem_perm.gid; + arg.buf->sem_perm.cuid = orig.sem_perm.cuid; + arg.buf->sem_perm.cgid = orig.sem_perm.cgid; + arg.buf->sem_perm.mode = orig.sem_perm.mode; + + arg.buf->sem_base = 0; + arg.buf->sem_nsems = orig.sem_nsems; + arg.buf->sem_otime = orig.sem_otime; + arg.buf->sem_ctime = orig.sem_ctime; + } + + return 0; +} diff --git a/src/kernel/emulation/linux/sysv_sem/semctl.h b/src/kernel/emulation/linux/sysv_sem/semctl.h new file mode 100644 index 000000000..549dc7523 --- /dev/null +++ b/src/kernel/emulation/linux/sysv_sem/semctl.h @@ -0,0 +1,52 @@ +#ifndef LINUX_SYSV_SEMCTL_H +#define LINUX_SYSV_SEMCTL_H +#include + +union semun +{ + struct bsd_semid_ds* buf; +}; + +struct linux_ipc_perm +{ + int32_t _key; + uint32_t uid; + uint32_t gid; + uint32_t cuid; + uint32_t cgid; + short int mode; +}; + +struct linux_semid_ds +{ + struct linux_ipc_perm sem_perm; + unsigned long long sem_otime; + unsigned long long sem_ctime; + unsigned long sem_nsems; +}; + +struct bsd_ipc_perm +{ + uint32_t uid; + uint32_t gid; + uint32_t cuid; + uint32_t cgid; + short int mode; +}; + +struct bsd_semid_ds +{ + struct bsd_ipc_perm sem_perm; + int32_t sem_base; + unsigned short sem_nsems; + unsigned long long sem_otime; + uint32_t sem_pad1; + unsigned long long sem_ctime; + uint32_t sem_pad2; +}; + +typedef union semun semun_t; + +long sys_semctl(int semid, int semnum, int cmd, semun_t arg); + +#endif diff --git a/src/kernel/emulation/linux/sysv_sem/semget.c b/src/kernel/emulation/linux/sysv_sem/semget.c new file mode 100644 index 000000000..be4067d0c --- /dev/null +++ b/src/kernel/emulation/linux/sysv_sem/semget.c @@ -0,0 +1,21 @@ +#include "semget.h" +#include "../base.h" +#include +#include "../errno.h" + +#define IPCOP_semop 1 +#define IPCOP_semget 2 +#define IPCOP_semctl 3 + +long sys_semget(int32_t key, int n, int fl) +{ +#ifdef __NR_semget + int ret = LINUX_SYSCALL(__NR_semget, key, n, fl); +#else + int ret = LINUX_SYSCALL(__NR_ipc, IPCOP_semget, key, n, fl); +#endif + + if (ret < 0) + return errno_linux_to_bsd(ret); + return 0; +} diff --git a/src/kernel/emulation/linux/sysv_sem/semget.h b/src/kernel/emulation/linux/sysv_sem/semget.h new file mode 100644 index 000000000..332b55160 --- /dev/null +++ b/src/kernel/emulation/linux/sysv_sem/semget.h @@ -0,0 +1,7 @@ +#ifndef LINUX_SYSV_SEMGET_H +#define LINUX_SYSV_SEMGET_H +#include + +long sys_semget(int32_t key, int nsems, int semflg); + +#endif diff --git a/src/kernel/emulation/linux/sysv_sem/semop.c b/src/kernel/emulation/linux/sysv_sem/semop.c new file mode 100644 index 000000000..accd7ab16 --- /dev/null +++ b/src/kernel/emulation/linux/sysv_sem/semop.c @@ -0,0 +1,21 @@ +#include "semop.h" +#include "../base.h" +#include "../errno.h" +#include + +#define IPCOP_semop 1 +#define IPCOP_semget 2 +#define IPCOP_semctl 3 + +long sys_semop(int semid, struct sembuf *sops, int nsops) +{ +#ifdef __NR_semop + int ret = LINUX_SYSCALL(__NR_semop, semid, sops, nsops); +#else + int ret = LINUX_SYSCALL(__NR_ipc, IPCOP_semop, semid, nsops, 0, sops); +#endif + + if (ret < 0) + return errno_linux_to_bsd(ret); + return 0; +} diff --git a/src/kernel/emulation/linux/sysv_sem/semop.h b/src/kernel/emulation/linux/sysv_sem/semop.h new file mode 100644 index 000000000..add1b10f6 --- /dev/null +++ b/src/kernel/emulation/linux/sysv_sem/semop.h @@ -0,0 +1,8 @@ +#ifndef LINUX_SYSV_SEMOP_H +#define LINUX_SYSV_SEMOP_H +#include + +struct sembuf; +long sys_semop(int semid, struct sembuf *sops, int nsops); + +#endif diff --git a/src/kernel/emulation/linux/vchroot_userspace.c b/src/kernel/emulation/linux/vchroot_userspace.c index acb958077..76026d815 100644 --- a/src/kernel/emulation/linux/vchroot_userspace.c +++ b/src/kernel/emulation/linux/vchroot_userspace.c @@ -102,6 +102,24 @@ int __darling_vchroot(int dfd) return 0; } +#ifndef TEST +VISIBLE +int __darling_vchroot_expand(const char* path, char* out) +{ + struct vchroot_expand_args a = { + .dfd = -100, + .flags = 0 + }; + + strcpy(a.path, path); + + int rv = vchroot_expand(&a); + + strcpy(out, a.path); + return rv; +} +#endif + static void init_vchroot_path(void) { struct vchroot_expand_args a = { -- 2.51.2