Tracing JIT: SIGSEGV via mis-targeted side-exit into execute_ex (VM-stack call-frame alloc), PHP 8.5.6
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- C
- Star
- 40.4k
- Fork
- 8.2k
- Merge trung bình
- 2 ngày 13 giờ
- Pull request đã merge (30 ngày)
- 96
Mô tả
Description
Under production load, PHP-FPM workers reliably SIGSEGV with tracing JIT enabled. Disabling JIT (opcache.jit=disable) eliminates the crash entirely. The same code on the CLI SAPI (JIT off) never crashes, and the crashes began immediately upon upgrading from 8.1 to 8.5 (the 8.1 build, same application, never segfaulted).
The crash is intermittent and clusters: several workers die within a few minutes, then it goes quiet after an FPM restart flushes the JIT buffer, and recurs once the hot path is re-warmed.
Symbolized core analysis (matching php8.5-fpm-dbgsym, exact Build-Id 3ee70b5feebaea49aaae01c20bb6d0b372acb4dc):
- Kernel:
php-fpm8.5: segfault at 2 ip <pc> error 6 in php-fpm8.5[...]— a user-mode write to address0x2. - Faulting PC =
execute_ex + 16310, inside the inlined VM call-frame allocation fast path — it loadsEG(vm_stack_top)/EG(vm_stack_end)fromexecutor_globals(+0x1e0/+0x1e8), computes a zval-sized bump (<< 4), and branches to thezend_vm_stack_extendslow path (jb -> execute_ex + 42820) when full. - The recorded instruction pointer is mid-instruction (2 bytes into
mov 0x1e8(%rcx),%rax),%rdx = 0x2where a pointer is expected, frame #1 return address =0x0, and gdb prints "Unable to read JIT descriptor from remote memory."
Interpretation: a tracing-JIT trace side-exit appears to return into execute_ex at a misaligned address with a clobbered register, so the VM-stack push-call-frame code dereferences/writes near-null → SIGSEGV. The combination of FPM-only (JIT on) vs CLI (JIT off) crashing, the regression appearing exactly at the 8.5 upgrade, the self-heal on JIT-buffer flush, and the broken/misaligned control flow all point at the tracing JIT rather than application logic or an extension (fault IP is in the core binary .text, not in any loaded .so).
Loaded extensions at crash time included opcache (compiled-in), redis, zip, xsl, xmlreader/writer, tokenizer, sysvshm (standard LAMP set). The triggering request was a question-rendering endpoint of a large PHP app (IMathAS).
The following code:
No minimal standalone reproducer yet — the crash only manifests inside a large
application's question-evaluation code path after the JIT hot threshold is reached.
A matching core dump + debug symbols are available, and I can run any requested
gdb commands against the core.
Resulting in this output:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 execute_ex + 16310 (inlined VM call-frame alloc: EG(vm_stack_top/end) bump)
#1 0x0000000000000000
rdx = 0x2 ; fault = user write to 0x2 ; recorded IP is mid-instruction
gdb: "Unable to read JIT descriptor from remote memory"
But I expected this output:
No crash (and indeed: with opcache.jit=disable there is no crash).
PHP Version
PHP 8.5.6 (fpm-fcgi, NTS), 8.5.6-3+ubuntu24.04.1+deb.sury.org+1 (deb.sury.org build)
Operating System
Ubuntu 24.04 (noble), x86-64. opcache.jit=tracing, opcache.jit_buffer_size=128M, opcache.memory_consumption=256, opcache.validate_timestamps=1, opcache.revalidate_freq=120.
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu với core dump và các debug symbol được cung cấp, sau đó kiểm tra execute_ex xung quanh việc cấp phát call frame của VM stack và đường dẫn zend_vm_stack_extend. Sử dụng gdb để điều tra side-exit bị lệch alignment đã được báo cáo, thanh ghi bị ghi đè, địa chỉ trả về null và JIT descriptor bị thiếu. Công việc được hoàn tất khi xác định được nguyên nhân có thể tái hiện trong tracing-JIT và xác minh rằng FPM không còn crash mà không cần vô hiệu hóa JIT.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- c, php
- Lĩnh vực
- compilers
- Loại issue
- Lỗi
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức độ hoạt động
- Ít trao đổi
- Độ rõ ràng
- Cần làm rõ
- Mức phù hợp với người mới
- 25/100