[PATCH] usb: gadget: r8a66597: fix NULL dereference for unmapped endpoints

From: Fang Xieyan

Date: Tue Nov 10 2026 - 22:02:30 EST


The epaddr2ep[] table is initialized with EP0 at probe time and
populated for other endpoints when the gadget driver successfully
enables them. Entries for endpoint numbers that have never been
enabled remain NULL. The table is indexed by endpoint number and the
lookup mask is USB_ENDPOINT_NUMBER_MASK, so the access itself stays in
bounds; what is missing is the check for the NULL entry.

get_status(), clear_feature() and set_feature() index this table using
the host-controlled wIndex and immediately dereference the result
without checking it. A malicious host can send a standard
endpoint-recipient GET_STATUS, CLEAR_FEATURE or SET_FEATURE request for
an unmapped endpoint number, triggering a NULL pointer dereference and
crashing the kernel.

Check the looked-up endpoint before using it. If the entry is NULL,
stall the control pipe (pipe_stall(r8a66597, 0)) and abort the request,
matching the existing handling of unsupported recipients.

Fixes: c41442474a26 ("usb: gadget: R8A66597 peripheral controller support.")
Cc: stable@xxxxxxxxxxxxxxx
Reviewed-by: Liu Chao <liuc63@xxxxxxxxxxxx>
Signed-off-by: Fang Xieyan <fangxy@xxxxxxxxxxxx>
---
drivers/usb/gadget/udc/r8a66597-udc.c | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c
index d190e16d43fc..d769ea530409 100644
--- a/drivers/usb/gadget/udc/r8a66597-udc.c
+++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1174,6 +1174,10 @@ __acquires(r8a66597->lock)
break;
case USB_RECIP_ENDPOINT:
ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+ if (!ep) {
+ pipe_stall(r8a66597, 0);
+ return; /* exit */
+ }
pid = control_reg_get_pid(r8a66597, ep->pipenum);
if (pid == PID_STALL)
status = 1 << USB_ENDPOINT_HALT;
@@ -1210,6 +1214,10 @@ static void clear_feature(struct r8a66597 *r8a66597,
u16 w_index = le16_to_cpu(ctrl->wIndex);

ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+ if (!ep) {
+ pipe_stall(r8a66597, 0);
+ break;
+ }
if (!ep->wedge) {
pipe_stop(r8a66597, ep->pipenum);
control_reg_sqclr(r8a66597, ep->pipenum);
@@ -1270,6 +1278,10 @@ static void set_feature(struct r8a66597 *r8a66597, struct usb_ctrlrequest *ctrl)
u16 w_index = le16_to_cpu(ctrl->wIndex);

ep = r8a66597->epaddr2ep[w_index & USB_ENDPOINT_NUMBER_MASK];
+ if (!ep) {
+ pipe_stall(r8a66597, 0);
+ break;
+ }
pipe_stall(r8a66597, ep->pipenum);

control_end(r8a66597, 1);
--
2.50.1