--- src/wine-lol/dlls/ntdll/unix/signal_i386.c 2021-07-18 22:54:25.073333256 +0200 +++ signal_i386-next.c 2021-07-18 22:54:05.089999921 +0200 @@ -27,6 +27,14 @@ #include "config.h" #include "wine/port.h" +#include +#include +#include +#include +#include +#include +#include + #include #include #include @@ -2057,6 +2065,23 @@ } } +/********************************************************************** + * sys_handler + * + * Handler for SIGSYS + */ +static void sys_handler( int signal, siginfo_t *siginfo, void *sigcontext ) +{ + ucontext_t *ctx = sigcontext; + + WINE_ERR( "SIGSYS (%d)\n", ctx->uc_mcontext.gregs[REG_EAX] ); + + // FIXME Relay to actual Nt syscall. + + ctx->uc_mcontext.gregs[REG_EAX] = 0; +} + + /*********************************************************************** * LDT support @@ -2347,6 +2372,55 @@ } +void seccomp_init(struct sigaction *sig_act) +{ + int ret; + char *tcbhead; + + // FIXME Allocate a range of syscall numbers for Wine, e.g. 1024+. This + // will be necessary to distinguish Linux syscall numbers from Wine + // syscall numbers. + struct sock_filter filter[] = { + { BPF_LD | BPF_W | BPF_ABS, 0, 0, 0 }, + { BPF_JMP | BPF_JEQ, 1, 0, 173 }, + { BPF_RET, 0, 0, SECCOMP_RET_ALLOW }, + { BPF_LD | BPF_W | BPF_ABS, 0, 0, 4 }, + { BPF_JMP | BPF_JEQ, 1, 0, AUDIT_ARCH_X86_64 }, + { BPF_RET, 0, 0, SECCOMP_RET_ALLOW }, + { BPF_RET, 0, 0, SECCOMP_RET_TRAP } + }; + struct sock_fprog prog = { 7, filter }; + + // FIXME There is no way to remove a seccomp upon execve. This should not + // have bad effects on non-Wine programs, provided we fix the syscall + // numbering, but we may be adding the same seccomp filter multiple + // times unnecessarily. + ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + TRACE( "prctl(SET_NO_NEW_PRIVS) = %d, %d\n", ret, errno ); + prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0); + TRACE( "prctl(SET_SECCOMP) = %d, %d\n", ret, errno ); + + sig_act->sa_mask = server_block_set; + sig_act->sa_flags = SA_SIGINFO | SA_RESTART; +#ifdef SA_ONSTACK + sig_act->sa_flags |= SA_ONSTACK; +#endif + sig_act->sa_sigaction = sys_handler; + ret = sigaction( SIGSYS, &sig_act, NULL ); + TRACE( "sigaction(SIGSYS) = %d\n", ret ); + + __asm__("mov %%gs:0, %0" : "=r" (tcbhead)); + TRACE( "gs:0 = %p\n", tcbhead ); + + // FIXME Requires a patched version of glibc to expand the reserved size + // at the top of (struct pthread). Upstream glibc only reserves 0x60 + // bytes on i386, and we require at least 0x68 bytes. The code below + // assumes at least 0x6C bytes are reserved. + *(uint64_t *)(tcbhead + 0x60) = (uintptr_t)(tcbhead + 0x68); +} + + + /********************************************************************** * signal_init_process */ @@ -2381,8 +2455,12 @@ if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error; sig_act.sa_sigaction = segv_handler; if (sigaction( SIGSEGV, &sig_act, NULL ) == -1) goto error; + sig_act.sa_sigaction = sys_handler; + if (sigaction( SIGSYS, &sig_act, NULL ) == -1) goto error; if (sigaction( SIGILL, &sig_act, NULL ) == -1) goto error; - if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error; + + seccomp_init(&sig_act); + return; error: