Skip to content
Permalink
Browse files
Bluetooth: hci_sock: Fix calling lock_sock when handling HCI_DEV_UNREG
This removes the reference of hci_dev to hci_pinfo since the reference
cannot prevent hdev to be freed hci_pinfo only keeps the index so in
case the device is unregistered and freed hci_dev_get will return NULL
thus prevent UAF.

On top of it commands cases where copy_from_user needs to be used are
now done without helding a reference to the hci_dev.

Link: https://syzkaller.appspot.com/bug?extid=a5df189917e79d5e59c9 [1]
Reported-by: syzbot <syzbot+a5df189917e79d5e59c9@syzkaller.appspotmail.com>
Tested-by: syzbot <syzbot+a5df189917e79d5e59c9@syzkaller.appspotmail.com>
Fixes: e305509 ("Bluetooth: use correct lock to prevent UAF of hdev object")
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  • Loading branch information
Vudentz authored and intel-lab-lkp committed Jul 18, 2021
1 parent 3c755b4 commit a02b154e687ba3e82afdd263f84570b1ca185a8a
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 55 deletions.
@@ -1261,8 +1261,10 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg);
int hci_get_dev_list(void __user *arg);
int hci_get_dev_info(void __user *arg);
int hci_get_conn_list(void __user *arg);
int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
int hci_get_conn_info(struct hci_dev *hdev, void __user *arg,
struct hci_conn_info_req *req);
int hci_get_auth_info(struct hci_dev *hdev, void __user *arg,
struct hci_auth_info_req *req);
int hci_inquiry(void __user *arg);

struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *list,
@@ -1701,18 +1701,15 @@ int hci_get_conn_list(void __user *arg)
return err ? -EFAULT : 0;
}

int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
int hci_get_conn_info(struct hci_dev *hdev, void __user *arg,
struct hci_conn_info_req *req)
{
struct hci_conn_info_req req;
struct hci_conn_info ci;
struct hci_conn *conn;
char __user *ptr = arg + sizeof(req);

if (copy_from_user(&req, arg, sizeof(req)))
return -EFAULT;
char __user *ptr = (char *)arg + sizeof(*req);

hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr);
conn = hci_conn_hash_lookup_ba(hdev, req->type, &req->bdaddr);
if (conn) {
bacpy(&ci.bdaddr, &conn->dst);
ci.handle = conn->handle;
@@ -1729,24 +1726,21 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg)
return copy_to_user(ptr, &ci, sizeof(ci)) ? -EFAULT : 0;
}

int hci_get_auth_info(struct hci_dev *hdev, void __user *arg)
int hci_get_auth_info(struct hci_dev *hdev, void __user *arg,
struct hci_auth_info_req *req)
{
struct hci_auth_info_req req;
struct hci_conn *conn;

if (copy_from_user(&req, arg, sizeof(req)))
return -EFAULT;

hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req->bdaddr);
if (conn)
req.type = conn->auth_type;
req->type = conn->auth_type;
hci_dev_unlock(hdev);

if (!conn)
return -ENOENT;

return copy_to_user(arg, &req, sizeof(req)) ? -EFAULT : 0;
return copy_to_user(arg, req, sizeof(*req)) ? -EFAULT : 0;
}

struct hci_chan *hci_chan_create(struct hci_conn *conn)

0 comments on commit a02b154

Please sign in to comment.