Skip to content

Commit fcd0421

Browse files
committed
Add system ID entropy API
The `zend_system_id` is a (true global) system ID that fingerprints a process state. When extensions add engine hooks during MINIT/startup, entropy is added the system ID for each hook. This allows extensions to identify that changes have been made to the engine since the last PHP process restart.
1 parent 9002e95 commit fcd0421

15 files changed

+140
-43
lines changed

Zend/zend_execute.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "zend_inheritance.h"
4141
#include "zend_type_info.h"
4242
#include "zend_smart_str.h"
43+
#include "zend_system_id.h"
4344

4445
/* Virtual current working directory support */
4546
#include "zend_virtual_cwd.h"
@@ -4531,7 +4532,7 @@ static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint
45314532

45324533
#include "zend_vm_execute.h"
45334534

4534-
ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
4535+
ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler, const char *module_name)
45354536
{
45364537
if (opcode != ZEND_USER_OPCODE) {
45374538
if (handler == NULL) {
@@ -4541,6 +4542,7 @@ ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler
45414542
zend_user_opcodes[opcode] = ZEND_USER_OPCODE;
45424543
}
45434544
zend_user_opcode_handlers[opcode] = handler;
4545+
zend_add_system_entropy(module_name, "zend_set_user_opcode_handler", &opcode, sizeof(zend_uchar));
45444546
return SUCCESS;
45454547
}
45464548
return FAILURE;

Zend/zend_execute.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ ZEND_API zval* zend_get_compiled_variable_value(const zend_execute_data *execute
324324

325325
#define ZEND_USER_OPCODE_DISPATCH_TO 0x100 /* call original handler of returned opcode */
326326

327-
ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler);
327+
ZEND_API int zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler, const char *module_name);
328328
ZEND_API user_opcode_handler_t zend_get_user_opcode_handler(zend_uchar opcode);
329329

330330
ZEND_API zval *zend_get_zval_ptr(const zend_op *opline, int op_type, const znode_op *node, const zend_execute_data *execute_data);

Zend/zend_extensions.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
#include "zend_extensions.h"
21+
#include "zend_system_id.h"
2122

2223
ZEND_API zend_llist zend_extensions;
2324
ZEND_API uint32_t zend_extension_flags = 0;
@@ -249,18 +250,19 @@ ZEND_API void zend_extension_dispatch_message(int message, void *arg)
249250
}
250251

251252

252-
ZEND_API int zend_get_resource_handle(zend_extension *extension)
253+
ZEND_API int zend_get_resource_handle(const char *module_name)
253254
{
254255
if (last_resource_number<ZEND_MAX_RESERVED_RESOURCES) {
255-
extension->resource_number = last_resource_number;
256+
zend_add_system_entropy(module_name, "zend_get_resource_handle", &last_resource_number, sizeof(int));
256257
return last_resource_number++;
257258
} else {
258259
return -1;
259260
}
260261
}
261262

262-
ZEND_API int zend_get_op_array_extension_handle(void)
263+
ZEND_API int zend_get_op_array_extension_handle(const char *module_name)
263264
{
265+
zend_add_system_entropy(module_name, "zend_get_op_array_extension_handle", &zend_op_array_extension_handles, sizeof(int));
264266
return zend_op_array_extension_handles++;
265267
}
266268

