All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] net/bluetooth: fix erroneous use of bitmap_from_u64()
@ 2022-06-05 16:25 Yury Norov
  2022-06-05 16:34 ` Linus Torvalds
  2022-06-05 17:14 ` bluez.test.bot
  0 siblings, 2 replies; 7+ messages in thread
From: Yury Norov @ 2022-06-05 16:25 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Augusto von Dentz,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Guo Ren, linux-bluetooth, netdev, linux-kernel, linux-csky
  Cc: Yury Norov, Sudip Mukherjee, Alexander Gordeev, Andy Shevchenko,
	Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
	Heiko Carstens, Janosch Frank, Rasmus Villemoes, Sven Schnelle,
	Vasily Gorbik, torvalds

The commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed
implementation of bitmap_from_u64(), so that it doesn't typecast
argument to u64, and actually dereferences memory.

With that change, compiler spotted few places in bluetooth code
where bitmap_from_u64 is called for 32-bit variable.

As reported by Sudip Mukherjee:

"arm allmodconfig" fails with the error:

In file included from ./include/linux/string.h:253,
                 from ./include/linux/bitmap.h:11,
                 from ./include/linux/cpumask.h:12,
                 from ./include/linux/smp.h:13,
                 from ./include/linux/lockdep.h:14,
                 from ./include/linux/mutex.h:17,
                 from ./include/linux/rfkill.h:35,
                 from net/bluetooth/hci_core.c:29:
In function 'fortify_memcpy_chk',
    inlined from 'bitmap_copy' at ./include/linux/bitmap.h:254:2,
    inlined from 'bitmap_copy_clear_tail' at ./include/linux/bitmap.h:263:2,
    inlined from 'bitmap_from_u64' at ./include/linux/bitmap.h:540:2,
    inlined from 'hci_bdaddr_list_add_with_flags' at net/bluetooth/hci_core.c:2156:2:
./include/linux/fortify-string.h:344:25: error: call to '__write_overflow_field' declared with attribute warning:
+detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning]
  344 |                         __write_overflow_field(p_size_field, size);

And, "csky allmodconfig" fails with the error:

In file included from ./include/linux/cpumask.h:12,
                 from ./include/linux/mm_types_task.h:14,
                 from ./include/linux/mm_types.h:5,
                 from ./include/linux/buildid.h:5,
                 from ./include/linux/module.h:14,
                 from net/bluetooth/mgmt.c:27:
In function 'bitmap_copy',
    inlined from 'bitmap_copy_clear_tail' at ./include/linux/bitmap.h:263:2,
    inlined from 'bitmap_from_u64' at ./include/linux/bitmap.h:540:2,
    inlined from 'set_device_flags' at net/bluetooth/mgmt.c:4534:4:
./include/linux/bitmap.h:254:9: error: 'memcpy' forming offset [4, 7] is out of the bounds [0, 4] of object 'flags'
+with type 'long unsigned int[1]' [-Werror=array-bounds]
  254 |         memcpy(dst, src, len);
      |         ^~~~~~~~~~~~~~~~~~~~~
In file included from ./include/linux/kasan-checks.h:5,
                 from ./include/asm-generic/rwonce.h:26,
                 from ./arch/csky/include/generated/asm/rwonce.h:1,
                 from ./include/linux/compiler.h:248,
                 from ./include/linux/build_bug.h:5,
                 from ./include/linux/container_of.h:5,
                 from ./include/linux/list.h:5,
                 from ./include/linux/module.h:12,
                 from net/bluetooth/mgmt.c:27:
net/bluetooth/mgmt.c: In function 'set_device_flags':
net/bluetooth/mgmt.c:4532:40: note: 'flags' declared here
 4532 |                         DECLARE_BITMAP(flags, __HCI_CONN_NUM_FLAGS);
      |                                        ^~~~~
./include/linux/types.h:11:23: note: in definition of macro 'DECLARE_BITMAP'
   11 |         unsigned long name[BITS_TO_LONGS(bits)]

