Skip to content

Commit b08efff

Browse files
committed
Merge: CVE-2024-49951: Bluetooth: MGMT: Fix possible crash on mgmt_index_removed
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/5621 JIRA: https://issues.redhat.com/browse/RHEL-64476 CVE: CVE-2024-49951 Depends: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/5549 ``` Bluetooth: MGMT: Fix possible crash on mgmt_index_removed If mgmt_index_removed is called while there are commands queued on cmd_sync it could lead to crashes like the bellow trace: 0x0000053D: __list_del_entry_valid_or_report+0x98/0xdc 0x0000053D: mgmt_pending_remove+0x18/0x58 [bluetooth] 0x0000053E: mgmt_remove_adv_monitor_complete+0x80/0x108 [bluetooth] 0x0000053E: hci_cmd_sync_work+0xbc/0x164 [bluetooth] So while handling mgmt_index_removed this attempts to dequeue commands passed as user_data to cmd_sync. Fixes: 7cf5c29 ("Bluetooth: hci_sync: Refactor remove Adv Monitor") Reported-by: jiaymao <quic_jiaymao@quicinc.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> (cherry picked from commit f53e1c9) ``` Signed-off-by: CKI Backport Bot <cki-ci-bot+cki-gitlab-backport-bot@redhat.com> Signed-off-by: Bastien Nocera <bnocera@redhat.com> --- <small>Created 2024-10-29 15:48 UTC by backporter - [KWF FAQ](https://red.ht/kernel_workflow_doc) - [Slack #team-kernel-workflow](https://redhat-internal.slack.com/archives/C04LRUPMJQ5) - [Source](https://gitlab.com/cki-project/kernel-workflow/-/blob/main/webhook/utils/backporter.py) - [Documentation](https://gitlab.com/cki-project/kernel-workflow/-/blob/main/docs/README.backporter.md) - [Report an issue](https://gitlab.com/cki-project/kernel-workflow/-/issues/new?issue%5Btitle%5D=backporter%20webhook%20issue)</small> Approved-by: Bastien Nocera <bnocera@redhat.com> Approved-by: Lenny Szubowicz <lszubowi@redhat.com> Approved-by: David Marlin <dmarlin@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Rado Vrbovsky <rvrbovsk@redhat.com>
2 parents 249750f + 67b3d90 commit b08efff

File tree

1 file changed

+32
-18
lines changed

1 file changed

+32
-18
lines changed

net/bluetooth/mgmt.c

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1446,10 +1446,15 @@ static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
14461446

