ftmod_isdn: Avoid stack smashing buffer overflow in isdn_tones_run().
The len variable can, in certain situations (large burst of incoming non-SLIN audio), exceed the size of the on-stack frame buffer, which causes ftdm_buffer_read_loop() to overwrite the dt_buffer pointer. Use ftdm_min() to make sure len (after conversion to SLIN units) isn't larger than the frame buffer size. Also adds are couple more code comments. Signed-off-by: Stefan Knoblich <stkn@openisdn.net>
This commit is contained in:
parent
036063d2a9
commit
2ad2b6d31b
|
@ -1936,6 +1936,11 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Teletone operates on SLIN data (2 bytes per sample).
|
||||||
|
* Convert the length of non-SLIN codecs, so we read
|
||||||
|
* the right amount of samples from the buffer.
|
||||||
|
*/
|
||||||
if (chan->effective_codec != FTDM_CODEC_SLIN) {
|
if (chan->effective_codec != FTDM_CODEC_SLIN) {
|
||||||
len *= 2;
|
len *= 2;
|
||||||
}
|
}
|
||||||
|
@ -1943,6 +1948,12 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
|
||||||
/* seek to current offset */
|
/* seek to current offset */
|
||||||
ftdm_buffer_seek(dt_buffer, data->offset);
|
ftdm_buffer_seek(dt_buffer, data->offset);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ftdm_channel_read() can read up to sizeof(frame) bytes
|
||||||
|
* (in certain situations). Avoid overflowing the stack (and smashing dt_buffer)
|
||||||
|
* if the codec is not slin and we had to double the length.
|
||||||
|
*/
|
||||||
|
len = ftdm_min(len, sizeof(frame));
|
||||||
rlen = ftdm_buffer_read_loop(dt_buffer, frame, len);
|
rlen = ftdm_buffer_read_loop(dt_buffer, frame, len);
|
||||||
|
|
||||||
if (chan->effective_codec != FTDM_CODEC_SLIN) {
|
if (chan->effective_codec != FTDM_CODEC_SLIN) {
|
||||||
|
@ -1954,6 +1965,12 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
|
||||||
codec_func = fio_slin2alaw;
|
codec_func = fio_slin2alaw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert SLIN to native format (a-law/u-law),
|
||||||
|
* input size is 2 bytes per sample, output size
|
||||||
|
* (after conversion) is one byte per sample
|
||||||
|
* (= max. half the input size).
|
||||||
|
*/
|
||||||
if (codec_func) {
|
if (codec_func) {
|
||||||
status = codec_func(frame, sizeof(frame), &rlen);
|
status = codec_func(frame, sizeof(frame), &rlen);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1968,11 +1985,12 @@ static void *ftdm_isdn_tones_run(ftdm_thread_t *me, void *obj)
|
||||||
* of data actually written to channel.
|
* of data actually written to channel.
|
||||||
*/
|
*/
|
||||||
if (chan->effective_codec != FTDM_CODEC_SLIN) {
|
if (chan->effective_codec != FTDM_CODEC_SLIN) {
|
||||||
data->offset += rlen << 1; /* teletone buffer is slin (= len * 2) */
|
data->offset += rlen << 1; /* Teletone buffer is in SLIN (= rlen * 2) */
|
||||||
} else {
|
} else {
|
||||||
data->offset += rlen;
|
data->offset += rlen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Limit offset to [0..Rate(Samples/s)-1] in SLIN (2 bytes per sample) units. */
|
||||||
data->offset %= (ts.rate << 1);
|
data->offset %= (ts.rate << 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue