Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 4a54964

Browse files
VudentzCarlos Llamas
authored andcommitted
UPSTREAM: 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") Change-Id: If816d3b42cb7b1c18e250c0a5ee266cdd48b4b01 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org> (cherry picked from commit 55b098a) Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
1 parent e0f526b commit 4a54964

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
@@ -806,6 +806,7 @@ struct hci_conn_params {
806806
extern struct list_head hci_dev_list;
807807
extern struct list_head hci_cb_list;
808808
extern rwlock_t hci_dev_list_lock;
809+
extern struct mutex hci_cb_list_lock;
809810

810811
#define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags)
811812
#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags)
@@ -2008,103 +2009,68 @@ struct hci_cb {
20082009

20092010
char *name;
20102011

2011-
bool (*match) (struct hci_conn *conn);
20122012
void (*connect_cfm) (struct hci_conn *conn, __u8 status);
20132013
void (*disconn_cfm) (struct hci_conn *conn, __u8 status);
20142014
void (*security_cfm) (struct hci_conn *conn, __u8 status,
2015-
__u8 encrypt);
2015+
__u8 encrypt);
20162016
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
20172017
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
20182018
};
20192019

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

2047-
list_for_each_entry_safe(cb, tmp, &list, list) {
2024+
mutex_lock(&hci_cb_list_lock);
2025+
list_for_each_entry(cb, &hci_cb_list, list) {
20482026
if (cb->connect_cfm)
20492027
cb->connect_cfm(conn, status);
2050-
kfree(cb);
20512028
}
2029+
mutex_unlock(&hci_cb_list_lock);
20522030

20532031
if (conn->connect_cfm_cb)
20542032
conn->connect_cfm_cb(conn, status);
20552033
}
20562034

