Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PW_SID:920373] [v2] Bluetooth: btusb: Add NULL check for data in btusb_suspend #2631

Open
wants to merge 18 commits into
base: workflow
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
4f562be
Bluetooth: MGMT: Fix slab-use-after-free Read in set_powered_sync
Vudentz Nov 15, 2024
4ae007f
Bluetooth: MGMT: Fix possible deadlocks
Vudentz Nov 21, 2024
ad0d88d
Bluetooth: SCO: remove the redundant sco_conn_put
ea1davis Nov 25, 2024
389eeaf
Bluetooth: Improve setsockopt() handling of malformed user input
mmhal Nov 19, 2024
47ebf09
Bluetooth: iso: Allow BIG re-sync
iulia-tanasescu Nov 28, 2024
20c9afd
Bluetooth: hci_core: Fix sleeping function called from invalid context
Vudentz Dec 3, 2024
042ca30
Bluetooth: hci_event: Fix using rcu_read_(un)lock while iterating
Vudentz Dec 4, 2024
869f46e
Bluetooth: iso: Always release hdev at the end of iso_listen_bis
iulia-tanasescu Dec 4, 2024
269f7b2
Bluetooth: iso: Fix recursive locking warning
iulia-tanasescu Dec 4, 2024
fd5bbbc
Bluetooth: SCO: Add support for 16 bits transparent voice setting
fdanis-oss Dec 5, 2024
c9f33b7
Bluetooth: iso: Fix circular lock in iso_listen_bis
iulia-tanasescu Dec 9, 2024
ea4f877
Bluetooth: iso: Fix circular lock in iso_conn_big_sync
iulia-tanasescu Dec 9, 2024
845b4c6
Bluetooth: btmtk: avoid UAF in btmtk_process_coredump
Dec 10, 2024
e8e5b05
Bluetooth: hci_sync: Fix not setting Random Address when required
Vudentz Nov 25, 2024
fcd17fe
Bluetooth: MGMT: Fix Add Device to responding before completing
Vudentz Nov 25, 2024
514e14b
Bluetooth: MGMT: Mark LL Privacy as stable
Vudentz Nov 25, 2024
710fda9
workflow: Add workflow files for ci
tedd-an Nov 5, 2020
99aacc7
Bluetooth: btusb: Add NULL check for data in btusb_suspend
rickywu0421 Dec 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: CI

on: [pull_request]

jobs:
ci:
runs-on: ubuntu-latest
name: CI for Pull Request
steps:
- name: Checkout the source code
uses: actions/checkout@v3
with:
path: src/src

- name: CI
uses: tedd-an/bzcafe@main
with:
task: ci
base_folder: src
space: kernel
github_token: ${{ secrets.GITHUB_TOKEN }}
email_token: ${{ secrets.EMAIL_TOKEN }}
patchwork_token: ${{ secrets.PATCHWORK_TOKEN }}
patchwork_user: ${{ secrets.PATCHWORK_USER }}

43 changes: 43 additions & 0 deletions .github/workflows/sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Sync

on:
schedule:
- cron: "*/30 * * * *"

jobs:
sync_repo:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: master

- name: Sync Repo
uses: tedd-an/bzcafe@main
with:
task: sync
upstream_repo: 'https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git'
github_token: ${{ secrets.GITHUB_TOKEN }}

- name: Cleanup PR
uses: tedd-an/bzcafe@main
with:
task: cleanup
github_token: ${{ secrets.ACTION_TOKEN }}

sync_patchwork:
needs: sync_repo
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3

- name: Sync Patchwork
uses: tedd-an/bzcafe@main
with:
task: patchwork
space: kernel
github_token: ${{ secrets.ACTION_TOKEN }}
email_token: ${{ secrets.EMAIL_TOKEN }}
patchwork_token: ${{ secrets.PATCHWORK_TOKEN }}
patchwork_user: ${{ secrets.PATCHWORK_USER }}

20 changes: 12 additions & 8 deletions drivers/bluetooth/btmtk.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btmtk_data *data = hci_get_priv(hdev);
int err;
bool complete = false;

