[3/3] libtrau: Fix off-by-one read access to gsm_fr_map
diff mbox

Message ID 9a4d2bcbaafce627042f4f9531e5f9543d13470b.1403881549.git.daniel@totalueberwachung.de
State Superseded
Headers show

Commit Message

Daniel Willmann June 27, 2014, 3:05 p.m. UTC
Address sanitizer complains with a buffer overflow to the end of
gsm_fr_map:

ERROR: AddressSanitizer: global-buffer-overflow on address 0x00000044f76c at pc 0x43c0dd bp 0x7fff18389db0 sp 0x7fff18389da8
READ of size 1 at 0x00000044f76c thread T0
    #0 0x43c0dc in trau_encode_fr /home/alphaone/scm/osmo/openbsc/openbsc/src/libtrau/trau_mux.c:441
    #1 0x42fad6 in test_trau_fr_efr /home/alphaone/scm/osmo/openbsc/openbsc/tests/trau/trau_test.c:35
    #2 0x4308f4 in main /home/alphaone/scm/osmo/openbsc/openbsc/tests/trau/trau_test.c:70
    #3 0x7f96e8cf04bc (/lib64/libc.so.6+0x224bc)
    #4 0x42f7ec (/home/alphaone/scm/osmo/openbsc/openbsc/tests/trau/trau_test+0x42f7ec)
0x00000044f76c is located 52 bytes to the left of global variable 'c_bits_check_fr' from 'trau_mux.c' (0x44f7a0) of size 5
0x00000044f76c is located 0 bytes to the right of global variable 'gsm_fr_map' from 'trau_mux.c' (0x44f720) of size 76
SUMMARY: AddressSanitizer: global-buffer-overflow /home/alphaone/scm/osmo/openbsc/openbsc/src/libtrau/trau_mux.c:441 trau_encode_fr

In the last iteration of the loop k is already set to the next element
in gsm_fr_map which leads to an out-of-bounds read. Instead decrement k
at the end of the loop and put the check before the data assignment.
This is functionally equivalent as k is never < 0 initially.

This happens in trau_decode_fr as well.
---
 openbsc/src/libtrau/trau_mux.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

Patch
diff mbox

diff --git a/openbsc/src/libtrau/trau_mux.c b/openbsc/src/libtrau/trau_mux.c
index 4f159e4..9b93eda 100644
--- a/openbsc/src/libtrau/trau_mux.c
+++ b/openbsc/src/libtrau/trau_mux.c
@@ -234,13 +234,14 @@  struct msgb *trau_decode_fr(uint32_t callref,
 	l = 0; /* counts element bits */
 	o = 0; /* offset input bits */
 	while (i < 260) {
-		data[j/8] |= (tf->d_bits[k+o] << (7-(j%8)));
-		if (--k < 0) {
+		if (k < 0) {
 			o += gsm_fr_map[l];
 			k = gsm_fr_map[++l]-1;
 		}
+		data[j/8] |= (tf->d_bits[k+o] << (7-(j%8)));
 		i++;
 		j++;
+		k--;
 	}
 	frame->msg_type = GSM_TCHF_FRAME;
 	frame->callref = callref;
@@ -435,16 +436,14 @@  void trau_encode_fr(struct decoded_trau_frame *tf,
 	l = 0; /* counts element bits */
 	o = 0; /* offset output bits */
 	while (i < 260) {
-		tf->d_bits[k+o] = (data[j/8] >> (7-(j%8))) & 1;
-		/* to avoid out-of-bounds access in gsm_fr_map[++l] */
-		if (i == 259)
-			break;
-		if (--k < 0) {
+		if (k < 0) {
 			o += gsm_fr_map[l];
 			k = gsm_fr_map[++l]-1;
 		}
+		tf->d_bits[k+o] = (data[j/8] >> (7-(j%8))) & 1;
 		i++;
 		j++;
+		k--;
 	}
 }