diff options
author | Szymon Janc <szymon.janc@tieto.com> | 2012-08-07 14:22:36 +0200 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-08-14 17:44:59 +0200 |
commit | d6caf6f5fdaab86c31f18dcde8e5818924428003 (patch) | |
tree | e00778f435c66fd7d297e9c1574996d639e05052 /src | |
parent | baf3a16dbb93fd67759a7939c47807716bbfc71f (diff) | |
download | neard-d6caf6f5fdaab86c31f18dcde8e5818924428003.tar.gz neard-d6caf6f5fdaab86c31f18dcde8e5818924428003.tar.bz2 neard-d6caf6f5fdaab86c31f18dcde8e5818924428003.zip |
bluetooth: Fix EIR parsing
Fix parsing of EIR data to avoid reading data from wrong offset.
This also fix invalid memory access reported by valgrind which could
potentially result in daemon crash.
neard[30296]: src/bluetooth.c:bt_parse_eir()
neard[30296]: Unknown EIR: x03 (len: 4)
neard[30296]: Unknown EIR: x00 (len: 253)
==30296== Invalid read of size 1
==30296== at 0x8064DF8: __near_bluetooth_parse_oob_record (bluetooth.c:531)
==30296== by 0x8060DF3: parse_mime_type.isra.3 (ndef.c:1299)
==30296== by 0x8062043: near_ndef_parse (ndef.c:2124)
==30296== by 0x8063BB7: near_tlv_parse (tlv.c:95)
==30296== by 0x8053252: data_recv (nfctype2.c:148)
==30296== by 0x8059D03: execute_recv_cb (adapter.c:846)
==30296== by 0x408D1BF: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.3306.0)
==30296== by 0x408FEF2: g_main_context_dispatch (in /lib/i386-linux-gnu/libglib-2.0.so.0.3306.0)
==30296== by 0x409028F: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.3306.0)
==30296== by 0x40906EA: g_main_loop_run (in /lib/i386-linux-gnu/libglib-2.0.so.0.3306.0)
==30296== by 0x41E44D2: (below main) (libc-start.c:226)
==30296== Address 0x4556405 is 13 bytes inside a block of size 22 free'd
==30296== at 0x402B06C: free (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==30296== by 0x4095FCA: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.3306.0)
==30296== by 0x409613F: g_free (in /lib/i386-linux-gnu/libglib-2.0.so.0.3306.0)
==30296== by 0x805CCAF: near_tag_get_tag (tag.c:94)
==30296== by 0x8052F36: meta_recv (nfctype2.c:221)
==30296== by 0x8059D03: execute_recv_cb (adapter.c:846)
==30296== by 0x408D1BF: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.3306.0)
==30296== by 0x408FEF2: g_main_context_dispatch (in /lib/i386-linux-gnu/libglib-2.0.so.0.3306.0)
==30296== by 0x409028F: ??? (in /lib/i386-linux-gnu/libglib-2.0.so.0.3306.0)
==30296== by 0x40906EA: g_main_loop_run (in /lib/i386-linux-gnu/libglib-2.0.so.0.3306.0)
==30296== by 0x41E44D2: (below main) (libc-start.c:226)
Diffstat (limited to 'src')
-rw-r--r-- | src/bluetooth.c | 62 |
1 files changed, 33 insertions, 29 deletions
diff --git a/src/bluetooth.c b/src/bluetooth.c index 01039a2..1a4d4d1 100644 --- a/src/bluetooth.c +++ b/src/bluetooth.c @@ -518,45 +518,51 @@ static int bt_refresh_adapter_props(DBusConnection *conn, void *user_data) } /* Parse and fill the bluetooth oob information block */ -static void bt_parse_eir(uint8_t *ptr, uint16_t bt_oob_data_size, - struct near_oob_data *oob) +static void bt_parse_eir(uint8_t *eir_data, uint16_t eir_data_len, + struct near_oob_data *oob) { - uint8_t eir_code; - uint8_t eir_length; char *tmp; + uint16_t len = 0; - DBG(""); + DBG("total len: %u", eir_data_len); - while (bt_oob_data_size) { - eir_length = *ptr++; /* EIR length */ - eir_code = *ptr++; /* EIR code */ + while (len < eir_data_len - 1) { + uint8_t eir_len = eir_data[0]; /* EIR field length */ + uint8_t eir_code; /* EIR field type*/ + uint8_t data_len; /* EIR data length */ + uint8_t *data; /* check for early termination */ - if (eir_length == 0) { - bt_oob_data_size = 0; - continue; - } + if (eir_len == 0) + break; + + len += eir_len + 1; - /* Remaining bytes */ - bt_oob_data_size = bt_oob_data_size - eir_length - EIR_SIZE_LEN; + /* Do not continue EIR Data parsing if got incorrect length */ + if (len > eir_data_len) + break; + + data_len = eir_len - 1; + + eir_code = eir_data[1]; /* EIR code */ + data = &eir_data[2]; - /* Remove len byte from eir_length */ - eir_length = eir_length - EIR_SIZE_LEN; + DBG("type 0x%.2X data_len %u", eir_code, data_len); switch (eir_code) { case EIR_NAME_SHORT: case EIR_NAME_COMPLETE: - oob->bt_name = g_try_malloc0(eir_length + 1); /* eos */ + oob->bt_name = g_try_malloc0(data_len + 1); /* eos */ if (oob->bt_name) { - oob->bt_name_len = eir_length; - memcpy(oob->bt_name, ptr, oob->bt_name_len); - oob->bt_name[eir_length] = 0; /* end str*/ + oob->bt_name_len = data_len; + memcpy(oob->bt_name, data, oob->bt_name_len); + oob->bt_name[data_len] = 0; /* end str*/ } break; case EIR_CLASS_OF_DEVICE: tmp = g_strdup_printf("%02X%02X%02X", - *ptr, *(ptr + 1), *(ptr + 2)); + *data, *(data + 1), *(data + 2)); if (tmp != NULL) oob->class_of_device = strtol(tmp, NULL, 16); g_free(tmp); @@ -565,18 +571,18 @@ static void bt_parse_eir(uint8_t *ptr, uint16_t bt_oob_data_size, case EIR_SP_HASH: oob->spair_hash = g_try_malloc0(OOB_SP_SIZE); if (oob->spair_hash) - memcpy(oob->spair_hash, ptr, OOB_SP_SIZE); + memcpy(oob->spair_hash, data, OOB_SP_SIZE); break; case EIR_SP_RANDOMIZER: oob->spair_randomizer = g_try_malloc0(OOB_SP_SIZE); if (oob->spair_randomizer) memcpy(oob->spair_randomizer, - ptr, OOB_SP_SIZE); + data, OOB_SP_SIZE); break; case EIR_SECURITY_MGR_FLAGS: - oob->security_manager_oob_flags = *ptr; + oob->security_manager_oob_flags = *data; break; case EIR_UUID128_ALL: @@ -585,15 +591,13 @@ static void bt_parse_eir(uint8_t *ptr, uint16_t bt_oob_data_size, break; default: /* ignore and skip */ - near_warn("Unknown EIR: x%02x (len: %d)", eir_code, - eir_length); + near_error("Unknown EIR x%02x (len: %d)", eir_code, + eir_len); break; } /* Next eir */ - ptr = ptr + eir_length; + eir_data += eir_len + 1; } - - return; } /* |