if (!IS_ENABLED(CONFIG_DEV_COREDUMP)) {
kfree_skb(skb);
Expand All @@ -416,19 +417,22 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
fallthrough;
case HCI_DEVCOREDUMP_ACTIVE:
default:
/* Mediatek coredump data would be more than MTK_COREDUMP_NUM */
if (data->cd_info.cnt >= MTK_COREDUMP_NUM &&
skb->len > MTK_COREDUMP_END_LEN)
if (!memcmp((char *)&skb->data[skb->len - MTK_COREDUMP_END_LEN],
MTK_COREDUMP_END, MTK_COREDUMP_END_LEN - 1))
complete = true;

err = hci_devcd_append(hdev, skb);
if (err < 0)
break;
data->cd_info.cnt++;

/* Mediatek coredump data would be more than MTK_COREDUMP_NUM */
if (data->cd_info.cnt > MTK_COREDUMP_NUM &&
skb->len > MTK_COREDUMP_END_LEN)
if (!memcmp((char *)&skb->data[skb->len - MTK_COREDUMP_END_LEN],
MTK_COREDUMP_END, MTK_COREDUMP_END_LEN - 1)) {
bt_dev_info(hdev, "Mediatek coredump end");
hci_devcd_complete(hdev);
}
if (complete) {
bt_dev_info(hdev, "Mediatek coredump end");
hci_devcd_complete(hdev);
}

break;
}
Expand Down
3 changes: 3 additions & 0 deletions drivers/bluetooth/btusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -4096,6 +4096,9 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)

BT_DBG("intf %p", intf);

if (!data)
return -ENODEV;

/* Don't auto-suspend if there are connections; external suspend calls
* shall never fail.
*/
Expand Down
10 changes: 1 addition & 9 deletions include/net/bluetooth/bluetooth.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ struct bt_voice {

#define BT_VOICE_TRANSPARENT 0x0003
#define BT_VOICE_CVSD_16BIT 0x0060
#define BT_VOICE_TRANSPARENT_16BIT 0x0063

#define BT_SNDMTU 12
#define BT_RCVMTU 13
Expand Down Expand Up @@ -590,15 +591,6 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
return skb;
}

static inline int bt_copy_from_sockptr(void *dst, size_t dst_size,
sockptr_t src, size_t src_size)
{
if (dst_size > src_size)
return -EINVAL;

return copy_from_sockptr(dst, src, dst_size);
}

int bt_to_errno(u16 code);
__u8 bt_status(int err);

Expand Down
1 change: 0 additions & 1 deletion include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,6 @@ enum {
HCI_FORCE_BREDR_SMP,
HCI_FORCE_STATIC_ADDR,
HCI_LL_RPA_RESOLUTION,
HCI_ENABLE_LL_PRIVACY,
HCI_CMD_PENDING,
HCI_FORCE_NO_MITM,
HCI_QUALITY_REPORT,
Expand Down
119 changes: 74 additions & 45 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,9 @@ struct bdaddr_list_with_irk {

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

Expand Down Expand Up @@ -804,7 +805,6 @@ struct hci_conn_params {
extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list;
extern rwlock_t hci_dev_list_lock;
extern struct mutex hci_cb_list_lock;

#define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags)
#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags)
Expand Down Expand Up @@ -1920,11 +1920,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn);

#define ll_privacy_capable(dev) ((dev)->le_features[0] & HCI_LE_LL_PRIVACY)

/* Use LL Privacy based address resolution if supported */
#define use_ll_privacy(dev) (ll_privacy_capable(dev) && \
hci_dev_test_flag(dev, HCI_ENABLE_LL_PRIVACY))

#define privacy_mode_capable(dev) (use_ll_privacy(dev) && \
#define privacy_mode_capable(dev) (ll_privacy_capable(dev) && \
(hdev->commands[39] & 0x04))

#define read_key_size_capable(dev) \
Expand Down Expand Up @@ -2017,68 +2013,103 @@ struct hci_cb {

char *name;

bool (*match) (struct hci_conn *conn);
void (*connect_cfm) (struct hci_conn *conn, __u8 status);
void (*disconn_cfm) (struct hci_conn *conn, __u8 status);
void (*security_cfm) (struct hci_conn *conn, __u8 status,
__u8 encrypt);
__u8 encrypt);
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
};

