aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-06-24 09:08:28 -0400
committerTakashi Iwai <tiwai@suse.de>2019-06-24 09:11:06 -0400
commit801ebf1043ae7b182588554cc9b9ad3c14bc2ab5 (patch)
tree0259d975fddf2d2efd55f82377fad81357d1591e
parentc5dfd4b885284e4eaaf66172b918894fdde7eb06 (diff)
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: syzbot+d952e5e28f5fb7718d23@syzkaller.appspotmail.com Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/usb/helper.c17
-rw-r--r--sound/usb/helper.h1
-rw-r--r--sound/usb/quirks.c18
3 files changed, 33 insertions, 3 deletions
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index 7712e2b84183..b1cc9499c57e 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -76,6 +76,20 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype
76 return NULL; 76 return NULL;
77} 77}
78 78
79/* check the validity of pipe and EP types */
80int 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
79/* 93/*
80 * Wrapper for usb_control_msg(). 94 * Wrapper for usb_control_msg().
81 * Allocates a temp buffer to prevent dmaing from/to the stack. 95 * 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,
88 void *buf = NULL; 102 void *buf = NULL;
89 int timeout; 103 int timeout;
90 104
105 if (snd_usb_pipe_sanity_check(dev, pipe))
106 return -EINVAL;
107
91 if (size > 0) { 108 if (size > 0) {
92 buf = kmemdup(data, size, GFP_KERNEL); 109 buf = kmemdup(data, size, GFP_KERNEL);
93 if (!buf) 110 if (!buf)
diff --git a/sound/usb/helper.h b/sound/usb/helper.h
index d338bd0e0ca6..6afb70156ec4 100644
--- a/sound/usb/helper.h
+++ b/sound/usb/helper.h
@@ -7,6 +7,7 @@ unsigned int snd_usb_combine_bytes(unsigned char *bytes, int size);
7void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype); 7void *snd_usb_find_desc(void *descstart, int desclen, void *after, u8 dtype);
8void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsubtype); 8void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsubtype);
9 9
10int snd_usb_pipe_sanity_check(struct usb_device *dev, unsigned int pipe);
10int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, 11int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe,
11 __u8 request, __u8 requesttype, __u16 value, __u16 index, 12 __u8 request, __u8 requesttype, __u16 value, __u16 index,
12 void *data, __u16 size); 13 void *data, __u16 size);
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index e6ce1bbe6ca6..057143330a28 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -840,11 +840,13 @@ static int snd_usb_novation_boot_quirk(struct usb_device *dev)
840static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev) 840static int snd_usb_accessmusic_boot_quirk(struct usb_device *dev)
841{ 841{
842 int err, actual_length; 842 int err, actual_length;
843
844 /* "midi send" enable */ 843 /* "midi send" enable */
845 static const u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 }; 844 static const u8 seq[] = { 0x4e, 0x73, 0x52, 0x01 };
845 void *buf;
846 846
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);
848 if (!buf) 850 if (!buf)
849 return -ENOMEM; 851 return -ENOMEM;
850 err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x05), buf, 852 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)
869 871
870static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev) 872static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
871{ 873{
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),
873 0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE, 879 0xaf, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
874 1, 0, NULL, 0, 1000); 880 1, 0, NULL, 0, 1000);
875 881
@@ -976,6 +982,8 @@ static int snd_usb_axefx3_boot_quirk(struct usb_device *dev)
976 982
977 dev_dbg(&dev->dev, "Waiting for Axe-Fx III to boot up...\n"); 983 dev_dbg(&dev->dev, "Waiting for Axe-Fx III to boot up...\n");
978 984
985 if (snd_usb_pipe_sanity_check(dev, usb_sndctrlpipe(dev, 0)))
986 return -EINVAL;
979 /* If the Axe-Fx III has not fully booted, it will timeout when trying 987 /* If the Axe-Fx III has not fully booted, it will timeout when trying
980 * to enable the audio streaming interface. A more generous timeout is 988 * to enable the audio streaming interface. A more generous timeout is
981 * used here to detect when the Axe-Fx III has finished booting as the 989 * 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,
1008{ 1016{
1009 int err, actual_length; 1017 int err, actual_length;
1010 1018
1019 if (snd_usb_pipe_sanity_check(dev, usb_sndintpipe(dev, 0x01)))
1020 return -EINVAL;
1011 err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x01), buf, *length, 1021 err = usb_interrupt_msg(dev, usb_sndintpipe(dev, 0x01), buf, *length,
1012 &actual_length, 1000); 1022 &actual_length, 1000);
1013 if (err < 0) 1023 if (err < 0)
@@ -1018,6 +1028,8 @@ static int snd_usb_motu_microbookii_communicate(struct usb_device *dev, u8 *buf,
1018 1028
1019 memset(buf, 0, buf_size); 1029 memset(buf, 0, buf_size);
1020 1030
1031 if (snd_usb_pipe_sanity_check(dev, usb_rcvintpipe(dev, 0x82)))
1032 return -EINVAL;
1021 err = usb_interrupt_msg(dev, usb_rcvintpipe(dev, 0x82), buf, buf_size, 1033 err = usb_interrupt_msg(dev, usb_rcvintpipe(dev, 0x82), buf, buf_size,
1022 &actual_length, 1000); 1034 &actual_length, 1000);
1023 if (err < 0) 1035 if (err < 0)