Aktuális helyzet: PHP2Shell. Két kritikus PHP-rés (CVSS 9,2) lehetővé teszi kártékony kód futtatását bejelentkezés nélkül. Javítások 2026. 10. 21. óta.Mi a teendő most →

Memóriahatárok beállítása systemd-vel és cgroupokkal

A php.net a PHP2Shell átmeneti intézkedéseként a memory_limit=-1 értéket és a PHP-n kívüli memóriahatárt javasolja. Így állítsa be ezt a határt systemd-vel és cgroupokkal úgy, hogy egyetlen worker se rántsa magával az egész szolgáltatást.

Állapot 6 perc olvasási időKeményítés és konfiguráció

Röviden: A memory_limit=-1 PHP2Shell-átmeneti intézkedéshez a PHP-FPM-nek a PHP-n kívüli memóriahatárra van szüksége. A systemd alatt ezt a MemoryHigh= féktényezővel és a MemoryMax= kemény felső határral állítsa be az FPM-szolgáltatás kiegészítő fájljában. Az ulimit, a LimitAS= vagy a LimitDATA= a php.net szerint erre alkalmatlan. Ellenőrizze emellett az OOMPolicy= értékét, hogy egyetlen worker ne állítsa le az egész szolgáltatást.

Egy ajánlás, amely elsőre meglepő

A php.net által 2026. október 21-én a PHP2Shellről közzétett átmeneti intézkedések között van egy, amely sok adminisztrátort megállított: memory_limit=-1, vagyis nincs memóriahatár magában a PHP-ban. Éveken át az ellenkezője számított jó gyakorlatnak.

A rés leírásával való összefüggés kézenfekvő. A CVE-2026-109618 esetében egy Out-of-Memory állapot megszakíthatja a PHP-t, miközben a kérésadatok csak részben vannak inicializálva. Az átmeneti intézkedés a memóriahatárt kihelyezi a PHP-ból az operációs rendszerbe. A php.net kifejezetten két feltételhez köti: az értéknek zároltnak kell lennie a felülírás ellen, és a határnak konténeren vagy cgroupon keresztül kell érkeznie, nem az RLIMIT_AS vagy RLIMIT_DATA útján.

Aki csak az első felét valósítja meg, annak olyan szervere lesz, amelyen semmilyen memóriahatár nincs. Ez a cikk a második felet mutatja. Együtt is átmenet marad az intézkedés: a rés csak a PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 vagy egy megerősített backport révén szűnik meg.

A cgroupok két mondatban

A Control Groups, röviden cgroupok, a Linux-kernel egy funkciója, amely csoportosítja a folyamatokat, és korlátozza az erőforrásaikat. A systemd minden szolgáltatáshoz automatikusan saját cgroupot hoz létre, és a szolgáltatás összes folyamata, az FPM-szolgáltatásnál tehát a master és az összes worker, ahhoz tartozik.

A systemd memóriaopciói a cgroup v2 memóriavezérlőjének értékeit állítják be. Hogy a rendszere használ-e cgroup v2-t, azt egy rövid parancs mutatja:

# A „cgroup2fs” azt jelenti: a cgroup v2 aktív
stat -fc %T /sys/fs/cgroup/

A gyakori disztribúciók aktuális verziói alapértelmezetten cgroup v2-t használnak. Ha a parancs mást mutat, az átállás előtt tisztázza ezt, mert a systemd dokumentációja a régi v1-opciókat elavultként írja le.

A systemd MemoryMax beállítása a PHP-FPM-hez

A határ egy kiegészítő fájlba, úgynevezett drop-inbe kerül. Így a csomag unit-fájlja változatlan marad, és egy frissítés nem írja felül az Ön beállítását. A szolgáltatásnevek disztribúciónként eltérnek; a példa Debiant és Ubuntut használ PHP 8.3-mal.

# Megnyit egy szerkesztőt a drop-inhez: sudo systemctl edit php8.3-fpm
# Eredmény: /etc/systemd/system/php8.3-fpm.service.d/override.conf
[Service]
MemoryAccounting=yes
MemoryHigh=1536M
MemoryMax=2G
MemorySwapMax=0
OOMPolicy=continue

Az opciók áttekintése a systemd dokumentációja szerint:

