Jest wpół do drugiej w nocy. Siedzę w biurze. Serwer Apache wygląda na stabilny. Dokładnie, wygląda.
Prawie wszystkie działające u nas aplikacje są zaimplementowane jako usługi FastCGI serwowane przez Lighttpd. Bazy danych działają w osobnych serwerach wirtualnych, podobnie odseparowany jest Apache, który dzierży brzemię mielenia PHP i przedzierania się przez gąszcze plików .htaccess.
Wszystko byłoby pięknie, gdyby Apache nie zaczął sobie chodzić na spacerek do krainy wiecznych łowów (jak to Indianie mają w zwyczaju czynić po SIGSEGV). Szybki (błyskawiczny rzekłbym, ale to nie prawda) strace i końcówka gdb pokazały, że ślad urywa się gdzieś w PHP.
Następny test — przestawienie PHP z mod_php (użytkownicy nie mają dostępu do kodu serwisów, więc nie bawiliśmy się w żadne separacje użytkowników) na CGI. Tym razem dzielny serwer przetrwał, w przeciwieństwie do skryptu. Kolejny strace i gdb na symulowanym środowisku CGI (w bardzo wysublimowany sposób — export QUERY_STRING=… i tak dalej) i okazuje się, że zdycha jednak biblioteka implementująca PCRE.
Dużo Google. Bardzo dużo. W końcu pomaga Qwiat. Miał to samo, pomógł downgrade pakietu pcre do wersji 6.7. Przebudowa wspomnianego pakietu we wspomnianej wersji, upgrade w vserwerze, restart usług. Działa. Nieźle się maskuje.
Kod serwisów zdaje się działać bez zarzutu. Chciałem zarzucić temat, ale obiecałem znaleźć syntetyczny testcase. Więcej Google. Na liście błędów pcre jest znana podatność na przepełnienie stosu. Autorzy zdają się mieć ją w dużym poważaniu. Wersja 7.x zdycha, wersja 6.x działa. A takiego.
<?php print 'A teraz coś z zupełnie innej beczki: '; preg_match('/(.(?!b))*/', str_repeat("a", 10000)); ?>
Powyższy kod położył mi każdą kombinację PHP i PCRE. Bardzo ładny sposób, żeby komuś zrobić DOS na PHP działające w trybie FastCGI (po n-tym padzie usługi w krótkim czasie serwer słusznie uzna, że jest uszkodzona i przestanie ją wskrzeszać, przynajmniej na jakiś czas).
I tym optymistycznym akcentem zakończę swoje gadanie od rzeczy i udam się do domu spać.

Perl zdaje się być niewrażliwy na takie coś. No, chyba że źle przepisałem powyższy kawałek:
#!/usr/bin/perl
print ‘A teraz coś z zupełnie innej beczki: ‘;
‘a’ x 10000 =~ /(.(?!b))*/;
Witam, ciekawi mnie ten fragment: “Prawie wszystkie działające u nas aplikacje są zaimplementowane jako usługi FastCGI serwowane przez Lighttpd.” Jakie to usługi, jeśli PHP jest obsługiwane przez Apache? I jak wykonuje sie takie rozdzielanie usług. No z tym ostatnim to może przesadziłem, bo ten blog to nie jakiś helpdesk ale bardzo mnie to zaciekawiło, a nie ma co ukrywać, jestem początkujący i póki co za bardzo nawet nie wiem jak zapytać google by grzecznie udzieliły mi odpowiedzi ;)
Max:
Większość usług u nas to aplikacje Pythona (Django).
Pisząc o rozdzieleniu miałem na myśli stosowanie
suexecalbosuPHPi uruchamianie skryptów z prawami ich właścicieli zamiast użytkownika, na którym działa Apache.@Max: “I jak wykonuje sie takie rozdzielanie usług.” - jeżeli miałeś na myśli te php na apache, a reszta na lighttpd to jest to dosyć częsta praktyka (np. Youtube tak działa, serwis na apache, statyczne ciągniete z lightiego). Ustawiasz normalnie Apacha na :80, Lighttpd:nacosinnego, w Apache korzystasz z mod_proxy i definiujesz jaki ruch ma iść na ten inny port którym się zajmie lighty.
Przykład implementacji:
http://www.linux.com/article.pl?sid=06/01/27/1813223
Wielkie dzięki. To wydaje sie naprawdę świetne. Pozdrawiam :)
Michał Górny:
PCRE to biblioteka, która naśladuje wyrażenia regularne Perla. Sam Perl z niej nie korzysta, używają jej za to Apache i PHP.
W Perlu takich głupich błędów nie ma ;) I poprawia się je natychmiast. Natomiast PHP… ktoś coś chłapnie, a potem olewa. A inni na tym bazują i się wściekają.
a:
To nie błąd w PHP, tylko w PCRE.
A swoje zdanie o PHP już kiedyś wyraziłem na łamach tego bloga.