Skip to content

Commit ab6ab70

Browse files
committed
Revert "Bluetooth: hci_core: Fix sleeping function called from invalid context"
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/[email protected]/T/#t Fixes: 4d94f05 ("Bluetooth: hci_core: Fix sleeping function called from invalid context") Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 0bdd889 commit ab6ab70

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)
@@ -2010,103 +2011,68 @@ struct hci_cb {
20102011

20112012
char *name;
20122013

2013-
bool (*match) (struct hci_conn *conn);
20142014
void (*connect_cfm) (struct hci_conn *conn, __u8 status);
20152015
void (*disconn_cfm) (struct hci_conn *conn, __u8 status);
20162016
void (*security_cfm) (struct hci_conn *conn, __u8 status,
2017-
__u8 encrypt);
2017+
__u8 encrypt);
20182018
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
20192019
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
20202020
};
20212021

2022-
static inline void hci_cb_lookup(struct hci_conn *conn, struct list_head *list)
2023-
{
2024-
struct hci_cb *cb, *cpy;
2025-
2026-
rcu_read_lock();
2027-
list_for_each_entry_rcu(cb, &hci_cb_list, list) {
2028-
if (cb->match && cb->match(conn)) {
2029-
cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC);
2030-
if (!cpy)
2031-
break;
2032-
2033-
*cpy = *cb;
2034-
INIT_LIST_HEAD(&cpy->list);
2035-
list_add_rcu(&cpy->list, list);
2036-
}
2037-
}
2038-
rcu_read_unlock();
2039-
}
2040-
20412022
static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
20422023
{
2043-
struct list_head list;
2044-
struct hci_cb *cb, *tmp;
2045-
2046-
INIT_LIST_HEAD(&list);
2047-
hci_cb_lookup(conn, &list);
2024+
struct hci_cb *cb;
20482025

2049-
list_for_each_entry_safe(cb, tmp, &list, list) {
2026+
mutex_lock(&hci_cb_list_lock);
2027+
list_for_each_entry(cb, &hci_cb_list, list) {
20502028
if (cb->connect_cfm)
20512029
cb->connect_cfm(conn, status);
2052-
kfree(cb);
20532030
}
2031+
mutex_unlock(&hci_cb_list_lock);
20542032

20552033
if (conn->connect_cfm_cb)
20562034
conn->connect_cfm_cb(conn, status);
20572035
}
20582036

20592037
static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason)
20602038
{
2061-
struct list_head list;
2062-
struct hci_cb *cb, *tmp;
2063-
2064-
INIT_LIST_HEAD(&list);
2065-
hci_cb_lookup(conn, &list);
2039+
struct hci_cb *cb;
20662040

2067-
list_for_each_entry_safe(cb, tmp, &list, list) {
2041+
mutex_lock(&hci_cb_list_lock);
2042+
list_for_each_entry(cb, &hci_cb_list, list) {
20682043
if (cb->disconn_cfm)
20692044
cb->disconn_cfm(conn, reason);
2070-
kfree(cb);
20712045
}
2046+
mutex_unlock(&hci_cb_list_lock);
20722047

20732048
if (conn->disconn_cfm_cb)
20742049
conn->disconn_cfm_cb(conn, reason);
20752050
}
20762051

2077-
static inline void hci_security_cfm(struct hci_conn *conn, __u8 status,
2078-
__u8 encrypt)
2079-
{
2080-
struct list_head list;
2081-
struct hci_cb *cb, *tmp;
2082-
2083-
INIT_LIST_HEAD(&list);
2084-
hci_cb_lookup(conn, &list);
2085-
2086-
list_for_each_entry_safe(cb, tmp, &list, list) {
2087-
if (cb->security_cfm)
2088-
cb->security_cfm(conn, status, encrypt);
2089-
kfree(cb);
2090-
}
2091-
2092-
if (conn->security_cfm_cb)
2093-
conn->security_cfm_cb(conn, status);
2094-
}
2095-
20962052
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
20972053
{
2054+
struct hci_cb *cb;
20982055
__u8 encrypt;
20992056

21002057
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
21012058
return;
21022059

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

2105-
hci_security_cfm(conn, status, encrypt);
2062+
mutex_lock(&hci_cb_list_lock);
2063+
list_for_each_entry(cb, &hci_cb_list, list) {
2064+
if (cb->security_cfm)
2065+
cb->security_cfm(conn, status, encrypt);
2066+
}
2067+
mutex_unlock(&hci_cb_list_lock);
2068+
2069+
if (conn->security_cfm_cb)
2070+
conn->security_cfm_cb(conn, status);
21062071
}
21072072

21082073
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
21092074
{
2075+
struct hci_cb *cb;
21102076
__u8 encrypt;
21112077

21122078
if (conn->state == BT_CONFIG) {
@@ -2133,38 +2099,40 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
21332099
conn->sec_level = conn->pending_sec_level;
21342100
}
21352101

2136-
hci_security_cfm(conn, status, encrypt);
2102+
mutex_lock(&hci_cb_list_lock);
2103+
list_for_each_entry(cb, &hci_cb_list, list) {
2104+
if (cb->security_cfm)
2105+
cb->security_cfm(conn, status, encrypt);
2106+
}
2107+
mutex_unlock(&hci_cb_list_lock);
2108+
2109+
if (conn->security_cfm_cb)
2110+
conn->security_cfm_cb(conn, status);
21372111
}
21382112

21392113
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
21402114
{
2141-
struct list_head list;
2142-
struct hci_cb *cb, *tmp;
2143-
2144-
INIT_LIST_HEAD(&list);
2145-
hci_cb_lookup(conn, &list);
2115+
struct hci_cb *cb;
21462116

2147-
list_for_each_entry_safe(cb, tmp, &list, list) {
2117+
mutex_lock(&hci_cb_list_lock);
2118+
list_for_each_entry(cb, &hci_cb_list, list) {
21482119
if (cb->key_change_cfm)
21492120
cb->key_change_cfm(conn, status);
2150-
kfree(cb);
21512121
}
2122+
mutex_unlock(&hci_cb_list_lock);
21522123
}
21532124

21542125
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
21552126
__u8 role)
21562127
{
2157-
struct list_head list;
2158-
struct hci_cb *cb, *tmp;
2159-
2160-
INIT_LIST_HEAD(&list);
2161-
hci_cb_lookup(conn, &list);
2128+
struct hci_cb *cb;
21622129

2163-
list_for_each_entry_safe(cb, tmp, &list, list) {
2130+
mutex_lock(&hci_cb_list_lock);
2131+
list_for_each_entry(cb, &hci_cb_list, list) {
21642132
if (cb->role_switch_cfm)
21652133
cb->role_switch_cfm(conn, status, role);
2166-
kfree(cb);
21672134
}
2135+
mutex_unlock(&hci_cb_list_lock);
21682136
}
21692137

21702138
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);
@@ -2972,7 +2973,9 @@ int hci_register_cb(struct hci_cb *cb)
29722973
{
29732974
BT_DBG("%p name %s", cb, cb->name);
29742975

2975-
list_add_tail_rcu(&cb->list, &hci_cb_list);
2976+
mutex_lock(&hci_cb_list_lock);
2977+
list_add_tail(&cb->list, &hci_cb_list);
2978+
mutex_unlock(&hci_cb_list_lock);
29762979

29772980
return 0;
29782981
}
@@ -2982,8 +2985,9 @@ int hci_unregister_cb(struct hci_cb *cb)
29822985
{
29832986
BT_DBG("%p name %s", cb, cb->name);
29842987

2985-
list_del_rcu(&cb->list);
2986-
synchronize_rcu();
2988+
mutex_lock(&hci_cb_list_lock);
2989+
list_del(&cb->list);
2990+
mutex_unlock(&hci_cb_list_lock);
29872991

29882992
return 0;
29892993
}

net/bluetooth/iso.c

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

2190-
static bool iso_match(struct hci_conn *hcon)
2191-
{
2192-
return hcon->type == ISO_LINK || hcon->type == LE_LINK;
2193-
}
2194-
21952190
static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
21962191
{
21972192
if (hcon->type != ISO_LINK) {
@@ -2373,7 +2368,6 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
23732368

23742369
static struct hci_cb iso_cb = {
23752370
.name = "ISO",
2376-
.match = iso_match,
23772371
.connect_cfm = iso_connect_cfm,
23782372
.disconn_cfm = iso_disconn_cfm,
23792373
};

net/bluetooth/l2cap_core.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7182,18 +7182,16 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
71827182
return NULL;
71837183
}
71847184

7185-
static bool l2cap_match(struct hci_conn *hcon)
7186-
{
7187-
return hcon->type == ACL_LINK || hcon->type == LE_LINK;
7188-
}
7189-
71907185
static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
71917186
{
71927187
struct hci_dev *hdev = hcon->hdev;
71937188
struct l2cap_conn *conn;
71947189
struct l2cap_chan *pchan;
71957190
u8 dst_type;
71967191

7192+
if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
7193+
return;
7194+
71977195
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
71987196

71997197
if (status) {
@@ -7258,6 +7256,9 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
72587256

72597257
static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
72607258
{
7259+
if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
7260+
return;
7261+
72617262
BT_DBG("hcon %p reason %d", hcon, reason);
72627263

72637264
l2cap_conn_del(hcon, bt_to_errno(reason));
@@ -7565,7 +7566,6 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
75657566

75667567
static struct hci_cb l2cap_cb = {
75677568
.name = "L2CAP",
7568-
.match = l2cap_match,
75697569
.connect_cfm = l2cap_connect_cfm,
75707570
.disconn_cfm = l2cap_disconn_cfm,
75717571
.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
@@ -1407,13 +1407,11 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
14071407
return lm;
14081408
}
14091409

1410-
static bool sco_match(struct hci_conn *hcon)
1411-
{
1412-
return hcon->type == SCO_LINK || hcon->type == ESCO_LINK;
1413-
}
1414-
14151410
static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
14161411
{
1412+
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
1413+
return;
1414+
14171415
BT_DBG("hcon %p bdaddr %pMR status %u", hcon, &hcon->dst, status);
14181416

14191417
if (!status) {
@@ -1430,6 +1428,9 @@ static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
14301428

14311429
static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
14321430
{
1431+
if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
1432+
return;
1433+
14331434
BT_DBG("hcon %p reason %d", hcon, reason);
14341435

14351436
sco_conn_del(hcon, bt_to_errno(reason));
@@ -1455,7 +1456,6 @@ void sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb)
14551456

14561457
static struct hci_cb sco_cb = {
14571458
.name = "SCO",
1458-
.match = sco_match,
14591459
.connect_cfm = sco_connect_cfm,
14601460
.disconn_cfm = sco_disconn_cfm,
14611461
};

0 commit comments

Comments
 (0)