Zend/zend_extensions.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ struct _zend_extension {
113113
BEGIN_EXTERN_C()
114114
extern ZEND_API int zend_op_array_extension_handles;
115115

116-
ZEND_API int zend_get_resource_handle(zend_extension *extension);
117-
ZEND_API int zend_get_op_array_extension_handle(void);
116+
ZEND_API int zend_get_resource_handle(const char *module_name);
117+
ZEND_API int zend_get_op_array_extension_handle(const char *module_name);
118118
ZEND_API void zend_extension_dispatch_message(int message, void *arg);
119119
END_EXTERN_C()
120120

Zend/zend_system_id.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Authors: Sammy Kaye Powers <[email protected]> |
14+
| Dmitry Stogov <[email protected]> |
15+
+----------------------------------------------------------------------+
16+
*/
17+
18+
#include "php.h"
19+
#include "zend_system_id.h"
20+
#include "zend_extensions.h"
21+
#include "ext/standard/md5.h"
22+
#include "ext/hash/php_hash.h"
23+
24+
ZEND_API char zend_system_id[32];
25+
26+
static PHP_MD5_CTX context;
27+
static int finalized = 0;
28+
29+
ZEND_API void zend_add_system_entropy(const char *module_name, const char *hook_name, const void *data, size_t size)
30+
{
31+
if (finalized == 0) {
32+
PHP_MD5Update(&context, module_name, strlen(module_name));
33+
PHP_MD5Update(&context, hook_name, strlen(hook_name));
34+
if (size) {
35+
PHP_MD5Update(&context, data, size);
36+
}
37+
}
38+
}
39+
40+
#define ZEND_BIN_ID "BIN_" ZEND_TOSTR(SIZEOF_INT) ZEND_TOSTR(SIZEOF_LONG) ZEND_TOSTR(SIZEOF_SIZE_T) ZEND_TOSTR(SIZEOF_ZEND_LONG) ZEND_TOSTR(ZEND_MM_ALIGNMENT)
41+
42+
void zend_startup_system_id(void)
43+
{
44+
PHP_MD5Init(&context);
45+
PHP_MD5Update(&context, PHP_VERSION, sizeof(PHP_VERSION)-1);
46+
PHP_MD5Update(&context, ZEND_EXTENSION_BUILD_ID, sizeof(ZEND_EXTENSION_BUILD_ID)-1);
47+
PHP_MD5Update(&context, ZEND_BIN_ID, sizeof(ZEND_BIN_ID)-1);
48+
if (strstr(PHP_VERSION, "-dev") != 0) {
49+
/* Development versions may be changed from build to build */
50+
PHP_MD5Update(&context, __DATE__, sizeof(__DATE__)-1);
51+
PHP_MD5Update(&context, __TIME__, sizeof(__TIME__)-1);
52+
}
53+
zend_system_id[0] = '\0';
54+
}
55+
56+
#define ZEND_HOOK_COMPILE_FILE (1 << 0)
57+
#define ZEND_HOOK_EXECUTE_EX (1 << 1)
58+
#define ZEND_HOOK_EXECUTE_INTERNAL (1 << 2)
59+
60+
void zend_finalize_system_id(void)
61+
{
62+
unsigned char digest[16];
63+
zend_long hooks = 0;
64+
65+
if (zend_compile_file != compile_file) {
66+
hooks |= ZEND_HOOK_COMPILE_FILE;
67+
}
68+
if (zend_execute_ex != execute_ex) {
69+
hooks |= ZEND_HOOK_EXECUTE_EX;
70+
}
71+
if (zend_execute_internal) {
72+
hooks |= ZEND_HOOK_EXECUTE_INTERNAL;
73+
}
74+
PHP_MD5Update(&context, &hooks, sizeof(zend_long));
75+
76+
PHP_MD5Final(digest, &context);
77+
php_hash_bin2hex(zend_system_id, digest, sizeof digest);
78+
finalized = 1;
79+
}

Zend/zend_system_id.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
+----------------------------------------------------------------------+
3+
| Copyright (c) The PHP Group |
4+
+----------------------------------------------------------------------+
5+
| This source file is subject to version 3.01 of the PHP license, |
6+
| that is bundled with this package in the file LICENSE, and is |
7+
| available through the world-wide-web at the following url: |
8+
| http://www.php.net/license/3_01.txt |
9+
| If you did not receive a copy of the PHP license and are unable to |
10+
| obtain it through the world-wide-web, please send a note to |
11+
| [email protected] so we can mail you a copy immediately. |
12+
+----------------------------------------------------------------------+
13+
| Author: Sammy Kaye Powers <[email protected]> |
14+
+----------------------------------------------------------------------+
15+
*/
16+
17+
#ifndef ZEND_SYSTEM_ID_H
18+
#define ZEND_SYSTEM_ID_H
19+
20+
BEGIN_EXTERN_C()
21+
/* True global; Write-only during MINIT/startup */
22+
extern ZEND_API char zend_system_id[32];
23+
24+
ZEND_API void zend_add_system_entropy(const char *module_name, const char *hook_name, const void *data, size_t size);
25+
END_EXTERN_C()
26+
27+
void zend_startup_system_id(void);
28+
void zend_finalize_system_id(void);
29+
30+
#endif /* ZEND_SYSTEM_ID_H */

configure.ac

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1460,7 +1460,8 @@ PHP_ADD_SOURCES(Zend, \
14601460
zend_iterators.c zend_interfaces.c zend_exceptions.c zend_strtod.c zend_gc.c \
14611461
zend_closures.c zend_weakrefs.c zend_float.c zend_string.c zend_signal.c zend_generators.c \
14621462
zend_virtual_cwd.c zend_ast.c zend_objects.c zend_object_handlers.c zend_objects_API.c \
1463-
zend_default_classes.c zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_gdb.c, \
1463+
zend_default_classes.c zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_gdb.c \
1464+
zend_system_id.c, \
14641465
-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
14651466

14661467
PHP_ADD_BUILD_DIR(main main/streams)

ext/opcache/Optimizer/zend_func_info.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -973,11 +973,10 @@ uint32_t zend_get_func_info(
973973

974974
int zend_func_info_startup(void)
975975
{
976-
zend_extension dummy;
977976
size_t i;
978977

979978
if (zend_func_info_rid == -1) {
980-
zend_func_info_rid = zend_get_resource_handle(&dummy);
979+
zend_func_info_rid = zend_get_resource_handle("Zend Optimizer");
981980
if (zend_func_info_rid < 0) {
982981
return FAILURE;
983982
}

ext/opcache/ZendAccelerator.c

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ ZEND_TSRMLS_CACHE_DEFINE()
106106
zend_accel_shared_globals *accel_shared_globals = NULL;
107107

108108
/* true globals, no need for thread safety */
109-
char accel_system_id[32];
110109
#ifdef ZEND_WIN32
111110
char accel_uname_id[32];
112111
#endif
@@ -126,7 +125,6 @@ static zif_handler orig_chdir = NULL;
126125
static ZEND_INI_MH((*orig_include_path_on_modify)) = NULL;
127126
static int (*orig_post_startup_cb)(void);
128127

129-
static void accel_gen_system_id(void);
130128
static int accel_post_startup(void);
131129
static int accel_finish_startup(void);
132130

@@ -2713,26 +2711,6 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals)
27132711
memset(accel_globals, 0, sizeof(zend_accel_globals));
27142712
}
27152713

2716-
#define ZEND_BIN_ID "BIN_" ZEND_TOSTR(SIZEOF_INT) ZEND_TOSTR(SIZEOF_LONG) ZEND_TOSTR(SIZEOF_SIZE_T) ZEND_TOSTR(SIZEOF_ZEND_LONG) ZEND_TOSTR(ZEND_MM_ALIGNMENT)
2717-
2718-
static void accel_gen_system_id(void)
2719-
{
2720-
PHP_MD5_CTX context;
2721-
unsigned char digest[16];
2722-
2723-
PHP_MD5Init(&context);
2724-
PHP_MD5Update(&context, PHP_VERSION, sizeof(PHP_VERSION)-1);
2725-
PHP_MD5Update(&context, ZEND_EXTENSION_BUILD_ID, sizeof(ZEND_EXTENSION_BUILD_ID)-1);
2726-
PHP_MD5Update(&context, ZEND_BIN_ID, sizeof(ZEND_BIN_ID)-1);
2727-
if (strstr(PHP_VERSION, "-dev") != 0) {
2728-
/* Development versions may be changed from build to build */
2729-
PHP_MD5Update(&context, __DATE__, sizeof(__DATE__)-1);
2730-
PHP_MD5Update(&context, __TIME__, sizeof(__TIME__)-1);
2731-
}
2732-
PHP_MD5Final(digest, &context);
2733-
php_hash_bin2hex(accel_system_id, digest, sizeof digest);
2734-
}
2735-
27362714
#ifdef HAVE_HUGE_CODE_PAGES
27372715
# ifndef _WIN32
27382716
# include <sys/mman.h>
@@ -2917,8 +2895,6 @@ static int accel_startup(zend_extension *extension)
29172895
# endif
29182896
#endif
29192897

2920-
accel_gen_system_id();
2921-
29222898
if (start_accel_module() == FAILURE) {
29232899
accel_startup_ok = 0;
29242900
zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": module registration failed!");

ext/opcache/ZendAccelerator.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ typedef struct _zend_accel_shared_globals {
289289
zend_string_table interned_strings;
290290
} zend_accel_shared_globals;
291291

292-
extern char accel_system_id[32];
293292
#ifdef ZEND_WIN32
294293
extern char accel_uname_id[32];
295294
#endif

ext/opcache/jit/zend_jit.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3761,7 +3761,7 @@ ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, zend_bool reattached)
37613761
return FAILURE;
37623762
}
37633763

3764-
zend_jit_profile_counter_rid = zend_get_op_array_extension_handle();
3764+
zend_jit_profile_counter_rid = zend_get_op_array_extension_handle(ACCELERATOR_PRODUCT_NAME);
37653765

37663766
#ifdef HAVE_GDB
37673767
zend_jit_gdb_init();

ext/opcache/shared_alloc_win32.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "zend_shared_alloc.h"
2525
#include "zend_accelerator_util_funcs.h"
2626
#include "zend_execute.h"
27+
#include "zend_system_id.h"
2728
#include "SAPI.h"
2829
#include "tsrm_win32.h"
2930
#include "win32/winutil.h"
@@ -70,7 +71,7 @@ static void zend_win_error_message(int type, char *msg, int err)
7071
static char *create_name_with_username(char *name)
7172
{
7273
static char newname[MAXPATHLEN + 32 + 4 + 1 + 32 + 21];
73-
snprintf(newname, sizeof(newname) - 1, "%s@%.32s@%.20s@%.32s", name, accel_uname_id, sapi_module.name, accel_system_id);
74+
snprintf(newname, sizeof(newname) - 1, "%s@%.32s@%.20s@%.32s", name, accel_uname_id, sapi_module.name, zend_system_id);
7475

7576
return newname;
7677
}
@@ -86,7 +87,7 @@ static char *get_mmap_base_file(void)
8687
l--;
8788
}
8889

