From: Minjong Kim minbell.kim@samsung.com
[ Upstream commit 185c926283da67a72df20a63a5046b3b4631b7d9 ]
in ntrig_report_version(), hdev parameter passed from hid_probe(). sending descriptor to /dev/uhid can make hdev->dev.parent->parent to null if hdev->dev.parent->parent is null, usb_dev has invalid address(0xffffffffffffff58) that hid_to_usb_dev(hdev) returned when usb_rcvctrlpipe() use usb_dev,it trigger page fault error for address(0xffffffffffffff58)
add null check logic to ntrig_report_version() before calling hid_to_usb_dev()
Signed-off-by: Minjong Kim minbell.kim@samsung.com Link: https://patch.msgid.link/20250813-hid-ntrig-page-fault-fix-v2-1-f98581f35106... Signed-off-by: Benjamin Tissoires bentiss@kernel.org Signed-off-by: Sasha Levin sashal@kernel.org ---
LLM Generated explanations, may be completely bogus:
Now let me analyze what I've found to make a decision on backporting.
## Backport Status: YES
This commit should be backported to stable kernel trees for the following reasons:
### 1. **Critical Bug Fix - Kernel Page Fault** The commit fixes a kernel page fault (crash) that can occur when using N-Trig HID devices with virtual HID interfaces (through /dev/uhid). The commit message describes: - When descriptors are sent through /dev/uhid, `hdev->dev.parent->parent` can be NULL - This causes `hid_to_usb_dev(hdev)` to return an invalid address (0xffffffffffffff58) - When `usb_rcvctrlpipe()` tries to use this invalid pointer, it triggers a page fault
### 2. **Simple and Contained Fix** The fix is minimal and surgical: ```c + if (!hid_is_usb(hdev)) + return; ``` This adds a single safety check before attempting USB-specific operations. The `hid_is_usb()` function is a well-established pattern in the kernel for determining if an HID device is actually backed by USB.
### 3. **Follows Established Pattern** The fix follows an established pattern in the kernel. My analysis shows: - The `hid_is_usb()` helper was introduced specifically for this purpose (commit f83baa0cb6cfc) - Multiple other HID drivers already use this check pattern to avoid similar issues - Greg KH's original commit adding `hid_is_usb()` was marked for stable (`Cc: stable@vger.kernel.org`)
### 4. **Security Implications** This bug could potentially be triggered from userspace through /dev/uhid, making it a potential denial-of-service vector. Any userspace application with access to /dev/uhid could potentially trigger a kernel crash.
### 5. **Minimal Risk of Regression** The fix: - Only adds a defensive check that returns early if the device is not USB - Does not change any existing logic for actual USB devices - Cannot break existing functionality as it only prevents invalid memory access - The kmalloc() allocation is moved after the check, which is also a good practice (avoiding unnecessary allocation)
### 6. **Affects Real Hardware** N-Trig devices are real touchscreen/digitizer hardware used in various tablets and touch-enabled devices. Users of these devices could experience kernel crashes when virtual HID tools interact with the driver.
### 7. **Clear Root Cause** The commit clearly identifies the root cause: the `hid_to_usb_dev()` macro directly dereferences `hdev->dev.parent->parent` without checking if it's valid. For non-USB HID devices (like those created through uhid), this pointer chain may not be valid.
The fix is appropriate for stable backporting as it: - Fixes a real crash that affects users - Is minimal and well-understood - Follows established kernel patterns - Has low risk of introducing new issues - Addresses a potential security concern (userspace-triggerable crash)
drivers/hid/hid-ntrig.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 2738ce947434f..0f76e241e0afb 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c @@ -144,6 +144,9 @@ static void ntrig_report_version(struct hid_device *hdev) struct usb_device *usb_dev = hid_to_usb_dev(hdev); unsigned char *data = kmalloc(8, GFP_KERNEL);
+ if (!hid_is_usb(hdev)) + return; + if (!data) goto err_free;