diff options
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/af_bluetooth.c | 7 | ||||
-rw-r--r-- | net/bluetooth/aosp.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 4 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 22 | ||||
-rw-r--r-- | net/bluetooth/hci_sync.c | 14 | ||||
-rw-r--r-- | net/bluetooth/iso.c | 57 | ||||
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 4 | ||||
-rw-r--r-- | net/bluetooth/lib.c | 2 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 10 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 3 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 9 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 4 | ||||
-rw-r--r-- | net/bluetooth/smp.c | 2 |
14 files changed, 89 insertions, 53 deletions
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index ee9bf84c88a7..2b94e2077203 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -364,6 +364,13 @@ int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, put_cmsg(msg, SOL_BLUETOOTH, BT_SCM_PKT_STATUS, sizeof(pkt_status), &pkt_status); } + + if (test_bit(BT_SK_PKT_SEQNUM, &bt_sk(sk)->flags)) { + u16 pkt_seqnum = hci_skb_pkt_seqnum(skb); + + put_cmsg(msg, SOL_BLUETOOTH, BT_SCM_PKT_SEQNUM, + sizeof(pkt_seqnum), &pkt_seqnum); + } } skb_free_datagram(sk, skb); diff --git a/net/bluetooth/aosp.c b/net/bluetooth/aosp.c index 1d67836e95e1..59025771af53 100644 --- a/net/bluetooth/aosp.c +++ b/net/bluetooth/aosp.c @@ -70,7 +70,7 @@ void aosp_do_open(struct hci_dev *hdev) rp = (struct aosp_rp_le_get_vendor_capa *)skb->data; version_supported = le16_to_cpu(rp->version_supported); - /* AOSP displays the verion number like v0.98, v1.00, etc. */ + /* AOSP displays the version number like v0.98, v1.00, etc. */ bt_dev_info(hdev, "AOSP extensions version v%u.%02u", version_supported >> 8, version_supported & 0xff); diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ce17e489c67c..e524bb59bff2 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -813,7 +813,7 @@ static int hci_le_big_terminate(struct hci_dev *hdev, u8 big, struct hci_conn *c * * Detects if there any BIS left connected in a BIG * broadcaster: Remove advertising instance and terminate BIG. - * broadcaster receiver: Teminate BIG sync and terminate PA sync. + * broadcaster receiver: Terminate BIG sync and terminate PA sync. */ static void bis_cleanup(struct hci_conn *conn) { diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 0aa8a591ce42..55e0722fd066 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1256,12 +1256,10 @@ struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, if (addr_type == irk->addr_type && bacmp(bdaddr, &irk->bdaddr) == 0) { irk_to_return = irk; - goto done; + break; } } -done: - if (irk_to_return && hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_IRK, irk_to_return->val)) { bt_dev_warn_ratelimited(hdev, "Identity key blocked for %pMR", diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 2ef5b3004197..fe49e8a7969f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -5758,7 +5758,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, conn->state = BT_CONFIG; /* Store current advertising instance as connection advertising instance - * when sotfware rotation is in use so it can be re-enabled when + * when software rotation is in use so it can be re-enabled when * disconnected. */ if (!ext_adv_capable(hdev)) @@ -6395,8 +6395,8 @@ static int hci_le_pa_term_sync(struct hci_dev *hdev, __le16 handle) return hci_send_cmd(hdev, HCI_OP_LE_PA_TERM_SYNC, sizeof(cp), &cp); } -static void hci_le_pa_sync_estabilished_evt(struct hci_dev *hdev, void *data, - struct sk_buff *skb) +static void hci_le_pa_sync_established_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_ev_le_pa_sync_established *ev = data; int mask = hdev->link_mode; @@ -6726,8 +6726,8 @@ unlock: hci_dev_unlock(hdev); } -static void hci_le_cis_estabilished_evt(struct hci_dev *hdev, void *data, - struct sk_buff *skb) +static void hci_le_cis_established_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_evt_le_cis_established *ev = data; struct hci_conn *conn; @@ -6955,7 +6955,7 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data, static void hci_le_big_sync_established_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_evt_le_big_sync_estabilished *ev = data; + struct hci_evt_le_big_sync_established *ev = data; struct hci_conn *bis, *conn; int i; @@ -7130,7 +7130,7 @@ unlock: /* Entries in this table shall have their position according to the subevent * opcode they handle so the use of the macros above is recommend since it does * attempt to initialize at its proper index using Designated Initializers that - * way events without a callback function can be ommited. + * way events without a callback function can be omitted. */ static const struct hci_le_ev { void (*func)(struct hci_dev *hdev, void *data, struct sk_buff *skb); @@ -7176,7 +7176,7 @@ static const struct hci_le_ev { HCI_MAX_EVENT_SIZE), /* [0x0e = HCI_EV_LE_PA_SYNC_ESTABLISHED] */ HCI_LE_EV(HCI_EV_LE_PA_SYNC_ESTABLISHED, - hci_le_pa_sync_estabilished_evt, + hci_le_pa_sync_established_evt, sizeof(struct hci_ev_le_pa_sync_established)), /* [0x0f = HCI_EV_LE_PER_ADV_REPORT] */ HCI_LE_EV_VL(HCI_EV_LE_PER_ADV_REPORT, @@ -7187,7 +7187,7 @@ static const struct hci_le_ev { HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt, sizeof(struct hci_evt_le_ext_adv_set_term)), /* [0x19 = HCI_EVT_LE_CIS_ESTABLISHED] */ - HCI_LE_EV(HCI_EVT_LE_CIS_ESTABLISHED, hci_le_cis_estabilished_evt, + HCI_LE_EV(HCI_EVT_LE_CIS_ESTABLISHED, hci_le_cis_established_evt, sizeof(struct hci_evt_le_cis_established)), /* [0x1a = HCI_EVT_LE_CIS_REQ] */ HCI_LE_EV(HCI_EVT_LE_CIS_REQ, hci_le_cis_req_evt, @@ -7200,7 +7200,7 @@ static const struct hci_le_ev { /* [0x1d = HCI_EV_LE_BIG_SYNC_ESTABLISHED] */ HCI_LE_EV_VL(HCI_EVT_LE_BIG_SYNC_ESTABLISHED, hci_le_big_sync_established_evt, - sizeof(struct hci_evt_le_big_sync_estabilished), + sizeof(struct hci_evt_le_big_sync_established), HCI_MAX_EVENT_SIZE), /* [0x1e = HCI_EVT_LE_BIG_SYNC_LOST] */ HCI_LE_EV_VL(HCI_EVT_LE_BIG_SYNC_LOST, @@ -7491,7 +7491,7 @@ static const struct hci_ev { /* [0x2c = HCI_EV_SYNC_CONN_COMPLETE] */ HCI_EV(HCI_EV_SYNC_CONN_COMPLETE, hci_sync_conn_complete_evt, sizeof(struct hci_ev_sync_conn_complete)), - /* [0x2d = HCI_EV_EXTENDED_INQUIRY_RESULT] */ + /* [0x2f = HCI_EV_EXTENDED_INQUIRY_RESULT] */ HCI_EV_VL(HCI_EV_EXTENDED_INQUIRY_RESULT, hci_extended_inquiry_result_evt, sizeof(struct hci_ev_ext_inquiry_result), HCI_MAX_EVENT_SIZE), diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index 7ca544d7791f..eefdb6134ca5 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -1325,7 +1325,7 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance) { struct hci_cp_le_set_ext_adv_params cp; struct hci_rp_le_set_ext_adv_params rp; - bool connectable; + bool connectable, require_privacy; u32 flags; bdaddr_t random_addr; u8 own_addr_type; @@ -1363,10 +1363,12 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance) return -EPERM; /* Set require_privacy to true only when non-connectable - * advertising is used. In that case it is fine to use a - * non-resolvable private address. + * advertising is used and it is not periodic. + * In that case it is fine to use a non-resolvable private address. */ - err = hci_get_random_address(hdev, !connectable, + require_privacy = !connectable && !(adv && adv->periodic); + + err = hci_get_random_address(hdev, require_privacy, adv_use_rpa(hdev, flags), adv, &own_addr_type, &random_addr); if (err < 0) @@ -5684,7 +5686,7 @@ int hci_abort_conn_sync(struct hci_dev *hdev, struct hci_conn *conn, u8 reason) } /* Cleanup hci_conn object if it cannot be cancelled as it - * likelly means the controller and host stack are out of sync + * likely means the controller and host stack are out of sync * or in case of LE it was still scanning so it can be cleanup * safely. */ @@ -6123,7 +6125,7 @@ static int hci_update_event_filter_sync(struct hci_dev *hdev) &b->bdaddr, HCI_CONN_SETUP_AUTO_ON); if (err) - bt_dev_dbg(hdev, "Failed to set event filter for %pMR", + bt_dev_err(hdev, "Failed to set event filter for %pMR", &b->bdaddr); else scan = SCAN_PAGE; diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index c21566e1494a..88602f19deca 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -111,6 +111,8 @@ static void iso_conn_free(struct kref *ref) /* Ensure no more work items will run since hci_conn has been dropped */ disable_delayed_work_sync(&conn->timeout_work); + kfree_skb(conn->rx_skb); + kfree(conn); } @@ -413,7 +415,7 @@ static int iso_connect_bis(struct sock *sk) sk->sk_state = BT_CONNECT; } else { sk->sk_state = BT_CONNECT; - iso_sock_set_timer(sk, sk->sk_sndtimeo); + iso_sock_set_timer(sk, READ_ONCE(sk->sk_sndtimeo)); } release_sock(sk); @@ -503,7 +505,7 @@ static int iso_connect_cis(struct sock *sk) sk->sk_state = BT_CONNECT; } else { sk->sk_state = BT_CONNECT; - iso_sock_set_timer(sk, sk->sk_sndtimeo); + iso_sock_set_timer(sk, READ_ONCE(sk->sk_sndtimeo)); } release_sock(sk); @@ -750,6 +752,13 @@ static void iso_sock_kill(struct sock *sk) BT_DBG("sk %p state %d", sk, sk->sk_state); + /* Sock is dead, so set conn->sk to NULL to avoid possible UAF */ + if (iso_pi(sk)->conn) { + iso_conn_lock(iso_pi(sk)->conn); + iso_pi(sk)->conn->sk = NULL; + iso_conn_unlock(iso_pi(sk)->conn); + } + /* Kill poor orphan */ bt_sock_unlink(&iso_sk_list, sk); sock_set_flag(sk, SOCK_DEAD); @@ -1687,6 +1696,17 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, clear_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); break; + case BT_PKT_SEQNUM: + err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen); + if (err) + break; + + if (opt) + set_bit(BT_SK_PKT_SEQNUM, &bt_sk(sk)->flags); + else + clear_bit(BT_SK_PKT_SEQNUM, &bt_sk(sk)->flags); + break; + case BT_ISO_QOS: if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECT2 && @@ -1891,7 +1911,7 @@ static void iso_sock_ready(struct sock *sk) static bool iso_match_big(struct sock *sk, void *data) { - struct hci_evt_le_big_sync_estabilished *ev = data; + struct hci_evt_le_big_sync_established *ev = data; return ev->handle == iso_pi(sk)->qos.bcast.big; } @@ -1912,7 +1932,7 @@ static void iso_conn_ready(struct iso_conn *conn) { struct sock *parent = NULL; struct sock *sk = conn->sk; - struct hci_ev_le_big_sync_estabilished *ev = NULL; + struct hci_ev_le_big_sync_established *ev = NULL; struct hci_ev_le_pa_sync_established *ev2 = NULL; struct hci_ev_le_per_adv_report *ev3 = NULL; struct hci_conn *hcon; @@ -2023,7 +2043,7 @@ static void iso_conn_ready(struct iso_conn *conn) hci_conn_hold(hcon); iso_chan_add(conn, sk, parent); - if ((ev && ((struct hci_evt_le_big_sync_estabilished *)ev)->status) || + if ((ev && ((struct hci_evt_le_big_sync_established *)ev)->status) || (ev2 && ev2->status)) { /* Trigger error signal on child socket */ sk->sk_err = ECONNREFUSED; @@ -2082,7 +2102,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) * proceed to establishing a BIG sync: * * 1. HCI_EV_LE_PA_SYNC_ESTABLISHED: The socket may specify a specific - * SID to listen to and once sync is estabilished its handle needs to + * SID to listen to and once sync is established its handle needs to * be stored in iso_pi(sk)->sync_handle so it can be matched once * receiving the BIG Info. * 2. HCI_EVT_LE_BIG_INFO_ADV_REPORT: When connect_ind is triggered by a @@ -2280,7 +2300,8 @@ static void iso_disconn_cfm(struct hci_conn *hcon, __u8 reason) void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) { struct iso_conn *conn = hcon->iso_data; - __u16 pb, ts, len; + struct skb_shared_hwtstamps *hwts; + __u16 pb, ts, len, sn; if (!conn) goto drop; @@ -2303,13 +2324,17 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) if (ts) { struct hci_iso_ts_data_hdr *hdr; - /* TODO: add timestamp to the packet? */ hdr = skb_pull_data(skb, HCI_ISO_TS_DATA_HDR_SIZE); if (!hdr) { BT_ERR("Frame is too short (len %d)", skb->len); goto drop; } + /* Record the timestamp to skb */ + hwts = skb_hwtstamps(skb); + hwts->hwtstamp = us_to_ktime(le32_to_cpu(hdr->ts)); + + sn = __le16_to_cpu(hdr->sn); len = __le16_to_cpu(hdr->slen); } else { struct hci_iso_data_hdr *hdr; @@ -2320,18 +2345,20 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) goto drop; } + sn = __le16_to_cpu(hdr->sn); len = __le16_to_cpu(hdr->slen); } flags = hci_iso_data_flags(len); len = hci_iso_data_len(len); - BT_DBG("Start: total len %d, frag len %d flags 0x%4.4x", len, - skb->len, flags); + BT_DBG("Start: total len %d, frag len %d flags 0x%4.4x sn %d", + len, skb->len, flags, sn); if (len == skb->len) { /* Complete frame received */ hci_skb_pkt_status(skb) = flags & 0x03; + hci_skb_pkt_seqnum(skb) = sn; iso_recv_frame(conn, skb); return; } @@ -2354,9 +2381,17 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) goto drop; hci_skb_pkt_status(conn->rx_skb) = flags & 0x03; + hci_skb_pkt_seqnum(conn->rx_skb) = sn; skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), skb->len); conn->rx_len = len - skb->len; + + /* Copy hw timestamp from skb to rx_skb if present */ + if (ts) { + hwts = skb_hwtstamps(conn->rx_skb); + hwts->hwtstamp = skb_hwtstamps(skb)->hwtstamp; + } + break; case ISO_CONT: @@ -2381,7 +2416,7 @@ void iso_recv(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), skb->len); conn->rx_len -= skb->len; - return; + break; case ISO_END: skb_copy_from_linear_data(skb, skb_put(conn->rx_skb, skb->len), diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 05b7480970f7..814fb8610ac4 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -255,7 +255,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), &la.l2_bdaddr, la.l2_bdaddr_type, - sk->sk_sndtimeo); + READ_ONCE(sk->sk_sndtimeo)); if (err) return err; @@ -1731,7 +1731,7 @@ static long l2cap_sock_get_sndtimeo_cb(struct l2cap_chan *chan) { struct sock *sk = chan->data; - return sk->sk_sndtimeo; + return READ_ONCE(sk->sk_sndtimeo); } static struct pid *l2cap_sock_get_peer_pid_cb(struct l2cap_chan *chan) diff --git a/net/bluetooth/lib.c b/net/bluetooth/lib.c index 43aa01fd07b9..305044a84478 100644 --- a/net/bluetooth/lib.c +++ b/net/bluetooth/lib.c @@ -54,7 +54,7 @@ EXPORT_SYMBOL(baswap); * bt_to_errno() - Bluetooth error codes to standard errno * @code: Bluetooth error code to be converted * - * This function takes a Bluetooth error code as input and convets + * This function takes a Bluetooth error code as input and converts * it to an equivalent Unix/standard errno value. * * Return: diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 225140fcb3d6..a3d16eece0d2 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4542,13 +4542,11 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev, return -ENOMEM; #ifdef CONFIG_BT_FEATURE_DEBUG - if (!hdev) { - flags = bt_dbg_get() ? BIT(0) : 0; + flags = bt_dbg_get() ? BIT(0) : 0; - memcpy(rp->features[idx].uuid, debug_uuid, 16); - rp->features[idx].flags = cpu_to_le32(flags); - idx++; - } + memcpy(rp->features[idx].uuid, debug_uuid, 16); + rp->features[idx].flags = cpu_to_le32(flags); + idx++; #endif if (hdev && hci_dev_le_state_simultaneous(hdev)) { diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 3b8f39618d65..96250807b32b 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1962,7 +1962,8 @@ static void rfcomm_accept_connection(struct rfcomm_session *s) int err; /* Fast check for a new connection. - * Avoids unnesesary socket allocations. */ + * Avoids unnecessary socket allocations. + */ if (list_empty(&bt_sk(sock->sk)->accept_q)) return; diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 21a5b5535ebc..376ce6de84be 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -438,7 +438,6 @@ static int __rfcomm_release_dev(void __user *arg) { struct rfcomm_dev_req req; struct rfcomm_dev *dev; - struct tty_struct *tty; if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; @@ -464,11 +463,7 @@ static int __rfcomm_release_dev(void __user *arg) rfcomm_dlc_close(dev->dlc, 0); /* Shut down TTY synchronously before freeing rfcomm_dev */ - tty = tty_port_tty_get(&dev->port); - if (tty) { - tty_vhangup(tty); - tty_kref_put(tty); - } + tty_port_tty_vhangup(&dev->port); if (!test_bit(RFCOMM_TTY_OWNED, &dev->status)) tty_port_put(&dev->port); @@ -980,7 +975,7 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, baud = RFCOMM_RPN_BR_230400; break; default: - /* 9600 is standard accordinag to the RFCOMM specification */ + /* 9600 is standard according to the RFCOMM specification */ baud = RFCOMM_RPN_BR_9600; break; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 2945d27e75dc..d382d980fd9a 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -338,7 +338,7 @@ static int sco_connect(struct sock *sk) hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst, sco_pi(sk)->setting, &sco_pi(sk)->codec, - sk->sk_sndtimeo); + READ_ONCE(sk->sk_sndtimeo)); if (IS_ERR(hcon)) { err = PTR_ERR(hcon); goto unlock; @@ -367,7 +367,7 @@ static int sco_connect(struct sock *sk) sk->sk_state = BT_CONNECTED; } else { sk->sk_state = BT_CONNECT; - sco_sock_set_timer(sk, sk->sk_sndtimeo); + sco_sock_set_timer(sk, READ_ONCE(sk->sk_sndtimeo)); } release_sock(sk); diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 8115d42fc15b..45512b2ba951 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -3189,7 +3189,7 @@ static void smp_ready_cb(struct l2cap_chan *chan) /* No need to call l2cap_chan_hold() here since we already own * the reference taken in smp_new_conn_cb(). This is just the * first time that we tie it to a specific pointer. The code in - * l2cap_core.c ensures that there's no risk this function wont + * l2cap_core.c ensures that there's no risk this function won't * get called if smp_new_conn_cb was previously called. */ conn->smp = chan; |