Skip to content

Commit 801ebf1

Browse files
committed
ALSA: usb-audio: Sanity checks for each pipe and EP types
The recent USB core code performs sanity checks for the given pipe and EP types, and it can be hit by manipulated USB descriptors by syzbot. For making syzbot happier, this patch introduces a local helper for a sanity check in the driver side and calls it at each place before the message handling, so that we can avoid the WARNING splats. Reported-by: [email protected] Signed-off-by: Takashi Iwai <[email protected]>
1 parent c5dfd4b commit 801ebf1

File tree

3 files changed

+33
-3
lines changed

3 files changed

+33
-3
lines changed

sound/usb/helper.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,20 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype
7676
return NULL;
7777
}
7878

79+
/* check the validity of pipe and EP types */
80+
int snd_usb_pipe_sanity_check(struct usb_device *dev, unsigned int pipe)
81+
{
82+
static const int pipetypes[4] = {
83+
PIPE_CONTROL, PIPE_ISOCHRONOUS, PIPE_BULK, PIPE_INTERRUPT
84+
};
85+
struct usb_host_endpoint *ep;
86+
87+
ep = usb_pipe_endpoint(dev, pipe);
88+
if (usb_pipetype(pipe) != pipetypes[usb_endpoint_type(&ep->desc)])
89+
return -EINVAL;
90+
return 0;
91+
}
92+
7993
/*
8094
* Wrapper for usb_control_msg().
8195
* Allocates a temp buffer to prevent dmaing from/to the stack.
@@ -88,6 +102,9 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
88102
void *buf = NULL;
89103
int timeout;
90104

105+
if (snd_usb_pipe_sanity_check(dev, pipe))
106+
return -EINVAL;
107+
91108
if (size > 0) {
92109
buf = kmemdup(data, size, GFP_KERNEL);
93110
if (!buf)

sound/usb/helper.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ unsigned int snd_usb_combine_bytes(unsigned char *bytes, int size);
77
void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype);
88
void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsubtype);
99

10+
int snd_usb_pipe_sanity_check(struct usb_device *dev, unsigned int pipe);
1011
int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe,
1112
__u8 request, __u8 requesttype, __u16 value, __u16 index,
1213
void *data, __u16 size);

sound/usb/quirks.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -840,11 +840,13 @@ static int snd_usb_novation_boot_quirk(struct usb_device *dev)
840840
static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
841841
{
842842
int err, actual_length;
843-
844843
/* "midi send" enable */
845844
static const u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 };
845+
void *buf;
846846

847-
void *buf = kmemdup(seq, ARRAY_SIZE(seq), GFP_KERNEL);
847+
if (snd_usb_pipe_sanity_check(dev, usb_sndintpipe(dev, 0x05)))
848+
return -EINVAL;
849+
buf = kmemdup(seq, ARRAY_SIZE(seq), GFP_KERNEL);
848850
if (!buf)
849851
return -ENOMEM;
850852
err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x05), buf,
@@ -869,7 +871,11 @@ static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
869871

870872
static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
871873
{
872-
int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
874+
int ret;
875+
876+
if (snd_usb_pipe_sanity_check(dev, usb_sndctrlpipe(dev, 0)))
877+
return -EINVAL;
878+
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
873879
0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
874880
1, 0, NULL, 0, 1000);
875881

@@ -976,6 +982,8 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev)
976982

977983
dev_dbg(&dev->dev, "Waiting for Axe-Fx III to boot up...\n");
978984

985+
if (snd_usb_pipe_sanity_check(dev, usb_sndctrlpipe(dev, 0)))
986+
return -EINVAL;
979987
/* If the Axe-Fx III has not fully booted, it will timeout when trying
980988
* to enable the audio streaming interface. A more generous timeout is
981989
* used here to detect when the Axe-Fx III has finished booting as the
@@ -1008,6 +1016,8 @@ static int snd_usb_motu_microbookii_communicate(struct usb_device *dev, u8 *buf,
10081016
{
10091017
int err, actual_length;
10101018

1019+
if (snd_usb_pipe_sanity_check(dev, usb_sndintpipe(dev, 0x01)))
1020+
return -EINVAL;
10111021
err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x01), buf, *length,
10121022
&actual_length, 1000);
10131023
if (err < 0)
@@ -1018,6 +1028,8 @@ static int snd_usb_motu_microbookii_communicate(struct usb_device *dev, u8 *buf,
10181028

10191029
memset(buf, 0, buf_size);
10201030

1031+
if (snd_usb_pipe_sanity_check(dev, usb_rcvintpipe(dev, 0x82)))
1032+
return -EINVAL;
10211033
err = usb_interrupt_msg(dev, usb_rcvintpipe(dev, 0x82), buf, buf_size,
10221034
&actual_length, 1000);
10231035
if (err < 0)

0 commit comments

Comments
 (0)