Opció Hatás Megjegyzés a PHP-FPM-hez
MemoryHigh= fojtási határ: a folyamatokat erősen lassítják, memóriát szereznek vissza a tényleges szabályozó érték, valamivel a MemoryMax alatt
MemoryMax= abszolút határ: ha nem tartható, aktívvá válik a szolgáltatáson belüli OOM-killer utolsó védelmi vonal
MemorySwapMax= a kiszervezés határa a 0 megakadályozza, hogy a szolgáltatás helyette a swapbe térjen ki
OOMPolicy= viselkedés egy OOM-esemény után: continue, stop vagy kill a continue hagyja tovább futni a többi workert
LimitAS=, LimitDATA= rlimitek folyamatonként a php.net szerint erre az intézkedésre alkalmatlan

Az OOMPolicy= különös figyelmet érdemel. stop vagy kill esetén a systemd egy OOM-esemény után leállítja az egész szolgáltatást, és az FPM-szolgáltatás összes weboldala kiesik. Hogy saját megadás nélkül melyik érték érvényes, azt a DefaultOOMPolicy= rendszeralapérték rögzíti. Ezért ellenőrizze a hatályos értéket, ahelyett hogy feltételezné.

Ezután indítsa újra a szolgáltatást, és zárolja a memory_limit értékét a poolban:

sudo systemctl restart php8.3-fpm
systemctl show php8.3-fpm -p MemoryHigh -p MemoryMax -p MemorySwapMax -p OOMPolicy -p MemoryCurrent
; Pool-fájl, pl. /etc/php/8.3/fpm/pool.d/seite1.conf
php_admin_value[memory_limit] = -1

Hogyan működik a zárolás, azt a php_admin_value: beállítások zárolása a felülírás ellen írja le.

A helyes érték megtalálása

Egy túl szűk határ megszakításokat okoz a normál üzemben, egy túl nagyvonalú alig véd. A kiindulópont a tényleges fogyasztás.

  1. Figyelje néhány napon át az összes FPM-folyamat tényleges memóriaigényét, a terhelési csúcsok idején is.
  2. Állapítsa meg egy worker tipikus igényét, és szorozza meg a szolgáltatás összes poolja pm.max_children értékével.
  3. Tervezzen felárat a master folyamatra, az OPcache-re és a csúcsokra.
  4. A MemoryHigh= értéket a mért csúcsérték fölé, kissé szorosan állítsa be, a MemoryMax= értéket némi távolsággal fölé.
  5. Egy hét után igazítsa az értékeket a mérések és az OOM-események alapján.
# Az összes PHP-FPM-folyamat memóriája MB-ban (Resident Set Size)
ps -C php-fpm8.3 -o rss= | awk '{s+=$1} END {printf "%.0f MB\n", s/1024}'
# Az összes cgroup folyamatos áttekintése memória szerint rendezve
systemd-cgtop -m

A memory_limit értékét az átállás előtt jegyezze fel. A frissítés után visszatérhet a PHP-ban egy rögzített határhoz; hogyan válassza meg ezt értelmesen, azt a memory_limit helyes beállítása cikk írja le.

Felügyelet: mikor lép működésbe a határ

Egy olyan memóriahatár, amelynek kiváltódását senki sem veszi észre, csendes hibaforrás. A kernel cgroupokként számolja az OOM-eseményeket, és a systemd valamint a kernelnapló feljegyzi őket.

# A szolgáltatás cgroupjának OOM-számlálója (útvonal cgroup v2 esetén)
cat /sys/fs/cgroup/system.slice/php8.3-fpm.service/memory.events
# Az OOM-killer üzenetei a kernelnaplóban
journalctl -k --since "-1 day" | grep -i "out of memory"

Ha az oom_kill számláló emelkedik, a kernel workereket állít le. Ez utalhat túl szűk határra, hibás alkalmazásra vagy szokatlan kérésekre. A jelenlegi helyzetben megéri az ilyen eseményeket egybevetni az ugyanezen időpontbeli hozzáférési naplókkal.

Fontos

A memóriahatár átmeneti intézkedés, és nem pótolja a PHP-frissítést. Tervezze párhuzamosan a frissítést, és utána indítsa újra az összes PHP-folyamatot. Az összes átmeneti intézkedés áttekintése az Azonnali intézkedések, ha még nem tud javítani oldalon található.

