CVE-2026-46232
Description
In the Linux kernel, the following vulnerability has been resolved:
HID: playstation: Clamp num_touch_reports
A device would never lie about the number of touch reports would it?
If it does the loop in dualshock4_parse_report will read off the end of the touch_reports array, up to about 2 KiB for the maximum number of 256 loop iteraions. The data that is read is emitted via evdev if the DS4_TOUCH_POINT_INACTIVE bit happens to be set. Protect against this by clamping the num_touch_reports value provided by the device to the maximum size of the touch_reports array.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
HID playstation driver in the Linux kernel lacks bounds checking on num_touch_reports, allowing out-of-bounds read via malicious USB/Bluetooth device.
Vulnerability
In the Linux kernel's HID: playstation driver, the dualshock4_parse_report function trusts the num_touch_reports field supplied by the device without validation. A malicious or malfunctioning device can set this field to a value up to 256, whereas the touch_reports array in the driver has a fixed size. This leads to an out-of-bounds read of up to approximately 2 KiB beyond the array [1]. The vulnerability affects versions prior to the patch commit 0bc4cf1a6ba00fb8c074531b179bc7b97502fbc4 [1].
Exploitation
The attacker must have physical or local access to connect a malicious USB or Bluetooth HID device that identifies itself as a DualShock 4 controller. No additional authentication is required. The device sends a crafted report with an inflated num_touch_reports value. The driver will iterate up to that value, reading past the end of the touch_reports array. If the read data accidentally has the DS4_TOUCH_POINT_INACTIVE bit set, that data is forwarded to the evdev subsystem [1].
Impact
An attacker can cause the kernel to read out-of-bounds memory from the heap. This may result in information disclosure of sensitive kernel memory contents via evdev events, potentially leaking data such as cryptographic keys, passwords, or other secrets. The CVSS v3 base score is 4.1 (Medium) with confidentiality impact partial, availability none, integrity none, and attack complexity high due to the bit check restriction [1].
Mitigation
The fix was applied to the Linux kernel stable tree in commit 0bc4cf1a6ba00fb8c074531b179bc7b97502fbc4, which clamps the num_touch_reports value to the maximum size of the touch_reports array [1]. Users should update to a kernel version containing this commit. No workaround is available; affected systems should ensure the kernel is patched. The vulnerability is not listed in CISA's Known Exploited Vulnerabilities catalog.
AI Insight generated on May 28, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
2Patches
10208f6d5b1dfdHID: playstation: Clamp num_touch_reports
2 files changed · +8 −6
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 3c0db8f93c829a..8d06ddff356a97 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2378,7 +2378,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2392,7 +2393,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 3c0db8f93c829a..8d06ddff356a97 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2378,7 +2378,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2392,7 +2393,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
7812694752a5HID: playstation: Clamp num_touch_reports
2 files changed · +8 −6
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 2ec6d4445e84ba..12fad45ac10654 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2378,7 +2378,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2392,7 +2393,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 2ec6d4445e84ba..12fad45ac10654 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2378,7 +2378,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2392,7 +2393,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
0bc4cf1a6ba0HID: playstation: Clamp num_touch_reports
2 files changed · +8 −6
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 199f76988bae89..4db50cacbf9af0 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2200,7 +2200,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2214,7 +2215,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else { hid_err(hdev, "Unhandled reportID=%d\n", report->id); -- cgit 1.3-korg
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 199f76988bae89..4db50cacbf9af0 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2200,7 +2200,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2214,7 +2215,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else { hid_err(hdev, "Unhandled reportID=%d\n", report->id); -- cgit 1.3-korg
9c031b24aed6HID: playstation: Clamp num_touch_reports
2 files changed · +8 −6
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index b13a8f27cda0cc..915b3ceb8d21b1 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2248,7 +2248,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2262,7 +2263,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index b13a8f27cda0cc..915b3ceb8d21b1 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2248,7 +2248,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2262,7 +2263,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
cac61b58a3b6HID: playstation: Clamp num_touch_reports
2 files changed · +8 −6
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index c43caac20b61b1..e485373316756a 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2384,7 +2384,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2404,7 +2405,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index c43caac20b61b1..e485373316756a 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2384,7 +2384,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2404,7 +2405,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
0bc4cf1a6ba0HID: playstation: Clamp num_touch_reports
2 files changed · +8 −6
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 199f76988bae89..4db50cacbf9af0 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2200,7 +2200,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2214,7 +2215,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else { hid_err(hdev, "Unhandled reportID=%d\n", report->id); -- cgit 1.3-korg
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 199f76988bae89..4db50cacbf9af0 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2200,7 +2200,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2214,7 +2215,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else { hid_err(hdev, "Unhandled reportID=%d\n", report->id); -- cgit 1.3-korg
7812694752a5HID: playstation: Clamp num_touch_reports
2 files changed · +8 −6
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 2ec6d4445e84ba..12fad45ac10654 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2378,7 +2378,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2392,7 +2393,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 2ec6d4445e84ba..12fad45ac10654 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2378,7 +2378,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2392,7 +2393,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
9c031b24aed6HID: playstation: Clamp num_touch_reports
2 files changed · +8 −6
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index b13a8f27cda0cc..915b3ceb8d21b1 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2248,7 +2248,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2262,7 +2263,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index b13a8f27cda0cc..915b3ceb8d21b1 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2248,7 +2248,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * struct dualshock4_input_report_usb *usb = (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2262,7 +2263,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
cac61b58a3b6HID: playstation: Clamp num_touch_reports
2 files changed · +8 −6
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index c43caac20b61b1..e485373316756a 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2384,7 +2384,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2404,7 +2405,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index c43caac20b61b1..e485373316756a 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2384,7 +2384,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2404,7 +2405,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
208f6d5b1dfdHID: playstation: Clamp num_touch_reports
2 files changed · +8 −6
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 3c0db8f93c829a..8d06ddff356a97 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2378,7 +2378,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2392,7 +2393,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
drivers/hid/hid-playstation.c+4 −3 modifieddiff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 3c0db8f93c829a..8d06ddff356a97 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2378,7 +2378,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2392,7 +2393,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing bounds check on a device-supplied `num_touch_reports` field allows out-of-bounds array read in `dualshock4_parse_report`."
Attack vector
An attacker with physical access to the system can connect a malicious USB or Bluetooth HID device that claims to be a DualShock 4 controller. The device sends a crafted HID report containing an artificially large `num_touch_reports` field (up to 255). The kernel's `dualshock4_parse_report` function uses this untrusted value as the loop bound, reading past the end of the fixed-size `touch_reports` array by up to approximately 2 KiB. If the out-of-bounds data happens to have the `DS4_TOUCH_POINT_INACTIVE` bit clear, the kernel emits that data via evdev, leaking sensitive kernel memory to the attacker.
Affected code
The vulnerability is in the `dualshock4_parse_report` function in `drivers/hid/hid-playstation.c` [patch_id=2897557]. The USB and Bluetooth code paths both read `num_touch_reports` from device-supplied HID report data without validation, then use that value as the loop bound when iterating over the `touch_reports` array.
What the fix does
The patch replaces the direct assignment `num_touch_reports = usb->num_touch_reports` (and the equivalent Bluetooth assignment) with `num_touch_reports = min_t(u8, usb->num_touch_reports, ARRAY_SIZE(usb->touch_reports))` [patch_id=2897557]. This clamps the device-supplied value to the actual size of the `touch_reports` array, preventing any out-of-bounds read regardless of what value the device reports. The same fix is applied to both the USB and Bluetooth code paths.
Preconditions
- physicalAttacker must have physical access to connect a malicious USB or Bluetooth HID device
- inputThe malicious device must present itself as a DualShock 4 controller to the HID subsystem
- configThe kernel must have the HID playstation driver (hid-playstation) loaded
Generated on May 28, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/0bc4cf1a6ba00fb8c074531b179bc7b97502fbc4nvd
- git.kernel.org/stable/c/208f6d5b1dfd6399bc6af9e11f27f1f496243ed0nvd
- git.kernel.org/stable/c/7812694752a5f295eaa05a093b90a2c332666051nvd
- git.kernel.org/stable/c/9c031b24aed6733b6dcc5d98527875b8654a04e9nvd
- git.kernel.org/stable/c/cac61b58a3b6340c52afa06bb15eac033158db2fnvd
News mentions
0No linked articles in our index yet.