Trumpai: memory_limit nustato, kiek atminties gali užimti viena PHP užklausa; numatytoji reikšmė yra 128M. Įprastu režimu nustatykite baigtinę, programai tinkamą reikšmę ir užrakinkite ją su php_admin_value. Kol PHP2Shell nepataisytas, php.net laikinai pataria memory_limit=-1, neperrašomą ir derinamą su riba per konteinerį ar cgroup, o ne per RLIMIT_AS ar RLIMIT_DATA. Po atnaujinimo vėl galioja baigtinė reikšmė.
Įprastas nustatymas, kuris staiga tapo saugumo tema
Daug metų memory_limit buvo kūrėjų reguliavimo varžtas. Jei svetainė praneša „Allowed memory size exhausted“, reikšmė padidinama ir problema išspręsta. Su PHP2Shell tai tapo saugumo klausimu, o php.net rekomendacija iš pirmo žvilgsnio atrodo paradoksali: pereinamuoju laikotarpiu PHP atminties riba turėtų visiškai išnykti.
Fonas yra CVE-2026-109618. Pasak PHP projekto, atminties trūkumo (Out-of-Memory) būsena gali nutraukti PHP, kol užklausos duomenys inicializuoti tik iš dalies. Tada užklausos sutvarkymas gali netinkamus duomenis traktuoti kaip tinkamus. Techninės detalės pateiktos skyriuje CVE-2026-109618, o kas vyksta PHP viduje trūkstant atminties, paaiškina memory_limit ir Out-of-Memory. Operatoriams svarbus klausimas: kuri reikšmė galioja kada ir kur ji turi būti nustatyta?
Ką memory_limit duoda įprastu režimu
Pasak PHP vadovo, memory_limit riboja atmintį, kurią gali užimti scenarijus, ir taip saugo serverį nuo prastai parašyto kodo. Numatytoji reikšmė yra 128M, -1 reiškia jokios ribos. Leidžiami sutrumpinimai, tokie kaip 256M ar 1G.
Saugumui svarbios dvi savybės. Pirma, reikšmę galima keisti bet kur, taip pat vykdymo metu per ini_set(). Daug CMS ir parduotuvių ją padidina pačios, pavyzdžiui, importams ar vaizdų apdorojimui. Kas nori reikšmę primesti, turi ją nustatyti su php_admin_value; pasak vadovo, taip nustatytų reikšmių negalima perrašyti per ini_set(). Antra, vadovas rekomenduoja, kad memory_limit būtų didesnis už post_max_size.
Kuri reikšmė tinka, priklauso nuo programos. Žvilgsnis į klaidų žurnalą parodo, ar pasitaiko pranešimų apie išsekusią atmintį ir per kokius kreipinius. Pasiteisino reikšmę kiekvienai svetainei nustatyti jos pačios FPM baseine: dosnesnę parduotuvei su importais, kuklesnę paprastam įmonės puslapiui. Bendrai labai didelė reikšmė visoms svetainėms prarandą apsauginį poveikį, nes tada viena klaidinga ar išnaudojama užklausa gali užimti daug atminties.
Nuo PHP 8.5 papildomai yra max_memory_limit. Šį nustatymą galima nustatyti tik paleidžiant, ir jis riboja, kiek aukštai apskritai galima nustatyti memory_limit. Didesnės reikšmės apkarpomos su įspėjimu. Numatytoji -1 reiškia viršutinės ribos nebuvimą.
memory_limit po PHP2Shell: pereinamoji php.net priemonė
Serveriams, kurie dar neatnaujinti iki 8.5.12, 8.4.27, 8.3.36 ar 8.2.35 arba patvirtinto atgalinio pataisų perkėlimo (backport), php.net 2026-10-21 saugumo pranešime nurodo šiuos žingsnius. Jie sumažina atskirų atakos kelių riziką, bet, pasak php.net, įdiegties nepadaro saugios:
- Nustatyti
memory_limit=-1, pageidautina taip, kad programos negalėtų perrašyti reikšmės, pavyzdžiui, suphp_admin_valueFPM baseine ar Apache konfigūracijoje. - Patikrinti, kad niekur vėl nenustatoma baigtinė riba, nei kitame baseine, nei katalogo konfigūracijoje, nei programoje.
- Nustatyti atminties ribą per konteinerį ar cgroup, kaip prieinamumo apsaugą, pageidautina taip, kad viršijus būtų nutraukiamas tik paveiktas darbinis procesas (worker).
- Nenaudoti
RLIMIT_ASarRLIMIT_DATA. Pasak php.net, šios ribos gali sukelti būtent pažeidžiamą klaidą prašant atminties.
php.net šia proga paaiškina, kad -1 pašalina tikslingai sukeliamą PHP atminties ribos pasiekimą, bet žemesnio lygio atminties klaida vis tiek gali pasiekti pažeidžiamą kelią. Visų pereinamųjų priemonių apžvalga pateikta skyriuje Skubios priemonės, kai dar negalite pataisyti.
; FPM baseinas, pvz., /etc/php/8.3/fpm/pool.d/www.conf (tik iki atnaujinimo)
php_admin_value[memory_limit] = -1
# Kur visur nustatomas memory_limit (tik skaitymas)
grep -rn 'memory_limit' /etc/php/ /etc/apache2/ 2>/dev/null
grep -rn --include='*.php' -E "ini_set\s*\(\s*['\"]memory_limit" /var/www | head -20
grep -rn --include='.user.ini' 'memory_limit' /var/www
Kaip nustatyti cgroup ribą FPM paslaugai, aprašo Atminties ribų nustatymas su systemd ir cgroups. Be šios išorinės ribos viena užklausa gali sukelti atminties stygių visam serveriui.
Po kiekvieno pakeitimo iš naujo paleiskite visus PHP darbinius procesus (worker). Veikiantis darbinis procesas išlaiko savo senas reikšmes.
Kas galioja po atnaujinimo
Su ištaisytomis versijomis, pasak PHP vadovo, pasikeitė ir memory_limit elgsena. Nuo 8.5.12, 8.4.27, 8.3.36 ir 8.2.35 tai yra minkšta riba: atminties prašymui, kuris ją viršija, daugeliu atvejų leidžiama dar užbaigti prieš sukeliant klaidą. Naujas nustatymas, memory_hard_limit_percent, nustato kietą ribą, kuri niekada neviršijama.
| Nustatymas | Reikšmė | Poveikis pasak vadovo |
|---|---|---|
memory_hard_limit_percent nenustatytas arba -1 |
numatytasis | kieta riba dvigubai didesnė už memory_limit iki 1G, virš to memory_limit plius 1G |
memory_hard_limit_percent = 150 |
pavyzdys | esant memory_limit=128M kieta riba 192M |
memory_limit = -1 |
jokios ribos | tada nėra ir kietos ribos |
Vadovas nurodo praktinį patikros tašką: jei memory_hard_limit_percent neatpažįstamas, naudojama PHP versija yra paveikta ir turi būti atnaujinta. Esant distribucijų atgaliniams pataisų perkėlimams (backport), būseną papildomai patikrinkite per paketo pakeitimų žurnalą.
# Ar FPM vykdomasis failas pažįsta naują nustatymą? (pritaikyti versijos numerį)
php-fpm8.3 -i | grep -E 'memory_hard_limit_percent|memory_limit'
Po atnaujinimo memory_limit=-1 atliko savo paskirtį. Grįžkite prie baigtinės, programai tinkamos reikšmės ir užrakinkite ją su php_admin_value. cgroup riba gali likti kaip papildomas apsaugos sluoksnis.
Kaip PHP SOS padeda konkrečiai?
- Išsiaiškiname, kur jūsų serveryje nustatomas ir perrašomas
memory_limit, įskaitant programas. - php.net pereinamąsias priemones įgyvendiname tinkamoje vietoje ir papildome cgroup riba FPM paslaugai.
- Per PHP pataisų paslaugą PHP atnaujiname iki ištaisytos būsenos ir iš naujo paleidžiame visus darbinius procesus (worker).
- Po to vėl nustatome tinkamą baigtinę reikšmę ir dokumentuojame nustatymus.
Dažni klausimai
Kokia yra numatytoji memory_limit reikšmė?
Pasak PHP vadovo, 128M. Reikšmė riboja, kiek atminties gali užimti vienas scenarijus. Ją galima keisti php.ini, serverio konfigūracijoje, FPM baseine ir vykdymo metu per ini_set(), jei ji neužrakinta su php_admin_value.
Kodėl php.net dėl PHP2Shell pataria memory_limit=-1?
Vienas iš pažeidžiamumų, CVE-2026-109618, susijęs su būsena trūkstant atminties. Pasak php.net, memory_limit=-1 pašalina tikslingai sukeliamą PHP atminties ribos pasiekimą, bet ne kiekvieną atminties klaidą. Priemonė nėra pilna apsauga ir turi būti derinama su atminties riba per konteinerį ar cgroup.
Ar vietoj to galiu nustatyti ribą su ulimit?
Ne. php.net aiškiai pataria nenaudoti RLIMIT_AS ar RLIMIT_DATA kaip pakaitalo, nes šios ribos gali sukelti būtent pažeidžiamą klaidą prašant atminties. Rekomenduojama riba per konteinerį ar cgroup.
Kas galioja po atnaujinimo į ištaisytą PHP versiją?
Pasak vadovo, ištaisytose versijose memory_limit yra minkšta riba, papildyta kieta riba per memory_hard_limit_percent. Pereinamoji priemonė su -1 tada atliko savo paskirtį ir vėl turėtų galioti baigtinė, programai tinkama reikšmė.