pkey state is now preserved on fork for Linux 5.0+
This patch is going to be backported to stable kernels, so the check could be expanded to allow recent enough stable kernel branches.pull/87/head
parent
c9df70d934
commit
4a000d96e2
21
h_malloc.c
21
h_malloc.c
|
@ -8,6 +8,7 @@
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "third_party/libdivide.h"
|
#include "third_party/libdivide.h"
|
||||||
|
@ -66,6 +67,7 @@ static union {
|
||||||
struct region_metadata *regions[2];
|
struct region_metadata *regions[2];
|
||||||
#ifdef USE_PKEY
|
#ifdef USE_PKEY
|
||||||
int metadata_pkey;
|
int metadata_pkey;
|
||||||
|
bool pkey_state_preserved_on_fork;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
char padding[PAGE_SIZE];
|
char padding[PAGE_SIZE];
|
||||||
|
@ -914,10 +916,12 @@ static void post_fork_child(void) {
|
||||||
thread_unseal_metadata();
|
thread_unseal_metadata();
|
||||||
|
|
||||||
#ifdef USE_PKEY
|
#ifdef USE_PKEY
|
||||||
// disable sealing to work around kernel bug causing fork to lose the pkey setup
|
if (!ro.pkey_state_preserved_on_fork) {
|
||||||
memory_protect_rw(&ro, sizeof(ro));
|
// disable sealing to work around kernel bug causing fork to lose the pkey setup
|
||||||
ro.metadata_pkey = -1;
|
memory_protect_rw(&ro, sizeof(ro));
|
||||||
memory_protect_ro(&ro, sizeof(ro));
|
ro.metadata_pkey = -1;
|
||||||
|
memory_protect_ro(&ro, sizeof(ro));
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mutex_init(&ro.region_allocator->lock);
|
mutex_init(&ro.region_allocator->lock);
|
||||||
|
@ -952,6 +956,15 @@ COLD static void init_slow_path(void) {
|
||||||
|
|
||||||
#ifdef USE_PKEY
|
#ifdef USE_PKEY
|
||||||
ro.metadata_pkey = pkey_alloc(0, 0);
|
ro.metadata_pkey = pkey_alloc(0, 0);
|
||||||
|
|
||||||
|
// pkey state is not preserved on fork before Linux 5.0 unless the patch was backported
|
||||||
|
struct utsname uts;
|
||||||
|
if (uname(&uts) == 0) {
|
||||||
|
unsigned long version = strtoul(uts.release, NULL, 10);
|
||||||
|
if (version >= 5) {
|
||||||
|
ro.pkey_state_preserved_on_fork = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (sysconf(_SC_PAGESIZE) != PAGE_SIZE) {
|
if (sysconf(_SC_PAGESIZE) != PAGE_SIZE) {
|
||||||
|
|
Loading…
Reference in New Issue