CVE-2022-49394 in Linux
Riassunto
di VulDB • 21/06/2026
Nel kernel Linux, è stata risolta la seguente vulnerabilità:
blk-iolatency: Correzione degli squilibri nel conteggio delle operazioni IO in corso (inflight) e dei blocchi (hang) delle IO durante la disattivazione offline.
iolatency deve tenere traccia del numero di operazioni IO in corso per ogni cgroup. Poiché questo monitoraggio può essere oneroso, viene disabilitato quando nessun cgroup ha configurato iolatency per il dispositivo. Per garantire che i contatori delle operazioni in corso rimangano bilanciati, iolatency_set_limit() congela la request_queue durante la manipolazione del contatore abilitato, assicurando che nessuna IO sia in corso e che tutti i contatori siano quindi a zero.
Sfortunatamente, iolatency_set_limit() non è l'unico punto in cui il contatore abilitato viene manipolato. Anche iolatency_pd_offline() può decrementare il contatore e innescare la disabilitazione. Poiché questa disabilitazione avviene senza congelare la coda (q), ciò può verificarsi facilmente mentre alcune IO sono in corso, causando una perdita (leak) dei conteggi.
Ciò può essere facilmente dimostrato attivando iolatency su un cgroup vuoto mentre sono in corso IO in altri cgroup e quindi rimuovendo il cgroup. Si noti che iolatency non dovrebbe essere stato attivato altrove nel sistema per garantire che la rimozione del cgroup disabiliti iolatency per l'intero dispositivo.
Il seguente comando continua ad attivare e disattivare iolatency su sda:
echo +io > /sys/fs/cgroup/cgroup.subtree_control while true; do mkdir -p /sys/fs/cgroup/test echo '8:0 target=100000' > /sys/fs/cgroup/test/io.latency sleep 1 rmdir /sys/fs/cgroup/test sleep 1 done
e c'è un processo fio concorrente che genera letture casuali dirette:
fio --name test --filename=/dev/sda --direct=1 --rw=randread \ --runtime=600 --time_based --iodepth=256 --numjobs=4 --bs=4k
mentre si monitora con il seguente script drgn:
while True: for css in css_for_each_descendant_pre(prog['blkcg_root'].css.address_of_()):
for pos in hlist_for_each(container_of(css, 'struct blkcg', 'css').blkg_list): blkg = container_of(pos, 'struct blkcg_gq', 'blkcg_node') pd = blkg.pd[prog['blkcg_policy_iolatency'].plid]
if pd.value_() == 0: continue iolat = container_of(pd, 'struct iolatency_grp', 'pd') inflight = iolat.rq_wait.inflight.counter.value_() if inflight: print(f'inflight={inflight} {disk_name(blkg.q.disk).decode("utf-8")} '
f'{cgroup_path(css.cgroup).decode("utf-8")}')
time.sleep(1)
L'output del monitoraggio appare come segue:
inflight=1 sda /user.slice inflight=1 sda /user.slice ... inflight=14 sda /user.slice inflight=13 sda /user.slice inflight=17 sda /user.slice inflight=20 sda /user.slice inflight=19 sda /user.slice <- fio stopped, inflight stuck at 19 inflight=19 sda /user.slice inflight=19 sda /user.slice
Se un cgroup con operazioni IO in corso bloccate finisce per essere sottoposto a throttling, le IO sottoposte a throttling non verranno mai emesse poiché non c'è un evento di completamento per svegliarlo, portando a un blocco indefinito.
Questa patch corregge il bug unificando la gestione dell'abilitazione in un elemento di lavoro che viene automaticamente avviato da iolatency_set_min_lat_nsec(), che viene chiamato sia dai percorsi iolatency_set_limit() che iolatency_pd_offline(). L'uso di un elemento di lavoro è necessario poiché iolatency_pd_offline() viene chiamato sotto spinlock mentre il congelamento di una request_queue richiede un contesto dormiente.
Questo semplifica anche il codice riducendo il numero di righe di codice (LOC) escludendo i commenti ed evita i congelamenti non necessari che si verificavano ogni volta che il target di latenza di un cgroup veniva impostato o cancellato.
If you want to get best quality of vulnerability data, you may have to visit VulDB.