diff options
author | John W. Linville <linville@tuxdriver.com> | 2010-12-06 15:35:34 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-12-06 15:35:34 -0500 |
commit | f435d9eea01309aa7b6c1f134569a7b5957918ae (patch) | |
tree | 2737a48d423a8191671098b15aabd6391af2d23a /net/bluetooth | |
parent | 5ee493767352314893520ac40aec5bb07d0147e0 (diff) | |
parent | 09f921f83faa49cdea25abfb98c439c01526b89d (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Diffstat (limited to 'net/bluetooth')
-rw-r--r-- | net/bluetooth/bnep/core.c | 1 | ||||
-rw-r--r-- | net/bluetooth/cmtp/core.c | 1 | ||||
-rw-r--r-- | net/bluetooth/hci_conn.c | 23 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 66 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 177 | ||||
-rw-r--r-- | net/bluetooth/hci_sock.c | 17 | ||||
-rw-r--r-- | net/bluetooth/hidp/core.c | 2 | ||||
-rw-r--r-- | net/bluetooth/l2cap.c | 94 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/core.c | 8 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/sock.c | 24 | ||||
-rw-r--r-- | net/bluetooth/rfcomm/tty.c | 28 | ||||
-rw-r--r-- | net/bluetooth/sco.c | 28 |
12 files changed, 305 insertions, 164 deletions
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index f10b41fb05a0..5868597534e5 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -648,6 +648,7 @@ int bnep_del_connection(struct bnep_conndel_req *req) static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s) { + memset(ci, 0, sizeof(*ci)); memcpy(ci->dst, s->eh.h_source, ETH_ALEN); strcpy(ci->device, s->dev->name); ci->flags = s->flags; diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index ec0a1347f933..8e5f292529ac 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -78,6 +78,7 @@ static void __cmtp_unlink_session(struct cmtp_session *session) static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci) { + memset(ci, 0, sizeof(*ci)); bacpy(&ci->bdaddr, &session->bdaddr); ci->flags = session->flags; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 0b1e460fe440..6b90a4191734 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -39,7 +39,7 @@ #include <net/sock.h> #include <asm/system.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> @@ -66,7 +66,8 @@ void hci_acl_connect(struct hci_conn *conn) bacpy(&cp.bdaddr, &conn->dst); cp.pscan_rep_mode = 0x02; - if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { + ie = hci_inquiry_cache_lookup(hdev, &conn->dst); + if (ie) { if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) { cp.pscan_rep_mode = ie->data.pscan_rep_mode; cp.pscan_mode = ie->data.pscan_mode; @@ -368,8 +369,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 BT_DBG("%s dst %s", hdev->name, batostr(dst)); - if (!(acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst))) { - if (!(acl = hci_conn_add(hdev, ACL_LINK, dst))) + acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); + if (!acl) { + acl = hci_conn_add(hdev, ACL_LINK, dst); + if (!acl) return NULL; } @@ -389,8 +392,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 if (type == ACL_LINK) return acl; - if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) { - if (!(sco = hci_conn_add(hdev, type, dst))) { + sco = hci_conn_hash_lookup_ba(hdev, type, dst); + if (!sco) { + sco = hci_conn_add(hdev, type, dst); + if (!sco) { hci_conn_put(acl); return NULL; } @@ -647,10 +652,12 @@ int hci_get_conn_list(void __user *arg) size = sizeof(req) + req.conn_num * sizeof(*ci); - if (!(cl = kmalloc(size, GFP_KERNEL))) + cl = kmalloc(size, GFP_KERNEL); + if (!cl) return -ENOMEM; - if (!(hdev = hci_dev_get(req.dev_id))) { + hdev = hci_dev_get(req.dev_id); + if (!hdev) { kfree(cl); return -ENODEV; } diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index bc2a052e518b..51c61f75a797 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -44,7 +44,7 @@ #include <net/sock.h> #include <asm/system.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> @@ -349,20 +349,23 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *b void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data) { struct inquiry_cache *cache = &hdev->inq_cache; - struct inquiry_entry *e; + struct inquiry_entry *ie; BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr)); - if (!(e = hci_inquiry_cache_lookup(hdev, &data->bdaddr))) { + ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr); + if (!ie) { /* Entry not in the cache. Add new one. */ - if (!(e = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC))) + ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC); + if (!ie) return; - e->next = cache->list; - cache->list = e; + + ie->next = cache->list; + cache->list = ie; } - memcpy(&e->data, data, sizeof(*data)); - e->timestamp = jiffies; + memcpy(&ie->data, data, sizeof(*data)); + ie->timestamp = jiffies; cache->timestamp = jiffies; } @@ -422,16 +425,20 @@ int hci_inquiry(void __user *arg) hci_dev_lock_bh(hdev); if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || - inquiry_cache_empty(hdev) || - ir.flags & IREQ_CACHE_FLUSH) { + inquiry_cache_empty(hdev) || + ir.flags & IREQ_CACHE_FLUSH) { inquiry_cache_flush(hdev); do_inquiry = 1; } hci_dev_unlock_bh(hdev); timeo = ir.length * msecs_to_jiffies(2000); - if (do_inquiry && (err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo)) < 0) - goto done; + + if (do_inquiry) { + err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo); + if (err < 0) + goto done; + } /* for unlimited number of responses we will use buffer with 255 entries */ max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp; @@ -439,7 +446,8 @@ int hci_inquiry(void __user *arg) /* cache_dump can't sleep. Therefore we allocate temp buffer and then * copy it to the user space. */ - if (!(buf = kmalloc(sizeof(struct inquiry_info) * max_rsp, GFP_KERNEL))) { + buf = kmalloc(sizeof(struct inquiry_info) *max_rsp, GFP_KERNEL); + if (!buf) { err = -ENOMEM; goto done; } @@ -611,7 +619,8 @@ int hci_dev_close(__u16 dev) struct hci_dev *hdev; int err; - if (!(hdev = hci_dev_get(dev))) + hdev = hci_dev_get(dev); + if (!hdev) return -ENODEV; err = hci_dev_do_close(hdev); hci_dev_put(hdev); @@ -623,7 +632,8 @@ int hci_dev_reset(__u16 dev) struct hci_dev *hdev; int ret = 0; - if (!(hdev = hci_dev_get(dev))) + hdev = hci_dev_get(dev); + if (!hdev) return -ENODEV; hci_req_lock(hdev); @@ -663,7 +673,8 @@ int hci_dev_reset_stat(__u16 dev) struct hci_dev *hdev; int ret = 0; - if (!(hdev = hci_dev_get(dev))) + hdev = hci_dev_get(dev); + if (!hdev) return -ENODEV; memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); @@ -682,7 +693,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) if (copy_from_user(&dr, arg, sizeof(dr))) return -EFAULT; - if (!(hdev = hci_dev_get(dr.dev_id))) + hdev = hci_dev_get(dr.dev_id); + if (!hdev) return -ENODEV; switch (cmd) { @@ -763,7 +775,8 @@ int hci_get_dev_list(void __user *arg) size = sizeof(*dl) + dev_num * sizeof(*dr); - if (!(dl = kzalloc(size, GFP_KERNEL))) + dl = kzalloc(size, GFP_KERNEL); + if (!dl) return -ENOMEM; dr = dl->dev_req; @@ -797,7 +810,8 @@ int hci_get_dev_info(void __user *arg) if (copy_from_user(&di, arg, sizeof(di))) return -EFAULT; - if (!(hdev = hci_dev_get(di.dev_id))) + hdev = hci_dev_get(di.dev_id); + if (!hdev) return -ENODEV; strcpy(di.name, hdev->name); @@ -905,7 +919,7 @@ int hci_register_dev(struct hci_dev *hdev) hdev->sniff_max_interval = 800; hdev->sniff_min_interval = 80; - tasklet_init(&hdev->cmd_task, hci_cmd_task,(unsigned long) hdev); + tasklet_init(&hdev->cmd_task, hci_cmd_task, (unsigned long) hdev); tasklet_init(&hdev->rx_task, hci_rx_task, (unsigned long) hdev); tasklet_init(&hdev->tx_task, hci_tx_task, (unsigned long) hdev); @@ -1368,7 +1382,8 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; hci_add_acl_hdr(skb, conn->handle, flags | ACL_START); - if (!(list = skb_shinfo(skb)->frag_list)) { + list = skb_shinfo(skb)->frag_list; + if (!list) { /* Non fragmented */ BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len); @@ -1609,7 +1624,8 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_conn_enter_active_mode(conn); /* Send to upper protocol */ - if ((hp = hci_proto[HCI_PROTO_L2CAP]) && hp->recv_acldata) { + hp = hci_proto[HCI_PROTO_L2CAP]; + if (hp && hp->recv_acldata) { hp->recv_acldata(conn, skb, flags); return; } @@ -1644,7 +1660,8 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) register struct hci_proto *hp; /* Send to upper protocol */ - if ((hp = hci_proto[HCI_PROTO_SCO]) && hp->recv_scodata) { + hp = hci_proto[HCI_PROTO_SCO]; + if (hp && hp->recv_scodata) { hp->recv_scodata(conn, skb); return; } @@ -1727,7 +1744,8 @@ static void hci_cmd_task(unsigned long arg) if (atomic_read(&hdev->cmd_cnt) && (skb = skb_dequeue(&hdev->cmd_q))) { kfree_skb(hdev->sent_cmd); - if ((hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC))) { + hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC); + if (hdev->sent_cmd) { atomic_dec(&hdev->cmd_cnt); hci_send_frame(skb); hdev->cmd_last_tx = jiffies; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 84093b0000b9..8923b36a67a2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -39,7 +39,7 @@ #include <net/sock.h> #include <asm/system.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> @@ -677,9 +677,50 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) hci_dev_unlock(hdev); } +static int hci_outgoing_auth_needed(struct hci_dev *hdev, + struct hci_conn *conn) +{ + if (conn->state != BT_CONFIG || !conn->out) + return 0; + + if (conn->sec_level == BT_SECURITY_SDP) + return 0; + + /* Only request authentication for SSP connections or non-SSP + * devices with sec_level HIGH */ + if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && + conn->sec_level != BT_SECURITY_HIGH) + return 0; + + return 1; +} + static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) { + struct hci_cp_remote_name_req *cp; + struct hci_conn *conn; + BT_DBG("%s status 0x%x", hdev->name, status); + + /* If successful wait for the name req complete event before + * checking for the need to do authentication */ + if (!status) + return; + + cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); + if (!cp) + return; + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); + if (conn && hci_outgoing_auth_needed(hdev, conn)) { + struct hci_cp_auth_requested cp; + cp.handle = __cpu_to_le16(conn->handle); + hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); + } + + hci_dev_unlock(hdev); } static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) @@ -955,12 +996,14 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk hci_dev_lock(hdev); - if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) + ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); + if (ie) memcpy(ie->data.dev_class, ev->dev_class, 3); conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); if (!conn) { - if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) { + conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); + if (!conn) { BT_ERR("No memory for new connection"); hci_dev_unlock(hdev); return; @@ -1090,9 +1133,23 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) { + struct hci_ev_remote_name *ev = (void *) skb->data; + struct hci_conn *conn; + BT_DBG("%s", hdev->name); hci_conn_check_pending(hdev); + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (conn && hci_outgoing_auth_needed(hdev, conn)) { + struct hci_cp_auth_requested cp; + cp.handle = __cpu_to_le16(conn->handle); + hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); + } + + hci_dev_unlock(hdev); } static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) @@ -1162,33 +1219,39 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); - if (conn) { - if (!ev->status) - memcpy(conn->features, ev->features, 8); + if (!conn) + goto unlock; - if (conn->state == BT_CONFIG) { - if (!ev->status && lmp_ssp_capable(hdev) && - lmp_ssp_capable(conn)) { - struct hci_cp_read_remote_ext_features cp; - cp.handle = ev->handle; - cp.page = 0x01; - hci_send_cmd(hdev, - HCI_OP_READ_REMOTE_EXT_FEATURES, - sizeof(cp), &cp); - } else if (!ev->status && conn->out && - conn->sec_level == BT_SECURITY_HIGH) { - struct hci_cp_auth_requested cp; - cp.handle = ev->handle; - hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, + if (!ev->status) + memcpy(conn->features, ev->features, 8); + + if (conn->state != BT_CONFIG) + goto unlock; + + if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { + struct hci_cp_read_remote_ext_features cp; + cp.handle = ev->handle; + cp.page = 0x01; + hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, sizeof(cp), &cp); - } else { - conn->state = BT_CONNECTED; - hci_proto_connect_cfm(conn, ev->status); - hci_conn_put(conn); - } - } + goto unlock; + } + + if (!ev->status) { + struct hci_cp_remote_name_req cp; + memset(&cp, 0, sizeof(cp)); + bacpy(&cp.bdaddr, &conn->dst); + cp.pscan_rep_mode = 0x02; + hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); } + if (!hci_outgoing_auth_needed(hdev, conn)) { + conn->state = BT_CONNECTED; + hci_proto_connect_cfm(conn, ev->status); + hci_conn_put(conn); + } + +unlock: hci_dev_unlock(hdev); } @@ -1449,10 +1512,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s conn->sent -= count; if (conn->type == ACL_LINK) { - if ((hdev->acl_cnt += count) > hdev->acl_pkts) + hdev->acl_cnt += count; + if (hdev->acl_cnt > hdev->acl_pkts) hdev->acl_cnt = hdev->acl_pkts; } else { - if ((hdev->sco_cnt += count) > hdev->sco_pkts) + hdev->sco_cnt += count; + if (hdev->sco_cnt > hdev->sco_pkts) hdev->sco_cnt = hdev->sco_pkts; } } @@ -1547,7 +1612,8 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk if (conn && !ev->status) { struct inquiry_entry *ie; - if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { + ie = hci_inquiry_cache_lookup(hdev, &conn->dst); + if (ie) { ie->data.clock_offset = ev->clock_offset; ie->timestamp = jiffies; } @@ -1581,7 +1647,8 @@ static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff * hci_dev_lock(hdev); - if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) { + ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); + if (ie) { ie->data.pscan_rep_mode = ev->pscan_rep_mode; ie->timestamp = jiffies; } @@ -1646,32 +1713,37 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); - if (conn) { - if (!ev->status && ev->page == 0x01) { - struct inquiry_entry *ie; + if (!conn) + goto unlock; - if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) - ie->data.ssp_mode = (ev->features[0] & 0x01); + if (!ev->status && ev->page == 0x01) { + struct inquiry_entry *ie; - conn->ssp_mode = (ev->features[0] & 0x01); - } + ie = hci_inquiry_cache_lookup(hdev, &conn->dst); + if (ie) + ie->data.ssp_mode = (ev->features[0] & 0x01); - if (conn->state == BT_CONFIG) { - if (!ev->status && hdev->ssp_mode > 0 && - conn->ssp_mode > 0 && conn->out && - conn->sec_level != BT_SECURITY_SDP) { - struct hci_cp_auth_requested cp; - cp.handle = ev->handle; - hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, - sizeof(cp), &cp); - } else { - conn->state = BT_CONNECTED; - hci_proto_connect_cfm(conn, ev->status); - hci_conn_put(conn); - } - } + conn->ssp_mode = (ev->features[0] & 0x01); } + if (conn->state != BT_CONFIG) + goto unlock; + + if (!ev->status) { + struct hci_cp_remote_name_req cp; + memset(&cp, 0, sizeof(cp)); + bacpy(&cp.bdaddr, &conn->dst); + cp.pscan_rep_mode = 0x02; + hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); + } + + if (!hci_outgoing_auth_needed(hdev, conn)) { + conn->state = BT_CONNECTED; + hci_proto_connect_cfm(conn, ev->status); + hci_conn_put(conn); + } + +unlock: hci_dev_unlock(hdev); } @@ -1821,7 +1893,8 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_ hci_dev_lock(hdev); - if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) + ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); + if (ie) ie->data.ssp_mode = (ev->features[0] & 0x01); hci_dev_unlock(hdev); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 83acd164d39e..b3753bad2a55 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -43,7 +43,7 @@ #include <net/sock.h> #include <asm/system.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> @@ -125,7 +125,8 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) continue; } - if (!(nskb = skb_clone(skb, GFP_ATOMIC))) + nskb = skb_clone(skb, GFP_ATOMIC); + if (!nskb) continue; /* Put type byte before the data */ @@ -370,7 +371,8 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le } if (haddr->hci_dev != HCI_DEV_NONE) { - if (!(hdev = hci_dev_get(haddr->hci_dev))) { + hdev = hci_dev_get(haddr->hci_dev); + if (!hdev) { err = -ENODEV; goto done; } @@ -457,7 +459,8 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (sk->sk_state == BT_CLOSED) return 0; - if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) + skb = skb_recv_datagram(sk, flags, noblock, &err); + if (!skb) return err; msg->msg_namelen = 0; @@ -499,7 +502,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, lock_sock(sk); - if (!(hdev = hci_pi(sk)->hdev)) { + hdev = hci_pi(sk)->hdev; + if (!hdev) { err = -EBADFD; goto done; } @@ -509,7 +513,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, goto done; } - if (!(skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) + skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); + if (!skb) goto done; if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index c0ee8b3928ed..29544c21f4b5 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -107,6 +107,7 @@ static void __hidp_unlink_session(struct hidp_session *session) static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci) { + memset(ci, 0, sizeof(*ci)); bacpy(&ci->bdaddr, &session->bdaddr); ci->flags = session->flags; @@ -115,7 +116,6 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin ci->vendor = 0x0000; ci->product = 0x0000; ci->version = 0x0000; - memset(ci->name, 0, 128); if (session->input) { ci->vendor = session->input->id.vendor; diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index cd8f6ea03841..c12eccfdfe01 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c @@ -57,7 +57,7 @@ #define VERSION "2.15" -static int disable_ertm = 0; +static int disable_ertm; static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; static u8 l2cap_fixed_chan[8] = { 0x02, }; @@ -83,6 +83,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); /* ---- L2CAP timers ---- */ +static void l2cap_sock_set_timer(struct sock *sk, long timeout) +{ + BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout); + sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); +} + +static void l2cap_sock_clear_timer(struct sock *sk) +{ + BT_DBG("sock %p state %d", sk, sk->sk_state); + sk_stop_timer(sk, &sk->sk_timer); +} + static void l2cap_sock_timeout(unsigned long arg) { struct sock *sk = (struct sock *) arg; @@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg) bh_lock_sock(sk); + if (sock_owned_by_user(sk)) { + /* sk is owned by user. Try again later */ + l2cap_sock_set_timer(sk, HZ / 5); + bh_unlock_sock(sk); + sock_put(sk); + return; + } + if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) reason = ECONNREFUSED; else if (sk->sk_state == BT_CONNECT && @@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg) sock_put(sk); } -static void l2cap_sock_set_timer(struct sock *sk, long timeout) -{ - BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout); - sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); -} - -static void l2cap_sock_clear_timer(struct sock *sk) -{ - BT_DBG("sock %p state %d", sk, sk->sk_state); - sk_stop_timer(sk, &sk->sk_timer); -} - /* ---- L2CAP channels ---- */ static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) { @@ -743,11 +751,13 @@ found: /* Find socket with psm and source bdaddr. * Returns closest match. */ -static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) +static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) { struct sock *sk = NULL, *sk1 = NULL; struct hlist_node *node; + read_lock(&l2cap_sk_list.lock); + sk_for_each(sk, node, &l2cap_sk_list.head) { if (state && sk->sk_state != state) continue; @@ -762,20 +772,10 @@ static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src sk1 = sk; } } - return node ? sk : sk1; -} -/* Find socket with given address (psm, src). - * Returns locked socket */ -static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) -{ - struct sock *s; - read_lock(&l2cap_sk_list.lock); - s = __l2cap_get_sock_by_psm(state, psm, src); - if (s) - bh_lock_sock(s); read_unlock(&l2cap_sk_list.lock); - return s; + + return node ? sk : sk1; } static void l2cap_sock_destruct(struct sock *sk) @@ -2926,6 +2926,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd goto sendresp; } + bh_lock_sock(parent); + /* Check if the ACL is secure enough (if not SDP) */ if (psm != cpu_to_le16(0x0001) && !hci_conn_check_link_mode(conn->hcon)) { @@ -3078,6 +3080,14 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd break; default: + /* don't delete l2cap channel if sk is owned by user */ + if (sock_owned_by_user(sk)) { + sk->sk_state = BT_DISCONN; + l2cap_sock_clear_timer(sk); + l2cap_sock_set_timer(sk, HZ / 5); + break; + } + l2cap_chan_del(sk, ECONNREFUSED); break; } @@ -3283,6 +3293,15 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd sk->sk_shutdown = SHUTDOWN_MASK; + /* don't delete l2cap channel if sk is owned by user */ + if (sock_owned_by_user(sk)) { + sk->sk_state = BT_DISCONN; + l2cap_sock_clear_timer(sk); + l2cap_sock_set_timer(sk, HZ / 5); + bh_unlock_sock(sk); + return 0; + } + l2cap_chan_del(sk, ECONNRESET); bh_unlock_sock(sk); @@ -3305,6 +3324,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd if (!sk) return 0; + /* don't delete l2cap channel if sk is owned by user */ + if (sock_owned_by_user(sk)) { + sk->sk_state = BT_DISCONN; + l2cap_sock_clear_timer(sk); + l2cap_sock_set_timer(sk, HZ / 5); + bh_unlock_sock(sk); + return 0; + } + l2cap_chan_del(sk, 0); bh_unlock_sock(sk); @@ -4134,11 +4162,10 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) __mod_retrans_timer(); pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; - if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { + if (pi->conn_state & L2CAP_CONN_SREJ_SENT) l2cap_send_ack(pi); - } else { + else l2cap_ertm_send(sk); - } } } @@ -4430,6 +4457,8 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str if (!sk) goto drop; + bh_lock_sock(sk); + BT_DBG("sk %p, len %d", sk, skb->len); if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) @@ -4841,8 +4870,10 @@ static int __init l2cap_init(void) return err; _busy_wq = create_singlethread_workqueue("l2cap"); - if (!_busy_wq) - goto error; + if (!_busy_wq) { + proto_unregister(&l2cap_proto); + return -ENOMEM; + } err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); if (err < 0) { @@ -4870,6 +4901,7 @@ static int __init l2cap_init(void) return 0; error: + destroy_workqueue(_busy_wq); proto_unregister(&l2cap_proto); return err; } diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index fa642aa652bd..c1e2bbafb549 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -41,7 +41,7 @@ #include <linux/slab.h> #include <net/sock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <asm/unaligned.h> #include <net/bluetooth/bluetooth.h> @@ -51,10 +51,10 @@ #define VERSION "1.11" -static int disable_cfc = 0; +static int disable_cfc; +static int l2cap_ertm; static int channel_mtu = -1; static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU; -static int l2cap_ertm = 0; static struct task_struct *rfcomm_thread; @@ -1901,7 +1901,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s) BT_DBG("%p state %ld", s, s->state); - switch(sk->sk_state) { + switch (sk->sk_state) { case BT_CONNECTED: s->state = BT_CONNECT; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index aec505f934df..66cc1f0c3df8 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -45,7 +45,7 @@ #include <net/sock.h> #include <asm/system.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -140,11 +140,13 @@ static struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src) /* Find socket with channel and source bdaddr. * Returns closest match. */ -static struct sock *__rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src) +static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src) { struct sock *sk = NULL, *sk1 = NULL; struct hlist_node *node; + read_lock(&rfcomm_sk_list.lock); + sk_for_each(sk, node, &rfcomm_sk_list.head) { if (state && sk->sk_state != state) continue; @@ -159,19 +161,10 @@ static struct sock *__rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t sk1 = sk; } } - return node ? sk : sk1; -} -/* Find socket with given address (channel, src). - * Returns locked socket */ -static inline struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src) -{ - struct sock *s; - read_lock(&rfcomm_sk_list.lock); - s = __rfcomm_get_sock_by_channel(state, channel, src); - if (s) bh_lock_sock(s); read_unlock(&rfcomm_sk_list.lock); - return s; + + return node ? sk : sk1; } static void rfcomm_sock_destruct(struct sock *sk) @@ -895,7 +888,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how) BT_DBG("sock %p, sk %p", sock, sk); - if (!sk) return 0; + if (!sk) + return 0; lock_sock(sk); if (!sk->sk_shutdown) { @@ -945,6 +939,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * if (!parent) return 0; + bh_lock_sock(parent); + /* Check for backlog size */ if (sk_acceptq_is_full(parent)) { BT_DBG("backlog full %d", parent->sk_ack_backlog); diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index a9b81f5dacd1..2575c2db6404 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -58,9 +58,9 @@ struct rfcomm_dev { bdaddr_t src; bdaddr_t dst; - u8 channel; + u8 channel; - uint modem_status; + uint modem_status; struct rfcomm_dlc *dlc; struct tty_struct *tty; @@ -69,7 +69,7 @@ struct rfcomm_dev { struct device *tty_dev; - atomic_t wmem_alloc; + atomic_t wmem_alloc; struct sk_buff_head pending; }; @@ -431,7 +431,8 @@ static int rfcomm_release_dev(void __user *arg) BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags); - if (!(dev = rfcomm_dev_get(req.dev_id))) + dev = rfcomm_dev_get(req.dev_id); + if (!dev) return -ENODEV; if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) { @@ -470,7 +471,8 @@ static int rfcomm_get_dev_list(void __user *arg) size = sizeof(*dl) + dev_num * sizeof(*di); - if (!(dl = kmalloc(size, GFP_KERNEL))) + dl = kmalloc(size, GFP_KERNEL); + if (!dl) return -ENOMEM; di = dl->dev_info; @@ -513,7 +515,8 @@ static int rfcomm_get_dev_info(void __user *arg) if (copy_from_user(&di, arg, sizeof(di))) return -EFAULT; - if (!(dev = rfcomm_dev_get(di.id))) + dev = rfcomm_dev_get(di.id); + if (!dev) return -ENODEV; di.flags = dev->flags; @@ -561,7 +564,8 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb) return; } - if (!(tty = dev->tty) || !skb_queue_empty(&dev->pending)) { + tty = dev->tty; + if (!tty || !skb_queue_empty(&dev->pending)) { skb_queue_tail(&dev->pending, skb); return; } @@ -796,7 +800,8 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in memcpy(skb_put(skb, size), buf + sent, size); - if ((err = rfcomm_dlc_send(dlc, skb)) < 0) { + err = rfcomm_dlc_send(dlc, skb); + if (err < 0) { kfree_skb(skb); break; } @@ -892,7 +897,7 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) /* Parity on/off and when on, odd/even */ if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) || - ((old->c_cflag & PARODD) != (new->c_cflag & PARODD)) ) { + ((old->c_cflag & PARODD) != (new->c_cflag & PARODD))) { changes |= RFCOMM_RPN_PM_PARITY; BT_DBG("Parity change detected."); } @@ -937,11 +942,10 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) /* POSIX does not support 1.5 stop bits and RFCOMM does not * support 2 stop bits. So a request for 2 stop bits gets * translated to 1.5 stop bits */ - if (new->c_cflag & CSTOPB) { + if (new->c_cflag & CSTOPB) stop_bits = RFCOMM_RPN_STOP_15; - } else { + else stop_bits = RFCOMM_RPN_STOP_1; - } /* Handle number of data bits [5-8] */ if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE)) diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index d0927d1fdada..960c6d1637da 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -44,7 +44,7 @@ #include <net/sock.h> #include <asm/system.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> @@ -52,7 +52,7 @@ #define VERSION "0.6" -static int disable_esco = 0; +static int disable_esco; static const struct proto_ops sco_sock_ops; @@ -138,16 +138,17 @@ static inline struct sock *sco_chan_get(struct sco_conn *conn) static int sco_conn_del(struct hci_conn *hcon, int err) { - struct sco_conn *conn; + struct sco_conn *conn = hcon->sco_data; struct sock *sk; - if (!(conn = hcon->sco_data)) + if (!conn) return 0; BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); /* Kill socket */ - if ((sk = sco_chan_get(conn))) { + sk = sco_chan_get(conn); + if (sk) { bh_lock_sock(sk); sco_sock_clear_timer(sk); sco_chan_del(sk, err); @@ -185,7 +186,8 @@ static int sco_connect(struct sock *sk) BT_DBG("%s -> %s", batostr(src), batostr(dst)); - if (!(hdev = hci_get_route(dst, src))) + hdev = hci_get_route(dst, src); + if (!hdev) return -EHOSTUNREACH; hci_dev_lock_bh(hdev); @@ -510,7 +512,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen /* Set destination address and psm */ bacpy(&bt_sk(sk)->dst, &sa->sco_bdaddr); - if ((err = sco_connect(sk))) + err = sco_connect(sk); + if (err) goto done; err = bt_sock_wait_state(sk, BT_CONNECTED, @@ -828,13 +831,14 @@ static void sco_chan_del(struct sock *sk, int err) static void sco_conn_ready(struct sco_conn *conn) { - struct sock *parent, *sk; + struct sock *parent; + struct sock *sk = conn->sk; BT_DBG("conn %p", conn); sco_conn_lock(conn); - if ((sk = conn->sk)) { + if (sk) { sco_sock_clear_timer(sk); bh_lock_sock(sk); sk->sk_state = BT_CONNECTED; @@ -882,7 +886,7 @@ static int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 type) int lm = 0; if (type != SCO_LINK && type != ESCO_LINK) - return 0; + return -EINVAL; BT_DBG("hdev %s, bdaddr %s", hdev->name, batostr(bdaddr)); @@ -908,7 +912,7 @@ static int sco_connect_cfm(struct hci_conn *hcon, __u8 status) BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) - return 0; + return -EINVAL; if (!status) { struct sco_conn *conn; @@ -927,7 +931,7 @@ static int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) BT_DBG("hcon %p reason %d", hcon, reason); if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK) - return 0; + return -EINVAL; sco_conn_del(hcon, bt_err(reason)); |