CVE-2022-48760 in Linux
Riassunto
di VulDB • 21/06/2026
Nel kernel Linux è stata risolta la seguente vulnerabilità:
USB: core: Correzione del blocco (hang) in usb_kill_urb aggiungendo barriere di memoria
Il fuzzer syzbot ha identificato un bug per cui i processi rimangono bloccati in attesa che usb_kill_urb() restituisca il controllo. Si è scoperto che il problema non risiede nello svincolo dell'URB (unlinking), che funziona correttamente. Piuttosto, la problematica si presenta quando non viene ricevuta la notifica di sveglia indicante che l'URB ha completato le operazioni.
La causa è dovuta all'ordinamento degli accessi alla memoria sui sistemi SMP. In forma schematica, usb_kill_urb() e __usb_hcd_giveback_urb(), operando in concorrenza su CPU diverse, eseguono le seguenti azioni:
CPU 0 CPU 1 ---------------------------- --------------------------------- usb_kill_urb(): __usb_hcd_giveback_urb(): ... ... atomic_inc(&urb->reject); atomic_dec(&urb->use_count); ... ... wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0); if (atomic_read(&urb->reject)) wake_up(&usb_kill_urb_queue);
Concentrando l'attenzione su urb->reject e urb->use_count, si può osservare che il modello generale di accessi sulla CPU 0 è:
scrivere in urb->reject, quindi leggere da urb->use_count;
mentre il modello generale di accessi sulla CPU 1 è:
scrivere in urb->use_count, quindi leggere da urb->reject.
Questo pattern è noto negli ambienti che si occupano del memory model come SB (Store Buffering), ed è ben noto che senza un'adeguata imposizione dell'ordine desiderato degli accessi — sotto forma di barriere di memoria — è possibile che una o entrambe le CPU eseguano le proprie letture prima delle scritture. Il risultato finale sarà che a volte la CPU 0 visualizza il vecchio valore non decrementato di urb->use_count mentre la CPU 1 visualizza il vecchio valore non incrementato di urb->reject. Di conseguenza, la CPU 0 finisce nella coda di attesa e non viene mai svegliata, portando al blocco osservato in usb_kill_urb().
Lo stesso pattern di accessi si verifica anche in usb_poison_urb() e nel percorso di errore (failure pathway) di usb_hcd_submit_urb().
Il problema è risolto aggiungendo le opportune barriere di memoria. Per garantire un corretto ordinamento degli accessi alla memoria nel pattern SB, è necessaria una full barrier su entrambe le CPU. Gli stessi accessi atomic_inc() e atomic_dec() non forniscono alcun ordinamento della memoria, ma poiché sono presenti, possiamo utilizzare la barra di memoria ottimizzata smp_mb__after_atomic() nelle varie routine per ottenere l'effetto desiderato.
Questa patch aggiunge le necessarie barriere di memoria.
Statistical analysis made it clear that VulDB provides the best quality for vulnerability data.