kernel panic

Pavel Kankovsky peak na argo.troja.mff.cuni.cz
Neděle Leden 7 12:19:57 CET 2007


On Fri, 5 Jan 2007, jan markus wrote:

> rozbalil a zkoumal zdojaky & zaplaty a porovnaval (moc to neslo) s
> ukazkou te "opravne" zaplaty na http://lkml.org/lkml/2003/2/23/156
> neco z te opravne zaplaty uz implementovano je, neco ne. [...]

Obávám se, že tahle z věc z roku 2003, což je vlastně unifikace
icmp_xmit_lock() a icmp_xmit_lock_bh() už byla do jádra dávno
zapracována. Akorát trochu jinak než je v tom patchi.

> na inkriminovanem radku icmp.c:252 se naleza toto: [...]
> hmm... tedy zrejme se to snazilo odemknout cosi, co nebylo zamceno.

Ano. Záhada je, jak k tomu může dojít.

Kontrolní otázka na původního tazatele: Jádro máte SMP, že ano?
A kolik máte skutečně CPU?

> v te zaplate z lkml.org je tato fukce "opravena" nejak takto:
> 
> static void icmp_xmit_unlock(void)
> {
>          if(unlikely(!spin_trylock(&icmp_socket->sk->sk_lock.slock)))
>              BUG();
> }

Ne, není. Neumíte číst patche. Tohle je ve skutečnosti navržené tělo
icmp_xmit_lock()! V oficiálním jádře to vypadá takto

236 static __inline__ int icmp_xmit_lock(void)
237 {
238         local_bh_disable();
239 
240         if (unlikely(!spin_trylock(&icmp_socket->sk->sk_lock.slock))) {
241                 /* This can happen if the output path signals a
242                  * dst_link_failure() for an outgoing ICMP packet.
243                  */
244                 local_bh_enable();
245                 return 1;
246         }
247         return 0;
248 }

tj. místo BUG() to vrátí jedničku a volající by to měl detekovat a rychle
skončit. Což vypadá, že obě místa, kde se to používá, splňují. Teď je
otázka, zda v CentOSu (a v RHEL) oproti vanille není nějaký patch, který
to v dobré víře pokazí.

> pokud nechcete, aby to priste znovu padlo na ***, mozna by pomohla
> nasledujici uprava:
> 
> static void icmp_xmit_unlock(void)
> {
>          if(spin_trylock(&icmp_socket->sk->sk_lock.slock))
>              spin_unlock_bh(&icmp_socket->sk->sk_lock.slock);
> }

To už by vůbec nefungovalo, protože kdyby to bylo zamknuté před vstupem do
této funkce, tak by spin_trylock() selhalo a zůstalo by to zamčené.
Kdyžtak by to muselo být bez toho "if", tj. zkusit nezávazně zamknout a
pak nepodmínečně odemknout. A ještě byste měl místo spin_trylock() udělat
spin_trylock_bh().

Ale tím by se ten problém jen maskoval a neodstranil.

--Pavel Kankovsky aka Peak  [ Boycott Microsoft--http://www.vcnet.com/bms ]
"Resistance is futile. Open your source code and prepare for assimilation."



Další informace o konferenci Linux