mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ben Hutchings <ben@decadent.org.uk>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: akpm@linux-foundation.org, "Takashi Iwai" <tiwai@suse.de>,
	"Dmitry Vyukov" <dvyukov@google.com>
Subject: [PATCH 3.2 34/67] ALSA: seq: Fix yet another races among ALSA timer accesses
Date: Tue, 23 Feb 2016 21:42:03 +0000	[thread overview]
Message-ID: <lsq.1456263723.195685599@decadent.org.uk> (raw)
In-Reply-To: <lsq.1456263722.390955919@decadent.org.uk>

3.2.78-rc1 review patch.  If anyone has any objections, please let me know.

------------------

From: Takashi Iwai <tiwai@suse.de>

commit 2cdc7b636d55cbcf42e1e6c8accd85e62d3e9ae8 upstream.

ALSA sequencer may open/close and control ALSA timer instance
dynamically either via sequencer events or direct ioctls.  These are
done mostly asynchronously, and it may call still some timer action
like snd_timer_start() while another is calling snd_timer_close().
Since the instance gets removed by snd_timer_close(), it may lead to
a use-after-free.

This patch tries to address such a race by protecting each
snd_timer_*() call via the existing spinlock and also by avoiding the
access to timer during close call.

BugLink: http://lkml.kernel.org/r/CACT4Y+Z6RzW5MBr-HUdV-8zwg71WQfKTdPpYGvOeS7v4cyurNQ@mail.gmail.com
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/seq/seq_timer.c | 87 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 67 insertions(+), 20 deletions(-)

--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -92,6 +92,9 @@ void snd_seq_timer_delete(struct snd_seq
 
 void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&tmr->lock, flags);
 	/* setup defaults */
 	tmr->ppq = 96;		/* 96 PPQ */
 	tmr->tempo = 500000;	/* 120 BPM */
@@ -107,21 +110,25 @@ void snd_seq_timer_defaults(struct snd_s
 	tmr->preferred_resolution = seq_default_timer_resolution;
 
 	tmr->skew = tmr->skew_base = SKEW_BASE;
+	spin_unlock_irqrestore(&tmr->lock, flags);
 }
 
-void snd_seq_timer_reset(struct snd_seq_timer * tmr)
+static void seq_timer_reset(struct snd_seq_timer *tmr)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&tmr->lock, flags);
-
 	/* reset time & songposition */
 	tmr->cur_time.tv_sec = 0;
 	tmr->cur_time.tv_nsec = 0;
 
 	tmr->tick.cur_tick = 0;
 	tmr->tick.fraction = 0;
+}
+
+void snd_seq_timer_reset(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
 
+	spin_lock_irqsave(&tmr->lock, flags);
+	seq_timer_reset(tmr);
 	spin_unlock_irqrestore(&tmr->lock, flags);
 }
 
