Commit 14bd22db authored by Vinayak Kariappa Chettimada's avatar Vinayak Kariappa Chettimada Committed by Anas Nashif
Browse files

Bluetooth: controller: Fix race in create connection cancel



Fix race conditional when create connection cancel is called
and actually a connection did get setup while initiator is
being stopped.

Signed-off-by: default avatarVinayak Kariappa Chettimada <vich@nordicsemi.no>
parent d72a1078
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ struct lll_conn {
	union {
		struct {
			uint8_t initiated:1;
			uint8_t cancelled:1;
		} master;
#if defined(CONFIG_BT_PERIPHERAL)
		struct {
+1 −1
Original line number Diff line number Diff line
@@ -12,7 +12,7 @@ struct lll_scan {
	 *       check ull_conn_setup how it access the connection LLL
	 *       context.
	 */
	struct lll_conn *conn;
	struct lll_conn *volatile conn;

	uint8_t  adv_addr[BDADDR_SIZE];
	uint32_t conn_win_offset_us;
+4 −2
Original line number Diff line number Diff line
@@ -140,7 +140,9 @@ static int prepare_cb(struct lll_prepare_param *p)
	/* Check if stopped (on connection establishment race between LLL and
	 * ULL.
	 */
	if (unlikely(lll->conn && lll->conn->master.initiated)) {
	if (unlikely(lll->conn &&
		     (lll->conn->master.initiated ||
		      lll->conn->master.cancelled))) {
		int err;

		err = lll_hfclock_off();
@@ -779,7 +781,7 @@ static inline int isr_rx_pdu(struct lll_scan *lll, struct pdu_adv *pdu_adv_rx,
	if (0) {
#if defined(CONFIG_BT_CENTRAL)
	/* Initiator */
	} else if (lll->conn &&
	} else if (lll->conn && !lll->conn->master.cancelled &&
		   isr_scan_init_check(lll, pdu_adv_rx, rl_idx)) {
		struct lll_conn *lll_conn;
		struct node_rx_ftr *ftr;
+21 −0
Original line number Diff line number Diff line
@@ -211,6 +211,7 @@ uint8_t ll_create_connection(uint16_t scan_interval, uint16_t scan_window,
	conn_lll->data_chan_use = 0;
	conn_lll->role = 0;
	conn_lll->master.initiated = 0;
	conn_lll->master.cancelled = 0;
	/* FIXME: END: Move to ULL? */
#if defined(CONFIG_BT_CTLR_CONN_META)
	memset(&conn_lll->conn_meta, 0, sizeof(conn_lll->conn_meta));
@@ -384,8 +385,28 @@ uint8_t ll_connect_disable(void **rx)
		return BT_HCI_ERR_CMD_DISALLOWED;
	}

	/* Check if initiator active */
	conn_lll = scan->lll.conn;
	if (!conn_lll) {
		/* Scanning not associated with initiation of a connection or
		 * connection setup already complete (was set to NULL in
		 * ull_master_setup), but HCI event not processed by host.
		 */
		return BT_HCI_ERR_CMD_DISALLOWED;
	}

	/* Indicate to LLL that a cancellation is requested */
	conn_lll->master.cancelled = 1U;
	cpu_dmb();

	/* Check if connection was established under race condition, i.e.
	 * before the cancelled flag was set.
	 */
	conn_lll = scan->lll.conn;
	if (!conn_lll) {
		/* Connection setup completed on race condition with cancelled
		 * flag, before it was set.
		 */
		return BT_HCI_ERR_CMD_DISALLOWED;
	}