Bluetooth: Mesh: add check for rx buffer overflow in pb adv

There is potential buffer overflow in pb adv.
If Transaction Continuation PDU comes before
Transaction Start PDU the last segment number is set to 0xff.
The current implementation has a strictly limited buffer size.
It is possible to receive malformed frame with wrong segment
number. All segments with number 2 and above will be stored
in the memory behind Rx buffer.

Signed-off-by: Aleksandr Khromykh <Aleksandr.Khromykh@nordicsemi.no>
This commit is contained in:
Aleksandr Khromykh 2022-04-21 16:11:48 +02:00 committed by Carles Cufí
commit 6896075b62

View file

@ -29,6 +29,7 @@
#define START_PAYLOAD_MAX 20 #define START_PAYLOAD_MAX 20
#define CONT_PAYLOAD_MAX 23 #define CONT_PAYLOAD_MAX 23
#define RX_BUFFER_MAX 65
#define START_LAST_SEG(gpc) (gpc >> 2) #define START_LAST_SEG(gpc) (gpc >> 2)
#define CONT_SEG_INDEX(gpc) (gpc >> 2) #define CONT_SEG_INDEX(gpc) (gpc >> 2)
@ -38,7 +39,8 @@
#define LINK_ACK 0x01 #define LINK_ACK 0x01
#define LINK_CLOSE 0x02 #define LINK_CLOSE 0x02
#define XACT_SEG_DATA(_seg) (&link.rx.buf->data[20 + ((_seg - 1) * 23)]) #define XACT_SEG_OFFSET(_seg) (20 + ((_seg - 1) * 23))
#define XACT_SEG_DATA(_seg) (&link.rx.buf->data[XACT_SEG_OFFSET(_seg)])
#define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg))) #define XACT_SEG_RECV(_seg) (link.rx.seg &= ~(1 << (_seg)))
#define XACT_ID_MAX 0x7f #define XACT_ID_MAX 0x7f
@ -116,7 +118,7 @@ struct prov_rx {
uint8_t gpc; uint8_t gpc;
}; };
NET_BUF_SIMPLE_DEFINE_STATIC(rx_buf, 65); NET_BUF_SIMPLE_DEFINE_STATIC(rx_buf, RX_BUFFER_MAX);
static struct pb_adv link = { .rx = { .buf = &rx_buf } }; static struct pb_adv link = { .rx = { .buf = &rx_buf } };
@ -383,6 +385,11 @@ static void gen_prov_cont(struct prov_rx *rx, struct net_buf_simple *buf)
return; return;
} }
if (XACT_SEG_OFFSET(seg) + buf->len > RX_BUFFER_MAX) {
BT_WARN("Rx buffer overflow. Malformed generic prov frame?");
return;
}
memcpy(XACT_SEG_DATA(seg), buf->data, buf->len); memcpy(XACT_SEG_DATA(seg), buf->data, buf->len);
XACT_SEG_RECV(seg); XACT_SEG_RECV(seg);