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;
|
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)
|
static int set_tone_zone(struct dahdi_chan *chan, int zone)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
@ -1838,6 +1849,9 @@ static int set_tone_zone(struct dahdi_chan *chan, int zone)
|
|||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
|
|
||||||
spin_lock_irqsave(&chan->lock, flags);
|
spin_lock_irqsave(&chan->lock, flags);
|
||||||
|
|
||||||
|
stop_tone(chan);
|
||||||
|
|
||||||
if (chan->curzone) {
|
if (chan->curzone) {
|
||||||
struct dahdi_zone *zone = chan->curzone;
|
struct dahdi_zone *zone = chan->curzone;
|
||||||
chan->curzone = NULL;
|
chan->curzone = NULL;
|
||||||
|
Loading…
Reference in New Issue
Block a user