diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/closures.c | 89 |
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 |