Skip to content

Commit eb5629c

Browse files
committed
Use Memory Protection Keys to protect the OPcache mapping
1 parent 0220731 commit eb5629c

4 files changed

Lines changed: 64 additions & 2 deletions

File tree

‎configure.ac‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ AC_CHECK_FUNCS([
579579
mmap
580580
nice
581581
nl_langinfo
582+
pkey_mprotect
582583
poll
583584
pthread_jit_write_protect_np
584585
putenv

‎ext/opcache/ZendAccelerator.h‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@
4646
# include <unistd.h>
4747
#endif
4848

49+
#ifdef HAVE_PKEY_MPROTECT
50+
/* PKEY_DISABLE_WRITE */
51+
# include "sys/mman.h"
52+
#endif
53+
4954
#include "zend_extensions.h"
5055
#include "zend_compile.h"
5156
#include "zend_API.h"
@@ -358,17 +363,27 @@ zend_op_array *zend_accel_compile_pfa(zend_ast *ast,
358363

359364
END_EXTERN_C()
360365

366+
#if defined(HAVE_PKEY_MPROTECT) && defined(PKEY_DISABLE_WRITE)
367+
# define ZEND_ACCEL_USE_PKEYS
368+
#endif
369+
370+
#ifdef ZEND_ACCEL_USE_PKEYS
371+
# define SHM_PROTECT_USE_PKEY zend_accel_pkey
372+
#else
373+
# define SHM_PROTECT_USE_PKEY 0
374+
#endif
375+
361376
/* memory write protection */
362377
#define SHM_PROTECT() \
363378
do { \
364-
if (ZCG(accel_directives).protect_memory) { \
379+
if (SHM_PROTECT_USE_PKEY || ZCG(accel_directives).protect_memory) { \
365380
zend_accel_shared_protect(true); \
366381
} \
367382
} while (0)
368383

369384
#define SHM_UNPROTECT() \
370385
do { \
371-
if (ZCG(accel_directives).protect_memory) { \
386+
if (SHM_PROTECT_USE_PKEY || ZCG(accel_directives).protect_memory) { \
372387
zend_accel_shared_protect(false); \
373388
} \
374389
} while (0)

‎ext/opcache/zend_shared_alloc.c‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ static const zend_shared_memory_handler_entry handler_table[] = {
8282
{ NULL, NULL}
8383
};
8484

85+
#ifdef ZEND_ACCEL_USE_PKEYS
86+
int zend_accel_pkey = 0; /* Memory Protection Key */
87+
#endif
88+
89+
static void zend_accel_shared_protect_init(void);
90+
8591
#ifndef ZEND_WIN32
8692
void zend_shared_alloc_create_lock(char *lockfile_path)
8793
{
@@ -268,6 +274,8 @@ int zend_shared_alloc_startup(size_t requested_size, size_t reserved_size)
268274
ZSMMG(shared_segments)[i]->end = ZSMMG(shared_segments)[i]->size;
269275
}
270276

277+
zend_accel_shared_protect_init();
278+
271279
shared_segments_array_size = ZSMMG(shared_segments_count) * S_H(segment_type_size)();
272280

273281
/* move shared_segments and shared_free to shared memory */
@@ -350,6 +358,13 @@ void zend_shared_alloc_shutdown(void)
350358
# ifdef ZTS
351359
tsrm_mutex_free(zts_lock);
352360
# endif
361+
362+
# ifdef ZEND_ACCEL_USE_PKEYS
363+
if (zend_accel_pkey) {
364+
pkey_free(zend_accel_pkey);
365+
}
366+
# endif
367+
353368
#endif
354369
#ifdef ZTS
355370
tsrm_mutex_free(zts_protect_lock);
@@ -639,8 +654,37 @@ const char *zend_accel_get_shared_model(void)
639654
return g_shared_model;
640655
}
641656

657+
static void zend_accel_shared_protect_init(void)
658+
{
659+
#ifdef ZEND_ACCEL_USE_PKEYS
660+
zend_accel_pkey = pkey_alloc(0, 0);
661+
if (zend_accel_pkey < 0) {
662+
zend_accel_error(ACCEL_LOG_DEBUG, "zend_accel_shared_protect_init: pkey_alloc() failed [%d] %s", errno, strerror(errno));
663+
zend_accel_pkey = 0;
664+
return;
665+
}
666+
667+
for (int i = 0; i < ZSMMG(shared_segments_count); i++) {
668+
if (pkey_mprotect(ZSMMG(shared_segments)[i]->p, ZSMMG(shared_segments)[i]->end, PROT_READ | PROT_WRITE, zend_accel_pkey) != 0) {
669+
zend_accel_error(ACCEL_LOG_DEBUG, "zend_accel_shared_protect_init: pkey_mprotect() failed [%d] %s", errno, strerror(errno));
670+
zend_accel_pkey = 0;
671+
break;
672+
}
673+
}
674+
#endif
675+
}
676+
642677
void zend_accel_shared_protect(bool protected)
643678
{
679+
#ifdef ZEND_ACCEL_USE_PKEYS
680+
if (zend_accel_pkey) {
681+
if (pkey_set(zend_accel_pkey, protected ? PKEY_DISABLE_WRITE : 0) != 0) {
682+
ZEND_UNREACHABLE();
683+
}
684+
return;
685+
}
686+
#endif
687+
644688
#if defined(HAVE_MPROTECT) || defined(ZEND_WIN32)
645689
int i;
646690

‎ext/opcache/zend_shared_alloc.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,8 @@ const char *zend_accel_get_shared_model(void);
196196
*/
197197
void zend_accel_shared_protect(bool protected);
198198

199+
extern int zend_accel_pkey;
200+
199201
#ifdef USE_MMAP
200202
extern const zend_shared_memory_handlers zend_alloc_mmap_handlers;
201203
#endif

0 commit comments

Comments
 (0)