summaryrefslogtreecommitdiff
path: root/debian/patches/libffi-pax.diff
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/libffi-pax.diff')
-rw-r--r--debian/patches/libffi-pax.diff161
1 files changed, 161 insertions, 0 deletions
diff --git a/debian/patches/libffi-pax.diff b/debian/patches/libffi-pax.diff
new file mode 100644
index 0000000..e8666f8
--- /dev/null
+++ b/debian/patches/libffi-pax.diff
@@ -0,0 +1,161 @@
+From 757876336c183f5b20b6620d674cc9817fd0d280 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stefan=20B=C3=BChler?= <buehler@cert.uni-stuttgart.de>
+Date: Wed, 7 Sep 2016 15:50:54 +0200
+Subject: [PATCH 2/2] always check for PaX MPROTECT on linux, make EMUTRAMP
+ experimental
+
+- ffi_prep_closure_loc doesn't necessarily generate trampolines recognized by
+ PaX EMUTRAMP handler; there is no way to check before, and it isn't working
+on x86-64 right now -> experimental
+- if MPROTECT is enabled use the same workaround as is used for SELinux (double
+ mmap())
+---
+ configure.ac | 11 +++++++---
+ src/closures.c | 68 +++++++++++++++++++++++++++++++++++++++-------------------
+ 2 files changed, 54 insertions(+), 25 deletions(-)
+
+--- a/src/libffi/configure.ac
++++ b/src/libffi/configure.ac
+@@ -177,12 +177,17 @@
+ ;;
+ esac
+
+-# On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC.
++# On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC;
++# if EMUTRAMP is active too ffi could try mapping without PROT_EXEC,
++# but the kernel needs to recognize the trampoline generated by ffi.
++# Otherwise fallback to double mmap trick.
+ AC_ARG_ENABLE(pax_emutramp,
+- [ --enable-pax_emutramp enable pax emulated trampolines, for we can't use PROT_EXEC],
++ [ --enable-pax_emutramp enable pax emulated trampolines (experimental)],
+ if test "$enable_pax_emutramp" = "yes"; then
++ AC_MSG_WARN([EMUTRAMP is experimental only. Use --enable-pax_emutramp=experimental to enforce.])
++ elif test "$enable_pax_emutramp" = "experimental"; then
+ AC_DEFINE(FFI_MMAP_EXEC_EMUTRAMP_PAX, 1,
+- [Define this if you want to enable pax emulated trampolines])
++ [Define this if you want to enable pax emulated trampolines (experimental)])
+ fi)
+
+ FFI_EXEC_TRAMPOLINE_TABLE=0
+--- a/src/libffi/src/closures.c
++++ b/src/libffi/src/closures.c
+@@ -53,14 +53,18 @@
+ # endif
+ #endif
+
+-#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
+-# ifdef __linux__
++#if FFI_MMAP_EXEC_WRIT && defined __linux__
++# if !defined FFI_MMAP_EXEC_SELINUX
+ /* When defined to 1 check for SELinux and if SELinux is active,
+ don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
+ might cause audit messages. */
+ # define FFI_MMAP_EXEC_SELINUX 1
+-# endif
+-#endif
++# endif /* !defined FFI_MMAP_EXEC_SELINUX */
++# if !defined FFI_MMAP_PAX
++/* Also check for PaX MPROTECT */
++# define FFI_MMAP_PAX 1
++# endif /* !defined FFI_MMAP_PAX */
++#endif /* FFI_MMAP_EXEC_WRIT && defined __linux__ */
+
+ #if FFI_CLOSURES
+
+@@ -172,14 +176,18 @@
+
+ #endif /* !FFI_MMAP_EXEC_SELINUX */
+
+-/* On PaX enable kernels that have MPROTECT enable we can't use PROT_EXEC. */
+-#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
++/* On PaX enable kernels that have MPROTECT enabled we can't use PROT_EXEC. */
++#if defined FFI_MMAP_PAX
+ #include <stdlib.h>
+
+-static int emutramp_enabled = -1;
++enum {
++ PAX_MPROTECT = (1 << 0),
++ PAX_EMUTRAMP = (1 << 1),
++};
++static int cached_pax_flags = -1;
+
+ static int
+-emutramp_enabled_check (void)
++pax_flags_check (void)
+ {
+ char *buf = NULL;
+ size_t len = 0;
+@@ -193,9 +201,10 @@
+ while (getline (&buf, &len, f) != -1)
+ if (!strncmp (buf, "PaX:", 4))
+ {
+- char emutramp;
+- if (sscanf (buf, "%*s %*c%c", &emutramp) == 1)
+- ret = (emutramp == 'E');
++ if (NULL != strchr (buf + 4, 'M'))
++ ret |= PAX_MPROTECT;
++ if (NULL != strchr (buf + 4, 'E'))
++ ret |= PAX_EMUTRAMP;
+ break;
+ }
+ free (buf);
+@@ -203,9 +212,13 @@
+ return ret;
+ }
+
+-#define is_emutramp_enabled() (emutramp_enabled >= 0 ? emutramp_enabled \
+- : (emutramp_enabled = emutramp_enabled_check ()))
+-#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
++#define get_pax_flags() (cached_pax_flags >= 0 ? cached_pax_flags \
++ : (cached_pax_flags = pax_flags_check ()))
++#define has_pax_flags(flags) ((flags) == ((flags) & get_pax_flags ()))
++#define is_mprotect_enabled() (has_pax_flags (PAX_MPROTECT))
++#define is_emutramp_enabled() (has_pax_flags (PAX_EMUTRAMP))
++
++#endif /* defined FFI_MMAP_PAX */
+
+ #elif defined (__CYGWIN__) || defined(__INTERIX)
+
+@@ -216,9 +229,10 @@
+
+ #endif /* !defined(X86_WIN32) && !defined(X86_WIN64) */
+
+-#ifndef FFI_MMAP_EXEC_EMUTRAMP_PAX
+-#define is_emutramp_enabled() 0
+-#endif /* FFI_MMAP_EXEC_EMUTRAMP_PAX */
++#if !defined FFI_MMAP_PAX
++# define is_mprotect_enabled() 0
++# define is_emutramp_enabled() 0
++#endif /* !defined FFI_MMAP_PAX */
+
+ /* Declare all functions defined in dlmalloc.c as static. */
+ static void *dlmalloc(size_t);
+@@ -525,13 +539,23 @@
+ printf ("mapping in %zi\n", length);
+ #endif
+
+- if (execfd == -1 && is_emutramp_enabled ())
++ /* -1 != execfd hints that we already decided to use dlmmap_locked
++ last time. */
++ if (execfd == -1 && is_mprotect_enabled ())
+ {
+- ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset);
+- return ptr;
++#ifdef FFI_MMAP_EXEC_EMUTRAMP_PAX
++ if (is_emutramp_enabled ())
++ {
++ /* emutramp requires the kernel recognizing the trampoline pattern
++ generated by ffi_prep_closure_loc; there is no way to test
++ in advance whether this will work, so this is experimental. */
++ ptr = mmap (start, length, prot & ~PROT_EXEC, flags, fd, offset);
++ return ptr;
++ }
++#endif
++ /* fallback to dlmmap_locked. */
+ }
+-
+- if (execfd == -1 && !is_selinux_enabled ())
++ else if (execfd == -1 && !is_selinux_enabled ())
+ {
+ ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
+