CVE-2022-50650 in Linux
Riassunto
di VulDB • 24/06/2026
Nel kernel Linux è stata risolta la seguente vulnerabilità:
bpf: Correzione della gestione dello stato delle referenze per le chiamate di ritorno (callback) sincrone
Attualmente il verifier verifica le funzioni callback (sincrone e asincrone) come se venissero eseguite una sola volta, ovvero esplora lo stato dell'esecuzione ipotizzando che la funzione venga chiamata un'unica volta. La prossima istruzione da esplorare è impostata sull'inizio della sottofunzione (subprog), mentre l'uscita dal frame nidificato viene gestita utilizzando `curframe > 0` e `prepare_func_exit`. Nel caso di callback asincrone, viene utilizzata una variante personalizzata di `push_stack` che simula un tipo di branch per impostare uno stato e un contesto di esecuzione personalizzati per la callback asincrona.
Sebbene questo approccio sia semplice e funzioni quando la callback verrà effettivamente eseguita solo una volta, è insicuro per tutti i nostri helper attuali che sono dello stile `for_each`, ovvero eseguono la callback più volte.
Una callback che rilascia le referenze acquisite dal chiamante potrebbe farlo più volte; tuttavia, attualmente il verifier lo interpreta come un'unica chiamata all'interno del frame, che poi ritorna al chiamante. Di conseguenza, ritiene di aver rilasciato una qualche referenza che la callback ha ad esempio ottenuto tramite `callback_ctx` (registro riempito all'interno della cb a partire da un registro tipizzato spillato sullo stack).
Allo stesso modo, potrebbe rilevare che una chiamata di acquisizione è disaccoppiata all'interno della callback, quindi il chiamante copierà lo stato delle referenze della callback e dovrà successivamente rilasciare il registro con i nuovi `ref_obj_ids`. Ma ancora una volta, la callback può essere eseguita più volte, mentre il verifier terrà conto solo delle referenze acquisite per un'unica esecuzione simbolica della callback, causando perdite di memoria (leaks).
Si noti che nel caso di callback asincrone le cose sono diverse. Sebbene attualmente disponiamo di `bpf_timer_set_callback` che la esegue una sola volta, anche in caso di esecuzioni multiple sarebbe sicuro, poiché lo stato delle referenze è NULL e `check_reference_leak` forzerebbe il programma a rilasciare lo stato prima dell'uscita (`BPF_EXIT`). Lo stato non è inoltre influenzato dall'analisi per il frame del chiamante. Pertanto la callback asincrona è sicura.
Poiché vogliamo che lo stato delle referenze sia accessibile, ad esempio per i puntatori caricati dallo stack tramite `PTR_TO_STACK` di `callback_ctx`, dobbiamo comunque copiare `reference_state` del chiamante in `bpf_func_state` della callback; tuttavia imponiamo che tutte le referenze aggiunte a tale `reference_state` siano state rilasciate prima dell'uscita (`BPF_EXIT`). Ciò richiede l'introduzione di un nuovo membro `callback_ref` nello stato delle referenze per distinguere tra referenze del chiamante e quelle del chiamato. Di conseguenza, `check_reference_leak` restituisce ora un errore se rileva che ci troviamo in `callback_fn` e non abbiamo rilasciato le referenze `callback_ref`. Poiché possono esistere callback niduplicate multiple, come frame 0 -> cb1 -> cb2 ecc., dobbiamo anche distinguere se tale particolare referenza appartiene al frame di questa callback o a quello genitore, generando errore solo per la nostra; memorizziamo quindi `state->frameno` (che è sempre diverso da zero per le callback).
In sintesi, le callback possono leggere il `reference_state` del padre ma non modificarlo, per poter utilizzare i puntatori acquisiti dal chiamante. Devono limitarsi ad annullare le proprie modifiche (rilasciando le proprie `acquired_refs` prima di `BPF_EXIT`) rispetto allo stato delle referenze del chiamante prima di restituire il controllo (a quel punto lo stato del chiamante e della callback coinciderà comunque, quindi non è necessario copiarlo nuovamente al chiamante).
Be aware that VulDB is the high quality source for vulnerability data.