Skip to content

Commit 6e0e34d

Browse files
foxiraingregkh
authored andcommitted
usb: gadget: f_uac1_legacy: validate control request size
f_audio_complete() copies req->length bytes into a 4-byte stack variable: u32 data = 0; memcpy(&data, req->buf, req->length); req->length is derived from the host-controlled USB request path, which can lead to a stack out-of-bounds write. Validate req->actual against the expected payload size for the supported control selectors and decode only the expected amount of data. This avoids copying a host-influenced length into a fixed-size stack object. Signed-off-by: Taegu Ha <hataegu0826@gmail.com> Cc: stable <stable@kernel.org> Link: https://patch.msgid.link/20260401191311.3604898-1-hataegu0826@gmail.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 01af542 commit 6e0e34d

1 file changed

Lines changed: 37 additions & 10 deletions

File tree

drivers/usb/gadget/function/f_uac1_legacy.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -360,19 +360,46 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
360360
static void f_audio_complete(struct usb_ep *ep, struct usb_request *req)
361361
{
362362
struct f_audio *audio = req->context;
363-
int status = req->status;
364-
u32 data = 0;
365363
struct usb_ep *out_ep = audio->out_ep;
366364

367-
switch (status) {
368-
369-
case 0: /* normal completion? */
370-
if (ep == out_ep)
365+
switch (req->status) {
366+
case 0:
367+
if (ep == out_ep) {
371368
f_audio_out_ep_complete(ep, req);
372-
else if (audio->set_con) {
373-
memcpy(&data, req->buf, req->length);
374-
audio->set_con->set(audio->set_con, audio->set_cmd,
375-
le16_to_cpu(data));
369+
} else if (audio->set_con) {
370+
struct usb_audio_control *con = audio->set_con;
371+
u8 type = con->type;
372+
u32 data;
373+
bool valid_request = false;
374+
375+
switch (type) {
376+
case UAC_FU_MUTE: {
377+
u8 value;
378+
379+
if (req->actual == sizeof(value)) {
380+
memcpy(&value, req->buf, sizeof(value));
381+
data = value;
382+
valid_request = true;
383+
}
384+
break;
385+
}
386+
case UAC_FU_VOLUME: {
387+
__le16 value;
388+
389+
if (req->actual == sizeof(value)) {
390+
memcpy(&value, req->buf, sizeof(value));
391+
data = le16_to_cpu(value);
392+
valid_request = true;
393+
}
394+
break;
395+
}
396+
}
397+
398+
if (valid_request)
399+
con->set(con, audio->set_cmd, data);
400+
else
401+
usb_ep_set_halt(ep);
402+
376403
audio->set_con = NULL;
377404
}
378405
break;

0 commit comments

Comments
 (0)