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 <matt@zigg.com> Signed-off-by: Shaun Ruffell <sruffell@digium.com> Signed-off-by: Russ Meyerriecks <rmeyerriecks@digium.com>
This commit is contained in:
parent
089b593b56
commit
a1ff3cb0c0
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user