CVE-2023-52738 in Linux
Summary
by MITRE • 05/21/2024
In the Linux kernel, the following vulnerability has been resolved:
drm/amdgpu/fence: Fix oops due to non-matching drm_sched init/fini
Currently amdgpu calls drm_sched_fini() from the fence driver sw fini routine - such function is expected to be called only after the respective init function - drm_sched_init() - was executed successfully.
Happens that we faced a driver probe failure in the Steam Deck recently, and the function drm_sched_fini() was called even without its counter-part had been previously called, causing the following oops:
amdgpu: probe of 0000:04:00.0 failed with error -110 BUG: kernel NULL pointer dereference, address: 0000000000000090 PGD 0 P4D 0 Oops: 0002 [#1] PREEMPT SMP NOPTI
CPU: 0 PID: 609 Comm: systemd-udevd Not tainted 6.2.0-rc3-gpiccoli #338 Hardware name: Valve Jupiter/Jupiter, BIOS F7A0113 11/04/2022 RIP: 0010:drm_sched_fini+0x84/0xa0 [gpu_sched]
[...]
Call Trace: amdgpu_fence_driver_sw_fini+0xc8/0xd0 [amdgpu]
amdgpu_device_fini_sw+0x2b/0x3b0 [amdgpu]
amdgpu_driver_release_kms+0x16/0x30 [amdgpu]
devm_drm_dev_init_release+0x49/0x70 [...]
To prevent that, check if the drm_sched was properly initialized for a given ring before calling its fini counter-part.
Notice ideally we'd use sched.ready for that; such field is set as the latest thing on drm_sched_init(). But amdgpu seems to "override" the meaning of such field - in the above oops for example, it was a GFX ring causing the crash, and the sched.ready field was set to true in the ring init routine, regardless of the state of the DRM scheduler. Hence, we ended-up using sched.ops as per Christian's suggestion [0], and also removed the no_scheduler check [1].
[0] https://lore.kernel.org/amd-gfx/[email protected]/
[1] https://lore.kernel.org/amd-gfx/[email protected]/
If you want to get best quality of vulnerability data, you may have to visit VulDB.
Analysis
by VulDB Data Team • 11/07/2024
The vulnerability described in CVE-2023-52738 represents a critical kernel NULL pointer dereference issue within the Linux kernel's amdgpu driver implementation. This flaw specifically affects the graphics subsystem's fence driver component and manifests as a system crash during device probe failure scenarios. The issue occurs when the drm_sched_fini() function is invoked without a corresponding drm_sched_init() call having been successfully executed first, creating a state where the scheduler's initialization is incomplete yet its cleanup routine attempts to operate on uninitialized resources.
The technical root cause stems from improper synchronization between initialization and finalization routines within the AMD GPU driver's scheduling subsystem. When the amdgpu driver encounters a probe failure on the Steam Deck device, it attempts to clean up resources through the fence driver's software finalization routine. However, this cleanup process calls drm_sched_fini() directly without verifying whether the scheduler was properly initialized, leading to a kernel NULL pointer dereference at address 0x0000000000000090. This particular memory access pattern triggers a kernel oops condition that results in system instability and potential denial of service.
The operational impact of this vulnerability extends beyond simple system crashes, as it represents a fundamental race condition and state management flaw within the graphics driver's resource lifecycle management. The vulnerability affects systems running Linux kernel versions that include the affected amdgpu driver code, particularly impacting gaming devices like the Steam Deck where graphics performance and system stability are paramount. The issue demonstrates poor defensive programming practices where proper state validation checks are omitted, allowing cleanup functions to operate on potentially uninitialized structures.
Security implications of this vulnerability align with CWE-476, which describes NULL pointer dereference conditions that can lead to system crashes and potentially provide attack vectors for privilege escalation or denial of service attacks. The flaw also relates to ATT&CK technique T1499.004, which covers system network configuration modifications, as improper driver cleanup can affect system stability and resource allocation. The fix implemented addresses this by introducing proper initialization state validation before calling the finalization routine, using the sched.ops field as a reliable indicator of scheduler state rather than relying on the overridden sched.ready field that was incorrectly set during the ring initialization process.
The mitigation strategy involves implementing proper conditional checks to ensure that drm_sched_fini() is only called when the corresponding drm_sched_init() has been successfully executed. This approach prevents the kernel from attempting to dereference uninitialized scheduler structures while maintaining the driver's ability to clean up resources properly during normal operation. The solution demonstrates proper defensive programming practices that align with kernel development best practices and security hardening guidelines. The fix specifically addresses the issue by replacing the unreliable sched.ready field check with the more reliable sched.ops field validation, which provides a true indicator of whether the scheduler has been properly initialized and configured for operation.