diff --git a/dlls/ntdll/thread.c b/dlls/ntdll/thread.c index c5b2008e44..96ca266921 100644 --- a/dlls/ntdll/thread.c +++ b/dlls/ntdll/thread.c @@ -268,6 +268,77 @@ static void set_process_name( int argc, char *argv[] ) } +#ifdef __i386__ +#include +#include +#include +#include +#include +#include +#include + +static void sigsys_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; +} + +// FIXME All of this code is i386 Linux-specific. It may want to live in +// signal_i386.c. +void seccomp_init(void) +{ + int ret; + char *tcbhead; + struct sigaction sig_act; + // 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 = sigsys_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); +} +#endif + + /*********************************************************************** * thread_init * @@ -370,6 +441,10 @@ TEB *thread_init(void) __wine_user_shared_data(); fill_cpu_info(); +#ifdef __i386__ + seccomp_init(); +#endif + return teb; }