Bluetooth: Restrict access for raw-only controllers

Bluetooth controllers that are marked for raw-only usage can only be
used with user channel access. Any other operation should be rejected.

This simplifies the whole raw-only support since it now depends on
the fact that the controller is marked with HCI_QUIRK_RAW_DEVICE and
runtime raw access is restricted to user channel operation.

The kernel internal processing of HCI commands and events is designed
around the case that either the kernel has full control over the device
or that the device is driven from userspace. This now makes a clear
distinction between these two possible operation modes.

Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 9852449..50db020 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2117,6 +2117,11 @@
 		goto done;
 	}
 
+	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+		err = -EOPNOTSUPP;
+		goto done;
+	}
+
 	if (hdev->dev_type != HCI_BREDR) {
 		err = -EOPNOTSUPP;
 		goto done;
@@ -2246,10 +2251,7 @@
 		ret = hdev->setup(hdev);
 
 	if (!ret) {
-		if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
-			set_bit(HCI_RAW, &hdev->flags);
-
-		if (!test_bit(HCI_RAW, &hdev->flags) &&
+		if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks) &&
 		    !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags))
 			ret = __hci_init(hdev);
 	}
@@ -2286,7 +2288,7 @@
 		}
 
 		hdev->close(hdev);
-		hdev->flags = 0;
+		hdev->flags &= BIT(HCI_RAW);
 	}
 
 done:
@@ -2305,6 +2307,21 @@
 	if (!hdev)
 		return -ENODEV;
 
+	/* Devices that are marked for raw-only usage can only be powered
+	 * up as user channel. Trying to bring them up as normal devices
+	 * will result into a failure. Only user channel operation is
+	 * possible.
+	 *
+	 * When this function is called for a user channel, the flag
+	 * HCI_USER_CHANNEL will be set first before attempting to
+	 * open the device.
+	 */
+	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks) &&
+	    !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+		err = -EOPNOTSUPP;
+		goto done;
+	}
+
 	/* We need to ensure that no other power on/off work is pending
 	 * before proceeding to call hci_dev_do_open. This is
 	 * particularly important if the setup procedure has not yet
@@ -2321,8 +2338,8 @@
 
 	err = hci_dev_do_open(hdev);
 
+done:
 	hci_dev_put(hdev);
-
 	return err;
 }
 
@@ -2374,7 +2391,7 @@
 	/* Reset device */
 	skb_queue_purge(&hdev->cmd_q);
 	atomic_set(&hdev->cmd_cnt, 1);
-	if (!test_bit(HCI_RAW, &hdev->flags) &&
+	if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks) &&
 	    !test_bit(HCI_AUTO_OFF, &hdev->dev_flags) &&
 	    test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) {
 		set_bit(HCI_INIT, &hdev->flags);
@@ -2405,7 +2422,7 @@
 	hdev->close(hdev);
 
 	/* Clear flags */
-	hdev->flags = 0;
+	hdev->flags &= BIT(HCI_RAW);
 	hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
 
 	if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
@@ -2474,6 +2491,11 @@
 		goto done;
 	}
 
+	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
 	/* Drop queues */
 	skb_queue_purge(&hdev->rx_q);
 	skb_queue_purge(&hdev->cmd_q);
@@ -2489,8 +2511,7 @@
 	atomic_set(&hdev->cmd_cnt, 1);
 	hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0;
 
-	if (!test_bit(HCI_RAW, &hdev->flags))
-		ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT);
+	ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT);
 
 done:
 	hci_req_unlock(hdev);
@@ -2512,6 +2533,11 @@
 		goto done;
 	}
 
+	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+		ret = -EOPNOTSUPP;
+		goto done;
+	}
+
 	memset(&hdev->stat, 0, sizeof(struct hci_dev_stats));
 
 done:
@@ -2537,6 +2563,11 @@
 		goto done;
 	}
 
+	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
+		err = -EOPNOTSUPP;
+		goto done;
+	}
+
 	if (hdev->dev_type != HCI_BREDR) {
 		err = -EOPNOTSUPP;
 		goto done;
@@ -2760,8 +2791,10 @@
 				   HCI_AUTO_OFF_TIMEOUT);
 	}
 
-	if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags))
-		mgmt_index_added(hdev);
+	if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) {
+		if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+			mgmt_index_added(hdev);
+	}
 }
 
 static void hci_power_off(struct work_struct *work)
@@ -3887,6 +3920,13 @@
 	list_add(&hdev->list, &hci_dev_list);
 	write_unlock(&hci_dev_list_lock);
 
+	/* Devices that are marked for raw-only usage need to set
+	 * the HCI_RAW flag to indicate that only user channel is
+	 * supported.
+	 */
+	if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
+		set_bit(HCI_RAW, &hdev->flags);
+
 	hci_notify(hdev, HCI_DEV_REG);
 	hci_dev_hold(hdev);
 
@@ -3929,7 +3969,8 @@
 	cancel_work_sync(&hdev->power_on);
 
 	if (!test_bit(HCI_INIT, &hdev->flags) &&
-	    !test_bit(HCI_SETUP, &hdev->dev_flags)) {
+	    !test_bit(HCI_SETUP, &hdev->dev_flags) &&
+	    !test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
 		hci_dev_lock(hdev);
 		mgmt_index_removed(hdev);
 		hci_dev_unlock(hdev);
@@ -4694,7 +4735,7 @@
 
 static void __check_timeout(struct hci_dev *hdev, unsigned int cnt)
 {
-	if (!test_bit(HCI_RAW, &hdev->flags)) {
+	if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
 		/* ACL tx timeout must be longer than maximum
 		 * link supervision timeout (40.9 seconds) */
 		if (!cnt && time_after(jiffies, hdev->acl_last_tx +
@@ -4877,7 +4918,7 @@
 	if (!hci_conn_num(hdev, LE_LINK))
 		return;
 
-	if (!test_bit(HCI_RAW, &hdev->flags)) {
+	if (!test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
 		/* LE tx timeout must be longer than maximum
 		 * link supervision timeout (40.9 seconds) */
 		if (!hdev->le_cnt && hdev->le_pkts &&
@@ -5122,8 +5163,7 @@
 			hci_send_to_sock(hdev, skb);
 		}
 
-		if (test_bit(HCI_RAW, &hdev->flags) ||
-		    test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
+		if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
 			kfree_skb(skb);
 			continue;
 		}