diff mbox series

[BlueZ] mesh: Fix segfault caused by re-enabling of HCI controller

Message ID 20200515061530.4983-1-inga.stotland@intel.com
State New
Headers show
Series [BlueZ] mesh: Fix segfault caused by re-enabling of HCI controller | expand

Commit Message

Inga Stotland May 15, 2020, 6:15 a.m. UTC
This fixes a crash incase when a controller used by bluetooth-meshd
is removed and then added back again.

Add a "restart" operation to mesh-io API to deal with a distinct case
of re-adding a previously used controller.

Backtrace:
0x00005618e754d040 in ?? ()
0x00005618e6e12d9a in io_ready_callback (user_data=0x5618e75538a0, result=<optimized out>) at mesh/mesh.c:174
0x00005618e6e3d2c8 in l_queue_foreach (queue=<optimized out>, function=0x5618e6e158e0 <process_read_info_req>, user_data=0x0)
    at ell/queue.c:441
0x00005618e6e37927 in request_complete (mgmt=mgmt@entry=0x5618e754ad50, status=<optimized out>, opcode=opcode@entry=4,
    index=index@entry=0, length=length@entry=280, param=0x5618e754b389) at src/shared/mgmt.c:261
---
 mesh/mesh-io-api.h     |  2 ++
 mesh/mesh-io-generic.c | 21 +++++++++++++++++++++
 mesh/mesh-io.c         |  8 ++++++++
 mesh/mesh-io.h         |  1 +
 mesh/mesh.c            | 12 +++++++++++-
 5 files changed, 43 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/mesh/mesh-io-api.h b/mesh/mesh-io-api.h
index 7a5b49c60..f6ca59833 100644
--- a/mesh/mesh-io-api.h
+++ b/mesh/mesh-io-api.h
@@ -22,6 +22,7 @@  struct mesh_io_private;
 typedef bool (*mesh_io_init_t)(struct mesh_io *io, void *opts,
 				mesh_io_ready_func_t cb, void *user_data);
 typedef bool (*mesh_io_destroy_t)(struct mesh_io *io);
+typedef bool (*mesh_io_restart_t)(struct mesh_io *io);
 typedef bool (*mesh_io_caps_t)(struct mesh_io *io, struct mesh_io_caps *caps);
 typedef bool (*mesh_io_send_t)(struct mesh_io *io,
 					struct mesh_io_send_info *info,
@@ -37,6 +38,7 @@  typedef bool (*mesh_io_tx_cancel_t)(struct mesh_io *io, const uint8_t *pattern,
 struct mesh_io_api {
 	mesh_io_init_t		init;
 	mesh_io_destroy_t	destroy;
+	mesh_io_restart_t	restart;
 	mesh_io_caps_t		caps;
 	mesh_io_send_t		send;
 	mesh_io_register_t	reg;
diff --git a/mesh/mesh-io-generic.c b/mesh/mesh-io-generic.c
index 2efd32f12..36aebc44f 100644
--- a/mesh/mesh-io-generic.c
+++ b/mesh/mesh-io-generic.c
@@ -769,6 +769,26 @@  static bool find_active(const void *a, const void *b)
 	return false;
 }
 
+static bool dev_restart(struct mesh_io *io)
+{
+	struct bt_hci_cmd_le_set_scan_enable cmd;
+	struct mesh_io_private *pvt = io->pvt;
+
+	if (!pvt)
+		return false;
+
+	if (l_queue_isempty(pvt->rx_regs))
+		return true;
+
+	pvt->active = l_queue_find(pvt->rx_regs, find_active, NULL);
+	cmd.enable = 0x00;	/* Disable scanning */
+	cmd.filter_dup = 0x00;	/* Report duplicates */
+	bt_hci_send(pvt->hci, BT_HCI_CMD_LE_SET_SCAN_ENABLE,
+				&cmd, sizeof(cmd), scan_disable_rsp, pvt, NULL);
+
+	return true;
+}
+
 static bool recv_register(struct mesh_io *io, const uint8_t *filter,
 			uint8_t len, mesh_io_recv_func_t cb, void *user_data)
 {
@@ -845,6 +865,7 @@  static bool recv_deregister(struct mesh_io *io, const uint8_t *filter,
 const struct mesh_io_api mesh_io_generic = {
 	.init = dev_init,
 	.destroy = dev_destroy,
+	.restart = dev_restart,
 	.caps = dev_caps,
 	.send = send_tx,
 	.reg = recv_register,
diff --git a/mesh/mesh-io.c b/mesh/mesh-io.c
index c4eaecefd..3cf5b0d67 100644
--- a/mesh/mesh-io.c
+++ b/mesh/mesh-io.c
@@ -96,6 +96,14 @@  fail:
 	return NULL;
 }
 
+void mesh_io_restart(struct mesh_io *io)
+{
+	io = l_queue_find(io_list, match_by_io, io);
+
+	if (io && io->api)
+		io->api->restart(io);
+}
+
 void mesh_io_destroy(struct mesh_io *io)
 {
 	io = l_queue_remove_if(io_list, match_by_io, io);
diff --git a/mesh/mesh-io.h b/mesh/mesh-io.h
index fc0422020..2af713d2c 100644
--- a/mesh/mesh-io.h
+++ b/mesh/mesh-io.h
@@ -83,6 +83,7 @@  typedef void (*mesh_io_ready_func_t)(void *user_data, bool result);
 
 struct mesh_io *mesh_io_new(enum mesh_io_type type, void *opts,
 				mesh_io_ready_func_t cb, void *user_data);
+void mesh_io_restart(struct mesh_io *io);
 void mesh_io_destroy(struct mesh_io *io);
 
 bool mesh_io_get_caps(struct mesh_io *io, struct mesh_io_caps *caps);
diff --git a/mesh/mesh.c b/mesh/mesh.c
index 890a3aa8f..e47587f43 100644
--- a/mesh/mesh.c
+++ b/mesh/mesh.c
@@ -66,6 +66,7 @@  struct bt_mesh {
 	uint16_t req_index;
 	uint8_t friend_queue_sz;
 	uint8_t max_filters;
+	bool initialized;
 };
 
 struct join_data{
@@ -91,7 +92,8 @@  static struct bt_mesh mesh = {
 	.lpn_support = false,
 	.proxy_support = false,
 	.crpl = DEFAULT_CRPL,
-	.friend_queue_sz = DEFAULT_FRIEND_QUEUE_SZ
+	.friend_queue_sz = DEFAULT_FRIEND_QUEUE_SZ,
+	.initialized = false
 };
 
 /* We allow only one outstanding Join request */
@@ -168,9 +170,17 @@  static void io_ready_callback(void *user_data, bool result)
 {
 	struct mesh_init_request *req = user_data;
 
+	if (mesh.initialized) {
+		if (result)
+			mesh_io_restart(mesh.io);
+		return;
+	}
+
 	if (result)
 		node_attach_io_all(mesh.io);
 
+	mesh.initialized = true;
+
 	req->cb(req->user_data, result);
 
 	l_free(req);