[Bug 297187] `bcm2835_audio_release()` Uses a Freed VCHI Service After Close
[email protected] Fri, 31 Jul 2026 07:20:59 +0000
| Newsgroups | gmane.os.freebsd.bugs |
|---|---|
| Message-ID | <[email protected]/bugzilla/> |
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D297187
Bug ID: 297187
Summary: `bcm2835_audio_release()` Uses a Freed VCHI Service
After Close
Product: Base System
Version: CURRENT
Hardware: Any
OS: Any
Status: New
Severity: Affects Some People
Priority: ---
Component: kern
Assignee: [email protected]
Reporter: [email protected]
## Summary
`bcm2835_audio_release()` calls `vchi_service_close()` and then uncondition=
ally
calls `vchi_service_release()` with the same service handle.
In the VCHI shim implementation, a successful `vchi_service_close()` calls
`service_free(service)`. The subsequent `vchi_service_release()` therefore
dereferences a freed `SHIM_SERVICE_T` object when it reads `service->handle=
`.
This is a real kernel heap-use-after-free during `bcm2835_audio` device det=
ach.
It can result in a kernel panic or other undefined kernel behavior.
I have not identified a remote network trigger. I am reporting this private=
ly
because it is a kernel use-after-free and I would appreciate the Security
Team's classification.
## Bug Details
### Vulnerable caller
At `sys/arm/broadcom/bcm2835/bcm2835_audio.c:358`, `bcm2835_audio_release()`
checks the service handle. At lines 363-367 it closes the service and then
releases the same handle:
```c
if (sc->vchi_handle !=3D VCHIQ_SERVICE_HANDLE_INVALID) {
success =3D vchi_service_close(sc->vchi_handle);
if (success !=3D 0)
BCM2835_LOG_ERROR(sc, "vchi_service_close failed: %d\\n",
success);
vchi_service_release(sc->vchi_handle);
sc->vchi_handle =3D VCHIQ_SERVICE_HANDLE_INVALID;
}
```
### Free in `vchi_service_close()`
At `sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c:694-708`, a successf=
ul
close frees the service object:
```c
int32_t vchi_service_close(const VCHI_SERVICE_HANDLE_T handle)
{
int32_t ret =3D -1;
SHIM_SERVICE_T *service =3D (SHIM_SERVICE_T *)handle;
if (service) {
VCHIQ_STATUS_T status =3D vchiq_close_service(service->hand=
le);
if (status =3D=3D VCHIQ_SUCCESS) {
service_free(service);
service =3D NULL;
}
ret =3D vchiq_status_to_vchi(status);
}
return ret;
}
```
`service_free()` at approximately
`sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c:625` deletes the queue =
and
frees the `SHIM_SERVICE_T` object.
### Use after free in `vchi_service_release()`
At `sys/contrib/vchiq/interface/vchiq_arm/vchiq_shim.c:851-860`,
`vchi_service_release()` casts the handle and reads `service->handle`:
```c
int32_t vchi_service_release(const VCHI_SERVICE_HANDLE_T handle)
{
int32_t ret =3D -1;
SHIM_SERVICE_T *service =3D (SHIM_SERVICE_T *)handle;
if (service)
ret =3D vchiq_status_to_vchi(
vchiq_release_service(service->handle));
return ret;
}
```
When `vchi_service_close()` returns success, `service` points to freed memo=
ry
before `vchi_service_release()` is called. The read of `service->handle` is
consequently a use-after-free.
The vulnerable call chain is:
```text
bcm2835_audio_detach()
-> bcm2835_audio_release() [bcm2835_audio.c:358]
-> vchi_service_close(sc->vchi_handle) [bcm2835_audio.c:363]
-> vchiq_close_service(service->handle) [vchiq_shim.c:699]
-> service_free(service) [vchiq_shim.c:701]
-> vchi_service_release(sc->vchi_handle) [bcm2835_audio.c:367]
-> vchiq_release_service(service->handle) [vchiq_shim.c:856]
```
## Impact and Severity
The direct impact is a kernel heap-use-after-free during audio device detac=
h.
Depending on allocator state and the contents of the freed object, this may
cause a kernel panic, failed driver unload, or other undefined kernel behav=
ior.
Preliminary assessment:
- **Confidentiality:** No impact observed.
- **Integrity:** No impact observed.
- **Availability:** Possible local kernel panic or denial of service.
- **Privilege requirement:** Device detach or driver unload likely requires
root or equivalent administrative privilege.
- **Remote exploitability:** Not demonstrated and unlikely through network
traffic.
- **Security classification:** Likely a local kernel reliability issue rath=
er
than a remotely exploitable DoS under the stated FreeBSD policy. It may be
suitable for a normal bug report or an Errata Notice rather than a Security
Advisory.
The use-after-free is nevertheless in kernel code and could warrant security
handling during initial triage.
## Proposed Fix
The minimal fix is to avoid calling `vchi_service_release()` after a succes=
sful
`vchi_service_close()`, because the close operation has already freed the s=
him
service object:
```diff
--- a/sys/arm/broadcom/bcm2835/bcm2835_audio.c
+++ b/sys/arm/broadcom/bcm2835/bcm2835_audio.c
@@ -360,12 +360,12 @@ bcm2835_audio_release(struct bcm2835_audio_info *sc)
if (sc->vchi_handle !=3D VCHIQ_SERVICE_HANDLE_INVALID) {
success =3D vchi_service_close(sc->vchi_handle);
if (success !=3D 0)
BCM2835_LOG_ERROR(sc, "vchi_service_close failed:
%d\\n",
success);
- vchi_service_release(sc->vchi_handle);
sc->vchi_handle =3D VCHIQ_SERVICE_HANDLE_INVALID;
}
```
The final fix should confirm the intended VCHI lifecycle semantics for a fa=
iled
`vchi_service_close()`. If `vchi_service_release()` is required only after a
failed close, the implementation should call it conditionally and only while
the handle remains valid. It should never be called after a successful close
has freed the shim service.
Reporter: Xuqing Yang
--=20
You are receiving this mail because:
You are the assignee for the bug.=