Repository navigation
dl() segfaults when module is already loaded #9589
Copy link
Copy link
Closed
Description
Description
The following code:
<?php
print("enable_dl: ".ini_get("enable_dl"));
dl("xml.so");Resulted in this output:
enable_dl: 1
Warning: Module "xml" is already loaded in Unknown on line 0
Segmentation fault (core dumped)
But I expected this output instead:
enable_dl: 1
Warning: Module "xml" is already loaded in Unknown on line 0
Working example:
% php --version
PHP 8.1.10 (cli) (built: Sep 16 2022 15:09:44) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.1.10, Copyright (c) Zend Technologies
% php -m
[PHP Modules]
Core
date
hash
json
libxml
mysqlnd
openssl
pcre
Reflection
SPL
standard
xml
zlib
[Zend Modules]
% cat > sigsegv.php <<EOF
? <?php
? print("enable_dl: ".ini_get("enable_dl"));
? dl("xml.so");
? EOF
% php sigsegv.php
enable_dl: 1
Warning: Module "xml" is already loaded in Unknown on line 0
Failing example:
% php --version
PHP 8.2.0RC2 (cli) (built: Sep 20 2022 20:24:30) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.0RC2, Copyright (c) Zend Technologies
% php -m
[PHP Modules]
Core
date
hash
json
libxml
mysqlnd
openssl
pcre
random
Reflection
SPL
standard
xml
zlib
[Zend Modules]
% cat > sigsegv.php <<EOF
? <?php
? print("enable_dl: ".ini_get("enable_dl"));
? dl("xml.so");
? EOF
% php sigsegv.php
enable_dl: 1
Warning: Module "xml" is already loaded in Unknown on line 0
Segmentation fault (core dumped)
% lldb --core php.core /usr/local/bin/php
(lldb) target create "/usr/local/bin/php" --core "php.core"
Core file '/tmp/php.core' (x86_64) was loaded.
Could not load history file
(lldb) bt all
* thread #1, name = 'php', stop reason = signal SIGSEGV
* frame #0: 0x00000000006939c3 php`___lldb_unnamed_symbol3142$$php + 19
frame #1: 0x000000000069b396 php`zend_hash_apply_with_argument + 118
frame #2: 0x000000000068e884 php`___lldb_unnamed_symbol3137$$php + 84
frame #3: 0x000000000069ac68 php`zend_hash_graceful_reverse_destroy + 536
frame #4: 0x0000000000683cc8 php`___lldb_unnamed_symbol3117$$php + 24
frame #5: 0x000000000060c189 php`php_module_shutdown + 41
frame #6: 0x0000000000772858 php`___lldb_unnamed_symbol4788$$php + 696
frame #7: 0x0000000000418fe0 php`_start + 256
(lldb)
It looks like a regression to me from 8.1 to 8.2.
PHP Version
PHP 8.2.0 RC2
Operating System
FreeBSD: 12.3-RELEASE-p7
Setup
Clean Poudriere throwaway Jails from FreeBSD ports, main branch.
Activity
[-]PHP 8.2.0 RC2 core dumps (SIGSEGV) when dl() is used[/-][+]A core dump (SIGSEGV) occurs when dl() is used[/+]cmb69 commentedon Sep 21, 2022
Indeed, I've stumbled upon this issue very recently, too.
arnaud-lb commentedon Sep 30, 2022
Smallest reproducer:
The first commit that crash is b63df3c
Backtrace:
Since this commit, the module entry lives in the shared library's data segment. This crashes because
ce->info.internal.modulepoints to the data segment of an unloaded module.clean_module_classesis called only for temporary modules, and temporary modules are unloaded first (because they are loaded last). So when it's called, the class table can not contain classes of unloaded modules.However, in this case the
xmlmodule is the first of the modules tables (so it's unloaded last), but it's considered a temporary module becausemodule_entry->typeis set toMODULE_TEMPORARYwhen its loaded a second time inphp-src/ext/standard/dl.c
Line 228 in ed0f1f0
So,
zlibis unloaded first (its classes are not cleared because it's a permanent module), thenxmlis unloaded and clean_module_classes is called because it's considered a temporary module.Fix phpGH-9589: dl() segfaults when module is already loaded
[-]A core dump (SIGSEGV) occurs when dl() is used[/-][+]dl() segfaults when module is already loaded[/+]Fix GH-9589: dl() segfaults when module is already loaded
Merge branch 'PHP-8.2'