6.6-stable review patch. If anyone has any objections, please let me know. ------------------ From: Aamir Ahmed commit e8241766794cf551d787fa3a77c0d54bbea6f6aa upstream. eir_get_service_data() reads a 16-bit UUID from the service data using get_unaligned_le16() without first checking that the data is long enough to hold a UUID16 (2 bytes). If a malformed EIR entry has a service data field with only 1 byte of payload (field_len=2), eir_get_data() returns dlen=1. The subsequent get_unaligned_le16() then reads 1 byte past the field boundary. Additionally, if the corrupted UUID happens to match, the length calculation "dlen - 2" underflows to SIZE_MAX since dlen is size_t. Current callers either pass NULL for the length parameter or bounds-check the returned length, but future callers may not. Add a check that dlen >= sizeof(u16) and skip fields that are too short to contain a valid UUID16. Fixes: 8f9ae5b3ae80 ("Bluetooth: eir: Add helpers for managing service data") Cc: stable@vger.kernel.org Signed-off-by: Aamir Ahmed Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/eir.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) --- a/net/bluetooth/eir.c +++ b/net/bluetooth/eir.c @@ -370,7 +370,15 @@ void *eir_get_service_data(u8 *eir, size size_t dlen; while ((eir = eir_get_data(eir, eir_len, EIR_SERVICE_DATA, &dlen))) { - u16 value = get_unaligned_le16(eir); + u16 value; + + if (dlen < sizeof(value)) { + eir += dlen; + eir_len = eir_end - eir; + continue; + } + + value = get_unaligned_le16(eir); if (uuid == value) { if (len)