Skip to content

PHP intl segfault (static build by musl gcc/g++ built with --enable-default-pie) #12442

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
henderkes opened this issue Oct 15, 2023 · 20 comments
Closed

Comments

@henderkes
Copy link

Description

The following code:

php --ri "intl"

Resulted in this output:

[root@alma static-php-cli]# ./buildroot/bin/php --ri "intl"

intl

Internationalization support => enabled
ICU version => 73.2
ICU Data version => 73.2
Segmentation fault (core dumped)
[root@alma static-php-cli]# gdb -q ./buildroot/bin/php
Reading symbols from ./buildroot/bin/php...
(gdb) run --ri "intl"
Starting program: /opt/static-php-cli/buildroot/bin/php --ri "intl"

intl

Internationalization support => enabled
ICU version => 73.2
ICU Data version => 73.2

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5db631b in __do_cleanup_push ()
(gdb) bt
#0  0x00007ffff5db631b in __do_cleanup_push ()
#1  0x00007ffff5daba93 in __pthread_once_full ()
#2  0x00007ffff5e68835 in ?? ()
#3  0x00007ffff5daba08 in pthread_mutex_unlock ()
#4  0x00007ffff7f7d878 in umtx_init::{lambda()#1}::operator()() const::storage ()
#5  0x000667a0e8022617 in ?? ()
#6  0x00007ffff7f7b360 in MAP_SYSTEM_ZONES ()
#7  0x00007fffffffcca0 in ?? ()
#8  0x0000000000000000 in ?? ()
(gdb) quit
A debugging session is active.

        Inferior 1 [process 1337827] will be killed.

Quit anyway? (y or n) y

But I expected this output instead:

[root@alma static-php-cli]# ./buildroot/bin/php --ri "intl"

intl

Internationalization support => enabled
ICU version => 73.2
ICU Data version => 73.2
ICU TZData version => 2023c
ICU Unicode version => 15.0

Directive => Local Value => Master Value
intl.default_locale => no value => no value
intl.error_level => 0 => 0
intl.use_exceptions => Off => Off

This happens with all versions of gcc >9. It happens with all version of php >= 8.0 and all versions of the icu library >= 71.1. Likewise, with all version of linux-headers >= 4. I didn't test lower versions.

Building musl-cross-make without --enable-default-pie fixes this issue!

To reproduce this, you may use static-php-cli with ./bin/spc build intl --build-cli --no-strip. It downloads a version of musl-cross-make that compiled gcc with --enable-default-pie hosted at https://musl.cc

To reproduce the fix, clone https://git.zv.io/toolchains/musl-cross-make.git, create a config.mak in the directory

FLAG = -g0 -O2 -Wno-error -fPIE
COMMON_CONFIG += CFLAGS="${FLAG}" CXXFLAGS="${FLAG}" LDFLAGS="-s"
BINUTILS_CONFIG += --enable-gold=yes
GCC_CONFIG += --enable-static-pie --disable-cet
#--enable-default-pie --disable-cet

CONFIG_SUB_REV = 888c8e3d5f7b
GCC_VER = 11.4.0
BINUTILS_VER = 2.40
MUSL_VER = 1.2.4
GMP_VER = 6.2.1
MPC_VER = 1.2.1
MPFR_VER = 4.1.0
LINUX_VER = 6.1.36

and build with make install -j TARGET=x86_64-linux-musl. The resulting c/c++ toolchain can now be used to compile php with the intl extension - but it won't support position independent executables generated using libphp.a.

The gcc/g++ built on musl-libc based distros such as alpine appears to be built with --enable-default-pie, but do not show the same problem. intl works.

For what it's worth, the following extensions compiled statically all work, except for intl:
./bin/spc build mbstring,mbregex,apcu,bcmath,calendar,ctype,curl,dom,exif,fileinfo,filter,gd,iconv,intl,ldap,xml,xmlreader,xmlwriter,simplexml,mysqli,mysqlnd,openssl,posix,pcntl,pdo_mysql,pdo_pgsql,pdo,pgsql,session,sysvsem,sodium,tokenizer,zlib,zip,opcache,snappy,imagick --with-libs=libpam,freetype,libavif,libjpeg,libwebp --build-embed --enable-zts