14471447
static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
14481448
{
1449-
if (cmd->cmd_complete) {
1450-
u8 *status = data;
1449+
struct cmd_lookup *match = data;
1450+
1451+
/* dequeue cmd_sync entries using cmd as data as that is about to be
1452+
* removed/freed.
1453+
*/
1454+
hci_cmd_sync_dequeue(match->hdev, NULL, cmd, NULL);
14511455

1452-
cmd->cmd_complete(cmd, *status);
1456+
if (cmd->cmd_complete) {
1457+
cmd->cmd_complete(cmd, match->mgmt_status);
14531458
mgmt_pending_remove(cmd);
14541459

14551460
return;
@@ -1498,7 +1503,8 @@ static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data,
14981503
bt_dev_dbg(hdev, "err %d", err);
14991504

15001505
/* Make sure cmd still outstanding. */
1501-
if (cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
1506+
if (err == -ECANCELED ||
1507+
cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
15021508
return;
15031509

15041510
hci_dev_lock(hdev);
@@ -1672,7 +1678,8 @@ static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data,
16721678
bt_dev_dbg(hdev, "err %d", err);
16731679

16741680
/* Make sure cmd still outstanding. */
1675-
if (cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
1681+
if (err == -ECANCELED ||
1682+
cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
16761683
return;
16771684

16781685
hci_dev_lock(hdev);
@@ -1905,7 +1912,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
19051912
bool changed;
19061913

19071914
/* Make sure cmd still outstanding. */
1908-
if (cmd != pending_find(MGMT_OP_SET_SSP, hdev))
1915+
if (err == -ECANCELED || cmd != pending_find(MGMT_OP_SET_SSP, hdev))
19091916
return;
19101917

19111918
if (err) {
@@ -3751,7 +3758,8 @@ static void set_name_complete(struct hci_dev *hdev, void *data, int err)
37513758

37523759
bt_dev_dbg(hdev, "err %d", err);
37533760

3754-
if (cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev))
3761+
if (err == -ECANCELED ||
3762+
cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev))
37553763
return;
37563764

37573765
if (status) {
@@ -3926,7 +3934,8 @@ static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err)
39263934
struct sk_buff *skb = cmd->skb;
39273935
u8 status = mgmt_status(err);
39283936

3929-
if (cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev))
3937+
if (err == -ECANCELED ||
3938+
cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev))
39303939
return;
39313940

39323941
if (!status) {
@@ -5817,13 +5826,16 @@ static void start_discovery_complete(struct hci_dev *hdev, void *data, int err)
58175826
{
58185827
struct mgmt_pending_cmd *cmd = data;
58195828

5829+
bt_dev_dbg(hdev, "err %d", err);
5830+
5831+
if (err == -ECANCELED)
5832+
return;
5833+
58205834
if (cmd != pending_find(MGMT_OP_START_DISCOVERY, hdev) &&
58215835
cmd != pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev) &&
58225836
cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev))
58235837
return;
58245838

5825-
bt_dev_dbg(hdev, "err %d", err);
5826-
58275839
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err),
58285840
cmd->param, 1);
58295841
mgmt_pending_remove(cmd);
@@ -6056,7 +6068,8 @@ static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err)
60566068
{
60576069
struct mgmt_pending_cmd *cmd = data;
60586070

6059-
if (cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev))
6071+
if (err == -ECANCELED ||
6072+
cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev))
60606073
return;
60616074

60626075
bt_dev_dbg(hdev, "err %d", err);
@@ -8015,7 +8028,8 @@ static void read_local_oob_ext_data_complete(struct hci_dev *hdev, void *data,
80158028
u8 status = mgmt_status(err);
80168029
u16 eir_len;
80178030

8018-
if (cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev))
8031+
if (err == -ECANCELED ||
8032+
cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev))
80198033
return;
80208034

80218035
if (!status) {
@@ -9337,12 +9351,12 @@ void mgmt_index_added(struct hci_dev *hdev)
93379351
void mgmt_index_removed(struct hci_dev *hdev)
93389352
{
93399353
struct mgmt_ev_ext_index ev;
9340-
u8 status = MGMT_STATUS_INVALID_INDEX;
9354+
struct cmd_lookup match = { NULL, hdev, MGMT_STATUS_INVALID_INDEX };
93419355

93429356
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
93439357
return;
93449358

9345-
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
9359+
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match);
93469360

93479361
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
93489362
mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0,
@@ -9393,7 +9407,7 @@ void mgmt_power_on(struct hci_dev *hdev, int err)
93939407
void __mgmt_power_off(struct hci_dev *hdev)
93949408
{
93959409
struct cmd_lookup match = { NULL, hdev };
9396-
u8 status, zero_cod[] = { 0, 0, 0 };
9410+
u8 zero_cod[] = { 0, 0, 0 };
93979411

93989412
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
93999413

@@ -9405,11 +9419,11 @@ void __mgmt_power_off(struct hci_dev *hdev)
94059419
* status responses.
94069420
*/
94079421
if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
9408-
status = MGMT_STATUS_INVALID_INDEX;
9422+
match.mgmt_status = MGMT_STATUS_INVALID_INDEX;
94099423
else
9410-
status = MGMT_STATUS_NOT_POWERED;
9424+
match.mgmt_status = MGMT_STATUS_NOT_POWERED;
94119425

9412-
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
9426+
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &match);
94139427

94149428
if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) {
94159429
mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,

0 commit comments

Comments
 (0)