Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ALSA: pcm: oss: Fix a few more UBSAN fixes

There are a few places that call round{up|down}_pow_of_two() with the
value zero, and this causes undefined behavior warnings. Avoid
calling those macros if such a nonsense value is passed; it's a minor
optimization as well, as we handle it as either an error or a value to
be skipped, instead.

Reported-by: syzbot+33ef0b6639a8d2d42b4c@syzkaller.appspotmail.com
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20201218161730.26596-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>

+14 -8
+14 -8
sound/core/oss/pcm_oss.c
··· 693 693 694 694 oss_buffer_size = snd_pcm_plug_client_size(substream, 695 695 snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, NULL)) * oss_frame_size; 696 + if (!oss_buffer_size) 697 + return -EINVAL; 696 698 oss_buffer_size = rounddown_pow_of_two(oss_buffer_size); 697 699 if (atomic_read(&substream->mmap_count)) { 698 700 if (oss_buffer_size > runtime->oss.mmap_bytes) ··· 730 728 731 729 min_period_size = snd_pcm_plug_client_size(substream, 732 730 snd_pcm_hw_param_value_min(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); 733 - min_period_size *= oss_frame_size; 734 - min_period_size = roundup_pow_of_two(min_period_size); 735 - if (oss_period_size < min_period_size) 736 - oss_period_size = min_period_size; 731 + if (min_period_size) { 732 + min_period_size *= oss_frame_size; 733 + min_period_size = roundup_pow_of_two(min_period_size); 734 + if (oss_period_size < min_period_size) 735 + oss_period_size = min_period_size; 736 + } 737 737 738 738 max_period_size = snd_pcm_plug_client_size(substream, 739 739 snd_pcm_hw_param_value_max(slave_params, SNDRV_PCM_HW_PARAM_PERIOD_SIZE, NULL)); 740 - max_period_size *= oss_frame_size; 741 - max_period_size = rounddown_pow_of_two(max_period_size); 742 - if (oss_period_size > max_period_size) 743 - oss_period_size = max_period_size; 740 + if (max_period_size) { 741 + max_period_size *= oss_frame_size; 742 + max_period_size = rounddown_pow_of_two(max_period_size); 743 + if (oss_period_size > max_period_size) 744 + oss_period_size = max_period_size; 745 + } 744 746 745 747 oss_periods = oss_buffer_size / oss_period_size; 746 748