]> granicus.if.org Git - php/commitdiff
Add system ID entropy API
authorSammy Kaye Powers <sammyk@php.net>
Thu, 16 Jul 2020 23:31:10 +0000 (16:31 -0700)
committerSammy Kaye Powers <sammyk@php.net>
Fri, 18 Sep 2020 21:26:44 +0000 (14:26 -0700)
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.

Closes GH-5871

16 files changed:
UPGRADING.INTERNALS
Zend/zend_execute.c
Zend/zend_extensions.c
Zend/zend_extensions.h
Zend/zend_observer.c
Zend/zend_system_id.c [new file with mode: 0644]
Zend/zend_system_id.h [new file with mode: 0644]
configure.ac
ext/opcache/Optimizer/zend_func_info.c
ext/opcache/ZendAccelerator.c
ext/opcache/ZendAccelerator.h
ext/opcache/jit/zend_jit.c
ext/opcache/shared_alloc_win32.c
ext/opcache/zend_file_cache.c
main/main.c
win32/build/config.w32

index 1815a9c264b21841209fa538f76d745c54df2d3d..ebced18ff327990fd416193d70b07e9e435edc8f 100644 (file)
@@ -369,6 +369,10 @@ PHP 8.0 INTERNALS UPGRADE NOTES
         - zend_stack_is_empty()
         - zend_ts_hash_exists()
         - zend_ts_hash_index_exists()
+     9. Argument void to const char* in Zend Engine 4.0:
+        - zend_get_op_array_extension_handle()
+     10. Argument zend_extension to const char* in Zend Engine 4.0:
+        - zend_get_resource_handle()
 
   u. Instead of overwriting zend_error_cb extensions with debugging, monitoring
      use-cases catching Errors/Exceptions are strongly encouraged to use
index e2e5aa83915d76b0dbb693e7fb5ebdea98caaa84..ab231f952f0ca48302c9547fd16e86e60f160b40 100644 (file)
@@ -41,6 +41,7 @@
 #include "zend_type_info.h"
 #include "zend_smart_str.h"
 #include "zend_observer.h"
+#include "zend_system_id.h"
 
 /* Virtual current working directory support */
 #include "zend_virtual_cwd.h"
index c44a2f30937525293de19398c80f251a96c13899..1741182ba3be00ecda667f4f845ea4128d4f69ba 100644 (file)
@@ -18,6 +18,7 @@
 */
 
 #include "zend_extensions.h"
+#include "zend_system_id.h"
 
 ZEND_API zend_llist zend_extensions;
 ZEND_API uint32_t zend_extension_flags = 0;
@@ -247,18 +248,19 @@ ZEND_API void zend_extension_dispatch_message(int message, void *arg)
 }
 
 
-ZEND_API int zend_get_resource_handle(zend_extension *extension)
+ZEND_API int zend_get_resource_handle(const char *module_name)
 {
        if (last_resource_number<ZEND_MAX_RESERVED_RESOURCES) {
-               extension->resource_number = last_resource_number;
+               zend_add_system_entropy(module_name, "zend_get_resource_handle", &last_resource_number, sizeof(int));
                return last_resource_number++;
        } else {
                return -1;
        }
 }
 
-ZEND_API int zend_get_op_array_extension_handle(void)
+ZEND_API int zend_get_op_array_extension_handle(const char *module_name)
 {
+       zend_add_system_entropy(module_name, "zend_get_op_array_extension_handle", &zend_op_array_extension_handles, sizeof(int));
        return zend_op_array_extension_handles++;
 }
 