PHP Version

Operating System

Glibc based UNIX systems

@henderkes
Copy link
Author

In case it helps, I've uploaded a precompiled toolchain without --enable-static-pie here: https://github.com/DubbleClick/static-php-cli/releases/tag/tools

Version compiled with it can be found here: https://musl.cc/x86_64-linux-musl-cross.tgz

@devnexen
Copy link
Member

Would you be able to build a version with debug symbols then providing a backtrace ?

@henderkes
Copy link
Author

Of the musl toolchain? I'll certainly try!

@devnexen
Copy link
Member

I meant more passing the --debug to spc perharps.

@henderkes
Copy link
Author

The stacktrace I've posted before is already with php built without stripping symbols.

@devnexen
Copy link
Member

I do not see php calls, only icu api in your stacktrace but I ll try to reproduce a bit later.

@henderkes
Copy link
Author

I'm not sure how the ./php --ri "intl" works internally, I'll try to execute ./php -r "echo phpinfo();" instead.

@henderkes
Copy link
Author

henderkes commented Oct 15, 2023

I've compiled the gcc/g++ toolchain with debug symbols again and used that to compile php (replace -Os with -O0 in LinuxBuilder.php in spc if you want to use it for convenience) but got the same stacktrace.

[root@alma static-php-cli]# gdb -q ./buildroot/bin/php
Reading symbols from ./buildroot/bin/php...
(gdb) run -r "echo NumberFormatter::class; echo phpinfo();"
Starting program: /opt/static-php-cli/buildroot/bin/php -r "echo NumberFormatter::class; echo phpinfo();"
NumberFormatter
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff5c9f6ab in __do_cleanup_push ()
(gdb) bt
#0  0x00007ffff5c9f6ab in __do_cleanup_push ()
#1  0x00007ffff5c94e23 in __pthread_once_full ()
#2  0x00007fffffff85b0 in ?? ()
#3  0x00007ffff5c94d98 in pthread_mutex_unlock ()
#4  0x00007ffff7ec2098 in umtx_init::{lambda()#1}::operator()() const::storage ()
#5  0x000667a0e8022bcb in ?? ()
#6  0x00007ffff7ebfb80 in MAP_SYSTEM_ZONES ()
#7  0x00007fffffff84b0 in ?? ()
#8  0x0000000000000000 in ?? ()
(gdb) info locals
No symbol table info available.
(gdb) info args
No symbol table info available.

The toolchain with debug symbols can be found here as well: https://github.com/DubbleClick/static-php-cli/releases/tag/tools

Rough steps to set everything up:

