Skip to content

dl() segfaults when module is already loaded #9589

Closed

Description

@michael-o

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

  1. changed the title [-]PHP 8.2.0 RC2 core dumps (SIGSEGV) when dl() is used[/-] [+]A core dump (SIGSEGV) occurs when dl() is used[/+] on Sep 21, 2022
  2. cmb69 commented on Sep 21, 2022

    @cmb69
    Member

    Indeed, I've stumbled upon this issue very recently, too.

  3. self-assigned this
    on Sep 21, 2022
  4. arnaud-lb commented on Sep 30, 2022

    @arnaud-lb
    Member

    Smallest reproducer:

    ./configure --disable-all --enable-debug --enable-xml=shared --with-libxml --with-zlib=shared
    make
    sapi/cli/php -n -dextension_dir=$(pwd)/modules -dextension=xml.so -dextension=zlib.so -r 'dl("xml.so");'
    

    The first commit that crash is b63df3c

    Backtrace:

    0x000055555598bbbc in clean_module_class (el=0x555556339db0, arg=0x7fffffffda1c) at Zend/zend_API.c:2940
    2940		if (ce->type == ZEND_INTERNAL_CLASS && ce->info.internal.module->module_number == module_number) {
    (gdb) bt
    #0  0x000055555598bbbc in clean_module_class (el=0x555556339db0, arg=0x7fffffffda1c) at Zend/zend_API.c:2940
    #1  0x000055555599b04c in zend_hash_apply_with_argument (ht=0x555556234960, apply_func=0x55555598bb82 <clean_module_class>, argument=0x7fffffffda1c) at Zend/zend_hash.c:2044
    #2  0x000055555598bc01 in clean_module_classes (module_number=12) at Zend/zend_API.c:2950
    #3  0x000055555598bc56 in module_destructor (module=0x7ffff7fb3300 <xml_module_entry>) at Zend/zend_API.c:2960
    #4  0x000055555597d46e in module_destructor_zval (zv=0x7fffffffdac0) at Zend/zend.c:844
    #5  0x0000555555998d4d in _zend_hash_del_el_ex (ht=0x55555621a7e0 <module_registry>, idx=9, p=0x555556242bb0, prev=0x0) at Zend/zend_hash.c:1408
    #6  0x0000555555998e47 in _zend_hash_del_el (ht=0x55555621a7e0 <module_registry>, idx=9, p=0x555556242bb0) at Zend/zend_hash.c:1435
    #7  0x000055555599ac28 in zend_hash_graceful_reverse_destroy (ht=0x55555621a7e0 <module_registry>) at Zend/zend_hash.c:1960
    #8  0x00005555559895b5 in zend_destroy_modules () at Zend/zend_API.c:2336
    #9  0x000055555597d84e in zend_shutdown () at Zend/zend.c:1089
    #10 0x00005555558d8aeb in php_module_shutdown () at main/main.c:2398
    #11 0x0000555555afc115 in main (argc=7, argv=0x5555562343d0) at sapi/cli/php_cli.c:1347
    
    

    Since this commit, the module entry lives in the shared library's data segment. This crashes because ce->info.internal.module points to the data segment of an unloaded module.

    clean_module_classes is 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 xml module is the first of the modules tables (so it's unloaded last), but it's considered a temporary module because module_entry->type is set to MODULE_TEMPORARY when its loaded a second time in

    module_entry->type = type;

    So, zlib is unloaded first (its classes are not cleared because it's a permanent module), then xml is unloaded and clean_module_classes is called because it's considered a temporary module.

  5. removed their assignment
    on Sep 30, 2022
  6. added a commit that references this issue on Oct 7, 2022
    6d9c84d
  7. changed the title [-]A core dump (SIGSEGV) occurs when dl() is used[/-] [+]dl() segfaults when module is already loaded[/+] on Oct 7, 2022
  8. added a commit that references this issue on Oct 10, 2022
    6e0505b
  9. added a commit that references this issue on Oct 10, 2022
    2979743
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions