From 9219b2a08c8a1ca9935b85ec4ab119bb55b0cb15 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Mon, 2 Jan 2012 20:08:04 -0200 Subject: Bluetooth: Fix bacpy in l2cap_core.c It should be the dst in the copy not src. 03a001948 introduced this bug. Reported-by: Vinicius Costa Gomes Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index cd7bb3d..d66aea8 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1190,7 +1190,7 @@ inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdad } /* Set destination address and psm */ - bacpy(&bt_sk(sk)->dst, src); + bacpy(&bt_sk(sk)->dst, dst); chan->psm = psm; chan->dcid = cid; -- cgit v0.10.2 From 95ca83f42fb5f5bf789b514635f79242afe555d1 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 27 Dec 2011 15:28:44 -0200 Subject: Bluetooth: Fix context in rfcomm_sock_lock Code now run in process context, does not need to disable interrupt anymore. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index aea2bdd1..f066678 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -370,7 +370,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr goto done; } - write_lock_bh(&rfcomm_sk_list.lock); + write_lock(&rfcomm_sk_list.lock); if (sa->rc_channel && __rfcomm_get_sock_by_addr(sa->rc_channel, &sa->rc_bdaddr)) { err = -EADDRINUSE; @@ -381,7 +381,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr sk->sk_state = BT_BOUND; } - write_unlock_bh(&rfcomm_sk_list.lock); + write_unlock(&rfcomm_sk_list.lock); done: release_sock(sk); @@ -455,7 +455,7 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) err = -EINVAL; - write_lock_bh(&rfcomm_sk_list.lock); + write_lock(&rfcomm_sk_list.lock); for (channel = 1; channel < 31; channel++) if (!__rfcomm_get_sock_by_addr(channel, src)) { @@ -464,7 +464,7 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) break; } - write_unlock_bh(&rfcomm_sk_list.lock); + write_unlock(&rfcomm_sk_list.lock); if (err < 0) goto done; @@ -982,7 +982,7 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p) struct sock *sk; struct hlist_node *node; - read_lock_bh(&rfcomm_sk_list.lock); + read_lock(&rfcomm_sk_list.lock); sk_for_each(sk, node, &rfcomm_sk_list.head) { seq_printf(f, "%s %s %d %d\n", @@ -991,7 +991,7 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p) sk->sk_state, rfcomm_pi(sk)->channel); } - read_unlock_bh(&rfcomm_sk_list.lock); + read_unlock(&rfcomm_sk_list.lock); return 0; } -- cgit v0.10.2 From 393432cd8dc02b88a00decd495913643aa5ff705 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 27 Dec 2011 15:28:45 -0200 Subject: Bluetooth: Fix context in RFCOMM tty We now run in process context, no need to disable interrupts. Calls from the tty layer also run in process context. rw_lock was converted to spinlock, we have more writers than readers in this case. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index fa8f4de5..a2d4f51 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c @@ -76,7 +76,7 @@ struct rfcomm_dev { }; static LIST_HEAD(rfcomm_dev_list); -static DEFINE_RWLOCK(rfcomm_dev_lock); +static DEFINE_SPINLOCK(rfcomm_dev_lock); static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb); static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err); @@ -146,7 +146,7 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) { struct rfcomm_dev *dev; - read_lock(&rfcomm_dev_lock); + spin_lock(&rfcomm_dev_lock); dev = __rfcomm_dev_get(id); @@ -157,7 +157,7 @@ static inline struct rfcomm_dev *rfcomm_dev_get(int id) rfcomm_dev_hold(dev); } - read_unlock(&rfcomm_dev_lock); + spin_unlock(&rfcomm_dev_lock); return dev; } @@ -205,7 +205,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) if (!dev) return -ENOMEM; - write_lock_bh(&rfcomm_dev_lock); + spin_lock(&rfcomm_dev_lock); if (req->dev_id < 0) { dev->id = 0; @@ -290,7 +290,7 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) __module_get(THIS_MODULE); out: - write_unlock_bh(&rfcomm_dev_lock); + spin_unlock(&rfcomm_dev_lock); if (err < 0) goto free; @@ -327,9 +327,9 @@ static void rfcomm_dev_del(struct rfcomm_dev *dev) if (atomic_read(&dev->opened) > 0) return; - write_lock_bh(&rfcomm_dev_lock); + spin_lock(&rfcomm_dev_lock); list_del_init(&dev->list); - write_unlock_bh(&rfcomm_dev_lock); + spin_unlock(&rfcomm_dev_lock); rfcomm_dev_put(dev); } @@ -473,7 +473,7 @@ static int rfcomm_get_dev_list(void __user *arg) di = dl->dev_info; - read_lock_bh(&rfcomm_dev_lock); + spin_lock(&rfcomm_dev_lock); list_for_each_entry(dev, &rfcomm_dev_list, list) { if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) @@ -488,7 +488,7 @@ static int rfcomm_get_dev_list(void __user *arg) break; } - read_unlock_bh(&rfcomm_dev_lock); + spin_unlock(&rfcomm_dev_lock); dl->dev_num = n; size = sizeof(*dl) + n * sizeof(*di); @@ -766,9 +766,9 @@ static void rfcomm_tty_close(struct tty_struct *tty, struct file *filp) rfcomm_dlc_unlock(dev->dlc); if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) { - write_lock_bh(&rfcomm_dev_lock); + spin_lock(&rfcomm_dev_lock); list_del_init(&dev->list); - write_unlock_bh(&rfcomm_dev_lock); + spin_unlock(&rfcomm_dev_lock); rfcomm_dev_put(dev); } -- cgit v0.10.2 From ee65d19e25c7ace7792bcd289776b2e24f4bf059 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 27 Dec 2011 15:28:46 -0200 Subject: Bluetooth: Remove *_bh locks from SCO Those locks are not shared between interrupt and process context anymore, so remove the part that disable interrupts. We are still safe because preemption is disabled. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 0d59e61..471283e 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -482,7 +482,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le goto done; } - write_lock_bh(&sco_sk_list.lock); + write_lock(&sco_sk_list.lock); if (bacmp(src, BDADDR_ANY) && __sco_get_sock_by_addr(src)) { err = -EADDRINUSE; @@ -492,7 +492,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le sk->sk_state = BT_BOUND; } - write_unlock_bh(&sco_sk_list.lock); + write_unlock(&sco_sk_list.lock); done: release_sock(sk); @@ -965,14 +965,14 @@ static int sco_debugfs_show(struct seq_file *f, void *p) struct sock *sk; struct hlist_node *node; - read_lock_bh(&sco_sk_list.lock); + read_lock(&sco_sk_list.lock); sk_for_each(sk, node, &sco_sk_list.head) { seq_printf(f, "%s %s %d\n", batostr(&bt_sk(sk)->src), batostr(&bt_sk(sk)->dst), sk->sk_state); } - read_unlock_bh(&sco_sk_list.lock); + read_unlock(&sco_sk_list.lock); return 0; } -- cgit v0.10.2 From 4b5dd696f81b210c1511ca7a969525126266c933 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 27 Dec 2011 15:28:47 -0200 Subject: Bluetooth: Remove local_bh_disable() from hci_sock.c Everything is in process context now, we do not need such a call. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 189a667..896a72f 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -767,7 +767,6 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, /* Detach sockets from device */ read_lock(&hci_sk_list.lock); sk_for_each(sk, node, &hci_sk_list.head) { - local_bh_disable(); bh_lock_sock_nested(sk); if (hci_pi(sk)->hdev == hdev) { hci_pi(sk)->hdev = NULL; @@ -778,7 +777,6 @@ static int hci_sock_dev_event(struct notifier_block *this, unsigned long event, hci_dev_put(hdev); } bh_unlock_sock(sk); - local_bh_enable(); } read_unlock(&hci_sk_list.lock); } -- cgit v0.10.2 From 94f5bfb8c1641080c3c4325714b8fe7d2839a906 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Tue, 27 Dec 2011 15:28:48 -0200 Subject: Bluetooth: Remove *_bh from socket list lock. We don't need it anymore. Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index cdcfcab..ef92864 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -156,17 +156,17 @@ static int bt_sock_create(struct net *net, struct socket *sock, int proto, void bt_sock_link(struct bt_sock_list *l, struct sock *sk) { - write_lock_bh(&l->lock); + write_lock(&l->lock); sk_add_node(sk, &l->head); - write_unlock_bh(&l->lock); + write_unlock(&l->lock); } EXPORT_SYMBOL(bt_sock_link); void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk) { - write_lock_bh(&l->lock); + write_lock(&l->lock); sk_del_node_init(sk); - write_unlock_bh(&l->lock); + write_unlock(&l->lock); } EXPORT_SYMBOL(bt_sock_unlink); -- cgit v0.10.2 From 59e294065ddee7074af91e4f5e12e6095eb1135b Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 30 Dec 2011 10:34:03 -0300 Subject: Bluetooth: Rename extfeatures This patch renames hdev->extfeatures to hdev->host_features since it holds the extended features Page 1 (aka host features). Signed-off-by: Andre Guedes Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 5e2e984..ea9231f 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -127,7 +127,7 @@ struct hci_dev { __u8 major_class; __u8 minor_class; __u8 features[8]; - __u8 extfeatures[8]; + __u8 host_features[8]; __u8 commands[64]; __u8 ssp_mode; __u8 hci_ver; @@ -676,7 +676,7 @@ void hci_conn_del_sysfs(struct hci_conn *conn); #define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE) /* ----- Extended LMP capabilities ----- */ -#define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE) +#define lmp_host_le_capable(dev) ((dev)->host_features[0] & LMP_HOST_LE) /* ----- HCI protocols ----- */ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 919e3c0..37c31c5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -711,7 +711,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, if (rp->status) return; - memcpy(hdev->extfeatures, rp->features, 8); + memcpy(hdev->host_features, rp->features, 8); hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2540944..38ec8ca 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -291,7 +291,7 @@ static u32 get_current_settings(struct hci_dev *hdev) if (!(hdev->features[4] & LMP_NO_BREDR)) settings |= MGMT_SETTING_BREDR; - if (hdev->extfeatures[0] & LMP_HOST_LE) + if (hdev->host_features[0] & LMP_HOST_LE) settings |= MGMT_SETTING_LE; if (test_bit(HCI_AUTH, &hdev->flags)) -- cgit v0.10.2 From b5b32b653dedb29eb95e57cbbaefc4abf7141cb2 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 30 Dec 2011 10:34:04 -0300 Subject: Bluetooth: Fix hci_cc_read_local_ext_features() Copy the Features value according to the Page number. Signed-off-by: Andre Guedes Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 37c31c5..10152d2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -711,7 +711,14 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, if (rp->status) return; - memcpy(hdev->host_features, rp->features, 8); + switch (rp->page) { + case 0: + memcpy(hdev->features, rp->features, 8); + break; + case 1: + memcpy(hdev->host_features, rp->features, 8); + break; + } hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); } -- cgit v0.10.2 From c1b9b4f45f014093231c568be9b5c2e392943696 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Mon, 2 Jan 2012 19:18:10 -0300 Subject: Bluetooth: Fix adv_work delay This patch fixes the adv_work delay. It should be set to ADV_ CLEAR_TIMEOUT instead of (jiffies + ADV_CLEAR_TIMEOUT) since queue_delayed_work() receives the number of jiffies to wait before queueing. It also removes the unnecessary cancel_delayed_ work_sync() call in case LE scan has been disabled. Signed-off-by: Andre Guedes Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 10152d2..444ca41 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1054,9 +1054,8 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, case LE_SCANNING_DISABLED: clear_bit(HCI_LE_SCAN, &hdev->dev_flags); - cancel_delayed_work_sync(&hdev->adv_work); queue_delayed_work(hdev->workqueue, &hdev->adv_work, - jiffies + ADV_CLEAR_TIMEOUT); + ADV_CLEAR_TIMEOUT); break; default: -- cgit v0.10.2 From d084329e2862922bbc9a2de04a5c8e7219bfceb9 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Mon, 2 Jan 2012 19:18:11 -0300 Subject: Bluetooth: Queue adv_work on system workqueue This patch queues hdev->adv_work on the system-wide workqueue instead of on hdev->workqueue. This way we keep only tx/rx works on hdev->workqueue. Signed-off-by: Andre Guedes Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 444ca41..08c0b42 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1054,8 +1054,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, case LE_SCANNING_DISABLED: clear_bit(HCI_LE_SCAN, &hdev->dev_flags); - queue_delayed_work(hdev->workqueue, &hdev->adv_work, - ADV_CLEAR_TIMEOUT); + schedule_delayed_work(&hdev->adv_work, ADV_CLEAR_TIMEOUT); break; default: -- cgit v0.10.2 From e75a8b0c332875b2a2d22acdc331fc2b83788cac Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Mon, 2 Jan 2012 16:50:53 -0300 Subject: Bluetooth: Fix mgmt_stop_discovery_failed() Stop Discovery Command Status Event should use mgmt status code. Signed-off-by: Andre Guedes Acked-by: Johan Hedberg Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 38ec8ca..bc8e59d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2756,7 +2756,7 @@ int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status) if (!cmd) return -ENOENT; - err = cmd_status(cmd->sk, hdev->id, cmd->opcode, status); + err = cmd_status(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status)); mgmt_pending_remove(cmd); return err; -- cgit v0.10.2 From 333055f2aaabadb951b5ecd90f6a20a9aee38c29 Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Thu, 22 Dec 2011 15:14:39 -0200 Subject: Bluetooth: Don't use *_bh locks anymore Those locks are not shared between interrupt and process context anymore, so remove the part that disable interrupts. We are still safe because preemption is disabled. Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d66aea8..3ee9bde 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -165,7 +165,7 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) { int err; - write_lock_bh(&chan_list_lock); + write_lock(&chan_list_lock); if (psm && __l2cap_global_chan_by_addr(psm, src)) { err = -EADDRINUSE; @@ -190,17 +190,17 @@ int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm) } done: - write_unlock_bh(&chan_list_lock); + write_unlock(&chan_list_lock); return err; } int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) { - write_lock_bh(&chan_list_lock); + write_lock(&chan_list_lock); chan->scid = scid; - write_unlock_bh(&chan_list_lock); + write_unlock(&chan_list_lock); return 0; } @@ -289,9 +289,9 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk) chan->sk = sk; - write_lock_bh(&chan_list_lock); + write_lock(&chan_list_lock); list_add(&chan->global_l, &chan_list); - write_unlock_bh(&chan_list_lock); + write_unlock(&chan_list_lock); INIT_DELAYED_WORK(&chan->chan_timer, l2cap_chan_timeout); @@ -306,9 +306,9 @@ struct l2cap_chan *l2cap_chan_create(struct sock *sk) void l2cap_chan_destroy(struct l2cap_chan *chan) { - write_lock_bh(&chan_list_lock); + write_lock(&chan_list_lock); list_del(&chan->global_l); - write_unlock_bh(&chan_list_lock); + write_unlock(&chan_list_lock); l2cap_chan_put(chan); } @@ -543,14 +543,14 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn) * 200 - 254 are used by utilities like l2ping, etc. */ - spin_lock_bh(&conn->lock); + spin_lock(&conn->lock); if (++conn->tx_ident > 128) conn->tx_ident = 1; id = conn->tx_ident; - spin_unlock_bh(&conn->lock); + spin_unlock(&conn->lock); return id; } @@ -4702,7 +4702,7 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) { struct l2cap_chan *c; - read_lock_bh(&chan_list_lock); + read_lock(&chan_list_lock); list_for_each_entry(c, &chan_list, global_l) { struct sock *sk = c->sk; @@ -4715,7 +4715,7 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) c->sec_level, c->mode); } - read_unlock_bh(&chan_list_lock); + read_unlock(&chan_list_lock); return 0; } -- cgit v0.10.2 From 3542b854bc26e5f8e42e0eab4d7f7453b74a362d Mon Sep 17 00:00:00 2001 From: "Gustavo F. Padovan" Date: Wed, 28 Dec 2011 13:54:17 -0200 Subject: Bluetooth: Keep chan->state and sk->sk_state in sync Those vars need to be in sync, otherwise l2cap_core.c can get the wrong state. Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 9ca5616..c61d967 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -587,6 +587,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch if (smp_conn_security(conn, sec.level)) break; sk->sk_state = BT_CONFIG; + chan->state = BT_CONFIG; /* or for ACL link, under defer_setup time */ } else if (sk->sk_state == BT_CONNECT2 && @@ -731,6 +732,7 @@ static int l2cap_sock_recvmsg(struct kiocb *iocb, struct socket *sock, struct ms if (sk->sk_state == BT_CONNECT2 && bt_sk(sk)->defer_setup) { sk->sk_state = BT_CONFIG; + pi->chan->state = BT_CONFIG; __l2cap_connect_rsp_defer(pi->chan); release_sock(sk); -- cgit v0.10.2 From c5993de864d96b3656e9fca38c377b130105d97a Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Fri, 30 Dec 2011 12:07:47 +0200 Subject: Bluetooth: Correct packet len calculation Remove unneeded skb_pull and correct packet length calculation removing magic number. Move BT_DBG after len check otherwise it could possibly access wrong memory. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 08c0b42..d37f5b2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2271,20 +2271,19 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s struct hci_ev_num_comp_pkts *ev = (void *) skb->data; int i; - skb_pull(skb, sizeof(*ev)); - - BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); - if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { BT_ERR("Wrong event for mode %d", hdev->flow_ctl_mode); return; } - if (skb->len < ev->num_hndl * 4) { + if (skb->len < sizeof(*ev) || skb->len < sizeof(*ev) + + ev->num_hndl * sizeof(struct hci_comp_pkts_info)) { BT_DBG("%s bad parameters", hdev->name); return; } + BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); + for (i = 0; i < ev->num_hndl; i++) { struct hci_comp_pkts_info *info = &ev->handles[i]; struct hci_conn *conn; -- cgit v0.10.2 From d90db4b12bc1b9b8a787ef28550fdb767ee25a49 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 4 Jan 2012 20:50:47 -0600 Subject: rtl8192se: Fix BUG caused by failure to check skb allocation When downloading firmware into the device, the driver fails to check the return when allocating an skb. When the allocation fails, a BUG can be generated, as seen in https://bugzilla.redhat.com/show_bug.cgi?id=771656. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c index 6f91a14..3fda6b1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/fw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/fw.c @@ -196,6 +196,8 @@ static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw *hw, /* Allocate skb buffer to contain firmware */ /* info and tx descriptor info. */ skb = dev_alloc_skb(frag_length); + if (!skb) + return false; skb_reserve(skb, extra_descoffset); seg_ptr = (u8 *)skb_put(skb, (u32)(frag_length - extra_descoffset)); @@ -573,6 +575,8 @@ static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw *hw, u8 h2c_cmd, len = _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE, 1, &cmd_len); skb = dev_alloc_skb(len); + if (!skb) + return false; cb_desc = (struct rtl_tcb_desc *)(skb->cb); cb_desc->queue_index = TXCMD_QUEUE; cb_desc->cmd_or_init = DESC_PACKET_TYPE_NORMAL; -- cgit v0.10.2 From e4922f2b5f1c2b3daa80b56a6eeca984cbee0dde Mon Sep 17 00:00:00 2001 From: Mohammed Shafi Shajakhan Date: Sat, 7 Jan 2012 21:06:02 +0530 Subject: ath9k_hw: fix a comment also remove an unused macro and a function declaration Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 2589b38..2b0bfb8 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -46,7 +46,7 @@ static const int m2ThreshExt_off = 127; * @chan: * * This is the function to change channel on single-chip devices, that is - * all devices after ar9280. + * for AR9300 family of chipsets. * * This function takes the channel value in MHz and sets * hardware channel value. Assumes writes have been enabled to analog bus. diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index b30e9fc..171ccf7 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -679,7 +679,6 @@ void ath9k_deinit_device(struct ath_softc *sc); void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); void ath9k_reload_chainmask_settings(struct ath_softc *sc); -void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw); bool ath9k_uses_beacons(int type); #ifdef CONFIG_ATH9K_PCI diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index 05b9dbf..3b33996d 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h @@ -19,7 +19,6 @@ #include "hw.h" -#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 #define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 #define NUM_NF_READINGS 6 -- cgit v0.10.2 From c40701eacbaebcfe3fb6fac8ef3da653021c212c Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Sun, 8 Jan 2012 23:41:21 +0100 Subject: brcm80211: Don't leak 'vbuffer' in brcmf_sdbrcm_write_vars() If the memory allocation 'nvram_ularray = kmalloc(varsize, GFP_ATOMIC);' fails we'll leak the memory allocated to 'vbuffer' when we return -ENOMEM from the function. This patch resolves the leak by kfree()'ing the allocated memory before the return. Signed-off-by: Jesper Juhl Acked-by: Arend van Spriel Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index 5a002a2..f7eeee1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -3119,8 +3119,10 @@ static int brcmf_sdbrcm_write_vars(struct brcmf_sdio *bus) /* Verify NVRAM bytes */ brcmf_dbg(INFO, "Compare NVRAM dl & ul; varsize=%d\n", varsize); nvram_ularray = kmalloc(varsize, GFP_ATOMIC); - if (!nvram_ularray) + if (!nvram_ularray) { + kfree(vbuffer); return -ENOMEM; + } /* Upload image to verify downloaded contents. */ memset(nvram_ularray, 0xaa, varsize); -- cgit v0.10.2 From 1a19f77f3642b8194ad9cf55548cc5d92e841766 Mon Sep 17 00:00:00 2001 From: Rajkumar Manoharan Date: Mon, 9 Jan 2012 15:37:53 +0530 Subject: ath9k: Fix regression in channelwidth switch at the same channel The commit "ath9k: Fix invalid noisefloor reading due to channel update" preserves the current channel noisefloor readings before updating channel type at the same channel index. It is also updating the curchan pointer. As survey updation is also referring curchan pointer to fetch the appropriate index, which might leads to invalid memory access. This patch partially reverts the change and stores the noise floor history buffer before updating channel type w/o updating curchan. Cc: stable@kernel.org Cc: Gary Morain Cc: Paul Stewart Reported-by: Mohammed Shafi Shajakhan Signed-off-by: Rajkumar Manoharan Signed-off-by: John W. Linville diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 172e33d..2f4b48e 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -400,6 +400,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) ah->noise = ath9k_hw_getchan_noise(ah, chan); return true; } +EXPORT_SYMBOL(ath9k_hw_getnf); void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, struct ath9k_channel *chan) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index e267c92..4a00806 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1629,7 +1629,6 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { struct ieee80211_channel *curchan = hw->conf.channel; - struct ath9k_channel old_chan; int pos = curchan->hw_value; int old_pos = -1; unsigned long flags; @@ -1654,11 +1653,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) * Preserve the current channel values, before updating * the same channel */ - if (old_pos == pos) { - memcpy(&old_chan, &sc->sc_ah->channels[pos], - sizeof(struct ath9k_channel)); - ah->curchan = &old_chan; - } + if (ah->curchan && (old_pos == pos)) + ath9k_hw_getnf(ah, ah->curchan); ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], curchan, conf->channel_type); -- cgit v0.10.2 From bdd3ae3d1e749cf6597f035a5357f297a1af8eb3 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 2 Jan 2012 13:30:03 +0100 Subject: nl80211: fix old station flags compatibility My patch to validate station flags broke compatibility with the old station flags setting where all flags are always set at once since it always set the mask as all possible flags which ended up being rejected later in the station add/modify code. Fix by parsing only the current flags in the old flags attribute -- new applications and new flags should use (and will now require) the new flags attribute where the mask is given by the application. Reported-and-tested-by: Thomas Hilber Signed-off-by: Johannes Berg Signed-off-by: John W. Linville diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index b3d3cf8..afeea32 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -2250,6 +2250,7 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { }; static int parse_station_flags(struct genl_info *info, + enum nl80211_iftype iftype, struct station_parameters *params) { struct nlattr *flags[NL80211_STA_FLAG_MAX + 1]; @@ -2283,8 +2284,33 @@ static int parse_station_flags(struct genl_info *info, nla, sta_flags_policy)) return -EINVAL; - params->sta_flags_mask = (1 << __NL80211_STA_FLAG_AFTER_LAST) - 1; - params->sta_flags_mask &= ~1; + /* + * Only allow certain flags for interface types so that + * other attributes are silently ignored. Remember that + * this is backward compatibility code with old userspace + * and shouldn't be hit in other cases anyway. + */ + switch (iftype) { + case NL80211_IFTYPE_AP: + case NL80211_IFTYPE_AP_VLAN: + case NL80211_IFTYPE_P2P_GO: + params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | + BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | + BIT(NL80211_STA_FLAG_WME) | + BIT(NL80211_STA_FLAG_MFP); + break; + case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_STATION: + params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | + BIT(NL80211_STA_FLAG_TDLS_PEER); + break; + case NL80211_IFTYPE_MESH_POINT: + params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) | + BIT(NL80211_STA_FLAG_MFP) | + BIT(NL80211_STA_FLAG_AUTHORIZED); + default: + return -EINVAL; + } for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++) if (flags[flag]) @@ -2585,7 +2611,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) if (!rdev->ops->change_station) return -EOPNOTSUPP; - if (parse_station_flags(info, ¶ms)) + if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) return -EINVAL; if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) @@ -2731,7 +2757,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (!rdev->ops->add_station) return -EOPNOTSUPP; - if (parse_station_flags(info, ¶ms)) + if (parse_station_flags(info, dev->ieee80211_ptr->iftype, ¶ms)) return -EINVAL; switch (dev->ieee80211_ptr->iftype) { -- cgit v0.10.2 From 1140afa862842ac3e56678693050760edc4ecde9 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Wed, 11 Jan 2012 09:26:54 +0100 Subject: mac80211: fix rx->key NULL pointer dereference in promiscuous mode Since: commit 816c04fe7ef01dd9649f5ccfe796474db8708be5 Author: Christian Lamparter Date: Sat Apr 30 15:24:30 2011 +0200 mac80211: consolidate MIC failure report handling is possible to that we dereference rx->key == NULL when driver set RX_FLAG_MMIC_STRIPPED and not RX_FLAG_IV_STRIPPED and we are in promiscuous mode. This happen with rt73usb and rt61pci at least. Before the commit we always check rx->key against NULL, so I assume fix should be done in mac80211 (also mic_fail path has similar check). References: https://bugzilla.redhat.com/show_bug.cgi?id=769766 http://rt2x00.serialmonkey.com/pipermail/users_rt2x00.serialmonkey.com/2012-January/004395.html Cc: stable@vger.kernel.org # 3.0+ Reported-by: Stuart D Gathman Reported-by: Kai Wohlfahrt Signed-off-by: Stanislaw Gruszka Signed-off-by: John W. Linville diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 93aab07..422b798 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -106,7 +106,7 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_MMIC_ERROR) goto mic_fail; - if (!(status->flag & RX_FLAG_IV_STRIPPED)) + if (!(status->flag & RX_FLAG_IV_STRIPPED) && rx->key) goto update_iv; return RX_CONTINUE; -- cgit v0.10.2