]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 20:49:21 +0000 (12:49 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 20:49:21 +0000 (12:49 -0800)
added patches:
alsa-timer-code-cleanup.patch
alsa-timer-fix-race-between-stop-and-interrupt.patch

queue-3.10/alsa-timer-code-cleanup.patch [new file with mode: 0644]
queue-3.10/alsa-timer-fix-leftover-link-at-closing.patch
queue-3.10/alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch
queue-3.10/alsa-timer-fix-race-between-stop-and-interrupt.patch [new file with mode: 0644]
queue-3.10/alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch
queue-3.10/series

diff --git a/queue-3.10/alsa-timer-code-cleanup.patch b/queue-3.10/alsa-timer-code-cleanup.patch
new file mode 100644 (file)
index 0000000..63e087f
--- /dev/null
@@ -0,0 +1,100 @@
+From c3b1681375dc6e71d89a3ae00cc3ce9e775a8917 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Thu, 14 Jan 2016 17:01:46 +0100
+Subject: ALSA: timer: Code cleanup
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit c3b1681375dc6e71d89a3ae00cc3ce9e775a8917 upstream.
+
+This is a minor code cleanup without any functional changes:
+- Kill keep_flag argument from _snd_timer_stop(), as all callers pass
+  only it false.
+- Remove redundant NULL check in _snd_timer_stop().
+
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/timer.c |   28 +++++++++++-----------------
+ 1 file changed, 11 insertions(+), 17 deletions(-)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -300,8 +300,7 @@ int snd_timer_open(struct snd_timer_inst
+       return 0;
+ }
+-static int _snd_timer_stop(struct snd_timer_instance *timeri,
+-                         int keep_flag, int event);
++static int _snd_timer_stop(struct snd_timer_instance *timeri, int event);
+ /*
+  * close a timer instance
+@@ -343,7 +342,7 @@ int snd_timer_close(struct snd_timer_ins
+               spin_unlock_irq(&timer->lock);
+               mutex_lock(&register_mutex);
+               list_del(&timeri->open_list);
+-              if (timer && list_empty(&timer->open_list_head) &&
++              if (list_empty(&timer->open_list_head) &&
+                   timer->hw.close)
+                       timer->hw.close(timer);
+               /* remove slave links */
+@@ -483,8 +482,7 @@ int snd_timer_start(struct snd_timer_ins
+       return result;
+ }
+-static int _snd_timer_stop(struct snd_timer_instance * timeri,
+-                         int keep_flag, int event)
++static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
+ {
+       struct snd_timer *timer;
+       unsigned long flags;
+@@ -493,13 +491,11 @@ static int _snd_timer_stop(struct snd_ti
+               return -ENXIO;
+       if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
+-              if (!keep_flag) {
+-                      spin_lock_irqsave(&slave_active_lock, flags);
+-                      timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+-                      list_del_init(&timeri->ack_list);
+-                      list_del_init(&timeri->active_list);
+-                      spin_unlock_irqrestore(&slave_active_lock, flags);
+-              }
++              spin_lock_irqsave(&slave_active_lock, flags);
++              timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
++              list_del_init(&timeri->ack_list);
++              list_del_init(&timeri->active_list);
++              spin_unlock_irqrestore(&slave_active_lock, flags);
+               goto __end;
+       }
+       timer = timeri->timer;
+@@ -520,9 +516,7 @@ static int _snd_timer_stop(struct snd_ti
+                       }
+               }
+       }
+-      if (!keep_flag)
+-              timeri->flags &=
+-                      ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
++      timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
+       spin_unlock_irqrestore(&timer->lock, flags);
+       __end:
+       if (event != SNDRV_TIMER_EVENT_RESOLUTION)
+@@ -541,7 +535,7 @@ int snd_timer_stop(struct snd_timer_inst
+       unsigned long flags;
+       int err;
+-      err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP);
++      err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP);
+       if (err < 0)
+               return err;
+       timer = timeri->timer;
+@@ -585,7 +579,7 @@ int snd_timer_continue(struct snd_timer_
+  */
+ int snd_timer_pause(struct snd_timer_instance * timeri)
+ {
+-      return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE);
++      return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE);
+ }
+ /*
index 0f26bafee1c1314b79d513e987bcacf0c904badc..fbfdd3375afad779c469b71849454cd09f6f139d 100644 (file)
@@ -33,7 +33,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 
 --- a/sound/core/timer.c
 +++ b/sound/core/timer.c
-@@ -702,8 +702,8 @@ void snd_timer_interrupt(struct snd_time
+@@ -696,8 +696,8 @@ void snd_timer_interrupt(struct snd_time
                        ti->cticks = ti->ticks;
                } else {
                        ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
index 81e6cc2d5f6df0ae29b6870d0e9e12a2878f6239..8d740762bad4178668f9a8a4fcdb1e7baf6fb09f 100644 (file)
@@ -30,7 +30,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 
 --- a/sound/core/timer.c
 +++ b/sound/core/timer.c
-@@ -444,6 +444,10 @@ static int snd_timer_start_slave(struct
+@@ -443,6 +443,10 @@ static int snd_timer_start_slave(struct
        unsigned long flags;
  
        spin_lock_irqsave(&slave_active_lock, flags);
@@ -41,7 +41,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
        timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
        if (timeri->master && timeri->timer) {
                spin_lock(&timeri->timer->lock);
-@@ -468,18 +472,26 @@ int snd_timer_start(struct snd_timer_ins
+@@ -467,18 +471,26 @@ int snd_timer_start(struct snd_timer_ins
                return -EINVAL;
        if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
                result = snd_timer_start_slave(timeri);
@@ -70,18 +70,18 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
        return result;
  }
  
-@@ -495,6 +507,10 @@ static int _snd_timer_stop(struct snd_ti
+@@ -492,6 +504,10 @@ static int _snd_timer_stop(struct snd_ti
        if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
-               if (!keep_flag) {
-                       spin_lock_irqsave(&slave_active_lock, flags);
-+                      if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
-+                              spin_unlock_irqrestore(&slave_active_lock, flags);
-+                              return -EBUSY;
-+                      }
-                       timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
-                       list_del_init(&timeri->ack_list);
-                       list_del_init(&timeri->active_list);
-@@ -506,6 +522,11 @@ static int _snd_timer_stop(struct snd_ti
+               spin_lock_irqsave(&slave_active_lock, flags);
++              if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
++                      spin_unlock_irqrestore(&slave_active_lock, flags);
++                      return -EBUSY;
++              }
+               timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+               list_del_init(&timeri->ack_list);
+               list_del_init(&timeri->active_list);
+@@ -502,6 +518,11 @@ static int _snd_timer_stop(struct snd_ti
        if (!timer)
                return -EINVAL;
        spin_lock_irqsave(&timer->lock, flags);
@@ -93,7 +93,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
        list_del_init(&timeri->ack_list);
        list_del_init(&timeri->active_list);
        if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) &&
-@@ -571,10 +592,15 @@ int snd_timer_continue(struct snd_timer_
+@@ -565,10 +586,15 @@ int snd_timer_continue(struct snd_timer_
        if (! timer)
                return -EINVAL;
        spin_lock_irqsave(&timer->lock, flags);
diff --git a/queue-3.10/alsa-timer-fix-race-between-stop-and-interrupt.patch b/queue-3.10/alsa-timer-fix-race-between-stop-and-interrupt.patch
new file mode 100644 (file)
index 0000000..e554aa1
--- /dev/null
@@ -0,0 +1,43 @@
+From ed8b1d6d2c741ab26d60d499d7fbb7ac801f0f51 Mon Sep 17 00:00:00 2001
+From: Takashi Iwai <tiwai@suse.de>
+Date: Tue, 9 Feb 2016 12:02:32 +0100
+Subject: ALSA: timer: Fix race between stop and interrupt
+
+From: Takashi Iwai <tiwai@suse.de>
+
+commit ed8b1d6d2c741ab26d60d499d7fbb7ac801f0f51 upstream.
+
+A slave timer element also unlinks at snd_timer_stop() but it takes
+only slave_active_lock.  When a slave is assigned to a master,
+however, this may become a race against the master's interrupt
+handling, eventually resulting in a list corruption.  The actual bug
+could be seen with a syzkaller fuzzer test case in BugLink below.
+
+As a fix, we need to take timeri->timer->lock when timer isn't NULL,
+i.e. assigned to a master, while the assignment to a master itself is
+protected by slave_active_lock.
+
+BugLink: http://lkml.kernel.org/r/CACT4Y+Y_Bm+7epAb=8Wi=AaWd+DYS7qawX52qxdCfOfY49vozQ@mail.gmail.com
+Signed-off-by: Takashi Iwai <tiwai@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/core/timer.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/sound/core/timer.c
++++ b/sound/core/timer.c
+@@ -508,9 +508,13 @@ static int _snd_timer_stop(struct snd_ti
+                       spin_unlock_irqrestore(&slave_active_lock, flags);
+                       return -EBUSY;
+               }
++              if (timeri->timer)
++                      spin_lock(&timeri->timer->lock);
+               timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+               list_del_init(&timeri->ack_list);
+               list_del_init(&timeri->active_list);
++              if (timeri->timer)
++                      spin_unlock(&timeri->timer->lock);
+               spin_unlock_irqrestore(&slave_active_lock, flags);
+               goto __end;
+       }
index 7625ebb51fe0f2b065ea0667ae3f498eb9139d1f..384e82933704ed1d1489617f05b922256eb3a795 100644 (file)
@@ -25,7 +25,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 
 --- a/sound/core/timer.c
 +++ b/sound/core/timer.c
-@@ -415,7 +415,7 @@ static void snd_timer_notify1(struct snd
+@@ -414,7 +414,7 @@ static void snd_timer_notify1(struct snd
        spin_lock_irqsave(&timer->lock, flags);
        list_for_each_entry(ts, &ti->slave_active_head, active_list)
                if (ts->ccallback)
index 6636b5c87f38d38be0914e6bdcb360729740f498..3a15336256718ce36b745568a4016c2168523b9d 100644 (file)
@@ -35,11 +35,13 @@ asoc-dpcm-fix-the-be-state-on-hw_free.patch
 alsa-seq-fix-yet-another-races-among-alsa-timer-accesses.patch
 alsa-seq-fix-race-at-closing-in-virmidi-driver.patch
 alsa-seq-fix-lockdep-warnings-due-to-double-mutex-locks.patch
+alsa-timer-code-cleanup.patch
 alsa-timer-fix-leftover-link-at-closing.patch
 alsa-timer-fix-link-corruption-due-to-double-start-or-stop.patch
 alsa-timer-fix-wrong-instance-passed-to-slave-callbacks.patch
 alsa-hda-fix-speaker-output-from-vaio-aio-machines.patch
 alsa-dummy-implement-timer-backend-switching-more-safely.patch
+alsa-timer-fix-race-between-stop-and-interrupt.patch
 saa7134-alsa-only-frees-registered-sound-cards.patch
 usb-ti_usb_3410_502-fix-id-table-size.patch
 usb-serial-visor-fix-crash-on-detecting-device-without-write_urbs.patch