* [PATCH 0/3] ALSA: usb-audio: fix OOB and return value check
@ 2017-11-28 0:36 Jaejoong Kim
2017-11-28 0:36 ` [PATCH 1/3] ALSA: usb-audio: Fix out-of-bound error Jaejoong Kim
` (3 more replies)
0 siblings, 4 replies; 11+ messages in thread
From: Jaejoong Kim @ 2017-11-28 0:36 UTC (permalink / raw)
To: Takashi Iwai; +Cc: Jaroslav Kysela, stable, alsa-devel, Jaejoong Kim
Hi,
This patch series fixes the out-of-bound error caused by the return value
of usb_string(). It was descovered by KASAN. The Patch 1 is the V2 about
http://www.spinics.net/lists/alsa-devel/msg69487.html
Chanes in V2:
- put an explicit error bail out(by Takashi iwai)
Patch1 was founded by connecting the following product.
http://www.lg.com/uk/lg-friends/lg-AFD-1200
I found that it only check if the return value from usb_string() is always
zero while modifying OOB KASAN message. So instead of making the
modifications to OOB to V2, I sent a patch series.
I am sorry to break the mail thread.
Thanks
jaejoong
Jaejoong Kim (3):
ALSA: usb-audio: Fix out-of-bound error
ALSA: usb-audio: Fix return value check for usb_string()
ALSA: usb-audio: Add check return value for usb_string()
sound/usb/mixer.c | 41 ++++++++++++++++++++++++-----------------
1 file changed, 24 insertions(+), 17 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 1/3] ALSA: usb-audio: Fix out-of-bound error 2017-11-28 0:36 [PATCH 0/3] ALSA: usb-audio: fix OOB and return value check Jaejoong Kim @ 2017-11-28 0:36 ` Jaejoong Kim 2017-11-28 0:36 ` [PATCH 2/3] ALSA: usb-audio: Fix return value check for usb_string() Jaejoong Kim ` (2 subsequent siblings) 3 siblings, 0 replies; 11+ messages in thread From: Jaejoong Kim @ 2017-11-28 0:36 UTC (permalink / raw) To: Takashi Iwai; +Cc: Jaroslav Kysela, stable, alsa-devel, Jaejoong Kim The snd_usb_copy_string_desc() retrieves the usb string corresponding to the index number through the usb_string(). The problem is that the usb_string() returns the length of the string (>= 0) when successful, but it can also return a negative value about the error case or status of usb_control_msg(). If iClockSource is '0' as shown below, usb_string() will returns -EINVAL. This will result in '0' being inserted into buf[-22], and the following KASAN out-of-bound error message will be output. AudioControl Interface Descriptor: bLength 8 bDescriptorType 36 bDescriptorSubtype 10 (CLOCK_SOURCE) bClockID 1 bmAttributes 0x07 Internal programmable Clock (synced to SOF) bmControls 0x07 Clock Frequency Control (read/write) Clock Validity Control (read-only) bAssocTerminal 0 iClockSource 0 To fix it, check usb_string() return value and bail out. ================================================================== BUG: KASAN: stack-out-of-bounds in parse_audio_unit+0x1327/0x1960 [snd_usb_audio] Write of size 1 at addr ffff88007e66735a by task systemd-udevd/18376 CPU: 0 PID: 18376 Comm: systemd-udevd Not tainted 4.13.0+ #3 Hardware name: LG Electronics 15N540-RFLGL/White Tip Mountain, BIOS 15N5 Call Trace: dump_stack+0x63/0x8d print_address_description+0x70/0x290 ? parse_audio_unit+0x1327/0x1960 [snd_usb_audio] kasan_report+0x265/0x350 __asan_store1+0x4a/0x50 parse_audio_unit+0x1327/0x1960 [snd_usb_audio] ? save_stack+0xb5/0xd0 ? save_stack_trace+0x1b/0x20 ? save_stack+0x46/0xd0 ? kasan_kmalloc+0xad/0xe0 ? kmem_cache_alloc_trace+0xff/0x230 ? snd_usb_create_mixer+0xb0/0x4b0 [snd_usb_audio] ? usb_audio_probe+0x4de/0xf40 [snd_usb_audio] ? usb_probe_interface+0x1f5/0x440 ? driver_probe_device+0x3ed/0x660 ? build_feature_ctl+0xb10/0xb10 [snd_usb_audio] ? save_stack_trace+0x1b/0x20 ? init_object+0x69/0xa0 ? snd_usb_find_csint_desc+0xa8/0xf0 [snd_usb_audio] snd_usb_mixer_controls+0x1dc/0x370 [snd_usb_audio] ? build_audio_procunit+0x890/0x890 [snd_usb_audio] ? snd_usb_create_mixer+0xb0/0x4b0 [snd_usb_audio] ? kmem_cache_alloc_trace+0xff/0x230 ? usb_ifnum_to_if+0xbd/0xf0 snd_usb_create_mixer+0x25b/0x4b0 [snd_usb_audio] ? snd_usb_create_stream+0x255/0x2c0 [snd_usb_audio] usb_audio_probe+0x4de/0xf40 [snd_usb_audio] ? snd_usb_autosuspend.part.7+0x30/0x30 [snd_usb_audio] ? __pm_runtime_idle+0x90/0x90 ? kernfs_activate+0xa6/0xc0 ? usb_match_one_id_intf+0xdc/0x130 ? __pm_runtime_set_status+0x2d4/0x450 usb_probe_interface+0x1f5/0x440 Cc: <stable@vger.kernel.org> Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com> --- Changes in V2: - put an explicit error bail-out(by Takashi iwai) sound/usb/mixer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index e630813..da7cbe7 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -204,6 +204,10 @@ static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen) { int len = usb_string(state->chip->dev, index, buf, maxlen - 1); + + if (len < 0) + return len; + buf[len] = 0; return len; } -- 2.7.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/3] ALSA: usb-audio: Fix return value check for usb_string() 2017-11-28 0:36 [PATCH 0/3] ALSA: usb-audio: fix OOB and return value check Jaejoong Kim 2017-11-28 0:36 ` [PATCH 1/3] ALSA: usb-audio: Fix out-of-bound error Jaejoong Kim @ 2017-11-28 0:36 ` Jaejoong Kim 2017-11-28 6:33 ` Takashi Iwai 2017-11-28 0:36 ` [PATCH 3/3] ALSA: usb-audio: Add check return value " Jaejoong Kim 2017-12-04 6:31 ` [PATCH V2 0/2] ALSA: usb-audio: fix OOB and return value check Jaejoong Kim 3 siblings, 1 reply; 11+ messages in thread From: Jaejoong Kim @ 2017-11-28 0:36 UTC (permalink / raw) To: Takashi Iwai; +Cc: Jaroslav Kysela, stable, alsa-devel, Jaejoong Kim In case of failure, the usb_string() can return a negative number. Therefore, the return value of snd_usb_copy_string_desc() and get_term_name() can also be negative. Check the return values for these functions as follows: len = snd_usb_copy_string_desc(); if (!len) ... If len is negative, the if-statement is false and fails to handle exceptions. So, we need to change it to a value less than or equal to zero. Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com> --- sound/usb/mixer.c | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index da7cbe7..8a434b7 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1235,7 +1235,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, { struct uac_feature_unit_descriptor *desc = raw_desc; struct usb_feature_control_info *ctl_info; - unsigned int len = 0; + int len = 0; int mapped_name = 0; int nameid = uac_feature_unit_iFeature(desc); struct snd_kcontrol *kctl; @@ -1313,14 +1313,14 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, * - if the connected output can be determined, use it. * - otherwise, anonymous name. */ - if (!len) { + if (len <= 0) { len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 1); - if (!len) + if (len <= 0) len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 1); - if (!len) + if (len <= 0) snprintf(kctl->id.name, sizeof(kctl->id.name), "Feature %d", unitid); } @@ -1343,7 +1343,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, " Switch" : " Volume"); break; default: - if (!len) + if (len <= 0) strlcpy(kctl->id.name, audio_feature_info[control-1].name, sizeof(kctl->id.name)); break; @@ -1610,7 +1610,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state, { struct usb_mixer_elem_info *cval; unsigned int num_outs = uac_mixer_unit_bNrChannels(desc); - unsigned int i, len; + unsigned int i; + int len; struct snd_kcontrol *kctl; const struct usbmix_name_map *map; @@ -1649,7 +1650,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, if (!len) len = get_term_name(state, iterm, kctl->id.name, sizeof(kctl->id.name), 0); - if (!len) + if (len <= 0) len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); append_ctl_name(kctl, " Volume"); @@ -1947,7 +1948,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); - if (!len) + if (len <= 0) strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); } append_ctl_name(kctl, " "); @@ -2077,7 +2078,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void *raw_desc) { struct uac_selector_unit_descriptor *desc = raw_desc; - unsigned int i, nameid, len; + unsigned int i, nameid; + int len; int err; struct usb_mixer_elem_info *cval; struct snd_kcontrol *kctl; @@ -2138,9 +2140,10 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, } len = check_mapped_selector_name(state, unitid, i, namelist[i], MAX_ITEM_NAME_LEN); - if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) + if (!len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); - if (! len) + + if (len <= 0) sprintf(namelist[i], "Input %u", i); } @@ -2164,7 +2167,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, else { len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 0); - if (!len) + if (len <= 0) strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) -- 2.7.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 2/3] ALSA: usb-audio: Fix return value check for usb_string() 2017-11-28 0:36 ` [PATCH 2/3] ALSA: usb-audio: Fix return value check for usb_string() Jaejoong Kim @ 2017-11-28 6:33 ` Takashi Iwai 2017-11-28 7:32 ` Jaejoong Kim 0 siblings, 1 reply; 11+ messages in thread From: Takashi Iwai @ 2017-11-28 6:33 UTC (permalink / raw) To: Jaejoong Kim; +Cc: Jaroslav Kysela, stable, alsa-devel On Tue, 28 Nov 2017 01:36:27 +0100, Jaejoong Kim wrote: > > In case of failure, the usb_string() can return a negative number. Therefore, > the return value of snd_usb_copy_string_desc() and get_term_name() can also > be negative. > > Check the return values for these functions as follows: > > len = snd_usb_copy_string_desc(); > if (!len) ... > > If len is negative, the if-statement is false and fails to handle exceptions. > So, we need to change it to a value less than or equal to zero. > > Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com> In that case, an easier (and likely safer) solution is to limit snd_usb_copy_string_desc() not to return a negative value. That is, at the first patch, instead of return len for a negative value, return 0. Then the second patch can be dropped. The drawback is that the caller can't know of the error, but the current code doesn't differentiate between error and zero length. And dealing such an error (e.g. EINVAL) as zero-length isn't bad, either, as it just indicates the invalid string, not a fatal error. thanks, Takashi > --- > sound/usb/mixer.c | 27 +++++++++++++++------------ > 1 file changed, 15 insertions(+), 12 deletions(-) > > diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c > index da7cbe7..8a434b7 100644 > --- a/sound/usb/mixer.c > +++ b/sound/usb/mixer.c > @@ -1235,7 +1235,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, > { > struct uac_feature_unit_descriptor *desc = raw_desc; > struct usb_feature_control_info *ctl_info; > - unsigned int len = 0; > + int len = 0; > int mapped_name = 0; > int nameid = uac_feature_unit_iFeature(desc); > struct snd_kcontrol *kctl; > @@ -1313,14 +1313,14 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, > * - if the connected output can be determined, use it. > * - otherwise, anonymous name. > */ > - if (!len) { > + if (len <= 0) { > len = get_term_name(state, iterm, kctl->id.name, > sizeof(kctl->id.name), 1); > - if (!len) > + if (len <= 0) > len = get_term_name(state, &state->oterm, > kctl->id.name, > sizeof(kctl->id.name), 1); > - if (!len) > + if (len <= 0) > snprintf(kctl->id.name, sizeof(kctl->id.name), > "Feature %d", unitid); > } > @@ -1343,7 +1343,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, > " Switch" : " Volume"); > break; > default: > - if (!len) > + if (len <= 0) > strlcpy(kctl->id.name, audio_feature_info[control-1].name, > sizeof(kctl->id.name)); > break; > @@ -1610,7 +1610,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state, > { > struct usb_mixer_elem_info *cval; > unsigned int num_outs = uac_mixer_unit_bNrChannels(desc); > - unsigned int i, len; > + unsigned int i; > + int len; > struct snd_kcontrol *kctl; > const struct usbmix_name_map *map; > > @@ -1649,7 +1650,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, > if (!len) > len = get_term_name(state, iterm, kctl->id.name, > sizeof(kctl->id.name), 0); > - if (!len) > + if (len <= 0) > len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); > append_ctl_name(kctl, " Volume"); > > @@ -1947,7 +1948,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, > len = snd_usb_copy_string_desc(state, nameid, > kctl->id.name, > sizeof(kctl->id.name)); > - if (!len) > + if (len <= 0) > strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); > } > append_ctl_name(kctl, " "); > @@ -2077,7 +2078,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, > void *raw_desc) > { > struct uac_selector_unit_descriptor *desc = raw_desc; > - unsigned int i, nameid, len; > + unsigned int i, nameid; > + int len; > int err; > struct usb_mixer_elem_info *cval; > struct snd_kcontrol *kctl; > @@ -2138,9 +2140,10 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, > } > len = check_mapped_selector_name(state, unitid, i, namelist[i], > MAX_ITEM_NAME_LEN); > - if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) > + if (!len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) > len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); > - if (! len) > + > + if (len <= 0) > sprintf(namelist[i], "Input %u", i); > } > > @@ -2164,7 +2167,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, > else { > len = get_term_name(state, &state->oterm, > kctl->id.name, sizeof(kctl->id.name), 0); > - if (!len) > + if (len <= 0) > strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); > > if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) > -- > 2.7.4 > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/3] ALSA: usb-audio: Fix return value check for usb_string() 2017-11-28 6:33 ` Takashi Iwai @ 2017-11-28 7:32 ` Jaejoong Kim 0 siblings, 0 replies; 11+ messages in thread From: Jaejoong Kim @ 2017-11-28 7:32 UTC (permalink / raw) To: Takashi Iwai; +Cc: Jaroslav Kysela, stable, alsa-devel 2017-11-28 15:33 GMT+09:00 Takashi Iwai <tiwai@suse.de>: > On Tue, 28 Nov 2017 01:36:27 +0100, > Jaejoong Kim wrote: >> >> In case of failure, the usb_string() can return a negative number. Therefore, >> the return value of snd_usb_copy_string_desc() and get_term_name() can also >> be negative. >> >> Check the return values for these functions as follows: >> >> len = snd_usb_copy_string_desc(); >> if (!len) ... >> >> If len is negative, the if-statement is false and fails to handle exceptions. >> So, we need to change it to a value less than or equal to zero. >> >> Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com> > > In that case, an easier (and likely safer) solution is to limit > snd_usb_copy_string_desc() not to return a negative value. > That is, at the first patch, instead of return len for a negative > value, return 0. Then the second patch can be dropped. I agree. Just return 0 is more simple way. > > The drawback is that the caller can't know of the error, but the > current code doesn't differentiate between error and zero length. > And dealing such an error (e.g. EINVAL) as zero-length isn't bad, > either, as it just indicates the invalid string, not a fatal error. > Right. The current code does not distinguish between errors and zero length. I will resend patch1 and patch 3 with your suggestion. Thanks for your feedback. jaejoong > > thanks, > > Takashi > >> --- >> sound/usb/mixer.c | 27 +++++++++++++++------------ >> 1 file changed, 15 insertions(+), 12 deletions(-) >> >> diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c >> index da7cbe7..8a434b7 100644 >> --- a/sound/usb/mixer.c >> +++ b/sound/usb/mixer.c >> @@ -1235,7 +1235,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, >> { >> struct uac_feature_unit_descriptor *desc = raw_desc; >> struct usb_feature_control_info *ctl_info; >> - unsigned int len = 0; >> + int len = 0; >> int mapped_name = 0; >> int nameid = uac_feature_unit_iFeature(desc); >> struct snd_kcontrol *kctl; >> @@ -1313,14 +1313,14 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, >> * - if the connected output can be determined, use it. >> * - otherwise, anonymous name. >> */ >> - if (!len) { >> + if (len <= 0) { >> len = get_term_name(state, iterm, kctl->id.name, >> sizeof(kctl->id.name), 1); >> - if (!len) >> + if (len <= 0) >> len = get_term_name(state, &state->oterm, >> kctl->id.name, >> sizeof(kctl->id.name), 1); >> - if (!len) >> + if (len <= 0) >> snprintf(kctl->id.name, sizeof(kctl->id.name), >> "Feature %d", unitid); >> } >> @@ -1343,7 +1343,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, >> " Switch" : " Volume"); >> break; >> default: >> - if (!len) >> + if (len <= 0) >> strlcpy(kctl->id.name, audio_feature_info[control-1].name, >> sizeof(kctl->id.name)); >> break; >> @@ -1610,7 +1610,8 @@ static void build_mixer_unit_ctl(struct mixer_build *state, >> { >> struct usb_mixer_elem_info *cval; >> unsigned int num_outs = uac_mixer_unit_bNrChannels(desc); >> - unsigned int i, len; >> + unsigned int i; >> + int len; >> struct snd_kcontrol *kctl; >> const struct usbmix_name_map *map; >> >> @@ -1649,7 +1650,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state, >> if (!len) >> len = get_term_name(state, iterm, kctl->id.name, >> sizeof(kctl->id.name), 0); >> - if (!len) >> + if (len <= 0) >> len = sprintf(kctl->id.name, "Mixer Source %d", in_ch + 1); >> append_ctl_name(kctl, " Volume"); >> >> @@ -1947,7 +1948,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, >> len = snd_usb_copy_string_desc(state, nameid, >> kctl->id.name, >> sizeof(kctl->id.name)); >> - if (!len) >> + if (len <= 0) >> strlcpy(kctl->id.name, name, sizeof(kctl->id.name)); >> } >> append_ctl_name(kctl, " "); >> @@ -2077,7 +2078,8 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, >> void *raw_desc) >> { >> struct uac_selector_unit_descriptor *desc = raw_desc; >> - unsigned int i, nameid, len; >> + unsigned int i, nameid; >> + int len; >> int err; >> struct usb_mixer_elem_info *cval; >> struct snd_kcontrol *kctl; >> @@ -2138,9 +2140,10 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, >> } >> len = check_mapped_selector_name(state, unitid, i, namelist[i], >> MAX_ITEM_NAME_LEN); >> - if (! len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) >> + if (!len && check_input_term(state, desc->baSourceID[i], &iterm) >= 0) >> len = get_term_name(state, &iterm, namelist[i], MAX_ITEM_NAME_LEN, 0); >> - if (! len) >> + >> + if (len <= 0) >> sprintf(namelist[i], "Input %u", i); >> } >> >> @@ -2164,7 +2167,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, >> else { >> len = get_term_name(state, &state->oterm, >> kctl->id.name, sizeof(kctl->id.name), 0); >> - if (!len) >> + if (len <= 0) >> strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); >> >> if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) >> -- >> 2.7.4 >> ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/3] ALSA: usb-audio: Add check return value for usb_string() 2017-11-28 0:36 [PATCH 0/3] ALSA: usb-audio: fix OOB and return value check Jaejoong Kim 2017-11-28 0:36 ` [PATCH 1/3] ALSA: usb-audio: Fix out-of-bound error Jaejoong Kim 2017-11-28 0:36 ` [PATCH 2/3] ALSA: usb-audio: Fix return value check for usb_string() Jaejoong Kim @ 2017-11-28 0:36 ` Jaejoong Kim 2017-12-04 6:31 ` [PATCH V2 0/2] ALSA: usb-audio: fix OOB and return value check Jaejoong Kim 3 siblings, 0 replies; 11+ messages in thread From: Jaejoong Kim @ 2017-11-28 0:36 UTC (permalink / raw) To: Takashi Iwai; +Cc: Jaroslav Kysela, stable, alsa-devel, Jaejoong Kim snd_usb_copy_string_desc() returns a negative number if usb_string() fails. In case of failure, we need to check the snd_usb_copy_string_desc()'s return value and add an exception case Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com> --- sound/usb/mixer.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 8a434b7..3501eb5 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2162,13 +2162,14 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, if (len) ; else if (nameid) - snd_usb_copy_string_desc(state, nameid, kctl->id.name, - sizeof(kctl->id.name)); - else { + len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, + sizeof(kctl->id.name)); + else len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 0); - if (len <= 0) - strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); + + if (len <= 0) { + strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) append_ctl_name(kctl, " Clock Source"); @@ -2177,7 +2178,6 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, else append_ctl_name(kctl, " Playback Source"); } - usb_audio_dbg(state->chip, "[%d] SU [%s] items = %d\n", cval->head.id, kctl->id.name, desc->bNrInPins); return snd_usb_mixer_add_control(&cval->head, kctl); -- 2.7.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH V2 0/2] ALSA: usb-audio: fix OOB and return value check 2017-11-28 0:36 [PATCH 0/3] ALSA: usb-audio: fix OOB and return value check Jaejoong Kim ` (2 preceding siblings ...) 2017-11-28 0:36 ` [PATCH 3/3] ALSA: usb-audio: Add check return value " Jaejoong Kim @ 2017-12-04 6:31 ` Jaejoong Kim 2017-12-04 6:31 ` [PATCH V2 1/2] ALSA: usb-audio: Fix out-of-bound error Jaejoong Kim 2017-12-04 6:31 ` [PATCH V2 2/2] ALSA: usb-audio: Add check return value for usb_string() Jaejoong Kim 3 siblings, 2 replies; 11+ messages in thread From: Jaejoong Kim @ 2017-12-04 6:31 UTC (permalink / raw) To: Takashi Iwai; +Cc: Jaroslav Kysela, stable, alsa-devel, Jaejoong Kim Hi, This patch series fixes the out-of-bound error caused by the return value of usb_string(). It was descovered by KASAN. KASAN OOB warning meesage was founded by connecting the following product. http://www.lg.com/uk/lg-friends/lg-AFD-1200 Changes in v2: - Changes return value check for second patch (by Takashi Iwai) - In case of failure case, return 0 not negative value (by Takashi Iwai) - Put an explicit error and bail out (by Takashi Iwai) Thanks jaejoong Jaejoong Kim (2): ALSA: usb-audio: Fix out-of-bound error ALSA: usb-audio: Add check return value for usb_string() sound/usb/mixer.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) -- 2.7.4 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH V2 1/2] ALSA: usb-audio: Fix out-of-bound error 2017-12-04 6:31 ` [PATCH V2 0/2] ALSA: usb-audio: fix OOB and return value check Jaejoong Kim @ 2017-12-04 6:31 ` Jaejoong Kim 2017-12-04 8:18 ` Takashi Iwai 2017-12-04 6:31 ` [PATCH V2 2/2] ALSA: usb-audio: Add check return value for usb_string() Jaejoong Kim 1 sibling, 1 reply; 11+ messages in thread From: Jaejoong Kim @ 2017-12-04 6:31 UTC (permalink / raw) To: Takashi Iwai; +Cc: Jaroslav Kysela, stable, alsa-devel, Jaejoong Kim The snd_usb_copy_string_desc() retrieves the usb string corresponding to the index number through the usb_string(). The problem is that the usb_string() returns the length of the string (>= 0) when successful, but it can also return a negative value about the error case or status of usb_control_msg(). If iClockSource is '0' as shown below, usb_string() will returns -EINVAL. This will result in '0' being inserted into buf[-22], and the following KASAN out-of-bound error message will be output. AudioControl Interface Descriptor: bLength 8 bDescriptorType 36 bDescriptorSubtype 10 (CLOCK_SOURCE) bClockID 1 bmAttributes 0x07 Internal programmable Clock (synced to SOF) bmControls 0x07 Clock Frequency Control (read/write) Clock Validity Control (read-only) bAssocTerminal 0 iClockSource 0 To fix it, check usb_string()'return value and bail out. ================================================================== BUG: KASAN: stack-out-of-bounds in parse_audio_unit+0x1327/0x1960 [snd_usb_audio] Write of size 1 at addr ffff88007e66735a by task systemd-udevd/18376 CPU: 0 PID: 18376 Comm: systemd-udevd Not tainted 4.13.0+ #3 Hardware name: LG Electronics 15N540-RFLGL/White Tip Mountain, BIOS 15N5 Call Trace: dump_stack+0x63/0x8d print_address_description+0x70/0x290 ? parse_audio_unit+0x1327/0x1960 [snd_usb_audio] kasan_report+0x265/0x350 __asan_store1+0x4a/0x50 parse_audio_unit+0x1327/0x1960 [snd_usb_audio] ? save_stack+0xb5/0xd0 ? save_stack_trace+0x1b/0x20 ? save_stack+0x46/0xd0 ? kasan_kmalloc+0xad/0xe0 ? kmem_cache_alloc_trace+0xff/0x230 ? snd_usb_create_mixer+0xb0/0x4b0 [snd_usb_audio] ? usb_audio_probe+0x4de/0xf40 [snd_usb_audio] ? usb_probe_interface+0x1f5/0x440 ? driver_probe_device+0x3ed/0x660 ? build_feature_ctl+0xb10/0xb10 [snd_usb_audio] ? save_stack_trace+0x1b/0x20 ? init_object+0x69/0xa0 ? snd_usb_find_csint_desc+0xa8/0xf0 [snd_usb_audio] snd_usb_mixer_controls+0x1dc/0x370 [snd_usb_audio] ? build_audio_procunit+0x890/0x890 [snd_usb_audio] ? snd_usb_create_mixer+0xb0/0x4b0 [snd_usb_audio] ? kmem_cache_alloc_trace+0xff/0x230 ? usb_ifnum_to_if+0xbd/0xf0 snd_usb_create_mixer+0x25b/0x4b0 [snd_usb_audio] ? snd_usb_create_stream+0x255/0x2c0 [snd_usb_audio] usb_audio_probe+0x4de/0xf40 [snd_usb_audio] ? snd_usb_autosuspend.part.7+0x30/0x30 [snd_usb_audio] ? __pm_runtime_idle+0x90/0x90 ? kernfs_activate+0xa6/0xc0 ? usb_match_one_id_intf+0xdc/0x130 ? __pm_runtime_set_status+0x2d4/0x450 usb_probe_interface+0x1f5/0x440 Cc: <stable@vger.kernel.org> Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com> --- Changes in v2: - In case of failure case, return 0 not negative value (by Takashi Iwai) - put an explicit error and bail out (by Takashi Iwai) sound/usb/mixer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 91bc8f1..3294e3a 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -204,6 +204,10 @@ static int snd_usb_copy_string_desc(struct mixer_build *state, int index, char *buf, int maxlen) { int len = usb_string(state->chip->dev, index, buf, maxlen - 1); + + if (len < 0) + return 0; + buf[len] = 0; return len; } -- 2.7.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH V2 1/2] ALSA: usb-audio: Fix out-of-bound error 2017-12-04 6:31 ` [PATCH V2 1/2] ALSA: usb-audio: Fix out-of-bound error Jaejoong Kim @ 2017-12-04 8:18 ` Takashi Iwai 0 siblings, 0 replies; 11+ messages in thread From: Takashi Iwai @ 2017-12-04 8:18 UTC (permalink / raw) To: Jaejoong Kim; +Cc: Jaroslav Kysela, stable, alsa-devel On Mon, 04 Dec 2017 07:31:48 +0100, Jaejoong Kim wrote: > > The snd_usb_copy_string_desc() retrieves the usb string corresponding to > the index number through the usb_string(). The problem is that the > usb_string() returns the length of the string (>= 0) when successful, but > it can also return a negative value about the error case or status of > usb_control_msg(). > > If iClockSource is '0' as shown below, usb_string() will returns -EINVAL. > This will result in '0' being inserted into buf[-22], and the following > KASAN out-of-bound error message will be output. > > AudioControl Interface Descriptor: > bLength 8 > bDescriptorType 36 > bDescriptorSubtype 10 (CLOCK_SOURCE) > bClockID 1 > bmAttributes 0x07 Internal programmable Clock (synced to SOF) > bmControls 0x07 > Clock Frequency Control (read/write) > Clock Validity Control (read-only) > bAssocTerminal 0 > iClockSource 0 > > To fix it, check usb_string()'return value and bail out. > > ================================================================== > BUG: KASAN: stack-out-of-bounds in parse_audio_unit+0x1327/0x1960 [snd_usb_audio] > Write of size 1 at addr ffff88007e66735a by task systemd-udevd/18376 > > CPU: 0 PID: 18376 Comm: systemd-udevd Not tainted 4.13.0+ #3 > Hardware name: LG Electronics 15N540-RFLGL/White Tip Mountain, BIOS 15N5 > Call Trace: > dump_stack+0x63/0x8d > print_address_description+0x70/0x290 > ? parse_audio_unit+0x1327/0x1960 [snd_usb_audio] > kasan_report+0x265/0x350 > __asan_store1+0x4a/0x50 > parse_audio_unit+0x1327/0x1960 [snd_usb_audio] > ? save_stack+0xb5/0xd0 > ? save_stack_trace+0x1b/0x20 > ? save_stack+0x46/0xd0 > ? kasan_kmalloc+0xad/0xe0 > ? kmem_cache_alloc_trace+0xff/0x230 > ? snd_usb_create_mixer+0xb0/0x4b0 [snd_usb_audio] > ? usb_audio_probe+0x4de/0xf40 [snd_usb_audio] > ? usb_probe_interface+0x1f5/0x440 > ? driver_probe_device+0x3ed/0x660 > ? build_feature_ctl+0xb10/0xb10 [snd_usb_audio] > ? save_stack_trace+0x1b/0x20 > ? init_object+0x69/0xa0 > ? snd_usb_find_csint_desc+0xa8/0xf0 [snd_usb_audio] > snd_usb_mixer_controls+0x1dc/0x370 [snd_usb_audio] > ? build_audio_procunit+0x890/0x890 [snd_usb_audio] > ? snd_usb_create_mixer+0xb0/0x4b0 [snd_usb_audio] > ? kmem_cache_alloc_trace+0xff/0x230 > ? usb_ifnum_to_if+0xbd/0xf0 > snd_usb_create_mixer+0x25b/0x4b0 [snd_usb_audio] > ? snd_usb_create_stream+0x255/0x2c0 [snd_usb_audio] > usb_audio_probe+0x4de/0xf40 [snd_usb_audio] > ? snd_usb_autosuspend.part.7+0x30/0x30 [snd_usb_audio] > ? __pm_runtime_idle+0x90/0x90 > ? kernfs_activate+0xa6/0xc0 > ? usb_match_one_id_intf+0xdc/0x130 > ? __pm_runtime_set_status+0x2d4/0x450 > usb_probe_interface+0x1f5/0x440 > > Cc: <stable@vger.kernel.org> > Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com> Applied, thanks. Takashi ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH V2 2/2] ALSA: usb-audio: Add check return value for usb_string() 2017-12-04 6:31 ` [PATCH V2 0/2] ALSA: usb-audio: fix OOB and return value check Jaejoong Kim 2017-12-04 6:31 ` [PATCH V2 1/2] ALSA: usb-audio: Fix out-of-bound error Jaejoong Kim @ 2017-12-04 6:31 ` Jaejoong Kim 2017-12-04 8:18 ` Takashi Iwai 1 sibling, 1 reply; 11+ messages in thread From: Jaejoong Kim @ 2017-12-04 6:31 UTC (permalink / raw) To: Takashi Iwai; +Cc: Jaroslav Kysela, stable, alsa-devel, Jaejoong Kim snd_usb_copy_string_desc() returns zero if usb_string() fails. In case of failure, we need to check the snd_usb_copy_string_desc()'s return value and add an exception case Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com> --- Changes in V2: - change return value check. sound/usb/mixer.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 3294e3a..84b9f9c 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -2165,13 +2165,14 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, if (len) ; else if (nameid) - snd_usb_copy_string_desc(state, nameid, kctl->id.name, + len = snd_usb_copy_string_desc(state, nameid, kctl->id.name, sizeof(kctl->id.name)); - else { + else len = get_term_name(state, &state->oterm, kctl->id.name, sizeof(kctl->id.name), 0); - if (!len) - strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); + + if (!len) { + strlcpy(kctl->id.name, "USB", sizeof(kctl->id.name)); if (desc->bDescriptorSubtype == UAC2_CLOCK_SELECTOR) append_ctl_name(kctl, " Clock Source"); -- 2.7.4 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH V2 2/2] ALSA: usb-audio: Add check return value for usb_string() 2017-12-04 6:31 ` [PATCH V2 2/2] ALSA: usb-audio: Add check return value for usb_string() Jaejoong Kim @ 2017-12-04 8:18 ` Takashi Iwai 0 siblings, 0 replies; 11+ messages in thread From: Takashi Iwai @ 2017-12-04 8:18 UTC (permalink / raw) To: Jaejoong Kim; +Cc: Jaroslav Kysela, stable, alsa-devel On Mon, 04 Dec 2017 07:31:49 +0100, Jaejoong Kim wrote: > > snd_usb_copy_string_desc() returns zero if usb_string() fails. > In case of failure, we need to check the snd_usb_copy_string_desc()'s > return value and add an exception case > > Signed-off-by: Jaejoong Kim <climbbb.kim@gmail.com> Applied, thanks. Takashi ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2017-12-04 8:18 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2017-11-28 0:36 [PATCH 0/3] ALSA: usb-audio: fix OOB and return value check Jaejoong Kim 2017-11-28 0:36 ` [PATCH 1/3] ALSA: usb-audio: Fix out-of-bound error Jaejoong Kim 2017-11-28 0:36 ` [PATCH 2/3] ALSA: usb-audio: Fix return value check for usb_string() Jaejoong Kim 2017-11-28 6:33 ` Takashi Iwai 2017-11-28 7:32 ` Jaejoong Kim 2017-11-28 0:36 ` [PATCH 3/3] ALSA: usb-audio: Add check return value " Jaejoong Kim 2017-12-04 6:31 ` [PATCH V2 0/2] ALSA: usb-audio: fix OOB and return value check Jaejoong Kim 2017-12-04 6:31 ` [PATCH V2 1/2] ALSA: usb-audio: Fix out-of-bound error Jaejoong Kim 2017-12-04 8:18 ` Takashi Iwai 2017-12-04 6:31 ` [PATCH V2 2/2] ALSA: usb-audio: Add check return value for usb_string() Jaejoong Kim 2017-12-04 8:18 ` Takashi Iwai
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).