// For flags

CVE-2021-46986

usb: dwc3: gadget: Free gadget structure only after freeing endpoints

Severity Score

"-"
*CVSS v-

Exploit Likelihood

*EPSS

Affected Versions

*CPE

Public Exploits

0
*Multiple Sources

Exploited in Wild

-
*KEV

Decision

Track
*SSVC
Descriptions

In the Linux kernel, the following vulnerability has been resolved:

usb: dwc3: gadget: Free gadget structure only after freeing endpoints

As part of commit e81a7018d93a ("usb: dwc3: allocate gadget structure
dynamically") the dwc3_gadget_release() was added which will free
the dwc->gadget structure upon the device's removal when
usb_del_gadget_udc() is called in dwc3_gadget_exit().

However, simply freeing the gadget results a dangling pointer
situation: the endpoints created in dwc3_gadget_init_endpoints()
have their dep->endpoint.ep_list members chained off the list_head
anchored at dwc->gadget->ep_list. Thus when dwc->gadget is freed,
the first dwc3_ep in the list now has a dangling prev pointer and
likewise for the next pointer of the dwc3_ep at the tail of the list.
The dwc3_gadget_free_endpoints() that follows will result in a
use-after-free when it calls list_del().

This was caught by enabling KASAN and performing a driver unbind.
The recent commit 568262bf5492 ("usb: dwc3: core: Add shutdown
callback for dwc3") also exposes this as a panic during shutdown.

There are a few possibilities to fix this. One could be to perform
a list_del() of the gadget->ep_list itself which removes it from
the rest of the dwc3_ep chain.

Another approach is what this patch does, by splitting up the
usb_del_gadget_udc() call into its separate "del" and "put"
components. This allows dwc3_gadget_free_endpoints() to be
called before the gadget is finally freed with usb_put_gadget().

En el kernel de Linux, se resolvió la siguiente vulnerabilidad: usb: dwc3: gadget: estructura de gadget libre solo después de liberar los puntos finales. Como parte de el commit e81a7018d93a ("usb: dwc3: asignar estructura de gadget dinámicamente"), se agregó dwc3_gadget_release() que libere la estructura dwc->gadget al retirar el dispositivo cuando se llama a usb_del_gadget_udc() en dwc3_gadget_exit(). Sin embargo, simplemente liberar el gadget da como resultado una situación de puntero colgante: los puntos finales creados en dwc3_gadget_init_endpoints() tienen sus miembros dep->endpoint.ep_list encadenados fuera del list_head anclado en dwc->gadget->ep_list. Por lo tanto, cuando se libera dwc->gadget, el primer dwc3_ep de la lista ahora tiene un puntero anterior colgante y lo mismo ocurre con el siguiente puntero de dwc3_ep al final de la lista. El dwc3_gadget_free_endpoints() que sigue dará como resultado un use-after-free cuando llame a list_del(). Esto se detectó habilitando KASAN y realizando una desvinculación del controlador. La reciente confirmación 568262bf5492 ("usb: dwc3: core: Add Shutdown Callback for dwc3") también expone esto como un pánico durante el apagado. Hay algunas posibilidades para solucionar este problema. Una podría ser realizar un list_del() del propio gadget->ep_list que lo elimine del resto de la cadena dwc3_ep. Otro enfoque es lo que hace este parche, al dividir la llamada usb_del_gadget_udc() en sus componentes separados "del" y "put". Esto permite llamar a dwc3_gadget_free_endpoints() antes de que el gadget se libere finalmente con usb_put_gadget().

*Credits: N/A
CVSS Scores
Attack Vector
-
Attack Complexity
-
Privileges Required
-
User Interaction
-
Scope
-
Confidentiality
-
Integrity
-
Availability
-
* Common Vulnerability Scoring System
SSVC
  • Decision:Track
Exploitation
None
Automatable
No
Tech. Impact
Partial
* Organization's Worst-case Scenario
Timeline
  • 2024-02-27 CVE Reserved
  • 2024-02-28 CVE Published
  • 2024-02-29 EPSS Updated
  • 2024-09-11 CVE Updated
  • ---------- Exploited in Wild
  • ---------- KEV Due Date
  • ---------- First Exploit
CWE
CAPEC
Affected Vendors, Products, and Versions
Vendor Product Version Other Status
Vendor Product Version Other Status <-- --> Vendor Product Version Other Status
Linux
Search vendor "Linux"
Linux Kernel
Search vendor "Linux" for product "Linux Kernel"
>= 5.10 < 5.10.38
Search vendor "Linux" for product "Linux Kernel" and version " >= 5.10 < 5.10.38"
en
Affected
Linux
Search vendor "Linux"
Linux Kernel
Search vendor "Linux" for product "Linux Kernel"
>= 5.10 < 5.11.22
Search vendor "Linux" for product "Linux Kernel" and version " >= 5.10 < 5.11.22"
en
Affected
Linux
Search vendor "Linux"
Linux Kernel
Search vendor "Linux" for product "Linux Kernel"
>= 5.10 < 5.12.5
Search vendor "Linux" for product "Linux Kernel" and version " >= 5.10 < 5.12.5"
en
Affected
Linux
Search vendor "Linux"
Linux Kernel
Search vendor "Linux" for product "Linux Kernel"
>= 5.10 < 5.13
Search vendor "Linux" for product "Linux Kernel" and version " >= 5.10 < 5.13"
en
Affected