opcache: smm_shared_globals left pointing to a dead stack frame when there is no SHM backend
Maintainer antworten meist innerhalb von 1 Tag
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 2/5
- Geschätzter Aufwand
- 1-3 Stunden
- Anfängerfreundlichkeit
- 72/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Bereich
- backend, performance
Rechercherichtung
Beginne in ext/opcache/zend_shared_alloc.c bei zend_shared_alloc_startup() und konzentriere dich auf die frühe Rückgabe bei handler_table == NULL sowie darauf, wie die anderen frühen Rückgaben smm_shared_globals zurücksetzen. Reproduziere den Fehler mit dem bereitgestellten embed-SAPI-Programm und dem AddressSanitizer-Setup oder untersuche die bestehenden Startpfade. Fertig ist die Aufgabe, wenn der Pfad ohne SHM keinen Zeiger auf die lokale Stack-Variable mehr hinterlässt und der Reproducer ohne einen Bericht über Stack-use-after-return durchläuft.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
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).
- Vorherrschende Sprache
- C
- Sterne
- 41.7k
- Forks
- 8.5k
- Ø Merge
- 2 T. 18 Std.
- Gemergte PRs (30 T.)
- 145
Entwicklungsumgebung
- Kein Dockerfile und keine Docker-Compose-Datei
- Keine Pull-Request-Vorlage
- Beitragsleitfaden lesen
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus php/php-src
-
SNMP accepts malformed remote portsEvtl. vergeben Ein verknüpfter Pull Request ist offen oder bereits gemergt. Offen
Schwierigkeit 2/5 Ein halber Tag Anfängerfreundlichkeit 62/100
php/php-src#25137 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
Bug Status: Needs Triage
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 64/100
Maintainer antworten meist innerhalb von 1 Tag
-
quoted_printable_encode() produces lines longer than 76 characters for bytes 0xF5 to 0xFFEvtl. vergeben Ein verknüpfter Pull Request ist offen oder bereits gemergt. Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
Maintainer antworten meist innerhalb von 1 Tag
-
Bug Status: Needs Triage
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 62/100
php/php-src#24196 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
Feature Status: Needs Triage
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 73/100
php/php-src#24183 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
Ähnliche Issues
-
[compiler-rt] Rtsan-aarch64-NoInstTest: error: no such file or directory: 'NOTFOUND' (libatomic)Offenbuild-problem compiler-rt:rtsan platform:linux
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 63/100
llvm/llvm-project#239039 ·
Maintainer antworten meist innerhalb von 1 Tag
-
component:obi contribfest go test
Schwierigkeit 2/5 Unter einer Stunde Anfängerfreundlichkeit 83/100
open-telemetry/opentelemetry-ebpf-instrumentation#4143 · 1 Kommentar ·
Maintainer antworten meist innerhalb von 1 Tag
-
Bug :bug:
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 72/100
sonic-net/sonic-buildimage#30541 ·
Maintainer antworten meist innerhalb von 1 Tag