mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
01af542392
commit
6e0e34d85c
@@ -360,19 +360,46 @@ static int f_audio_out_ep_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
static void f_audio_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
struct f_audio *audio = req->context;
|
||||
int status = req->status;
|
||||
u32 data = 0;
|
||||
struct usb_ep *out_ep = audio->out_ep;
|
||||
|
||||
switch (status) {
|
||||
|
||||
case 0: /* normal completion? */
|
||||
if (ep == out_ep)
|
||||
switch (req->status) {
|
||||
case 0:
|
||||
if (ep == out_ep) {
|
||||
f_audio_out_ep_complete(ep, req);
|
||||
else if (audio->set_con) {
|
||||
memcpy(&data, req->buf, req->length);
|
||||
audio->set_con->set(audio->set_con, audio->set_cmd,
|
||||
le16_to_cpu(data));
|
||||
} else if (audio->set_con) {
|
||||
struct usb_audio_control *con = audio->set_con;
|
||||
u8 type = con->type;
|
||||
u32 data;
|
||||
bool valid_request = false;
|
||||
|
||||
switch (type) {
|
||||
case UAC_FU_MUTE: {
|
||||
u8 value;
|
||||
|
||||
if (req->actual == sizeof(value)) {
|
||||
memcpy(&value, req->buf, sizeof(value));
|
||||
data = value;
|
||||
valid_request = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UAC_FU_VOLUME: {
|
||||
__le16 value;
|
||||
|
||||
if (req->actual == sizeof(value)) {
|
||||
memcpy(&value, req->buf, sizeof(value));
|
||||
data = le16_to_cpu(value);
|
||||
valid_request = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_request)
|
||||
con->set(con, audio->set_cmd, data);
|
||||
else
|
||||
usb_ep_set_halt(ep);
|
||||
|
||||
audio->set_con = NULL;
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user