static inline void hci_cb_lookup(struct hci_conn *conn, struct list_head *list)
{
struct hci_cb *cb, *cpy;

rcu_read_lock();
list_for_each_entry_rcu(cb, &hci_cb_list, list) {
if (cb->match && cb->match(conn)) {
cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC);
if (!cpy)
break;

*cpy = *cb;
INIT_LIST_HEAD(&cpy->list);
list_add_rcu(&cpy->list, list);
}
}
rcu_read_unlock();
}

static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
{
struct hci_cb *cb;
struct list_head list;
struct hci_cb *cb, *tmp;

INIT_LIST_HEAD(&list);
hci_cb_lookup(conn, &list);

mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->connect_cfm)
cb->connect_cfm(conn, status);
kfree(cb);
}
mutex_unlock(&hci_cb_list_lock);

if (conn->connect_cfm_cb)
conn->connect_cfm_cb(conn, status);
}

static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason)
{
struct hci_cb *cb;
struct list_head list;
struct hci_cb *cb, *tmp;

INIT_LIST_HEAD(&list);
hci_cb_lookup(conn, &list);

mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->disconn_cfm)
cb->disconn_cfm(conn, reason);
kfree(cb);
}
mutex_unlock(&hci_cb_list_lock);

if (conn->disconn_cfm_cb)
conn->disconn_cfm_cb(conn, reason);
}

static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
static inline void hci_security_cfm(struct hci_conn *conn, __u8 status,
__u8 encrypt)
{
struct hci_cb *cb;
__u8 encrypt;

if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
return;
struct list_head list;
struct hci_cb *cb, *tmp;

encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00;
INIT_LIST_HEAD(&list);
hci_cb_lookup(conn, &list);

mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
kfree(cb);
}
mutex_unlock(&hci_cb_list_lock);

if (conn->security_cfm_cb)
conn->security_cfm_cb(conn, status);
}

static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
{
__u8 encrypt;

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

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

hci_security_cfm(conn, status, encrypt);
}

static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
{
struct hci_cb *cb;
__u8 encrypt;

if (conn->state == BT_CONFIG) {
Expand All @@ -2105,40 +2136,38 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
conn->sec_level = conn->pending_sec_level;
}

mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
}
mutex_unlock(&hci_cb_list_lock);

if (conn->security_cfm_cb)
conn->security_cfm_cb(conn, status);
hci_security_cfm(conn, status, encrypt);
}

static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
{
struct hci_cb *cb;
struct list_head list;
struct hci_cb *cb, *tmp;

INIT_LIST_HEAD(&list);
hci_cb_lookup(conn, &list);

mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->key_change_cfm)
cb->key_change_cfm(conn, status);
kfree(cb);
}
mutex_unlock(&hci_cb_list_lock);
}

static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
__u8 role)
{
struct hci_cb *cb;
struct list_head list;
struct hci_cb *cb, *tmp;

INIT_LIST_HEAD(&list);
hci_cb_lookup(conn, &list);

mutex_lock(&hci_cb_list_lock);
list_for_each_entry(cb, &hci_cb_list, list) {
list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->role_switch_cfm)
cb->role_switch_cfm(conn, status, role);
kfree(cb);
}
mutex_unlock(&hci_cb_list_lock);
}

static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)
Expand Down
9 changes: 3 additions & 6 deletions net/bluetooth/hci_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2993,9 +2993,7 @@ int hci_register_cb(struct hci_cb *cb)
{
BT_DBG("%p name %s", cb, cb->name);

mutex_lock(&hci_cb_list_lock);
list_add_tail(&cb->list, &hci_cb_list);
mutex_unlock(&hci_cb_list_lock);
list_add_tail_rcu(&cb->list, &hci_cb_list);

return 0;
}
Expand All @@ -3005,9 +3003,8 @@ int hci_unregister_cb(struct hci_cb *cb)
{
BT_DBG("%p name %s", cb, cb->name);

mutex_lock(&hci_cb_list_lock);
list_del(&cb->list);
mutex_unlock(&hci_cb_list_lock);
list_del_rcu(&cb->list);
synchronize_rcu();

return 0;
}
Expand Down
Loading
Loading