@@ -140,8 +147,11 @@ static void snd_seq_timer_interrupt(stru
 	tmr = q->timer;
 	if (tmr == NULL)
 		return;
-	if (!tmr->running)
+	spin_lock_irqsave(&tmr->lock, flags);
+	if (!tmr->running) {
+		spin_unlock_irqrestore(&tmr->lock, flags);
 		return;
+	}
 
 	resolution *= ticks;
 	if (tmr->skew != tmr->skew_base) {
@@ -150,8 +160,6 @@ static void snd_seq_timer_interrupt(stru
 			(((resolution & 0xffff) * tmr->skew) >> 16);
 	}
 
-	spin_lock_irqsave(&tmr->lock, flags);
-
 	/* update timer */
 	snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
 
@@ -298,26 +306,30 @@ int snd_seq_timer_open(struct snd_seq_qu
 	t->callback = snd_seq_timer_interrupt;
 	t->callback_data = q;
 	t->flags |= SNDRV_TIMER_IFLG_AUTO;
+	spin_lock_irq(&tmr->lock);
 	tmr->timeri = t;
+	spin_unlock_irq(&tmr->lock);
 	return 0;
 }
 
 int snd_seq_timer_close(struct snd_seq_queue *q)
 {
 	struct snd_seq_timer *tmr;
+	struct snd_timer_instance *t;
 	
 	tmr = q->timer;
 	if (snd_BUG_ON(!tmr))
 		return -EINVAL;
-	if (tmr->timeri) {
-		snd_timer_stop(tmr->timeri);
-		snd_timer_close(tmr->timeri);
-		tmr->timeri = NULL;
-	}
+	spin_lock_irq(&tmr->lock);
+	t = tmr->timeri;
+	tmr->timeri = NULL;
+	spin_unlock_irq(&tmr->lock);
+	if (t)
+		snd_timer_close(t);
 	return 0;
 }
 
-int snd_seq_timer_stop(struct snd_seq_timer * tmr)
+static int seq_timer_stop(struct snd_seq_timer *tmr)
 {
 	if (! tmr->timeri)
 		return -EINVAL;
@@ -328,6 +340,17 @@ int snd_seq_timer_stop(struct snd_seq_ti
 	return 0;
 }
 
+int snd_seq_timer_stop(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&tmr->lock, flags);
+	err = seq_timer_stop(tmr);
+	spin_unlock_irqrestore(&tmr->lock, flags);
+	return err;
+}
+
 static int initialize_timer(struct snd_seq_timer *tmr)
 {
 	struct snd_timer *t;
@@ -360,13 +383,13 @@ static int initialize_timer(struct snd_s
 	return 0;
 }
 
-int snd_seq_timer_start(struct snd_seq_timer * tmr)
+static int seq_timer_start(struct snd_seq_timer *tmr)
 {
 	if (! tmr->timeri)
 		return -EINVAL;
 	if (tmr->running)
-		snd_seq_timer_stop(tmr);
-	snd_seq_timer_reset(tmr);
+		seq_timer_stop(tmr);
+	seq_timer_reset(tmr);
 	if (initialize_timer(tmr) < 0)
 		return -EINVAL;
 	snd_timer_start(tmr->timeri, tmr->ticks);
@@ -375,14 +398,25 @@ int snd_seq_timer_start(struct snd_seq_t
 	return 0;
 }
 
-int snd_seq_timer_continue(struct snd_seq_timer * tmr)
+int snd_seq_timer_start(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&tmr->lock, flags);
+	err = seq_timer_start(tmr);
+	spin_unlock_irqrestore(&tmr->lock, flags);
+	return err;
+}
+
+static int seq_timer_continue(struct snd_seq_timer *tmr)
 {
 	if (! tmr->timeri)
 		return -EINVAL;
 	if (tmr->running)
 		return -EBUSY;
 	if (! tmr->initialized) {
-		snd_seq_timer_reset(tmr);
+		seq_timer_reset(tmr);
 		if (initialize_timer(tmr) < 0)
 			return -EINVAL;
 	}
@@ -392,11 +426,24 @@ int snd_seq_timer_continue(struct snd_se
 	return 0;
 }
 
+int snd_seq_timer_continue(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&tmr->lock, flags);
+	err = seq_timer_continue(tmr);
+	spin_unlock_irqrestore(&tmr->lock, flags);
+	return err;
+}
+
 /* return current 'real' time. use timeofday() to get better granularity. */
 snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
 {
 	snd_seq_real_time_t cur_time;
+	unsigned long flags;
 
+	spin_lock_irqsave(&tmr->lock, flags);
 	cur_time = tmr->cur_time;
 	if (tmr->running) { 
 		struct timeval tm;
@@ -412,7 +459,7 @@ snd_seq_real_time_t snd_seq_timer_get_cu
 		}
 		snd_seq_sanity_real_time(&cur_time);
 	}
-                
+	spin_unlock_irqrestore(&tmr->lock, flags);
 	return cur_time;	
 }
 

  parent reply	other threads:[~2016-02-23 21:55 UTC|newest]

Thread overview: 74+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-23 21:42 [PATCH 3.2 00/67] 3.2.78-rc1 review Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 24/67] tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 03/67] timerfd: Handle relative timers with CONFIG_TIME_LOW_RES proper Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 63/67] unix: correctly track in-flight fds in sending process user_struct Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 36/67] libata: fix sff host state machine locking while polling Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 39/67] ALSA: seq: Fix lockdep warnings due to double mutex locks Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 15/67] ALSA: seq: Fix incorrect sanity check at snd_seq_oss_synth_cleanup() Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 28/67] x86/mm/pat: Avoid truncation when converting cpa->numpages to address Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 52/67] ALSA: dummy: Implement timer backend switching more safely Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 22/67] perf annotate browser: Fix behaviour of Shift-Tab with nothing focussed Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 02/67] hrtimer: Handle remaining time proper for TIME_LOW_RES Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 35/67] ALSA: timer: Fix link corruption due to double start or stop Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 45/67] [media] saa7134-alsa: Only frees registered sound cards Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 20/67] virtio_pci: fix use after free on release Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 16/67] ALSA: seq: Degrade the error message for too many opens Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 14/67] USB: serial: option: Adding support for Telit LE922 Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 64/67] pipe: limit the per-user amount of pages allocated in pipes Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 57/67] ALSA: timer: Fix race at concurrent reads Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 56/67] ALSA: timer: Fix race between stop and interrupt Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 40/67] Revert "xhci: don't finish a TD if we get a short-transfer event mid TD" Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 25/67] crypto: shash - Fix has_key setting Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 17/67] USB: serial: ftdi_sio: add support for Yaesu SCU-18 cable Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 33/67] ALSA: pcm: Fix potential deadlock in OSS emulation Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 54/67] ARM: 8517/1: ICST: avoid arithmetic overflow in icst_hz() Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 58/67] ahci: Intel DNV device IDs SATA Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 31/67] ALSA: seq: Fix race at closing in virmidi driver Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 08/67] af_unix: fix struct pid memory leak Ben Hutchings
2016-02-23 22:07   ` Rainer Weikusat
2016-02-24 21:24     ` Ben Hutchings
2016-02-25  7:26       ` Willy Tarreau
2016-02-23 21:42 ` [PATCH 3.2 53/67] ALSA: timer: Fix wrong instance passed to slave callbacks Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 13/67] USB: serial: visor: fix crash on detecting device without write_urbs Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 59/67] ARM: 8519/1: ICST: try other dividends than 1 Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 19/67] libata: disable forced PORTS_IMPL for >= AHCI 1.3 Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 47/67] mm, vmstat: fix wrong WQ sleep when memory reclaim doesn't make any progress Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 23/67] SCSI: fix crashes in sd and sr runtime PM Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 11/67] USB: cp210x: add ID for IAI USB to RS485 adaptor Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 01/67] KVM: vmx: fix MPX detection Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 43/67] [media] tda1004x: only update the frontend properties if locked Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 29/67] crypto: algif_hash - wait for crypto_ahash_init() to complete Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 42/67] xhci: Fix list corruption in urb dequeue at host removal Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 62/67] unix: properly account for FDs passed over unix sockets Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 05/67] itimers: Handle relative timers with CONFIG_TIME_LOW_RES proper Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 41/67] usb: xhci: apply XHCI_PME_STUCK_QUIRK to Intel Broxton-M platforms Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 44/67] ALSA: timer: Fix leftover link at closing Ben Hutchings
2016-02-23 21:42 ` Ben Hutchings [this message]
2016-02-23 21:42 ` [PATCH 3.2 65/67] iw_cxgb3: Fix incorrectly returning error on success Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 38/67] ALSA: rawmidi: Fix race at copying & updating the position Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 27/67] drm/vmwgfx: respect 'nomodeset' Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 10/67] sctp: allow setting SCTP_SACK_IMMEDIATELY by the application Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 67/67] sched: fix __sched_setscheduler() vs load balancing race Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 46/67] scsi_dh_rdac: always retry MODE SELECT on command lock violation Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 26/67] ALSA: dummy: Disable switching timer backend via sysfs Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 50/67] crypto: algif_skcipher - Do not dereference ctx without socket lock Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 60/67] btrfs: properly set the termination value of ctx->pos in readdir Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 09/67] pptp: fix illegal memory access caused by multiple bind()s Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 06/67] usb: cdc-acm: send zero packet for intel 7260 modem Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 55/67] sctp: translate network order to host order when users get a hmacid Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 18/67] PCI/AER: Flush workqueue on device remove to avoid use-after-free Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 21/67] rfkill: fix rfkill_fop_read wait_event usage Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 32/67] ALSA: rawmidi: Remove kernel WARNING for NULL user-space buffer check Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 61/67] ALSA: usb-audio: avoid freeing umidi object twice Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 12/67] USB: visor: fix null-deref at probe Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 04/67] posix-timers: Handle relative timers with CONFIG_TIME_LOW_RES proper Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 07/67] cdc-acm:exclude Samsung phone 04e8:685d Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 30/67] intel_scu_ipcutil: underflow in scu_reg_access() Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 66/67] pipe: Fix buffer offset after partially failed read Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 49/67] crypto: user - lock crypto_alg_list on alg dump Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 48/67] ocfs2/dlm: clear refmap bit of recovery lock while doing local recovery cleanup Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 51/67] klist: fix starting point removed bug in klist iterators Ben Hutchings
2016-02-23 21:42 ` [PATCH 3.2 37/67] ALSA: rawmidi: Make snd_rawmidi_transmit() race-free Ben Hutchings
2016-02-24  0:48 ` [PATCH 3.2 00/67] 3.2.78-rc1 review Ben Hutchings
2016-02-24  2:48 ` Guenter Roeck
2016-02-24 14:41   ` Ben Hutchings

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=lsq.1456263723.195685599@decadent.org.uk \
    --to=ben@decadent.org.uk \
    --cc=akpm@linux-foundation.org \
    --cc=dvyukov@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®