Skip to content

Instantly share code, notes, and snippets.

@mmtrt
Last active May 31, 2020 18:51
Show Gist options
  • Save mmtrt/5ee395e88d9a45b6af2f59f2016f4a6b to your computer and use it in GitHub Desktop.
Save mmtrt/5ee395e88d9a45b6af2f59f2016f4a6b to your computer and use it in GitHub Desktop.
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 <asm/ldt.h>
+#include <linux/audit.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+#include <linux/unistd.h>
+#include <sys/prctl.h>
+#include <errno.h>
+
+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
*
@@ -497,6 +497,11 @@ TEB *thread_init(void)
unix_funcs->get_paths( &build_dir, &data_dir, &config_dir );
set_process_name( __wine_main_argc, __wine_main_argv );
fill_cpu_info();
+
+#ifdef __i386__
+ seccomp_init();
+#endif
+
return teb;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment