Skip to content

Commit 88d604d

Browse files
committed
drv/bluetooth/cc2640: protect against write_buf use while reading
Due to the use of write_buf_size as a flag to indicate if write_buf is currently in use, there was a possibility that the UART service or Pybricks service could write to write_buf and set write_buf_size while a read-only SPI transaction was in progress, which would cause data to be lost.
1 parent 58f568a commit 88d604d

File tree

2 files changed

+18
-9
lines changed

2 files changed

+18
-9
lines changed

lib/ble5stack/central/hci_tl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,8 @@
3838
#include <stdint.h>
3939

4040
/* HCI Buffer size */
41-
#define TX_BUFFER_SIZE 256
42-
#define RX_BUFFER_SIZE 256
41+
#define TX_BUFFER_SIZE 255
42+
#define RX_BUFFER_SIZE 255
4343

4444
#define HCI_FRAME_SIZE 0x04
4545

lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,18 +1184,29 @@ PROCESS_THREAD(pbdrv_bluetooth_spi_process, ev, data) {
11841184
start_task(init_task, NULL);
11851185

11861186
while (true) {
1187+
static uint8_t real_write_xfer_size;
1188+
11871189
PROCESS_WAIT_UNTIL(spi_srdy || write_xfer_size);
11881190

11891191
spi_set_mrdy(true);
11901192

1193+
// Need to make a copy of the write transfer size for the case where we
1194+
// are reading only. In this case we still have to set write_xfer_size
1195+
// to a non-zero value to indicate that write_buf is being used. But we
1196+
// still need the real size later to figure out the actual size of the
1197+
// SPI transfer.
1198+
real_write_xfer_size = write_xfer_size;
1199+
11911200
// we can either read, write, or read and write at the same time
11921201

1193-
if (write_xfer_size) {
1202+
if (real_write_xfer_size) {
11941203
// if we are writing only, we have to wait until SRDY is asserted
11951204
PROCESS_WAIT_UNTIL(spi_srdy);
11961205
} else {
11971206
// if we are reading only, the write buffer has to be all 0s
11981207
memset(write_buf, 0, PBIO_ARRAY_SIZE(write_buf));
1208+
// indicates that write_buf is in use
1209+
write_xfer_size = PBIO_ARRAY_SIZE(write_buf);
11991210
}
12001211

12011212
// send the write header
@@ -1205,10 +1216,10 @@ PROCESS_THREAD(pbdrv_bluetooth_spi_process, ev, data) {
12051216

12061217
// Total transfer size is biggest of read and write sizes.
12071218
read_xfer_size = 0;
1208-
if (get_npi_rx_size(&read_xfer_size) && read_xfer_size > write_xfer_size - 4) {
1219+
if (get_npi_rx_size(&read_xfer_size) && read_xfer_size > real_write_xfer_size - 4) {
12091220
xfer_size = read_xfer_size + 4;
12101221
} else {
1211-
xfer_size = write_xfer_size;
1222+
xfer_size = real_write_xfer_size;
12121223
}
12131224

12141225
// read the remaining message
@@ -1220,10 +1231,8 @@ PROCESS_THREAD(pbdrv_bluetooth_spi_process, ev, data) {
12201231
spi_set_mrdy(false);
12211232
PROCESS_WAIT_UNTIL(!spi_srdy);
12221233

1223-
if (write_xfer_size) {
1224-
// set to 0 to indicate that xfer is complete
1225-
write_xfer_size = 0;
1226-
}
1234+
// set to 0 to indicate that xfer is complete
1235+
write_xfer_size = 0;
12271236

12281237
if (read_xfer_size) {
12291238
// handle the received data

0 commit comments

Comments
 (0)