Do not use RTLD_DEEPBIND if dlmopen is available (#18612)

DL_LOAD now doesn't use RTLD_DEEPBIND deepbind anymore on platforms
where dlmopen with LM_ID_NEWLM is available:
this means shared library symbol isolation (if needed) must be enabled on
the user side when requiring libphp.so, by using dlmopen with LM_ID_NEWLM
instead of dlopen.
RTLD_DEEPBIND is still enabled when the Apache SAPI is in use.

Closes GH-10670.
This commit is contained in:
Daniil Gentili 2025-06-23 21:44:58 +02:00 committed by GitHub
parent 6eed02bacc
commit 591b3249da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 23 additions and 1 deletions

1
NEWS
View file

@ -58,6 +58,7 @@ PHP NEWS
. Added the pipe (|>) operator. (crell)
. Added support for `final` with constructor property promotion.
(DanielEScherzer)
. Do not use RTLD_DEEPBIND if dlmopen is available. (Daniil Gentili)
- Curl:
. Added curl_multi_get_handles(). (timwolla)

View file

@ -17,6 +17,12 @@ PHP 8.5 INTERNALS UPGRADE NOTES
- Core
. PG(arg_separator).input and PG(arg_separator).output are now `zend_string*`
instead of `char*`.
. DL_LOAD now doesn't use RTLD_DEEPBIND deepbind anymore on platforms
where dlmopen with LM_ID_NEWLM is available:
this means shared library symbol isolation (if needed) must be enabled on
the user side when requiring libphp.so, by using dlmopen with LM_ID_NEWLM
instead of dlopen.
RTLD_DEEPBIND is still enabled when the Apache SAPI is in use.
- Zend
. Added zend_safe_assign_to_variable_noref() function to safely assign

View file

@ -40,6 +40,8 @@
/* these variables are true statics/globals, and have to be mutex'ed on every access */
ZEND_API HashTable module_registry;
ZEND_API bool zend_dl_use_deepbind = false;
static zend_module_entry **module_request_startup_handlers;
static zend_module_entry **module_request_shutdown_handlers;
static zend_module_entry **module_post_deactivate_handlers;
@ -47,6 +49,11 @@ static zend_module_entry **modules_dl_loaded;
static zend_class_entry **class_cleanup_handlers;
ZEND_API void zend_set_dl_use_deepbind(bool use_deepbind)
{
zend_dl_use_deepbind = use_deepbind;
}
ZEND_API zend_result zend_get_parameters_array_ex(uint32_t param_count, zval *argument_array) /* {{{ */
{
zval *param_ptr;

View file

@ -343,6 +343,8 @@ typedef struct _zend_fcall_info_cache {
ZEND_API int zend_next_free_module(void);
BEGIN_EXTERN_C()
ZEND_API void zend_set_dl_use_deepbind(bool use_deepbind);
ZEND_API zend_result zend_get_parameters_array_ex(uint32_t param_count, zval *argument_array);
/* internal function to efficiently copy parameters when executing __call() */

View file

@ -165,7 +165,12 @@
# if defined(RTLD_GROUP) && defined(RTLD_WORLD) && defined(RTLD_PARENT)
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT)
# elif defined(RTLD_DEEPBIND) && !defined(__SANITIZE_ADDRESS__) && !__has_feature(memory_sanitizer)
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_DEEPBIND)
# if defined(LM_ID_NEWLM)
ZEND_API extern bool zend_dl_use_deepbind;
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | (zend_dl_use_deepbind ? RTLD_DEEPBIND : 0))
# else
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_DEEPBIND)
# endif
# else
# define DL_LOAD(libname) dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL)
# endif

View file

@ -466,6 +466,7 @@ php_apache_server_startup(apr_pool_t *pconf, apr_pool_t *plog, apr_pool_t *ptemp
{
void *data = NULL;
const char *userdata_key = "apache2hook_post_config";
zend_set_dl_use_deepbind(true);
/* Apache will load, unload and then reload a DSO module. This
* prevents us from starting PHP until the second load. */