index a26a6f9fc7e253a38b43207f8d92c7dd5b650dfa..708a1fe02a465eeefa230b96f5007af50b2299b4 100644 (file)
@@ -113,8 +113,8 @@ struct _zend_extension {
 BEGIN_EXTERN_C()
 extern ZEND_API int zend_op_array_extension_handles;
 
-ZEND_API int zend_get_resource_handle(zend_extension *extension);
-ZEND_API int zend_get_op_array_extension_handle(void);
+ZEND_API int zend_get_resource_handle(const char *module_name);
+ZEND_API int zend_get_op_array_extension_handle(const char *module_name);
 ZEND_API void zend_extension_dispatch_message(int message, void *arg);
 END_EXTERN_C()
 
index 5544039c3e87fc97bd89d16b0f58f399353181f0..68cf43ce66248ed10b9e7fdf8384e4cfbeccd53d 100644 (file)
@@ -50,7 +50,7 @@ ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init init) {
        /* We don't want to get an extension handle unless an ext installs an observer */
        if (!ZEND_OBSERVER_ENABLED) {
                zend_observer_fcall_op_array_extension =
-                       zend_get_op_array_extension_handle();
+                       zend_get_op_array_extension_handle("Zend Observer");
 
                /* ZEND_CALL_TRAMPOLINE has SPEC(OBSERVER) but zend_init_call_trampoline_op()
                 * is called before any extensions have registered as an observer. So we
diff --git a/Zend/zend_system_id.c b/Zend/zend_system_id.c
new file mode 100644 (file)
index 0000000..93bca57
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+   +----------------------------------------------------------------------+
+   | Copyright (c) The PHP Group                                          |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Authors: Sammy Kaye Powers <sammyk@php.net>                          |
+   |          Dmitry Stogov <dmitry@php.net>                              |
+   +----------------------------------------------------------------------+
+ */
+
+#include "php.h"
+#include "zend_system_id.h"
+#include "zend_extensions.h"
+#include "ext/standard/md5.h"
+#include "ext/hash/php_hash.h"
+
+ZEND_API char zend_system_id[32];
+
+static PHP_MD5_CTX context;
+static int finalized = 0;
+
+ZEND_API ZEND_RESULT_CODE zend_add_system_entropy(const char *module_name, const char *hook_name, const void *data, size_t size)
+{
+       if (finalized == 0) {
+               PHP_MD5Update(&context, module_name, strlen(module_name));
+               PHP_MD5Update(&context, hook_name, strlen(hook_name));
+               if (size) {
+                       PHP_MD5Update(&context, data, size);
+               }
+               return SUCCESS;
+       }
+       return FAILURE;
+}
+
+#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)
+
+void zend_startup_system_id(void)
+{
+       PHP_MD5Init(&context);
+       PHP_MD5Update(&context, PHP_VERSION, sizeof(PHP_VERSION)-1);
+       PHP_MD5Update(&context, ZEND_EXTENSION_BUILD_ID, sizeof(ZEND_EXTENSION_BUILD_ID)-1);
+       PHP_MD5Update(&context, ZEND_BIN_ID, sizeof(ZEND_BIN_ID)-1);
+       if (strstr(PHP_VERSION, "-dev") != 0) {
+               /* Development versions may be changed from build to build */
+               PHP_MD5Update(&context, __DATE__, sizeof(__DATE__)-1);
+               PHP_MD5Update(&context, __TIME__, sizeof(__TIME__)-1);
+       }
+       zend_system_id[0] = '\0';
+}
+
+#define ZEND_HOOK_AST_PROCESS      (1 << 0)
+#define ZEND_HOOK_COMPILE_FILE     (1 << 1)
+#define ZEND_HOOK_EXECUTE_EX       (1 << 2)
+#define ZEND_HOOK_EXECUTE_INTERNAL (1 << 3)
+
+void zend_finalize_system_id(void)
+{
+       unsigned char digest[16];
+       zend_uchar hooks = 0;
+
+       if (zend_ast_process) {
+               hooks |= ZEND_HOOK_AST_PROCESS;
+       }
+       if (zend_compile_file != compile_file) {
+               hooks |= ZEND_HOOK_COMPILE_FILE;
+       }
+       if (zend_execute_ex != execute_ex) {
+               hooks |= ZEND_HOOK_EXECUTE_EX;
+       }
+       if (zend_execute_internal) {
+               hooks |= ZEND_HOOK_EXECUTE_INTERNAL;
+       }
+       PHP_MD5Update(&context, &hooks, sizeof hooks);
+
+       for (int16_t i = 0; i < 256; i++) {
+               if (zend_get_user_opcode_handler((zend_uchar) i) != NULL) {
+                       PHP_MD5Update(&context, &i, sizeof i);
+               }
+       }
+
+       PHP_MD5Final(digest, &context);
+       php_hash_bin2hex(zend_system_id, digest, sizeof digest);
+       finalized = 1;
+}
diff --git a/Zend/zend_system_id.h b/Zend/zend_system_id.h
new file mode 100644 (file)
index 0000000..cea111e
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+   +----------------------------------------------------------------------+
+   | Copyright (c) The PHP Group                                          |
+   +----------------------------------------------------------------------+
+   | This source file is subject to version 3.01 of the PHP license,      |
+   | that is bundled with this package in the file LICENSE, and is        |
+   | available through the world-wide-web at the following url:           |
+   | http://www.php.net/license/3_01.txt                                  |
+   | If you did not receive a copy of the PHP license and are unable to   |
+   | obtain it through the world-wide-web, please send a note to          |
+   | license@php.net so we can mail you a copy immediately.               |
+   +----------------------------------------------------------------------+
+   | Author: Sammy Kaye Powers <sammyk@php.net>                           |
+   +----------------------------------------------------------------------+
+*/
+
+#ifndef ZEND_SYSTEM_ID_H
+#define ZEND_SYSTEM_ID_H
+
+BEGIN_EXTERN_C()
+/* True global; Write-only during MINIT/startup */
+extern ZEND_API char zend_system_id[32];
+
+ZEND_API ZEND_RESULT_CODE zend_add_system_entropy(const char *module_name, const char *hook_name, const void *data, size_t size);
+END_EXTERN_C()
+
+void zend_startup_system_id(void);
+void zend_finalize_system_id(void);
+
+#endif /* ZEND_SYSTEM_ID_H */
index f82783a03b04e96f6d1e98d82cc1e4d50b941efa..a6ff4e707aa38185b6fdbf2f19ea8d06c109e8ad 100644 (file)
@@ -1464,7 +1464,7 @@ PHP_ADD_SOURCES(Zend, \
     zend_closures.c zend_weakrefs.c zend_float.c zend_string.c zend_signal.c zend_generators.c \
     zend_virtual_cwd.c zend_ast.c zend_objects.c zend_object_handlers.c zend_objects_API.c \
     zend_default_classes.c zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_gdb.c \
-    zend_observer.c, \
+    zend_observer.c zend_system_id.c, \
        -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
 
 PHP_ADD_BUILD_DIR(main main/streams)
index edbc068dda2ece035aa455698451a95cc01ca602..6b8cb33f5690b926ef3d48caf7a1e138b13bcd3a 100644 (file)
@@ -942,11 +942,10 @@ uint32_t zend_get_func_info(
 
 int zend_func_info_startup(void)
 {
-       zend_extension dummy;
        size_t i;
 
        if (zend_func_info_rid == -1) {
-               zend_func_info_rid = zend_get_resource_handle(&dummy);
+               zend_func_info_rid = zend_get_resource_handle("Zend Optimizer");
                if (zend_func_info_rid < 0) {
                        return FAILURE;
                }
index 71af3203dca383f3081f24473c02ef077def6520..23ea50a4e3c49a06252b3e1a11f5c334892fce21 100644 (file)
@@ -106,7 +106,6 @@ ZEND_TSRMLS_CACHE_DEFINE()
 zend_accel_shared_globals *accel_shared_globals = NULL;
 
 /* true globals, no need for thread safety */
-char accel_system_id[32];
 #ifdef ZEND_WIN32
 char accel_uname_id[32];
 #endif
@@ -126,7 +125,6 @@ static zif_handler orig_chdir = NULL;
 static ZEND_INI_MH((*orig_include_path_on_modify)) = NULL;
 static zend_result (*orig_post_startup_cb)(void);
 
-static void accel_gen_system_id(void);
 static zend_result accel_post_startup(void);
 static int accel_finish_startup(void);
 
@@ -2709,46 +2707,6 @@ static void accel_globals_ctor(zend_accel_globals *accel_globals)
        memset(accel_globals, 0, sizeof(zend_accel_globals));
 }
 
-#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)
-
-static void accel_gen_system_id(void)
-{
-       PHP_MD5_CTX context;
-       unsigned char digest[16];
-       zend_module_entry *module;
-       zend_extension *extension;
-       zend_llist_position pos;
-
-       PHP_MD5Init(&context);
-       PHP_MD5Update(&context, PHP_VERSION, sizeof(PHP_VERSION)-1);
-       PHP_MD5Update(&context, ZEND_EXTENSION_BUILD_ID, sizeof(ZEND_EXTENSION_BUILD_ID)-1);
-       PHP_MD5Update(&context, ZEND_BIN_ID, sizeof(ZEND_BIN_ID)-1);
-       if (strstr(PHP_VERSION, "-dev") != 0) {
-               /* Development versions may be changed from build to build */
-               PHP_MD5Update(&context, __DATE__, sizeof(__DATE__)-1);
-               PHP_MD5Update(&context, __TIME__, sizeof(__TIME__)-1);
-       }
-       /* Modules may have changed after restart which can cause dangling pointers from
-     * custom opcode handlers in the second-level cache files
-     */
-       ZEND_HASH_FOREACH_PTR(&module_registry, module) {
-               PHP_MD5Update(&context, module->name, strlen(module->name));
-               if (module->version != NULL) {
-                       PHP_MD5Update(&context, module->version, strlen(module->version));
-               }
-       } ZEND_HASH_FOREACH_END();
-       extension = (zend_extension *) zend_llist_get_first_ex(&zend_extensions, &pos);
-       while (extension) {
-               PHP_MD5Update(&context, extension->name, strlen(extension->name));
-               if (extension->version != NULL) {
-                       PHP_MD5Update(&context, extension->version, strlen(extension->version));
-               }
-               extension = (zend_extension *) zend_llist_get_next_ex(&zend_extensions, &pos);
-       }
-       PHP_MD5Final(digest, &context);
-       php_hash_bin2hex(accel_system_id, digest, sizeof digest);
-}
-
 #ifdef HAVE_HUGE_CODE_PAGES
 # ifndef _WIN32
 #  include <sys/mman.h>
@@ -2933,8 +2891,6 @@ static int accel_startup(zend_extension *extension)
 # endif
 #endif
 
-       accel_gen_system_id();
-
        if (start_accel_module() == FAILURE) {
                accel_startup_ok = 0;
                zend_error(E_WARNING, ACCELERATOR_PRODUCT_NAME ": module registration failed!");
index 500647265cb9631476be114beb2e427007518f87..b9e3f2a81de835af19a2924c2b9b2dffa6fdc09f 100644 (file)
@@ -289,7 +289,6 @@ typedef struct _zend_accel_shared_globals {
        zend_string_table interned_strings;
 } zend_accel_shared_globals;
 
-extern char accel_system_id[32];
 #ifdef ZEND_WIN32
 extern char accel_uname_id[32];
 #endif
index 094f4d56d6d34d9e04913aa49832d4ca21db543f..348f15c4fccdff7e2ad8db26034d395ef7b68517 100644 (file)
@@ -4071,7 +4071,7 @@ ZEND_EXT_API int zend_jit_startup(void *buf, size_t size, zend_bool reattached)
                return FAILURE;
        }
 
-       zend_jit_profile_counter_rid = zend_get_op_array_extension_handle();
+       zend_jit_profile_counter_rid = zend_get_op_array_extension_handle(ACCELERATOR_PRODUCT_NAME);
 
 #ifdef HAVE_GDB
        zend_jit_gdb_init();
index 6cda6471044af8b94671810021ebcc3353eb5f87..06df5270d4b7b24eaec5527b9eeff4558e3ccf80 100644 (file)
@@ -24,6 +24,7 @@
 #include "zend_shared_alloc.h"
 #include "zend_accelerator_util_funcs.h"
 #include "zend_execute.h"
+#include "zend_system_id.h"
 #include "SAPI.h"
 #include "tsrm_win32.h"
 #include "win32/winutil.h"
@@ -71,7 +72,7 @@ static void zend_win_error_message(int type, char *msg, int err)
 static char *create_name_with_username(char *name)
 {
        static char newname[MAXPATHLEN + 32 + 4 + 1 + 32 + 21];
-       snprintf(newname, sizeof(newname) - 1, "%s@%.32s@%.20s@%.32s", name, accel_uname_id, sapi_module.name, accel_system_id);
+       snprintf(newname, sizeof(newname) - 1, "%s@%.32s@%.20s@%.32s", name, accel_uname_id, sapi_module.name, zend_system_id);
 
        return newname;
 }
index 581ef6a3921bb900eefb87d2e65ad68541a6780a..62a2d261ff27b69336bea2b7940380b004e74e59 100644 (file)
@@ -22,6 +22,7 @@
 #include "zend_vm.h"
 #include "zend_interfaces.h"
 #include "zend_attributes.h"
+#include "zend_system_id.h"
 
 #include "php.h"
 #ifdef ZEND_WIN32
@@ -884,7 +885,7 @@ static void zend_file_cache_serialize(zend_persistent_script   *script,
        zend_persistent_script *new_script;
 
        memcpy(info->magic, "OPCACHE", 8);
-       memcpy(info->system_id, accel_system_id, 32);
+       memcpy(info->system_id, zend_system_id, 32);
        info->mem_size = script->size;
        info->str_size = 0;
        info->script_offset = (char*)script - (char*)script->mem;
@@ -914,7 +915,7 @@ static char *zend_file_cache_get_bin_file_path(zend_string *script_path)
        filename = emalloc(len + 33 + ZSTR_LEN(script_path) + sizeof(SUFFIX));
        memcpy(filename, ZCG(accel_directives).file_cache, len);
        filename[len] = '/';
-       memcpy(filename + len + 1, accel_system_id, 32);
+       memcpy(filename + len + 1, zend_system_id, 32);
        memcpy(filename + len + 33, ZSTR_VAL(script_path), ZSTR_LEN(script_path));
        memcpy(filename + len + 33 + ZSTR_LEN(script_path), SUFFIX, sizeof(SUFFIX));
 #else
@@ -928,7 +929,7 @@ static char *zend_file_cache_get_bin_file_path(zend_string *script_path)
        len += 1 + 32;
        filename[len] = '\\';
 
-       memcpy(filename + len + 1, accel_system_id, 32);
+       memcpy(filename + len + 1, zend_system_id, 32);
 
        if (ZSTR_LEN(script_path) >= 7 && ':' == ZSTR_VAL(script_path)[4] && '/' == ZSTR_VAL(script_path)[5]  && '/' == ZSTR_VAL(script_path)[6]) {
                /* phar:// or file:// */
@@ -1688,7 +1689,7 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
                efree(filename);
                return NULL;
        }
-       if (memcmp(info.system_id, accel_system_id, 32) != 0) {
+       if (memcmp(info.system_id, zend_system_id, 32) != 0) {
                zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot read from file '%s' (wrong \"system_id\")\n", filename);
                zend_file_cache_flock(fd, LOCK_UN);
                close(fd);
index 103c10a06b2415a83ccc5a46b5a4307ea4527bfc..3667432f94a5f596a592d2d32f70bea8f2906cf2 100644 (file)
@@ -72,6 +72,7 @@
 #include "zend_ini.h"
 #include "zend_dtrace.h"
 #include "zend_observer.h"
+#include "zend_system_id.h"
 
 #include "php_content_types.h"
 #include "php_ticks.h"
@@ -2194,6 +2195,9 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
        zend_set_utility_values(&zuv);
        php_startup_sapi_content_types();
 
+       /* Begin to fingerprint the process state */
+       zend_startup_system_id();
+
        /* startup extensions statically compiled in */
        if (php_register_internal_extensions_func() == FAILURE) {
                php_printf("Unable to start builtin modules\n");
@@ -2237,6 +2241,9 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
                module->info_func = PHP_MINFO(php_core);
        }
 
+       /* Extensions that add engine hooks after this point do so at their own peril */
+       zend_finalize_system_id();
+
        module_initialized = 1;
 
        if (zend_post_startup() != SUCCESS) {
index 94e4cbe1c5fbf42800d900eb9ff549505b7de067..7eb6593acafad5606008fd6d9522161fe5789d50 100644 (file)
@@ -237,7 +237,7 @@ ADD_SOURCES("Zend", "zend_language_parser.c zend_language_scanner.c \
        zend_object_handlers.c zend_objects_API.c \
        zend_default_classes.c zend_execute.c zend_strtod.c zend_gc.c zend_closures.c zend_weakrefs.c \
        zend_float.c zend_string.c zend_generators.c zend_virtual_cwd.c zend_ast.c \
-       zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_observer.c");
+       zend_inheritance.c zend_smart_str.c zend_cpuinfo.c zend_observer.c zend_system_id.c");
 
 ADD_FLAG("CFLAGS_BD_ZEND", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
 if (VS_TOOLSET && VCVERS >= 1914) {