summaryrefslogtreecommitdiff
path: root/mesh/mesh-io.c
diff options
context:
space:
mode:
authorInga Stotland <inga.stotland@gmail.com>2023-03-31 17:16:02 -0700
committerBrian Gix <brian.gix@gmail.com>2023-04-03 13:29:00 -0700
commitcffd5832a52cab71679e0bc6ee02a8f7816f1950 (patch)
tree1521bc779269d8bd7b97679952bddcc9ee710021 /mesh/mesh-io.c
parentde8e7cfce25b8d717f5ee60ee3b79d426fdcc681 (diff)
downloadbluez-cffd5832a52cab71679e0bc6ee02a8f7816f1950.tar.gz
mesh: Tighten IO and fix out-of-bounds array access
This fixes the out-of-bounds array access in mesh-io-mgmt.c caught by address sanitizer. Similar fixes were applied earlier to generic and unit IOs. With this patch, the common code is factored into a centralized location.
Diffstat (limited to 'mesh/mesh-io.c')
-rw-r--r--mesh/mesh-io.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/mesh/mesh-io.c b/mesh/mesh-io.c
index 3e68dc090..48e3f4226 100644
--- a/mesh/mesh-io.c
+++ b/mesh/mesh-io.c
@@ -28,13 +28,6 @@
#include "mesh/mesh-io-generic.h"
#include "mesh/mesh-io-unit.h"
-struct mesh_io_reg {
- mesh_io_recv_func_t cb;
- void *user_data;
- uint8_t len;
- uint8_t filter[];
-} packed;
-
struct loop_data {
uint16_t len;
uint8_t data[];
@@ -104,7 +97,6 @@ static void ctl_alert(int index, bool up, bool pwr, bool mesh, void *user_data)
if (mesh && type != MESH_IO_TYPE_GENERIC)
api = io_api(MESH_IO_TYPE_MGMT);
-
else if (!pwr)
api = io_api(MESH_IO_TYPE_GENERIC);
@@ -130,6 +122,23 @@ static void free_io(struct mesh_io *io)
}
}
+static struct mesh_io_reg *find_by_filter(struct l_queue *rx_regs,
+ const uint8_t *filter, uint8_t len)
+{
+ const struct l_queue_entry *entry;
+
+ entry = l_queue_get_entries(rx_regs);
+
+ for (; entry; entry = entry->next) {
+ struct mesh_io_reg *rx_reg = entry->data;
+
+ if (rx_reg->len == len && !memcmp(rx_reg->filter, filter, len))
+ return rx_reg;
+ }
+
+ return NULL;
+}
+
struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts,
mesh_io_ready_func_t cb, void *user_data)
{
@@ -194,14 +203,20 @@ bool mesh_io_register_recv_cb(struct mesh_io *io, const uint8_t *filter,
if (io == NULL)
io = default_io;
- if (io != default_io)
+ if (io != default_io || !cb || !filter || !len)
return false;
+ rx_reg = find_by_filter(io->rx_regs, filter, len);
+
+ l_free(rx_reg);
+ l_queue_remove(io->rx_regs, rx_reg);
+
rx_reg = l_malloc(sizeof(struct mesh_io_reg) + len);
rx_reg->cb = cb;
rx_reg->len = len;
rx_reg->user_data = user_data;
memcpy(rx_reg->filter, filter, len);
+
l_queue_push_head(io->rx_regs, rx_reg);
if (io && io->api && io->api->reg)
@@ -210,14 +225,6 @@ bool mesh_io_register_recv_cb(struct mesh_io *io, const uint8_t *filter,
return false;
}
-static bool by_filter(const void *a, const void *b)
-{
- const struct mesh_io_reg *rx_reg = a;
- const uint8_t *filter = b;
-
- return rx_reg->filter[0] == filter[0];
-}
-
bool mesh_io_deregister_recv_cb(struct mesh_io *io, const uint8_t *filter,
uint8_t len)
{
@@ -226,7 +233,9 @@ bool mesh_io_deregister_recv_cb(struct mesh_io *io, const uint8_t *filter,
if (io != default_io)
return false;
- rx_reg = l_queue_remove_if(io->rx_regs, by_filter, filter);
+ rx_reg = find_by_filter(io->rx_regs, filter, len);
+
+ l_queue_remove(io->rx_regs, rx_reg);
l_free(rx_reg);
if (io && io->api && io->api->dereg)