Hogy mi történik a PHP belsejében memóriahiány esetén, azt a memory_limit és Out-of-Memory magyarázza. Az Apache-nál mod_php esetén ugyanez a technika érvényes az Apache-szolgáltatásra, a PHP azonban ekkor magával a webszerverrel osztozik a határon.

Összegzés: ne feledkezzen meg a második feléről

A memory_limit=-1 csak külső határral együtt vállalható átmeneti intézkedés. A systemd néhány sorral lehetővé teszi ezt a határt: a MemoryHigh fékként, a MemoryMax kemény felső határként, a MemorySwapMax a swapbe való kitérés ellen, és egy tudatosan választott OOMPolicy. Előtte mérjen, utána figyeljen, és tartsa szem előtt, hogy egy szolgáltatás összes poolja osztozik a határon.

De mindenekelőtt: tervezze meg az intézkedés végét. A javított PHP-verzióra való frissítés után térjen vissza egy rögzített memory_limit értékhez. A cgroup-határt kiegészítő védelemként megtarthatja az elszabaduló folyamatok ellen.

Hogyan segít konkrétan a PHP SOS?

  • Mérés: Felmérjük a PHP-szolgáltatásai memóriaigényét, és ebből levezetjük a megfelelő határokat.
  • Megvalósítás: MemoryHigh, MemoryMax és megfelelő OOMPolicy értékkel drop-ineket állítunk be, zároljuk a memory_limit értékét a poolban, és a szolgáltatásokat ellenőrzötten újraindítjuk.
  • Megfigyelés: Az OOM-eseményeket bevonjuk a felügyeletbe, és utánigazítjuk az értékeket.
  • Eljuttatás a javításig: A PHP-javítási szolgáltatáson keresztül telepítjük a frissítést, majd rendezetten visszavonjuk az átmeneti értékeket.

Gyakori kérdések

Miért kell a memory_limit értékének -1-nek lennie? Nem veszélyes ez?

Önmagában az lenne. A php.net a memory_limit=-1 értéket átmeneti intézkedésként kifejezetten konténeren vagy cgroupon keresztüli memóriahatárral együtt javasolja. A korlátozás így kikerül a PHP-ból az operációs rendszerbe. Ezen külső határ nélkül ne állítsa be az értéket.

Használhatom helyette az ulimit-et vagy a LimitAS=-t?

Nem. A php.net kifejezetten óv az RLIMIT_AS és RLIMIT_DATA használatától, és éppen ezeket a határokat állítja be az ulimit -v, a LimitAS= és a LimitDATA=. A systemd dokumentációja ezenkívül rámutat, hogy a LimitAS= a címteret korlátozza, nem a memóriahasználatot.

Mi történik, ha a PHP-FPM eléri a határt?

A MemoryHigh esetén a kernel lassítja a folyamatokat, és memóriát szerez vissza. A MemoryMax esetén a szolgáltatáson belül aktívvá válik az OOM-killer, és leállít egy folyamatot, többnyire egy nagy workert. Hogy utána az egész szolgáltatás leáll-e, azt az OOMPolicy= szabályozza.

Minden poolra külön érvényes a határ?

Nem. Egy FPM-szolgáltatás összes poolja egy cgroupon osztozik, és így egy közös határon. A weboldalanként külön határokhoz külön FPM-szolgáltatások vagy konténerek kellenek.

Hogyan állítom be a határt Dockerben vagy Kubernetesben?

A konténer memóriakorlátozásán keresztül, például a docker run --memory opciójával vagy a Kubernetesben a resources.limits.memory-val. Mindkettő szintén cgroupokat használ. Az alapelv ugyanaz marad: határ a PHP-n kívül, a memory_limit zárolva a PHP-ban.

Források

Azonnali kapcsolat

Minden óra számít. Írjon nekünk most.

Ismertesse röviden a rendszert, a PHP-verziót és a megfigyelését. Jelentkezünk, tisztázzuk a helyzetet, és távolról dolgozunk, amíg az incidens le nem zárul és dokumentálva nem lesz.

Azonnali segítség