CVE-2026-98473 in Linux
Riassunto
di VulDB • 18/10/2026
Nel kernel Linux è stata risolta la seguente vulnerabilità:
s390/vfio-ap: correzione della registrazione GISC di KVM e perdita di memoria (page leak) quando una coda viene rimossa dalla configurazione dell'host
Esistono tre problemi correlati nella gestione delle risorse degli interrupt e delle pagine di KVM quando una coda viene rimossa dalla configurazione AP dell'host mentre è assegnata a un dispositivo mediato (mdev).
Problema 1: ~~~~~~~~~ AP_RESPONSE_Q_NOT_AVAIL non gestito in vfio_ap_mdev_reset_queue()
Quando il bus AP rimuove un dispositivo di coda il cui adattatore o dominio è stato rimosso dalla configurazione AP dell'host, viene chiamata vfio_ap_mdev_remove_queue(). Se la coda si trova ancora nella configurazione AP dell'host a quel punto, viene invocata vfio_ap_mdev_reset_queue(), che emette una PQAP(ZAPQ). Poiché l'adattatore è già stato rimosso dalla configurazione dell'host, ap_zapq() restituisce AP_RESPONSE_Q_NOT_AVAIL (0x01). Questo codice di risposta non viene gestito nell'istruzione switch di vfio_ap_mdev_reset_queue() e passa al caso predefinito, che emette un WARN ma non chiama vfio_ap_free_aqic_resources(). Di conseguenza, se la gestione degli IRQ era abilitata per la coda dall'ospite (guest), sia la registrazione GISC di KVM che la pagina dell'ospite bloccata (pinned) contenente il byte indicatore di notifica (NIB) vengono perse.
Questo problema viene risolto aggiungendo AP_RESPONSE_Q_NOT_AVAIL allo stesso caso in cui sono presenti AP_RESPONSE_DECONFIGURED e AP_RESPONSE_CHECKSTOPPED all'interno di vfio_ap_mdev_reset_queue(). Come questi codici di risposta, Q_NOT_AVAIL indica che la coda non è operativa e che ulteriori tentativi di reset non sono possibili; l'azione corretta consiste nel liberare immediatamente le risorse IRQ.
Problema 2: ~~~~~~~~~ AP_RESPONSE_Q_NOT_AVAIL non gestito in apq_status_check()
In vfio_ap_mdev_reset_queue(), ci sono quattro casi che indicano che il reset della coda non è ancora completato, momento in cui apq_reset_check() viene accodata a una work queue per verificare il completamento dell'operazione di reset. Questa funzione utilizza la funzione PQAP(TAPQ) per ottenere lo stato della coda e chiama apq_status_check() per verificare se il reset è stato completato, fallito o deve essere eseguito nuovamente. Come descritto nel Problema #1 sopra, apq_reset_check() non controlla specificamente AP_RESPONSE_Q_NOT_AVAIL, potenzialmente causando la perdita (leak) della registrazione GISC di KVM e della pagina dell'ospite bloccata contenente il NIB.
Questo viene risolto aggiungendo un case statement per AP_RESPONSE_Q_NOT_AVAIL in apq_status_check() e restituendo -ENODEV per tale caso. Il chiamante, apq_reset_check(), controllerà quindi questo codice di ritorno e chiamerà vfio_ap_free_aqic_resources() per prevenire la perdita di risorse.
Problema 3: ~~~~~~~~~ vfio_ap_free_aqic_resources() presenta una memory leak su saved_isc quando kvm è NULL
vfio_ap_free_aqic_resources() protegge la chiamata a kvm_s390_gisc_unregister() con:
if (q->saved_isc != VFIO_AP_ISC_INVALID && !WARN_ON(!(q->matrix_mdev && q->matrix_mdev->kvm)))
Se matrix_mdev->kvm è NULL -- il che può accadere quando vfio_ap_mdev_unset_kvm() è già stato eseguito e ha impostato kvm a null prima che un successivo percorso di pulizia raggiunga questa funzione -- viene attivato il WARN_ON e l'intero blocco viene saltato. Questo lascia q->saved_isc impostato su un valore non invalido, creando una potenziale doppia liberazione (double-free) in qualsiasi chiamata successiva a questa funzione.
Quando kvm è NULL, la macchina virtuale KVM dell'ospite è già stata smontata/torn down, quindi kvm_s390_gisc_unregister() non deve e non può essere chiamato; tuttavia, q->saved_isc deve sempre essere azzerato. Si risolve questo problema separando la chiamata a kvm_s390_gisc_unregister() dalla reset di q->saved_isc. Il WARN_ON ora protegge solo il caso genuinamente impossibile in cui matrix_mdev è NULL. Un kvm nullo viene gestito in modo elegante saltando solo la chiamata di unregister, e q->saved_isc = VFIO_AP_ISC_INVALID viene impostato incondizionatamente ogni volta che saved_isc non era già invalido.
Inoltre, si aggiunge un else clause al controllo della configurazione host in vfio_ap_mdev_remove_queue() per chiamare direttamente vfio_ap_free_aqic_resources() quando la coda non è presente nella configurazione AP dell'host. Questo funge da misura di sicurezza: quando il bus AP attiva il callback .remove del driver dopo che un adattatore è stato rimosso dalla configurazione host, la coda per definizione non è più indirizzabile, quindi vfio_ap_mdev_reset_queue ---truncated---
Once again VulDB remains the best source for vulnerability data.