Fix it by replacing bitmap_from_u64 with bitmap_from_arr32.

Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Signed-off-by: Yury Norov <yury.norov@gmail.com>
---
 net/bluetooth/hci_core.c | 2 +-
 net/bluetooth/mgmt.c     | 7 ++++---
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5abb2ca5b129..2de7e1ec4035 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2153,7 +2153,7 @@ int hci_bdaddr_list_add_with_flags(struct list_head *list, bdaddr_t *bdaddr,
 
 	bacpy(&entry->bdaddr, bdaddr);
 	entry->bdaddr_type = type;
-	bitmap_from_u64(entry->flags, flags);
+	bitmap_from_arr32(entry->flags, &flags, 32);
 
 	list_add(&entry->list, list);
 
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 74937a834648..b63025c70c2c 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4519,7 +4519,8 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 							      cp->addr.type);
 
 		if (br_params) {
-			bitmap_from_u64(br_params->flags, current_flags);
+			bitmap_from_arr32(br_params->flags, &current_flags,
+					  __HCI_CONN_NUM_FLAGS);
 			status = MGMT_STATUS_SUCCESS;
 		} else {
 			bt_dev_warn(hdev, "No such BR/EDR device %pMR (0x%x)",
@@ -4531,7 +4532,7 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 		if (params) {
 			DECLARE_BITMAP(flags, __HCI_CONN_NUM_FLAGS);
 
-			bitmap_from_u64(flags, current_flags);
+			bitmap_from_arr32(flags, &current_flags, __HCI_CONN_NUM_FLAGS);
 
 			/* Devices using RPAs can only be programmed in the
 			 * acceptlist LL Privacy has been enable otherwise they
@@ -4546,7 +4547,7 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 				goto unlock;
 			}
 
-			bitmap_from_u64(params->flags, current_flags);
+			bitmap_from_arr32(params->flags, &current_flags, __HCI_CONN_NUM_FLAGS);
 			status = MGMT_STATUS_SUCCESS;
 
 			/* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
-- 
2.32.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] net/bluetooth: fix erroneous use of bitmap_from_u64()
  2022-06-05 16:25 [PATCH] net/bluetooth: fix erroneous use of bitmap_from_u64() Yury Norov
@ 2022-06-05 16:34 ` Linus Torvalds
  2022-06-05 18:51   ` Linus Torvalds
  2022-06-05 17:14 ` bluez.test.bot
  1 sibling, 1 reply; 7+ messages in thread
From: Linus Torvalds @ 2022-06-05 16:34 UTC (permalink / raw)
  To: Yury Norov
  Cc: Marcel Holtmann, Johan Hedberg, Luiz Augusto von Dentz,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Guo Ren, linux-bluetooth, Netdev, Linux Kernel Mailing List,
	linux-csky, Sudip Mukherjee, Alexander Gordeev, Andy Shevchenko,
	Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
	Heiko Carstens, Janosch Frank, Rasmus Villemoes, Sven Schnelle,
	Vasily Gorbik

On Sun, Jun 5, 2022 at 9:25 AM Yury Norov <yury.norov@gmail.com> wrote:
>
> The commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed
> implementation of bitmap_from_u64(), so that it doesn't typecast
> argument to u64, and actually dereferences memory.

Gaah.

That code shouldn't use DECLARE_BITMAP() at all, it should just use

    struct bdaddr_list_with_flags {
            ..
            unsigned long flags;
    };

and then use '&br_params->flags' when it nneds the actual atomic
'set_bit()' things and friends, and then when it copies the flags
around it should just use 'flags' as an integer value.

The bitmap functions are literally defined to work as "bit N in a set
of 'unsigned long'" exactly so that you can do that mixing of values
and bit operations, and not have to worry about insane architectures
that do big-endian bit ordering or things like that.

Using a 'bitmap' as if it's some bigger or potentially variable-sized
thing for this kind of flags usage is crazy, when the code already
does

  /* Make sure number of flags doesn't exceed sizeof(current_flags) */
  static_assert(__HCI_CONN_NUM_FLAGS < 32);

because other parts are limited to 32 bits.

I wonder how painful it would be to just fix that odd type mistake.

                  Linus

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: net/bluetooth: fix erroneous use of bitmap_from_u64()
  2022-06-05 16:25 [PATCH] net/bluetooth: fix erroneous use of bitmap_from_u64() Yury Norov
  2022-06-05 16:34 ` Linus Torvalds
@ 2022-06-05 17:14 ` bluez.test.bot
  1 sibling, 0 replies; 7+ messages in thread
From: bluez.test.bot @ 2022-06-05 17:14 UTC (permalink / raw)
  To: linux-bluetooth, yury.norov

[-- Attachment #1: Type: text/plain, Size: 2839 bytes --]

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=647461

---Test result---

Test Summary:
CheckPatch                    FAIL      1.95 seconds
GitLint                       FAIL      1.03 seconds
SubjectPrefix                 FAIL      0.87 seconds
BuildKernel                   PASS      36.71 seconds
BuildKernel32                 PASS      32.83 seconds
Incremental Build with patchesPASS      44.05 seconds
TestRunner: Setup             PASS      546.12 seconds
TestRunner: l2cap-tester      PASS      18.98 seconds
TestRunner: bnep-tester       PASS      6.98 seconds
TestRunner: mgmt-tester       PASS      113.33 seconds
TestRunner: rfcomm-tester     PASS      10.88 seconds
TestRunner: sco-tester        PASS      10.46 seconds
TestRunner: smp-tester        PASS      10.53 seconds
TestRunner: userchan-tester   PASS      7.30 seconds

Details
##############################
Test: CheckPatch - FAIL - 1.95 seconds
Run checkpatch.pl script with rule in .checkpatch.conf
net/bluetooth: fix erroneous use of bitmap_from_u64()\WARNING:COMMIT_LOG_LONG_LINE: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#117: 
    inlined from 'bitmap_copy_clear_tail' at ./include/linux/bitmap.h:263:2,

total: 0 errors, 1 warnings, 0 checks, 33 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
      mechanically convert to the typical style using --fix or --fix-inplace.

/github/workspace/src/12869809.patch has style problems, please review.

NOTE: Ignored message types: UNKNOWN_COMMIT_ID

NOTE: If any of the errors are false positives, please report
      them to the maintainer, see CHECKPATCH in MAINTAINERS.


##############################
Test: GitLint - FAIL - 1.03 seconds
Run gitlint with rule in .gitlint
net/bluetooth: fix erroneous use of bitmap_from_u64()
26: B1 Line exceeds max length (85>80): "    inlined from 'hci_bdaddr_list_add_with_flags' at net/bluetooth/hci_core.c:2156:2:"
27: B1 Line exceeds max length (113>80): "./include/linux/fortify-string.h:344:25: error: call to '__write_overflow_field' declared with attribute warning:"
28: B1 Line exceeds max length (107>80): "+detected write beyond size of field (1st parameter); maybe use struct_group()? [-Werror=attribute-warning]"
43: B1 Line exceeds max length (115>80): "./include/linux/bitmap.h:254:9: error: 'memcpy' forming offset [4, 7] is out of the bounds [0, 4] of object 'flags'"


##############################
Test: SubjectPrefix - FAIL - 0.87 seconds
Check subject contains "Bluetooth" prefix
"Bluetooth: " is not specified in the subject



---
Regards,
Linux Bluetooth


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] net/bluetooth: fix erroneous use of bitmap_from_u64()
  2022-06-05 16:34 ` Linus Torvalds
@ 2022-06-05 18:51   ` Linus Torvalds
  2022-06-05 23:56     ` Linus Torvalds
  0 siblings, 1 reply; 7+ messages in thread
From: Linus Torvalds @ 2022-06-05 18:51 UTC (permalink / raw)
  To: Yury Norov
  Cc: Marcel Holtmann, Johan Hedberg, Luiz Augusto von Dentz,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Guo Ren, linux-bluetooth, Netdev, Linux Kernel Mailing List,
	linux-csky, Sudip Mukherjee, Alexander Gordeev, Andy Shevchenko,
	Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
	Heiko Carstens, Janosch Frank, Rasmus Villemoes, Sven Schnelle,
	Vasily Gorbik

[-- Attachment #1: Type: text/plain, Size: 1759 bytes --]

On Sun, Jun 5, 2022 at 9:34 AM Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> That code shouldn't use DECLARE_BITMAP() at all, it should just use
>
>     struct bdaddr_list_with_flags {
>             ..
>             unsigned long flags;
>     };
>
> and then use '&br_params->flags' when it needs the actual atomic
> 'set_bit()' things and friends,

Actually, I'm not convinced those things should be atomic at all.

*Most* of the accesses to those connection flags seem to be with
hci_dev_lock() held, and the ones that aren't can't possibly depend on
atomicity since those things are currently copied around with random
other "copy bitmaps" functions.

So I think the bluetooth code would actually be much better off with
something like

    /* Bitmask of connection flags */
    enum hci_conn_flags {
        HCI_CONN_FLAG_REMOTE_WAKEUP = 1,
        HCI_CONN_FLAG_DEVICE_PRIVACY = 2,
    };
    typedef u8 hci_conn_flags_t;

instead of playing games with DECLARE_BITMAP() and then using a mix of
atomic set_bit/clear_bit() and random non-atomic "copy bitmap values
around".

This attached patch builds cleanly for me, doing the above. But see a
few comments about those atomicity issues...

And no, it doesn't really need that new "hci_conn_flags_t", and it
could just use "u32" (which is what "current_flags" and
"supported_flags" use in the code), but those structures that contain
those connection flags do seem to have various other byte fields and
it would appear to pack better using just that simple one-byte type.

It *literally* just uses two bits in it, after all, and as mentioned,
the whole atomicity situation right now is very very dubious, so it
seems to make sense to do something like this.

Reactions?

                 Linus

[-- Attachment #2: patch.diff --]
[-- Type: text/x-patch, Size: 8713 bytes --]

 include/net/bluetooth/hci_core.h | 17 +++++++----------
 net/bluetooth/hci_core.c         |  4 ++--
 net/bluetooth/hci_request.c      |  2 +-
 net/bluetooth/hci_sync.c         |  6 +++---
 net/bluetooth/mgmt.c             | 37 ++++++++++++++-----------------------
 5 files changed, 27 insertions(+), 39 deletions(-)

diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 5a52a2018b56..c0ea2a4892b1 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -155,21 +155,18 @@ struct bdaddr_list_with_irk {
 	u8 local_irk[16];
 };
 
+/* Bitmask of connection flags */
 enum hci_conn_flags {
-	HCI_CONN_FLAG_REMOTE_WAKEUP,
-	HCI_CONN_FLAG_DEVICE_PRIVACY,
-
-	__HCI_CONN_NUM_FLAGS,
+	HCI_CONN_FLAG_REMOTE_WAKEUP = 1,
+	HCI_CONN_FLAG_DEVICE_PRIVACY = 2,
 };
-
-/* Make sure number of flags doesn't exceed sizeof(current_flags) */
-static_assert(__HCI_CONN_NUM_FLAGS < 32);
+typedef u8 hci_conn_flags_t;
 
 struct bdaddr_list_with_flags {
 	struct list_head list;
 	bdaddr_t bdaddr;
 	u8 bdaddr_type;
-	DECLARE_BITMAP(flags, __HCI_CONN_NUM_FLAGS);
+	hci_conn_flags_t flags;
 };
 
 struct bt_uuid {
@@ -576,7 +573,7 @@ struct hci_dev {
 	struct rfkill		*rfkill;
 
 	DECLARE_BITMAP(dev_flags, __HCI_NUM_FLAGS);
-	DECLARE_BITMAP(conn_flags, __HCI_CONN_NUM_FLAGS);
+	hci_conn_flags_t	conn_flags;
 
 	__s8			adv_tx_power;
 	__u8			adv_data[HCI_MAX_EXT_AD_LENGTH];
@@ -775,7 +772,7 @@ struct hci_conn_params {
 
 	struct hci_conn *conn;
 	bool explicit_connect;
-	DECLARE_BITMAP(flags, __HCI_CONN_NUM_FLAGS);
+	hci_conn_flags_t flags;
 	u8  privacy_mode;
 };
 
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5abb2ca5b129..59a5c1341c26 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2153,7 +2153,7 @@ int hci_bdaddr_list_add_with_flags(struct list_head *list, bdaddr_t *bdaddr,
 
 	bacpy(&entry->bdaddr, bdaddr);
 	entry->bdaddr_type = type;
-	bitmap_from_u64(entry->flags, flags);
+	entry->flags = flags;
 
 	list_add(&entry->list, list);
 
@@ -2634,7 +2634,7 @@ int hci_register_dev(struct hci_dev *hdev)
 	 * callback.
 	 */
 	if (hdev->wakeup)
-		set_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, hdev->conn_flags);
+		hdev->conn_flags |= HCI_CONN_FLAG_REMOTE_WAKEUP;
 
 	hci_sock_dev_event(hdev, HCI_DEV_REG);
 	hci_dev_hold(hdev);
diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c
index 635cc5fb451e..38ecaf9264ee 100644
--- a/net/bluetooth/hci_request.c
+++ b/net/bluetooth/hci_request.c
@@ -482,7 +482,7 @@ static int add_to_accept_list(struct hci_request *req,
 
 	/* During suspend, only wakeable devices can be in accept list */
 	if (hdev->suspended &&
-	    !test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, params->flags))
+	    !(params->flags & HCI_CONN_FLAG_REMOTE_WAKEUP))
 		return 0;
 
 	*num_entries += 1;
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index 4d2203c5f1bb..286d6767f017 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -1637,7 +1637,7 @@ static int hci_le_set_privacy_mode_sync(struct hci_dev *hdev,
 	 * indicates that LL Privacy has been enabled and
 	 * HCI_OP_LE_SET_PRIVACY_MODE is supported.
 	 */
-	if (!test_bit(HCI_CONN_FLAG_DEVICE_PRIVACY, params->flags))
+	if (!(params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY))
 		return 0;
 
 	irk = hci_find_irk_by_addr(hdev, &params->addr, params->addr_type);
@@ -1666,7 +1666,7 @@ static int hci_le_add_accept_list_sync(struct hci_dev *hdev,
 
 	/* During suspend, only wakeable devices can be in acceptlist */
 	if (hdev->suspended &&
-	    !test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, params->flags))
+	    !(params->flags & HCI_CONN_FLAG_REMOTE_WAKEUP))
 		return 0;
 
 	/* Select filter policy to accept all advertising */
@@ -4888,7 +4888,7 @@ static int hci_update_event_filter_sync(struct hci_dev *hdev)
 	hci_clear_event_filter_sync(hdev);
 
 	list_for_each_entry(b, &hdev->accept_list, list) {
-		if (!test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, b->flags))
+		if (!(b->flags & HCI_CONN_FLAG_REMOTE_WAKEUP))
 			continue;
 
 		bt_dev_dbg(hdev, "Adding event filters for %pMR", &b->bdaddr);
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 74937a834648..ae758ab1b558 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -4013,10 +4013,11 @@ static int exp_ll_privacy_feature_changed(bool enabled, struct hci_dev *hdev,
 	memcpy(ev.uuid, rpa_resolution_uuid, 16);
 	ev.flags = cpu_to_le32((enabled ? BIT(0) : 0) | BIT(1));
 
+	// Do we need to be atomic with the conn_flags?
 	if (enabled && privacy_mode_capable(hdev))
-		set_bit(HCI_CONN_FLAG_DEVICE_PRIVACY, hdev->conn_flags);
+		hdev->conn_flags |= HCI_CONN_FLAG_DEVICE_PRIVACY;
 	else
-		clear_bit(HCI_CONN_FLAG_DEVICE_PRIVACY, hdev->conn_flags);
+		hdev->conn_flags &= ~HCI_CONN_FLAG_DEVICE_PRIVACY;
 
 	return mgmt_limited_event(MGMT_EV_EXP_FEATURE_CHANGED, hdev,
 				  &ev, sizeof(ev),
@@ -4435,8 +4436,7 @@ static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 
 	hci_dev_lock(hdev);
 
-	bitmap_to_arr32(&supported_flags, hdev->conn_flags,
-			__HCI_CONN_NUM_FLAGS);
+	supported_flags = hdev->conn_flags;
 
 	memset(&rp, 0, sizeof(rp));
 
@@ -4447,8 +4447,7 @@ static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 		if (!br_params)
 			goto done;
 
-		bitmap_to_arr32(&current_flags, br_params->flags,
-				__HCI_CONN_NUM_FLAGS);
+		current_flags = br_params->flags;
 	} else {
 		params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
 						le_addr_type(cp->addr.type));
@@ -4456,8 +4455,7 @@ static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 		if (!params)
 			goto done;
 
-		bitmap_to_arr32(&current_flags, params->flags,
-				__HCI_CONN_NUM_FLAGS);
+		current_flags = params->flags;
 	}
 
 	bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
@@ -4502,8 +4500,8 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 		   &cp->addr.bdaddr, cp->addr.type,
 		   __le32_to_cpu(current_flags));
 
-	bitmap_to_arr32(&supported_flags, hdev->conn_flags,
-			__HCI_CONN_NUM_FLAGS);
+	// We should take hci_dev_lock() early, I think.. conn_flags can change
+	supported_flags = hdev->conn_flags;
 
 	if ((supported_flags | current_flags) != supported_flags) {
 		bt_dev_warn(hdev, "Bad flag given (0x%x) vs supported (0x%0x)",
@@ -4519,7 +4517,7 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 							      cp->addr.type);
 
 		if (br_params) {
-			bitmap_from_u64(br_params->flags, current_flags);
+			br_params->flags = current_flags;
 			status = MGMT_STATUS_SUCCESS;
 		} else {
 			bt_dev_warn(hdev, "No such BR/EDR device %pMR (0x%x)",
@@ -4529,15 +4527,11 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 		params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
 						le_addr_type(cp->addr.type));
 		if (params) {
-			DECLARE_BITMAP(flags, __HCI_CONN_NUM_FLAGS);
-
-			bitmap_from_u64(flags, current_flags);
-
 			/* Devices using RPAs can only be programmed in the
 			 * acceptlist LL Privacy has been enable otherwise they
 			 * cannot mark HCI_CONN_FLAG_REMOTE_WAKEUP.
 			 */
-			if (test_bit(HCI_CONN_FLAG_REMOTE_WAKEUP, flags) &&
+			if ((current_flags & HCI_CONN_FLAG_REMOTE_WAKEUP) &&
 			    !use_ll_privacy(hdev) &&
 			    hci_find_irk_by_addr(hdev, &params->addr,
 						 params->addr_type)) {
@@ -4546,14 +4540,13 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
 				goto unlock;
 			}
 
-			bitmap_from_u64(params->flags, current_flags);
+			params->flags = current_flags;
 			status = MGMT_STATUS_SUCCESS;
 
 			/* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
 			 * has been set.
 			 */
-			if (test_bit(HCI_CONN_FLAG_DEVICE_PRIVACY,
-				     params->flags))
+			if (params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY)
 				hci_update_passive_scan(hdev);
 		} else {
 			bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
@@ -7154,8 +7147,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
 		params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
 						addr_type);
 		if (params)
-			bitmap_to_arr32(&current_flags, params->flags,
-					__HCI_CONN_NUM_FLAGS);
+			current_flags = params->flags;
 	}
 
 	err = hci_cmd_sync_queue(hdev, add_device_sync, NULL, NULL);
@@ -7164,8 +7156,7 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
 
 added:
 	device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
-	bitmap_to_arr32(&supported_flags, hdev->conn_flags,
-			__HCI_CONN_NUM_FLAGS);
+	supported_flags = hdev->conn_flags;
 	device_flags_changed(NULL, hdev, &cp->addr.bdaddr, cp->addr.type,
 			     supported_flags, current_flags);
 

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH] net/bluetooth: fix erroneous use of bitmap_from_u64()
  2022-06-05 18:51   ` Linus Torvalds
@ 2022-06-05 23:56     ` Linus Torvalds
  2022-06-07  6:00       ` Luiz Augusto von Dentz
  0 siblings, 1 reply; 7+ messages in thread
From: Linus Torvalds @ 2022-06-05 23:56 UTC (permalink / raw)
  To: Yury Norov
  Cc: Marcel Holtmann, Johan Hedberg, Luiz Augusto von Dentz,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Guo Ren, linux-bluetooth, Netdev, Linux Kernel Mailing List,
	linux-csky, Sudip Mukherjee, Alexander Gordeev, Andy Shevchenko,
	Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
	Heiko Carstens, Janosch Frank, Rasmus Villemoes, Sven Schnelle,
	Vasily Gorbik

On Sun, Jun 5, 2022 at 11:51 AM Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> *Most* of the accesses to those connection flags seem to be with
> hci_dev_lock() held, and the ones that aren't can't possibly depend on
> atomicity since those things are currently copied around with random
> other "copy bitmaps" functions.

I've committed that patch as commit e1cff7002b71 ("bluetooth: don't
use bitmaps for random flag accesses").

That basically ends up reverting

  a9a347655d22 ("Bluetooth: MGMT: Add conditions for setting
HCI_CONN_FLAG_REMOTE_WAKEUP")
  6126ffabba6b ("Bluetooth: Introduce HCI_CONN_FLAG_DEVICE_PRIVACY device flag")

which did horrible things, and would end up overwriting the end of the
bitmap allocation on 32-bit architectures.

Luiz, if the reason for the change to use a bitmap type was because of
some atomicity concerns, then you can do that by

 (a) change 'hci_conn_flags_t' to be an 'atomic_t' instead of a 'u8'

 (b) change the regular accesses to it to use 'atomic_read/write()'

 (c) change the "bitfield" operations to use 'atomic_or/andnot()'

but honestly, when it used to mix atomic ops
(set_bit/clear_bit/test_bit) with random non-atomic users
(bitmap_from_u64(), bitmap_to_arr32() etc) it was never atomic to
begin with.

Regardless, trying to use bitmaps for this was absolutely not the
right thing to ever do. It looks like gcc randomly started complaining
when 'bitmap_from_u64()' was changed, but it was buggy before that
too.

                 Linus

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] net/bluetooth: fix erroneous use of bitmap_from_u64()
  2022-06-05 23:56     ` Linus Torvalds
@ 2022-06-07  6:00       ` Luiz Augusto von Dentz
  2022-06-07 18:49         ` Linus Torvalds
  0 siblings, 1 reply; 7+ messages in thread
From: Luiz Augusto von Dentz @ 2022-06-07  6:00 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Yury Norov, Marcel Holtmann, Johan Hedberg, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Guo Ren,
	linux-bluetooth, Netdev, Linux Kernel Mailing List, linux-csky,
	Sudip Mukherjee, Alexander Gordeev, Andy Shevchenko,
	Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
	Heiko Carstens, Janosch Frank, Rasmus Villemoes, Sven Schnelle,
	Vasily Gorbik

Hi Linus,

On Sun, Jun 5, 2022 at 5:02 PM Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> On Sun, Jun 5, 2022 at 11:51 AM Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
> >
> > *Most* of the accesses to those connection flags seem to be with
> > hci_dev_lock() held, and the ones that aren't can't possibly depend on
> > atomicity since those things are currently copied around with random
> > other "copy bitmaps" functions.
>
> I've committed that patch as commit e1cff7002b71 ("bluetooth: don't
> use bitmaps for random flag accesses").
>
> That basically ends up reverting
>
>   a9a347655d22 ("Bluetooth: MGMT: Add conditions for setting
> HCI_CONN_FLAG_REMOTE_WAKEUP")
>   6126ffabba6b ("Bluetooth: Introduce HCI_CONN_FLAG_DEVICE_PRIVACY device flag")
>
> which did horrible things, and would end up overwriting the end of the
> bitmap allocation on 32-bit architectures.
>
> Luiz, if the reason for the change to use a bitmap type was because of
> some atomicity concerns, then you can do that by
>
>  (a) change 'hci_conn_flags_t' to be an 'atomic_t' instead of a 'u8'
>
>  (b) change the regular accesses to it to use 'atomic_read/write()'
>
>  (c) change the "bitfield" operations to use 'atomic_or/andnot()'
>
> but honestly, when it used to mix atomic ops
> (set_bit/clear_bit/test_bit) with random non-atomic users
> (bitmap_from_u64(), bitmap_to_arr32() etc) it was never atomic to
> begin with.
>
> Regardless, trying to use bitmaps for this was absolutely not the
> right thing to ever do. It looks like gcc randomly started complaining
> when 'bitmap_from_u64()' was changed, but it was buggy before that
> too.

Right, thanks for fixing it. About some of the changes perhaps we
should use BIT when declaring values in enum hci_conn_flags?


-- 
Luiz Augusto von Dentz

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] net/bluetooth: fix erroneous use of bitmap_from_u64()
  2022-06-07  6:00       ` Luiz Augusto von Dentz
@ 2022-06-07 18:49         ` Linus Torvalds
  0 siblings, 0 replies; 7+ messages in thread
From: Linus Torvalds @ 2022-06-07 18:49 UTC (permalink / raw)
  To: Luiz Augusto von Dentz
  Cc: Yury Norov, Marcel Holtmann, Johan Hedberg, David S . Miller,
	Eric Dumazet, Jakub Kicinski, Paolo Abeni, Guo Ren,
	linux-bluetooth, Netdev, Linux Kernel Mailing List, linux-csky,
	Sudip Mukherjee, Alexander Gordeev, Andy Shevchenko,
	Christian Borntraeger, Claudio Imbrenda, David Hildenbrand,
	Heiko Carstens, Janosch Frank, Rasmus Villemoes, Sven Schnelle,
	Vasily Gorbik

On Mon, Jun 6, 2022 at 11:00 PM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> Right, thanks for fixing it. About some of the changes perhaps we
> should use BIT when declaring values in enum hci_conn_flags?

That sounds sane, although with just two flag values I'm not sure it matters.

But I guess it would document the fact that it's a bitmask, not an
ordinal value, and it looks like that header is already using BIT()
elsewhere so there are no new header file dependencies..

              Linus

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2022-06-07 22:08 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-05 16:25 [PATCH] net/bluetooth: fix erroneous use of bitmap_from_u64() Yury Norov
2022-06-05 16:34 ` Linus Torvalds
2022-06-05 18:51   ` Linus Torvalds
2022-06-05 23:56     ` Linus Torvalds
2022-06-07  6:00       ` Luiz Augusto von Dentz
2022-06-07 18:49         ` Linus Torvalds
2022-06-05 17:14 ` bluez.test.bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.