| From: Takashi Iwai <tiwai@suse.de> |
| Date: Tue, 28 Feb 2017 14:49:07 +0100 |
| Subject: ALSA: timer: Reject user params with too small ticks |
| |
| commit 71321eb3f2d0df4e6c327e0b936eec4458a12054 upstream. |
| |
| When a user sets a too small ticks with a fine-grained timer like |
| hrtimer, the kernel tries to fire up the timer irq too frequently. |
| This may lead to the condensed locks, eventually the kernel spinlock |
| lockup with warnings. |
| |
| For avoiding such a situation, we define a lower limit of the |
| resolution, namely 1ms. When the user passes a too small tick value |
| that results in less than that, the kernel returns -EINVAL now. |
| |
| Reported-by: Dmitry Vyukov <dvyukov@google.com> |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| sound/core/timer.c | 18 +++++++++++++++--- |
| 1 file changed, 15 insertions(+), 3 deletions(-) |
| |
| --- a/sound/core/timer.c |
| +++ b/sound/core/timer.c |
| @@ -1669,9 +1669,21 @@ static int snd_timer_user_params(struct |
| return -EBADFD; |
| if (copy_from_user(¶ms, _params, sizeof(params))) |
| return -EFAULT; |
| - if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE) && params.ticks < 1) { |
| - err = -EINVAL; |
| - goto _end; |
| + if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) { |
| + u64 resolution; |
| + |
| + if (params.ticks < 1) { |
| + err = -EINVAL; |
| + goto _end; |
| + } |
| + |
| + /* Don't allow resolution less than 1ms */ |
| + resolution = snd_timer_resolution(tu->timeri); |
| + resolution *= params.ticks; |
| + if (resolution < 1000000) { |
| + err = -EINVAL; |
| + goto _end; |
| + } |
| } |
| if (params.queue_size > 0 && |
| (params.queue_size < 32 || params.queue_size > 1024)) { |