summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnthony Green <green@moxielogic.com>2022-09-06 21:15:58 -0400
committerAnthony Green <green@moxielogic.com>2022-09-06 21:15:58 -0400
commitda905276850342df0f9dfe2c775f6c649d4eed6b (patch)
tree9a76c2401ec5d5bf7645e7ebe269ce46763b8961 /src
parentb86c3dc0950ad5d8991e3970d56daeb409650d60 (diff)
downloadlibffi-da905276850342df0f9dfe2c775f6c649d4eed6b.tar.gz
dlmmap fix and always check for PaX MPROTECT on linux
Also make EMUTRAMP experimental From Stefan Bühler https://github.com/libffi/libffi/pull/282
Diffstat (limited to 'src')
-rw-r--r--src/closures.c89
1 files changed, 54 insertions, 35 deletions
diff --git a/src/closures.c b/src/closures.c
index db7ec94..6cbe2f0 100644
--- a/src/closures.c
+++ b/src/closures.c
@@ -141,14 +141,18 @@ ffi_tramp_is_present (__attribute__((unused)) void *ptr)
# endif
#endif
-#if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
-# if defined(__linux__) && !defined(__ANDROID__)
-/* 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
+#if FFI_MMAP_EXEC_WRIT && defined(__linux__) && !defined(__ANDROID__)
+# 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 /* !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__) && !defined(__ANDROID__)
#if FFI_CLOSURES
@@ -479,14 +483,18 @@ selinux_enabled_check (void)
#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;
@@ -500,9 +508,10 @@ emutramp_enabled_check (void)
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);
@@ -510,9 +519,13 @@ emutramp_enabled_check (void)
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)
@@ -523,9 +536,10 @@ emutramp_enabled_check (void)
#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);
@@ -890,13 +904,23 @@ dlmmap (void *start, size_t length, int prot,
return ptr;
}
- 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);
@@ -909,16 +933,11 @@ dlmmap (void *start, size_t length, int prot,
MREMAP_DUP and prot at this point. */
}
- if (execsize == 0 || execfd == -1)
- {
- pthread_mutex_lock (&open_temp_exec_file_mutex);
- ptr = dlmmap_locked (start, length, prot, flags, offset);
- pthread_mutex_unlock (&open_temp_exec_file_mutex);
-
- return ptr;
- }
+ pthread_mutex_lock (&open_temp_exec_file_mutex);
+ ptr = dlmmap_locked (start, length, prot, flags, offset);
+ pthread_mutex_unlock (&open_temp_exec_file_mutex);
- return dlmmap_locked (start, length, prot, flags, offset);
+ return ptr;
}
/* Release memory at the given address, as well as the corresponding