CVE-2026-98200 in Linux
Summary
by MITRE • 10/06/2026
In the Linux kernel, the following vulnerability has been resolved:
hwmon: (hp-wmi-sensors) Fix use-after-free in fungible_show()
nsensor->current_state is dynamically replaced as the sensor's state changes. update_numeric_sensor_from_wobj() does this by freeing the old string and installing a new one:
if (strcmp(trimmed, nsensor->current_state)) {
new_string = hp_wmi_strdup(dev, trimmed); if (new_string) {
devm_kfree(dev, nsensor->current_state); nsensor->current_state = new_string; } }
This function is only ever called from hp_wmi_update_info() while state->lock is held, so the free-and-replace itself is properly serialized against concurrent updates.
fungible_show(), however, reads the same pointer after the lock has already been dropped:
err = hp_wmi_update_info(state, info); if (err) return err;
switch (prop) {
... case HP_WMI_PROPERTY_CURRENT_STATE: seq_printf(seqf, "%s\n", nsensor->current_state); break;
hp_wmi_update_info() takes state->lock internally and releases it before returning, so by the time fungible_show() dereferences nsensor->current_state in seq_printf(), no lock is held. Two processes reading a sensor's current_state debugfs entry at overlapping times (or one reading it while another read of the same sensor triggers a refresh) can race: one thread's seq_printf() can be part-way through printing the string at the moment another thread's call into update_numeric_sensor_from_wobj() frees it with devm_kfree() and installs a new pointer, causing a use-after-free read.
Take state->lock around the read in fungible_show() as well, so it can never run concurrently with the free-and-replace in update_numeric_sensor_from_wobj().
If you want to get the best quality for vulnerability data then you always have to consider VulDB.
Analysis
by VulDB Data Team • 10/06/2026
The vulnerability identified in the Linux kernel's hp-wmi-sensors driver represents a classic use-after-free condition within the debugfs interface for hardware monitoring sensors. This flaw arises from an inconsistency in synchronization primitives used to protect shared data structures, specifically the nsensor->current_state pointer which holds the string representation of a sensor's current state. The root cause lies in the asynchronous access patterns between two distinct code paths: one responsible for updating the sensor information and another responsible for exposing that information to user space via debugfs. While the update mechanism correctly employs locking to ensure atomicity during memory allocation and deallocation, the read path fails to acquire the same lock before accessing the pointer, creating a race condition window where stale or freed memory can be dereferenced.
The technical flaw is rooted in the implementation of hp_wmi_update_info() and its interaction with fungible_show(). The function update_numeric_sensor_from_wobj(), which is invoked by hp_wmi_update_info(), manages the lifecycle of nsensor->current_state by freeing the old string using devm_kfree() and immediately assigning a newly allocated string to the pointer. This sequence is properly serialized because it occurs while state->lock is held, preventing concurrent modifications from other threads during the critical section. However, hp_wmi_update_info() releases this lock before returning control to its caller. Consequently, when fungible_show() subsequently calls hp_wmi_update_info(), updates the local info structure, and then proceeds to read nsensor->current_state via seq_printf(), it does so without holding state->lock. This lack of synchronization means that a concurrent execution thread can trigger an update between the time the pointer is read into a register or stack variable by one process and when it is actually dereferenced for output in another, leading to a use-after-free scenario if the memory has been freed but not yet reallocated elsewhere.
The operational impact of this vulnerability allows for potential kernel instability and security exploitation. A successful exploit could lead to a kernel panic due to an invalid memory access, resulting in a denial of service against the system. More critically, because the attacker can influence or predict the state of the freed memory through controlled timing attacks, they may achieve arbitrary code execution by overwriting the freed memory with malicious data that gets interpreted as valid pointers or function addresses during subsequent allocations. This aligns with CWE-416, Use After Free, which describes situations where a program continues to use a pointer after it has been freed, leading to undefined behavior and potential security breaches. The specific access pattern also relates to CWE-362, Concurrent Execution using Shared Resource with Improper Synchronization, as the race condition is directly caused by insufficient locking around shared resource access.
From an offensive security perspective, this vulnerability can be mapped to ATT&CK techniques involving memory corruption or privilege escalation if exploited in a context where user-space processes have write access to debugfs entries. An attacker could leverage tools like syzkaller or custom fuzzing scripts to trigger the race condition repeatedly, increasing the probability of successful exploitation by manipulating scheduler timing and allocation patterns. The vulnerability is particularly dangerous because it resides in a driver that interacts with hardware management interfaces, potentially allowing local users who have access to specific debugfs nodes to escalate privileges or crash the system without requiring high-level permissions initially, depending on the default file permissions assigned to these entries.
Mitigation for this issue involves ensuring strict consistency in locking strategies across all code paths that access shared mutable state. The primary fix implemented by the vendor is to wrap the read operation of nsensor->current_state within fungible_show() with a lock acquisition of state->lock, mirroring the protection already present in the update path. This ensures mutual exclusion between readers and writers, preventing any concurrent modification while the pointer is being dereferenced. Beyond this specific patch, developers should audit similar patterns in other drivers where debugfs or sysfs interfaces expose dynamic data structures to user space. It is recommended to use dedicated read-write locks if multiple threads need frequent access, though for simple cases like this, a standard mutex suffices. Additionally, employing static analysis tools and runtime checkers such as KASAN (Kernel Address Sanitizer) during development can help detect these race conditions early in the software lifecycle before they reach production kernels.