20572035
static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason)
20582036
{
2059-
struct list_head list;
2060-
struct hci_cb *cb, *tmp;
2061-
2062-
INIT_LIST_HEAD(&list);
2063-
hci_cb_lookup(conn, &list);
2037+
struct hci_cb *cb;
20642038

2065-
list_for_each_entry_safe(cb, tmp, &list, list) {
2039+
mutex_lock(&hci_cb_list_lock);
2040+
list_for_each_entry(cb, &hci_cb_list, list) {
20662041
if (cb->disconn_cfm)
20672042
cb->disconn_cfm(conn, reason);
2068-
kfree(cb);
20692043
}
2044+
mutex_unlock(&hci_cb_list_lock);
20702045

20712046
if (conn->disconn_cfm_cb)
20722047
conn->disconn_cfm_cb(conn, reason);
20732048
}
20742049

2075-
static inline void hci_security_cfm(struct hci_conn *conn, __u8 status,
2076-
__u8 encrypt)
2077-
{
2078-
struct list_head list;
2079-
struct hci_cb *cb, *tmp;
2080-
2081-
INIT_LIST_HEAD(&list);
2082-
hci_cb_lookup(conn, &list);
2083-
2084-
list_for_each_entry_safe(cb, tmp, &list, list) {
2085-
if (cb->security_cfm)
2086-
cb->security_cfm(conn, status, encrypt);
2087-
kfree(cb);
2088-
}
2089-
2090-
if (conn->security_cfm_cb)
2091-
conn->security_cfm_cb(conn, status);
2092-
}
2093-
20942050
static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
20952051
{
2052+
struct hci_cb *cb;
20962053
__u8 encrypt;
20972054

20982055
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
20992056
return;
21002057

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

2103-
hci_security_cfm(conn, status, encrypt);
2060+
mutex_lock(&hci_cb_list_lock);
2061+
list_for_each_entry(cb, &hci_cb_list, list) {
2062+
if (cb->security_cfm)
2063+
cb->security_cfm(conn, status, encrypt);
2064+
}
2065+
mutex_unlock(&hci_cb_list_lock);
2066+
2067+
if (conn->security_cfm_cb)
2068+
conn->security_cfm_cb(conn, status);
21042069
}
21052070

21062071
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
21072072
{
2073+
struct hci_cb *cb;
21082074
__u8 encrypt;
21092075

21102076
if (conn->state == BT_CONFIG) {
@@ -2131,38 +2097,40 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
21312097
conn->sec_level = conn->pending_sec_level;
21322098
}
21332099

2134-
hci_security_cfm(conn, status, encrypt);
2100+
mutex_lock(&hci_cb_list_lock);
2101+
list_for_each_entry(cb, &hci_cb_list, list) {
2102+
if (cb->security_cfm)
2103+
cb->security_cfm(conn, status, encrypt);
2104+
}
2105+
mutex_unlock(&hci_cb_list_lock);
2106+
2107+
if (conn->security_cfm_cb)
2108+
conn->security_cfm_cb(conn, status);
21352109
}
21362110

21372111
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
21382112
{
2139-
struct list_head list;
2140-
struct hci_cb *cb, *tmp;
2141-
2142-
INIT_LIST_HEAD(&list);
2143-
hci_cb_lookup(conn, &list);
2113+
struct hci_cb *cb;
21442114

2145-
list_for_each_entry_safe(cb, tmp, &list, list) {
2115+
mutex_lock(&hci_cb_list_lock);
2116+
list_for_each_entry(cb, &hci_cb_list, list) {
21462117
if (cb->key_change_cfm)
21472118
cb->key_change_cfm(conn, status);
2148-
kfree(cb);
21492119
}
2120+
mutex_unlock(&hci_cb_list_lock);
21502121
}
21512122

21522123
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
21532124
__u8 role)
21542125
{
2155-
struct list_head list;
2156-
struct hci_cb *cb, *tmp;
2157-
2158-
INIT_LIST_HEAD(&list);
2159-
hci_cb_lookup(conn, &list);
2126+
struct hci_cb *cb;
21602127

2161-
list_for_each_entry_safe(cb, tmp, &list, list) {
2128+
mutex_lock(&hci_cb_list_lock);
2129+
list_for_each_entry(cb, &hci_cb_list, list) {
21622130
if (cb->role_switch_cfm)
21632131
cb->role_switch_cfm(conn, status, role);
2164-
kfree(cb);
21652132
}
2133+
mutex_unlock(&hci_cb_list_lock);
21662134
}
21672135

21682136
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);
@@ -2994,7 +2995,9 @@ int hci_register_cb(struct hci_cb *cb)
29942995
{
29952996
BT_DBG("%p name %s", cb, cb->name);
29962997

2997-
list_add_tail_rcu(&cb->list, &hci_cb_list);
2998+
mutex_lock(&hci_cb_list_lock);
2999+
list_add_tail(&cb->list, &hci_cb_list);
3000+
mutex_unlock(&hci_cb_list_lock);
29983001

29993002
return 0;
30003003
}
@@ -3004,8 +3007,9 @@ int hci_unregister_cb(struct hci_cb *cb)
30043007
{
30053008
BT_DBG("%p name %s", cb, cb->name);
30063009

3007-
list_del_rcu(&cb->list);
3008-
synchronize_rcu();
3010+
mutex_lock(&hci_cb_list_lock);
3011+
list_del(&cb->list);
3012+
mutex_unlock(&hci_cb_list_lock);
30093013

30103014
return 0;
30113015
}

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
@@ -7230,18 +7230,16 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
72307230
return NULL;
72317231
}
72327232

7233-
static bool l2cap_match(struct hci_conn *hcon)
7234-
{
7235-
return hcon->type == ACL_LINK || hcon->type == LE_LINK;
7236-
}
7237-
72387233
static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
72397234
{
72407235
struct hci_dev *hdev = hcon->hdev;
72417236
struct l2cap_conn *conn;
72427237
struct l2cap_chan *pchan;
72437238
u8 dst_type;
72447239

7240+
if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
7241+
return;
7242+
72457243
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
72467244

72477245
if (status) {
@@ -7306,6 +7304,9 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
73067304

73077305
static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
73087306
{
7307+
if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
7308+
return;
7309+
73097310
BT_DBG("hcon %p reason %d", hcon, reason);
73107311

73117312
l2cap_conn_del(hcon, bt_to_errno(reason));
@@ -7605,7 +7606,6 @@ void l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags)
76057606

76067607
static struct hci_cb l2cap_cb = {
76077608
.name = "L2CAP",
7608-
.match = l2cap_match,
76097609
.connect_cfm = l2cap_connect_cfm,
76107610
.disconn_cfm = l2cap_disconn_cfm,
76117611
.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)