From a1ff3cb0c0f3f4e65d734f4a71a090f5484505b4 Mon Sep 17 00:00:00 2001 From: Shaun Ruffell Date: Sat, 5 Jul 2014 14:52:46 -0500 Subject: [PATCH] dahdi: Stop tones on channel when updating tone zone. If a channel is currently playing a tone when the tone zone is updated, the existing tone zone could be freed while the channel keeps a reference to the current tone (curtone) that points into the freed zone. If the newly freed tone is then modified, there was a window where it was possible to corrupt 'struct dahdi_chan' (by overrunning swritechunk[]) resulting in a "BUG: unable to handle kernel paging request at virtual address" panic in the context of __dahdi_transmit_chunk(). Reported-and-Tested-by: Matt Behrens Signed-off-by: Shaun Ruffell Signed-off-by: Russ Meyerriecks --- drivers/dahdi/dahdi-base.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index 40131a4..d46d7eb 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -1811,6 +1811,17 @@ static int start_tone(struct dahdi_chan *chan, int tone) return res; } +/** + * stop_tone - Stops any tones on a channel. + * + * Must be called with chan->lock held. + * + */ +static inline int stop_tone(struct dahdi_chan *chan) +{ + return start_tone(chan, -1); +} + static int set_tone_zone(struct dahdi_chan *chan, int zone) { int res = 0; @@ -1838,6 +1849,9 @@ static int set_tone_zone(struct dahdi_chan *chan, int zone) return -ENODATA; spin_lock_irqsave(&chan->lock, flags); + + stop_tone(chan); + if (chan->curzone) { struct dahdi_zone *zone = chan->curzone; chan->curzone = NULL;