89-
snprintf(windir + l, sizeof(windir) - l - 1, "\\%s@%.32s@%.20s@%.32s", ACCEL_FILEMAP_BASE, accel_uname_id, sapi_module.name, accel_system_id);
90+
snprintf(windir + l, sizeof(windir) - l - 1, "\\%s@%.32s@%.20s@%.32s", ACCEL_FILEMAP_BASE, accel_uname_id, sapi_module.name, zend_system_id);
9091

9192
return windir;
9293
}

ext/opcache/zend_file_cache.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "zend_vm.h"
2323
#include "zend_interfaces.h"
2424
#include "zend_attributes.h"
25+
#include "zend_system_id.h"
2526

2627
#include "php.h"
2728
#ifdef ZEND_WIN32
@@ -876,7 +877,7 @@ static void zend_file_cache_serialize(zend_persistent_script *script,
876877
zend_persistent_script *new_script;
877878

878879
memcpy(info->magic, "OPCACHE", 8);
879-
memcpy(info->system_id, accel_system_id, 32);
880+
memcpy(info->system_id, zend_system_id, 32);
880881
info->mem_size = script->size;
881882
info->str_size = 0;
882883
info->script_offset = (char*)script - (char*)script->mem;
@@ -906,7 +907,7 @@ static char *zend_file_cache_get_bin_file_path(zend_string *script_path)
906907
filename = emalloc(len + 33 + ZSTR_LEN(script_path) + sizeof(SUFFIX));
907908
memcpy(filename, ZCG(accel_directives).file_cache, len);
908909
filename[len] = '/';
909-
memcpy(filename + len + 1, accel_system_id, 32);
910+
memcpy(filename + len + 1, zend_system_id, 32);
910911
memcpy(filename + len + 33, ZSTR_VAL(script_path), ZSTR_LEN(script_path));
911912
memcpy(filename + len + 33 + ZSTR_LEN(script_path), SUFFIX, sizeof(SUFFIX));
912913
#else
@@ -920,7 +921,7 @@ static char *zend_file_cache_get_bin_file_path(zend_string *script_path)
920921
len += 1 + 32;
921922
filename[len] = '\\';
922923

923-
memcpy(filename + len + 1, accel_system_id, 32);
924+
memcpy(filename + len + 1, zend_system_id, 32);
924925

925926
if (ZSTR_LEN(script_path) >= 7 && ':' == ZSTR_VAL(script_path)[4] && '/' == ZSTR_VAL(script_path)[5] && '/' == ZSTR_VAL(script_path)[6]) {
926927
/* phar:// or file:// */
@@ -1672,7 +1673,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
16721673
efree(filename);
16731674
return NULL;
16741675
}
1675-
if (memcmp(info.system_id, accel_system_id, 32) != 0) {
1676+
if (memcmp(info.system_id, zend_system_id, 32) != 0) {
16761677
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong \"system_id\")\n", filename);
16771678
zend_file_cache_flock(fd, LOCK_UN);
16781679
close(fd);

main/main.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
#include "zend_extensions.h"
7272
#include "zend_ini.h"
7373
#include "zend_dtrace.h"
74+
#include "zend_system_id.h"
7475

7576
#include "php_content_types.h"
7677
#include "php_ticks.h"
@@ -2239,6 +2240,9 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
22392240
zend_set_utility_values(&zuv);
22402241
php_startup_sapi_content_types();
22412242

2243+
/* Begin to fingerprint the process state */
2244+
zend_startup_system_id();
2245+
22422246
/* startup extensions statically compiled in */
22432247
if (php_register_internal_extensions_func() == FAILURE) {
22442248
php_printf("Unable to start builtin modules\n");
@@ -2282,6 +2286,9 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
22822286
module->info_func = PHP_MINFO(php_core);
22832287
}
22842288

2289+
/* Extensions that add engine hooks after this point do so at their own peril */
2290+
zend_finalize_system_id();
2291+
22852292
module_initialized = 1;
22862293

22872294
if (zend_post_startup() != SUCCESS) {

win32/build/config.w32

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \
237237
zend_object_handlers.c zend_objects_API.c \
238238
zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c zend_weakrefs.c \
239239
zend_float.c zend_string.c zend_generators.c zend_virtual_cwd.c zend_ast.c \
240-
zend_inheritance.c zend_smart_str.c zend_cpuinfo.c");
240+
zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_system_id.c");
241241

242242
ADD_FLAG("CFLAGS_BD_ZEND", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
243243
if (VS_TOOLSET && VCVERS >= 1914) {

0 commit comments

Comments
 (0)