opcache: smm_shared_globals left pointing to a dead stack frame when there is no SHM backend
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 72/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Ambito
- backend, performance
Direzione di ricerca
Inizia in ext/opcache/zend_shared_alloc.c, in zend_shared_alloc_startup(), concentrandoti sul ritorno anticipato quando handler_table == NULL e su come gli altri ritorni anticipati reimpostano smm_shared_globals. Riproduci il problema con il programma embed SAPI fornito e la configurazione di AddressSanitizer, oppure esamina i percorsi di avvio esistenti. Il lavoro è completato quando il percorso senza SHM non lascia più un puntatore alla variabile locale nello stack e il riproduttore termina senza segnalare un uso dello stack dopo il ritorno.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Description
When opcache has no shared memory backend (handler_table is empty), zend_shared_alloc_startup() returns NO_SHM_BACKEND with smm_shared_globals still pointing to its local tmp_shared_globals. The other early returns (FAILED_REATTACHED, ALLOC_FALLBACK) reset it to NULL; this one does not.
Nothing reads it while opcache is disabled. But if the engine is started again in the same process (embed SAPI: php_embed_init() / php_embed_shutdown()), with opcache.file_cache_only=1, zend_shared_alloc_startup() is not called. zend_accel_in_shm() then reads ZSMMG(shared_segments_count) and ZSMMG(shared_segments) from that dead frame, and zend_persist uses its answer to decide what is already persisted.
We hit it with PHP compiled to WebAssembly (emscripten), which has no SHM backend, as a memory corruption ("memory access out of bounds") when opcache later compiled some files to its file cache. Here is a native reproducer, with the SHM backends disabled at configure time:
php_cv_shm_ipc=no php_cv_shm_mmap_anon=no php_cv_shm_mmap_posix=no \
./configure --enable-embed --disable-all --disable-opcache-jit --enable-address-sanitizer
make && make install
gcc -fsanitize=address repro.c -o repro $(php-config --includes) -L/usr/local/lib -lphp
mkdir /tmp/opcache
USE_ZEND_ALLOC=0 ASAN_OPTIONS=detect_leaks=0:detect_stack_use_after_return=1 ./repro
repro.c:
#include <sapi/embed/php_embed.h>
#include <stdlib.h>
static void start(const char *phprc, const char *code)
{
setenv("PHPRC", phprc, 1);
php_embed_init(0, NULL);
zend_first_try {
zend_eval_string((char *) code, NULL, "repro");
} zend_end_try();
php_embed_shutdown();
}
int main(void)
{
start("/repro/first", "var_dump(opcache_get_status(false));");
start("/repro/second", "var_dump(opcache_compile_file('/repro/script.php'));");
return 0;
}
/repro/first/php.ini:
opcache.enable=1
opcache.log_verbosity_level=4
/repro/second/php.ini:
opcache.enable=1
opcache.file_cache=/tmp/opcache
opcache.file_cache_only=1
/repro/script.php:
<?php
const PRIMES = [2, 3, 5, 7];
function primes(): array
{
static $calls = [];
$calls[] = true;
return PRIMES;
}
Resulted in this output:
Message Opcode Caching is disabled: No available SHM backend. Set opcache.enable=0 to hide this message.
bool(false)
==1==ERROR: AddressSanitizer: stack-use-after-return on address 0x7f1327702a38 at pc 0x7f1329e77995 bp 0x7ffe0f741820 sp 0x7ffe0f741818
READ of size 4 at 0x7f1327702a38 thread T0
#0 0x7f1329e77994 in zend_accel_in_shm /php-src/ext/opcache/zend_shared_alloc.c:701
#1 0x7f1329e598f4 in zend_persist_op_array_calc_ex /php-src/ext/opcache/zend_persist_calc.c:244
#2 0x7f1329e61c73 in zend_accel_script_persist_calc /php-src/ext/opcache/zend_persist_calc.c:665
#3 0x7f1329e797c2 in store_script_in_file_cache /php-src/ext/opcache/ZendAccelerator.c:1520
#4 0x7f1329e8da01 in cache_script_in_file_cache /php-src/ext/opcache/ZendAccelerator.c:1571
#5 0x7f1329e8da01 in file_cache_compile_file /php-src/ext/opcache/ZendAccelerator.c:1962
#6 0x7f1329e9396d in persistent_compile_file /php-src/ext/opcache/ZendAccelerator.c:2017
#7 0x7f1329e3e564 in zif_opcache_compile_file /php-src/ext/opcache/zend_accelerator_module.c:1013
Address 0x7f1327702a38 is located in stack of thread T0 at offset 56 in frame
#0 0x7f1329e75c2f in zend_shared_alloc_startup /php-src/ext/opcache/zend_shared_alloc.c:185
This frame has 1 object(s):
[48, 128) 'tmp_shared_globals' (line 188) <== Memory access at offset 56 is inside this variable
But I expected this output instead:
Message Opcode Caching is disabled: No available SHM backend. Set opcache.enable=0 to hide this message.
bool(false)
bool(true)
Resetting it before that return gives the expected output, with no ASan report:
if (handler_table->name == NULL) {
+ smm_shared_globals = NULL;
return NO_SHM_BACKEND;
}
I can open a PR with this fix.
PHP Version
PHP 8.5.12, and master (d15160d5)
Operating System
Debian trixie, x86_64, gcc 14.2 (ASan). First seen with emscripten 6.0.13 (WebAssembly).
- Lingua principale
- C
- Stelle
- 41.7k
- Fork
- 8.5k
- Merge medio
- 2g 18h
- PR unite (30g)
- 145
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di php/php-src
-
SNMP accepts malformed remote portsForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 Mezza giornata Idoneità per principianti 62/100
php/php-src#25137 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Bug Status: Needs Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
I maintainer di solito rispondono entro 1 giorno
-
quoted_printable_encode() produces lines longer than 76 characters for bytes 0xF5 to 0xFFForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
-
Bug Status: Needs Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
php/php-src#24196 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Feature Status: Needs Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 73/100
php/php-src#24183 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Issue simili
-
[compiler-rt] Rtsan-aarch64-NoInstTest: error: no such file or directory: 'NOTFOUND' (libatomic)Apertabuild-problem compiler-rt:rtsan platform:linux
Difficoltà 2/5 1-3 ore Idoneità per principianti 63/100
llvm/llvm-project#239039 ·
I maintainer di solito rispondono entro 1 giorno
-
component:obi contribfest go test
Difficoltà 2/5 Meno di un'ora Idoneità per principianti 83/100
open-telemetry/opentelemetry-ebpf-instrumentation#4143 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Bug :bug:
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
sonic-net/sonic-buildimage#30541 ·
I maintainer di solito rispondono entro 1 giorno