mkdir /usr/local/musl
export PATH=/usr/local/musl/bin:$PATH
git clone -b cplusplus https://github.com/DubbleClick/static-php-cli.git
wget https://github.com/DubbleClick/static-php-cli/releases/download/tools/debug-musl.tgz
tar -xzf debug-musl.tgz
mv output/* /usr/local/musl
cd static-php-cli
chmod +x ./bin/spc
composer install
yes | ./bin/spc doctor
./bin/spc build intl --build-cli --enable-zts --debug --no-strip
./buildroot/bin/php --ri "intl"

-> segfault

If you replace the

wget https://github.com/DubbleClick/static-php-cli/releases/download/tools/debug-musl.tgz
tar -xzf debug-musl.tgz
mv output/* /usr/local/musl

with

wget https://github.com/DubbleClick/static-php-cli/releases/download/tools/x86_64-musl-toolchain.tgz
tar -xzf x86_64-musl-toolchain.tgz
mv x86_64-musl-toolchain/* /usr/local/musl

instead, it should work, as that toolchain is compiled without --enable-default-pie.

The debug toolchain was compiled with config.mak:

STAT = -static --static
FLAG = -g -O0 -Wno-error

ifneq ($(NATIVE),)
COMMON_CONFIG += CC="$(HOST)-gcc ${STAT}" CXX="$(HOST)-g++ ${STAT}"
else
COMMON_CONFIG += CC="gcc ${STAT}" CXX="g++ ${STAT}"
endif

COMMON_CONFIG += CFLAGS="${FLAG}" CXXFLAGS="${FLAG}" LDFLAGS="${STAT}"
BINUTILS_CONFIG += --enable-gold=yes
GCC_CONFIG += --enable-default-pie --enable-static-pie --disable-cet

CONFIG_SUB_REV = 888c8e3d5f7b
GCC_VER = 11.4.0
BINUTILS_VER = 2.40
MUSL_VER = 1.2.4
GMP_VER = 6.2.1
MPC_VER = 1.2.1
MPFR_VER = 4.2.0
LINUX_VER = 6.1.36

@henderkes
Copy link
Author

henderkes commented Oct 15, 2023

Oh important note: do NOT do this on a musl-libc based distro as moving statically linked compiler toolchains into your path would kill the system. I've used RHEL 9.2 (or AlmaLinux), but Debian shows the same behaviour.

@devnexen
Copy link
Member

devnexen commented Oct 16, 2023

seems to come down to the ucal_getTZDataVersion call during the module info init phase. More precisely, the usage of the library's global mutex. indeed the aforementioned call protects the tz data version update with its own lock guard with the callback. Even if instead I call the callback directly without the mutex, it still occurs.

@henderkes
Copy link
Author

Thank you for tackling this so quickly!

@devnexen
Copy link
Member

I did not forget about this, I kept it in the back of my mind but will have a better look at it.

@devnexen devnexen self-assigned this Jan 18, 2024
@devnexen
Copy link
Member

@DubbleClick would you mind trying to build the musl toolchain with a gcc 13 release (e.g. 13.2) ? with you config.mak the segfault shows up however if I change the GCC_VER setting, there is none locally.

@henderkes
Copy link
Author

I'll try to build a gcc 13.2 targeting musl in the next days.

@devnexen
Copy link
Member

Any luck since :) ?

@henderkes
Copy link
Author

Hi, unfortunately my pc decided to die just before I went on vacation. I'm back and on it right now.

@henderkes
Copy link
Author

henderkes commented Feb 18, 2024

Can't manage to compile php-src with the produced gcc 13.2 chain:

Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 13.2.0 (GCC) 
./configure: line 4233: 406051 Segmentation fault      (core dumped) $CC -v 1>&5
configure:4242: $? = 139
configure:4231: x86_64-linux-musl-gcc -V >&5
x86_64-linux-musl-gcc: error: unrecognized command-line option '-V'
x86_64-linux-musl-gcc: fatal error: no input files
compilation terminated.
./configure: line 4233: 406061 Segmentation fault      (core dumped) $CC -V 1>&5
configure:4242: $? = 139
configure:4231: x86_64-linux-musl-gcc -qversion >&5
x86_64-linux-musl-gcc: error: unrecognized command-line option '-qversion'; did you mean '--version'?
x86_64-linux-musl-gcc: fatal error: no input files
compilation terminated.
./configure: line 4233: 406071 Segmentation fault      (core dumped) $CC -qversion 1>&5
configure:4242: $? = 139
configure:4262: checking whether the C compiler works
configure:4284: x86_64-linux-musl-gcc  -I/opt/static-php-cli/buildroot/include -L/opt/static-php-cli/buildroot/lib conftest.c -ldl -lpthread >&5
x86_64-linux-musl-gcc: internal compiler error: Segmentation fault signal terminated program collect2
Please submit a full bug report, with preprocessed source (by using -freport-bug).
See <https://gcc.gnu.org/bugs/> for instructions.
./configure: line 4286: 406086 Segmentation fault      (core dumped) $CC $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5
configure:4288: $? = 139
configure:4326: result: no

I will try to investigate further later. Compiling the necessary libraries with the toolchain worked just fine.

@henderkes
Copy link
Author

It's linked to my set environment variables when running the command. I couldn't yet figure out which ones, but running ./configure without them works (with obvious linking errors following when running make).

@henderkes
Copy link
Author

Managed to build it manually, I still haven't found out which environment variables lead to the segmentation fault.

I can confirm that the produced ./sapi/cli/php executable works fine with intl. @devnexen

@devnexen
Copy link
Member

Thanks for your feedback and resilience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants