Skip to content

Commit 55b098a

Browse files
Vudentzgregkh
authored andcommitted
Revert "Bluetooth: hci_core: Fix sleeping function called from invalid context"
[ Upstream commit ab6ab70 ] This reverts commit 4d94f05 which has problems (see [1]) and is no longer needed since 581dd2d ("Bluetooth: hci_event: Fix using rcu_read_(un)lock while iterating") has reworked the code where the original bug has been found. [1] Link: https://lore.kernel.org/linux-bluetooth/877c55ci1r.wl-tiwai@suse.de/T/#t Fixes: 4d94f05 ("Bluetooth: hci_core: Fix sleeping function called from invalid context") Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 0677a4f commit 55b098a

File tree

6 files changed

+57
-97
lines changed

6 files changed

+57
-97
lines changed

include/net/bluetooth/hci_core.h

Lines changed: 38 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@ struct hci_conn_params {
804804
extern struct list_head hci_dev_list;
805805
extern struct list_head hci_cb_list;
806806
extern rwlock_t hci_dev_list_lock;
807+
extern struct mutex hci_cb_list_lock;
807808

808809
#define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags)
809810
#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags)
@@ -2006,103 +2007,68 @@ struct hci_cb {
20062007

20072008
char *name;
20082009

2009-
bool (*match) (struct hci_conn *conn);
20102010
void (*connect_cfm) (struct hci_conn *conn, __u8 status);
20112011
void (*disconn_cfm) (struct hci_conn *conn, __u8 status);
20122012
void (*security_cfm) (struct hci_conn *conn, __u8 status,
2013-
__u8 encrypt);
2013+
__u8 encrypt);
20142014
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
20152015
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
20162016
};
20172017

2018-
static inline void hci_cb_lookup(struct hci_conn *conn, struct list_head *list)
2019-
{
2020-
struct hci_cb *cb, *cpy;
2021-
2022-
rcu_read_lock();
2023-
list_for_each_entry_rcu(cb, &hci_cb_list, list) {
2024-
if (cb->match && cb->match(conn)) {
2025-
cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC);
2026-
if (!cpy)
2027-
break;
2028-
2029-
*cpy = *cb;
2030-
INIT_LIST_HEAD(&cpy->list);
2031-
list_add_rcu(&cpy->list, list);
2032-
}
2033-
}
2034-
rcu_read_unlock();
2035-
}
2036-
20372018
static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
20382019
{
2039-
struct list_head list;
2040-
struct hci_cb *cb, *tmp;
2041-
2042-
INIT_LIST_HEAD(&list);
2043-
hci_cb_lookup(conn, &list);
2020+
struct hci_cb *cb;
20442021

2045-
list_for_each_entry_safe(cb, tmp, &list, list) {
2022+
mutex_lock(&hci_cb_list_lock);
2023+
list_for_each_entry(cb, &hci_cb_list, list) {
20462024
if (cb->connect_cfm)
20472025
cb->connect_cfm(conn, status);
2048-
kfree(cb);
20492026
}
2027+
mutex_unlock(&hci_cb_list_lock);
20502028

20512029
if (conn->connect_cfm_cb)
20522030
conn->connect_cfm_cb(conn, status);
20532031
}
20542032

20552033
static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason)
20562034
{
2057-
struct list_head list;
2058-
struct hci_cb *cb, *tmp;
2059-
2060-
INIT_LIST_HEAD(&list);
2061-
hci_cb_lookup(conn, &list);
2035+
struct hci_cb *cb;
20622036

2063-
list_for_each_entry_safe(cb, tmp, &list, list) {
2037+
mutex_lock(&hci_cb_list_lock);
2038+
list_for_each_entry(cb, &hci_cb_list, list) {
20642039
if (cb->disconn_cfm)
20652040
cb->disconn_cfm(conn, reason);
2066-
kfree(cb);
20672041
}
2042+
mutex_unlock(&hci_cb_list_lock);
20682043

20692044
if (conn->disconn_cfm_cb)
20702045
conn->disconn_cfm_cb(conn, reason);
20712046
}
20722047

2073-
static inline void hci_security_cfm(struct hci_conn *conn, __u8 status,
2074-
__u8 encrypt)
2075-
{
2076-
struct list_head list;
2077-
struct hci_cb *cb, *tmp;
2078-
2079-
INIT_LIST_HEAD(&list);
2080-
hci_cb_lookup(conn, &list);
2081-
2082-
list_for_each_entry_safe(cb, tmp, &list, list) {
2083-
if (cb->security_cfm)
2084-
cb->security_cfm(conn, status, encrypt);
2085-
kfree(cb);
2086-
}
2087-
2088-
if (conn->security_cfm_cb)
2089-
conn->security_cfm_cb(conn, status);
2090-
}
2091-
20922048
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
20932049
{
2050+
struct hci_cb *cb;
20942051
__u8 encrypt;
20952052

20962053
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
20972054
return;
20982055

20992056
encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00;
21002057

2101-
hci_security_cfm(conn, status, encrypt);
2058+
mutex_lock(&hci_cb_list_lock);
2059+
list_for_each_entry(cb, &hci_cb_list, list) {
2060+
if (cb->security_cfm)
2061+
cb->security_cfm(conn, status, encrypt);
2062+
}
2063+
mutex_unlock(&hci_cb_list_lock);
2064+
2065+
if (conn->security_cfm_cb)
2066+
conn->security_cfm_cb(conn, status);
21022067
}
21032068

21042069
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
21052070
{
2071+
struct hci_cb *cb;
21062072
__u8 encrypt;
21072073

21082074
if (conn->state == BT_CONFIG) {
@@ -2129,38 +2095,40 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
21292095
conn->sec_level = conn->pending_sec_level;
21302096
}
21312097

2132-
hci_security_cfm(conn, status, encrypt);
2098+
mutex_lock(&hci_cb_list_lock);
2099+
list_for_each_entry(cb, &hci_cb_list, list) {
2100+
if (cb->security_cfm)
2101+
cb->security_cfm(conn, status, encrypt);
2102+
}
2103+
mutex_unlock(&hci_cb_list_lock);
2104+
2105+
if (conn->security_cfm_cb)
2106+
conn->security_cfm_cb(conn, status);
21332107
}
21342108

21352109
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
21362110
{
2137-
struct list_head list;
2138-
struct hci_cb *cb, *tmp;
2139-
2140-
INIT_LIST_HEAD(&list);
2141-
hci_cb_lookup(conn, &list);
2111+
struct hci_cb *cb;
21422112

2143-
list_for_each_entry_safe(cb, tmp, &list, list) {
2113+
mutex_lock(&hci_cb_list_lock);
2114+
list_for_each_entry(cb, &hci_cb_list, list) {
21442115
if (cb->key_change_cfm)
21452116
cb->key_change_cfm(conn, status);
2146-
kfree(cb);
21472117
}
2118+
mutex_unlock(&hci_cb_list_lock);
21482119
}
21492120

21502121
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
21512122
__u8 role)
21522123
{
2153-
struct list_head list;
2154-
struct hci_cb *cb, *tmp;
2155-
2156-
INIT_LIST_HEAD(&list);
2157-
hci_cb_lookup(conn, &list);
2124+
struct hci_cb *cb;
21582125

2159-
list_for_each_entry_safe(cb, tmp, &list, list) {
2126+
mutex_lock(&hci_cb_list_lock);
2127+
list_for_each_entry(cb, &hci_cb_list, list) {
21602128
if (cb->role_switch_cfm)
21612129
cb->role_switch_cfm(conn, status, role);
2162-
kfree(cb);
21632130
}
2131+
mutex_unlock(&hci_cb_list_lock);
21642132
}
21652133

21662134
static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)

net/bluetooth/hci_core.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ DEFINE_RWLOCK(hci_dev_list_lock);
5757

5858
/* HCI callback list */
5959
LIST_HEAD(hci_cb_list);
60+
DEFINE_MUTEX(hci_cb_list_lock);
6061

6162
/* HCI ID Numbering */
6263
static DEFINE_IDA(hci_index_ida);
@@ -2992,7 +2993,9 @@ int hci_register_cb(struct hci_cb *cb)
29922993
{
29932994
BT_DBG("%p name %s", cb, cb->name);
29942995

2995-
list_add_tail_rcu(&cb->list, &hci_cb_list);
2996+
mutex_lock(&hci_cb_list_lock);
2997+
list_add_tail(&cb->list, &hci_cb_list);
2998+
mutex_unlock(&hci_cb_list_lock);
29962999

29973000
return 0;
29983001
}
@@ -3002,8 +3005,9 @@ int hci_unregister_cb(struct hci_cb *cb)
30023005
{
30033006
BT_DBG("%p name %s", cb, cb->name);
30043007

3005-
list_del_rcu(&cb->list);
3006-
synchronize_rcu();
3008+
mutex_lock(&hci_cb_list_lock);
3009+
list_del(&cb->list);
3010+
mutex_unlock(&hci_cb_list_lock);
30073011

30083012
return 0;
30093013
}

net/bluetooth/iso.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2137,11 +2137,6 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
21372137
return HCI_LM_ACCEPT;
21382138
}
21392139

2140-
static bool iso_match(struct hci_conn *hcon)
2141-
{
2142-
return hcon->type == ISO_LINK || hcon->type == LE_LINK;
2143-
}
2144-
21452140
static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
21462141
{
21472142
if (hcon->type != ISO_LINK) {
@@ -2323,7 +2318,6 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
23232318

23242319
static struct hci_cb iso_cb = {
23252320
.name = "ISO",
2326-
.match = iso_match,
23272321
.connect_cfm = iso_connect_cfm,
23282322
.disconn_cfm = iso_disconn_cfm,
23292323
};

net/bluetooth/l2cap_core.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7222,18 +7222,16 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
72227222
return NULL;
72237223
}
72247224

7225-
static bool l2cap_match(struct hci_conn *hcon)
7226-
{
7227-
return hcon->type == ACL_LINK || hcon->type == LE_LINK;
7228-
}
7229-
72307225
static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
72317226
{
72327227
struct hci_dev *hdev = hcon->hdev;
72337228
struct l2cap_conn *conn;
72347229
struct l2cap_chan *pchan;
72357230
u8 dst_type;
72367231

7232+
if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
7233+
return;
7234+
72377235
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
72387236

72397237
if (status) {
@@ -7298,6 +7296,9 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
72987296

72997297
static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
73007298
{
7299+
if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
7300+
return;
7301+
73017302
BT_DBG("hcon %p reason %d", hcon, reason);
73027303

73037304
l2cap_conn_del(hcon, bt_to_errno(reason));
@@ -7576,7 +7577,6 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
75767577

75777578
static struct hci_cb l2cap_cb = {
75787579
.name = "L2CAP",
7579-
.match = l2cap_match,
75807580
.connect_cfm = l2cap_connect_cfm,
75817581
.disconn_cfm = l2cap_disconn_cfm,
75827582
.security_cfm = l2cap_security_cfm,

net/bluetooth/rfcomm/core.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2134,11 +2134,6 @@ static int rfcomm_run(void *unused)
21342134
return 0;
21352135
}
21362136

2137-
static bool rfcomm_match(struct hci_conn *hcon)
2138-
{
2139-
return hcon->type == ACL_LINK;
2140-
}
2141-
21422137
static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
21432138
{
21442139
struct rfcomm_session *s;
@@ -2185,7 +2180,6 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
21852180

21862181
static struct hci_cb rfcomm_cb = {
21872182
.name = "RFCOMM",
2188-
.match = rfcomm_match,
21892183
.security_cfm = rfcomm_security_cfm
21902184
};
21912185

net/bluetooth/sco.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,13 +1355,11 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
13551355
return lm;
13561356
}
13571357

1358-
static bool sco_match(struct hci_conn *hcon)
1359-
{
1360-
return hcon->type == SCO_LINK || hcon->type == ESCO_LINK;
1361-
}
1362-
13631358
static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
13641359
{
1360+
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
1361+
return;
1362+
13651363
BT_DBG("hcon %p bdaddr %pMR status %u", hcon, &hcon->dst, status);
13661364

13671365
if (!status) {
@@ -1376,6 +1374,9 @@ static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
13761374

13771375
static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
13781376
{
1377+
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
1378+
return;
1379+
13791380
BT_DBG("hcon %p reason %d", hcon, reason);
13801381

13811382
sco_conn_del(hcon, bt_to_errno(reason));
@@ -1401,7 +1402,6 @@ void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
14011402

14021403
static struct hci_cb sco_cb = {
14031404
.name = "SCO",
1404-
.match = sco_match,
14051405
.connect_cfm = sco_connect_cfm,
14061406
.disconn_cfm = sco_disconn_cfm,
14071407
};

0 commit comments

Comments
 (0)