Co się stało apache'owi? (kolejny pad, z debuginfo)
Jakub Bogusz
qboosh at pld-linux.org
Fri Jul 1 17:20:07 CEST 2011
On Fri, Jul 01, 2011 at 08:33:11AM +0200, Jacek Osiecki wrote:
> On Wed, 29 Jun 2011, Pawel Sikora wrote:
>
> > On Wednesday 29 of June 2011 12:10:27 Jacek Osiecki wrote:
> >> On Wed, 29 Jun 2011, Pawel Sikora wrote:
> >>> On Wednesday 29 of June 2011 11:52:46 Jacek Osiecki wrote:
> >>>> Pozwolę sobie więc wrzucić końcówkę z gdb:
> >>>> (gdb) bt
> >>>> #0 0x000074b5880c8243 in select () from /lib64/libc.so.6
> >>>> #1 0x000074b575680119 in ?? () from /lib64/libgcrypt.so.11
> >>>> #2 0x000074b57567d630 in ?? () from /lib64/libgcrypt.so.11
> >>>> #3 0x000074b57567e914 in ?? () from /lib64/libgcrypt.so.11
> >>>> #4 0x000074b57567d9bf in ?? () from /lib64/libgcrypt.so.11
> >>>
> >>> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doinstaluj jeszcze pakiety -debuginfo, t obedzie cos wiecej widac.
> >> No tego właśnie się obawiałem ;)
> >> Zobaczymy - jeśli po tych upgrade'ach które zrobiłem problem nie wystąpi,
> >> to sprawa zamknięta. Jeśli wystąpi, to zainstaluję debuginfo i się zobaczy
> >> co z tego wyniknie.
>
> No i znowu było bum, mimo wszelkich upgrade'ów... Tym razem były pakiety
> debuginfo. chyba jednak nie php jest winne... a może się mylę?
>
> Loaded symbols for /usr/lib64/php/zlib.so
> 0x0000666af9bda430 in __write_nocancel () at
> ../sysdeps/unix/syscall-template.S:82
> 82 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
> (gdb) catch syscall select
> Catchpoint 1 (syscall 'select' [23])
> (gdb) continue
> Continuing.
>
> Catchpoint 1 (call to syscall 'select'), 0x0000666af9be1b23 in
> __select_nocancel () at ../sysdeps/unix/syscall-template.S:82
> 82 T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
> (gdb) bt
> #0 0x0000666af9be1b23 in __select_nocancel () at ../sysdeps/unix/syscall-template.S:82
> #1 0x0000666ae6d6bdcf in _gcry_rndlinux_gather_random (add=0x666ae6d69700 <add_randomness>, origin=RANDOM_ORIGIN_SLOWPOLL, length=120, level=<value optimized out>) at rndlinux.c:133
No to błąd do zgłoszenia w libgcrypt: przy tworzeniu zbioru dla select()
nie ma sprawdzenia, czy otrzymany deskryptor nie przekracza FD_SETSIZE.
Czyli mamy przepełnienie zmiennej na stosie. W przypadku kiedy
deskryptor nieznacznie przekracza FD_SETSIZE (=1024 normalnie), to
nadpisuje zmienną zawierającą timeout (ewentualnie zmiana tej zmiennej
zmienia wartość tego, co potem select() ze zbyt dużym pierwszym
parametrem uważa za fdset).
Tak w ogóle to zamiast select()a tam powinien być poll() i by nie było
problemu. Deskryptor jest jeden, więc nie ma sensu używanie epolla.
Swoją drogą to ciekawe, ile jeszcze bibliotek korzysta z select()a,
przez co ma podobne problemy w przypadku przekroczenia 1024
deskryptorów w ramach procesu... apache+php tworzy środowisko podatne na
takie błędy.
Doraźnie - zapewne uruchamianie php via fcgi albo wyłączenie curla
by problem wyeliminowało.
--
Jakub Bogusz http://qboosh.pl/
More information about the pld-devel-pl
mailing list