From 476585ecf08067ac4e81d1a4cb19e2caf2093471 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 6 Jun 2012 18:54:15 +0800 Subject: Bluetooth: Fix SMP pairing method selection The tk_request function takes the local IO capability as the second last parameter and the remote IO capability as the last parameter. They were previously swapped: when we receive a pairing response req->io_capability contains the local one and rsp->io_capability the remote one. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/smp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 6fc7c4708f3e..c4ac2849d9c2 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -648,7 +648,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; - ret = tk_request(conn, 0, auth, rsp->io_capability, req->io_capability); + ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability); if (ret) return SMP_UNSPECIFIED; -- cgit v1.3-14-g43fede From 4c47d7396420160d27209f578680141874c0110b Mon Sep 17 00:00:00 2001 From: Vishal Agarwal Date: Thu, 7 Jun 2012 20:27:35 +0530 Subject: Bluetooth: Fix LE pairing completion on connection failure For BR/EDR pairing is assumed to be finished when connection is done. For LE if connection is successful it did not necessarily mean that pairing is also done but if the connection is unsuccessful it should be assumed that pairing procedure is also finished. This patch registers a new function with connect_cfm_cb callback for LE link which sends the pairing complete signal to user space if connection is unsuccessful. Signed-off-by: Vishal Agarwal Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/mgmt.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'net') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 25d220776079..991d5b667674 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1873,6 +1873,22 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status) pairing_complete(cmd, mgmt_status(status)); } +static void le_connect_complete_cb(struct hci_conn *conn, u8 status) +{ + struct pending_cmd *cmd; + + BT_DBG("status %u", status); + + if (!status) + return; + + cmd = find_pairing(conn); + if (!cmd) + BT_DBG("Unable to find a pending command"); + else + pairing_complete(cmd, mgmt_status(status)); +} + static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { @@ -1934,6 +1950,8 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, /* For LE, just connecting isn't a proof that the pairing finished */ if (cp->addr.type == BDADDR_BREDR) conn->connect_cfm_cb = pairing_complete_cb; + else + conn->connect_cfm_cb = le_connect_complete_cb; conn->security_cfm_cb = pairing_complete_cb; conn->disconn_cfm_cb = pairing_complete_cb; -- cgit v1.3-14-g43fede From d06cc416f517a25713dedd9e2a9ccf4f3086c09a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 6 Jun 2012 18:44:11 +0800 Subject: Bluetooth: Fix deadlock and crash when SMP pairing times out The l2cap_conn_del function tries to cancel_sync the security timer, but when it's called from the timeout function itself a deadlock occurs. Subsequently the "hcon->l2cap_data = NULL" that's supposed to protect multiple calls to l2cap_conn_del never gets cleared and when the connection finally drops we double free's etc which will crash the kernel. This patch fixes the issue by using the HCI_CONN_LE_SMP_PEND for protecting against this. The same flag is also used for the same purpose in other places in the SMP code. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 24f144b72a96..8394e3615ef6 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1295,7 +1295,12 @@ static void security_timeout(struct work_struct *work) struct l2cap_conn *conn = container_of(work, struct l2cap_conn, security_timer.work); - l2cap_conn_del(conn->hcon, ETIMEDOUT); + BT_DBG("conn %p", conn); + + if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) { + smp_chan_destroy(conn); + l2cap_conn_del(conn->hcon, ETIMEDOUT); + } } static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) -- cgit v1.3-14-g43fede From 4dab786482d706a2a41cd16cf174671d640a9870 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 7 Jun 2012 14:58:37 +0800 Subject: Bluetooth: Fix SMP security elevation from medium to high If we have an unauthenticated key it is not sufficient to acheive high security. Therefore, when deciding whether to encrypt the link or request pairing, it is essential to in addition to checking the existence of a key to also check whether it is authenticated or not. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/smp.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index c4ac2849d9c2..37df4e9b3896 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -703,7 +703,7 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) return 0; } -static u8 smp_ltk_encrypt(struct l2cap_conn *conn) +static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) { struct smp_ltk *key; struct hci_conn *hcon = conn->hcon; @@ -712,6 +712,9 @@ static u8 smp_ltk_encrypt(struct l2cap_conn *conn) if (!key) return 0; + if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated) + return 0; + if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) return 1; @@ -732,7 +735,7 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) hcon->pending_sec_level = authreq_to_seclevel(rp->auth_req); - if (smp_ltk_encrypt(conn)) + if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) return 0; if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) @@ -771,7 +774,7 @@ int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level) return 1; if (hcon->link_mode & HCI_LM_MASTER) - if (smp_ltk_encrypt(conn)) + if (smp_ltk_encrypt(conn, sec_level)) goto done; if (test_and_set_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) -- cgit v1.3-14-g43fede From 1c2e004183178e1947882cd2e74f37826f45230e Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 8 Jun 2012 23:31:13 +0800 Subject: Bluetooth: Add support for encryption key refresh With LE/SMP the completion of a security level elavation from medium to high is indicated by a HCI Encryption Key Refresh Complete event. The necessary behavior upon receiving this event is a mix of what's done for auth_complete and encryption_change, which is also where most of the event handling code has been copied from. Signed-off-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 6 ++++++ net/bluetooth/hci_event.c | 48 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) (limited to 'net') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 66a7b579e31c..3def64ba77fa 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1144,6 +1144,12 @@ struct extended_inquiry_info { __u8 data[240]; } __packed; +#define HCI_EV_KEY_REFRESH_COMPLETE 0x30 +struct hci_ev_key_refresh_complete { + __u8 status; + __le16 handle; +} __packed; + #define HCI_EV_IO_CAPA_REQUEST 0x31 struct hci_ev_io_capa_request { bdaddr_t bdaddr; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4eefb7f65cf6..94ad124a4ea3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3043,6 +3043,50 @@ static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct hci_dev_unlock(hdev); } +static void hci_key_refresh_complete_evt(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_ev_key_refresh_complete *ev = (void *) skb->data; + struct hci_conn *conn; + + BT_DBG("%s status %u handle %u", hdev->name, ev->status, + __le16_to_cpu(ev->handle)); + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); + if (!conn) + goto unlock; + + if (!ev->status) + conn->sec_level = conn->pending_sec_level; + + clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); + + if (ev->status && conn->state == BT_CONNECTED) { + hci_acl_disconn(conn, HCI_ERROR_AUTH_FAILURE); + hci_conn_put(conn); + goto unlock; + } + + if (conn->state == BT_CONFIG) { + if (!ev->status) + conn->state = BT_CONNECTED; + + hci_proto_connect_cfm(conn, ev->status); + hci_conn_put(conn); + } else { + hci_auth_cfm(conn, ev->status); + + hci_conn_hold(conn); + conn->disc_timeout = HCI_DISCONN_TIMEOUT; + hci_conn_put(conn); + } + +unlock: + hci_dev_unlock(hdev); +} + static inline u8 hci_get_auth_req(struct hci_conn *conn) { /* If remote requests dedicated bonding follow that lead */ @@ -3559,6 +3603,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_extended_inquiry_result_evt(hdev, skb); break; + case HCI_EV_KEY_REFRESH_COMPLETE: + hci_key_refresh_complete_evt(hdev, skb); + break; + case HCI_EV_IO_CAPA_REQUEST: hci_io_capa_request_evt(hdev, skb); break; -- cgit v1.3-14-g43fede From d13e14148154e5ce58467e76321eef1dd912c416 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 9 Jun 2012 10:31:09 +0200 Subject: mac80211: add some missing kernel-doc Add a few kernel-doc descriptions that were missed during development. Reported-by: Randy Dunlap Signed-off-by: Johannes Berg --- include/net/mac80211.h | 6 ++++++ net/mac80211/sta_info.h | 2 ++ 2 files changed, 8 insertions(+) (limited to 'net') diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 1937c7d98304..95e39b6a02ec 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -1940,6 +1940,11 @@ enum ieee80211_rate_control_changed { * to also unregister the device. If it returns 1, then mac80211 * will also go through the regular complete restart on resume. * + * @set_wakeup: Enable or disable wakeup when WoWLAN configuration is + * modified. The reason is that device_set_wakeup_enable() is + * supposed to be called when the configuration changes, not only + * in suspend(). + * * @add_interface: Called when a netdevice attached to the hardware is * enabled. Because it is not called for monitor mode devices, @start * and @stop must be implemented. @@ -2966,6 +2971,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, * ieee80211_generic_frame_duration - Calculate the duration field for a frame * @hw: pointer obtained from ieee80211_alloc_hw(). * @vif: &struct ieee80211_vif pointer from the add_interface callback. + * @band: the band to calculate the frame duration on * @frame_len: the length of the frame. * @rate: the rate at which the frame is going to be transmitted. * diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 3bb24a121c95..525ce5077e1c 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -278,6 +278,8 @@ struct sta_ampdu_mlme { * @sta: station information we share with the driver * @sta_state: duplicates information about station state (for debug) * @beacon_loss_count: number of times beacon loss has triggered + * @supports_40mhz: tracks whether the station advertised 40 MHz support + * as we overwrite its HT parameters with the currently used value */ struct sta_info { /* General information, mostly static */ -- cgit v1.3-14-g43fede From f8cdddb8d61d16a156229f0910f7ecfc7a82c003 Mon Sep 17 00:00:00 2001 From: Michal Kazior Date: Fri, 8 Jun 2012 10:55:44 +0200 Subject: cfg80211: check iface combinations only when iface is running Don't validate interface combinations on a stopped interface. Otherwise we might end up being able to create a new interface with a certain type, but won't be able to change an existing interface into that type. This also skips some other functions when interface is stopped and changing interface type. Signed-off-by: Michal Kazior Signed-off-by: Johannes Berg --- net/wireless/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/wireless/util.c b/net/wireless/util.c index 8f2d68fc3a44..316cfd00914f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -804,7 +804,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, ntype == NL80211_IFTYPE_P2P_CLIENT)) return -EBUSY; - if (ntype != otype) { + if (ntype != otype && netif_running(dev)) { err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, ntype); if (err) -- cgit v1.3-14-g43fede From 5fcb08befaf57faa1b00e514915c1660252b8c26 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 11 Jun 2012 10:18:13 -0500 Subject: 9p: BUG before corrupting memory The BUG_ON() in pack_sg_list() would get triggered only one time after we've corrupted some memory by sg_set_buf() into an invalid sg buffer. I'm still working on figuring out why I manage to trigger that bug... Signed-off-by: Sasha Levin Signed-off-by: Eric Van Hensbergen --- net/9p/trans_virtio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 5af18d11b518..2a167658bb95 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -192,10 +192,10 @@ static int pack_sg_list(struct scatterlist *sg, int start, s = rest_of_page(data); if (s > count) s = count; + BUG_ON(index > limit); sg_set_buf(&sg[index++], data, s); count -= s; data += s; - BUG_ON(index > limit); } return index-start; -- cgit v1.3-14-g43fede From 8f321f853ea33330c7141977cd34804476e2e07e Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Fri, 8 Jun 2012 11:33:33 +0200 Subject: Bluetooth: Fix using uninitialized option in RFCMode If remote device sends bogus RFC option with invalid length, undefined options values are used. Fix this by using defaults when remote misbehaves. This also fixes the following warning reported by gcc 4.7.0: net/bluetooth/l2cap_core.c: In function 'l2cap_config_rsp': net/bluetooth/l2cap_core.c:3302:13: warning: 'rfc.max_pdu_size' may be used uninitialized in this function [-Wmaybe-uninitialized] net/bluetooth/l2cap_core.c:3266:24: note: 'rfc.max_pdu_size' was declared here net/bluetooth/l2cap_core.c:3298:25: warning: 'rfc.monitor_timeout' may be used uninitialized in this function [-Wmaybe-uninitialized] net/bluetooth/l2cap_core.c:3266:24: note: 'rfc.monitor_timeout' was declared here net/bluetooth/l2cap_core.c:3297:25: warning: 'rfc.retrans_timeout' may be used uninitialized in this function [-Wmaybe-uninitialized] net/bluetooth/l2cap_core.c:3266:24: note: 'rfc.retrans_timeout' was declared here net/bluetooth/l2cap_core.c:3295:2: warning: 'rfc.mode' may be used uninitialized in this function [-Wmaybe-uninitialized] net/bluetooth/l2cap_core.c:3266:24: note: 'rfc.mode' was declared here Signed-off-by: Szymon Janc Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8394e3615ef6..4554e80d16a3 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2915,12 +2915,14 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) while (len >= L2CAP_CONF_OPT_SIZE) { len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val); - switch (type) { - case L2CAP_CONF_RFC: - if (olen == sizeof(rfc)) - memcpy(&rfc, (void *)val, olen); - goto done; - } + if (type != L2CAP_CONF_RFC) + continue; + + if (olen != sizeof(rfc)) + break; + + memcpy(&rfc, (void *)val, olen); + goto done; } /* Use sane default values in case a misbehaving remote device -- cgit v1.3-14-g43fede From 1dd45581e6dc98467c539ea67ae5c847646f0efd Mon Sep 17 00:00:00 2001 From: Ashok Nagarajan Date: Mon, 11 Jun 2012 10:23:35 -0700 Subject: mac80211: add missing kernel-doc Add a few kernel-doc descriptions that were missed during mesh development. Reported-by: Randy Dunlap Signed-off-by: Ashok Nagarajan Acked-by: Randy Dunlap Signed-off-by: Johannes Berg --- net/mac80211/sta_info.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net') diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 525ce5077e1c..a470e1123a55 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h @@ -271,6 +271,9 @@ struct sta_ampdu_mlme { * @plink_timer: peer link watch timer * @plink_timer_was_running: used by suspend/resume to restore timers * @t_offset: timing offset relative to this host + * @t_offset_setpoint: reference timing offset of this sta to be used when + * calculating clockdrift + * @ch_type: peer's channel type * @debugfs: debug filesystem info * @dead: set to true when sta is unlinked * @uploaded: set to true when sta is uploaded to the driver -- cgit v1.3-14-g43fede From fe20b39ec32e975f1054c0b7866c873a954adf05 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 12 Jun 2012 12:53:13 +0300 Subject: cfg80211: fix potential deadlock in regulatory reg_timeout_work() calls restore_regulatory_settings() which takes cfg80211_mutex. reg_set_request_processed() already holds cfg80211_mutex before calling cancel_delayed_work_sync(reg_timeout), so it might deadlock. Call the async cancel_delayed_work instead, in order to avoid the potential deadlock. This is the relevant lockdep warning: cfg80211: Calling CRDA for country: XX ====================================================== [ INFO: possible circular locking dependency detected ] 3.4.0-rc5-wl+ #26 Not tainted ------------------------------------------------------- kworker/0:2/1391 is trying to acquire lock: (cfg80211_mutex){+.+.+.}, at: [] restore_regulatory_settings+0x34/0x418 [cfg80211] but task is already holding lock: ((reg_timeout).work){+.+...}, at: [] process_one_work+0x1f0/0x480 which lock already depends on the new lock. the existing dependency chain (in reverse order) is: -> #2 ((reg_timeout).work){+.+...}: [] validate_chain+0xb94/0x10f0 [] __lock_acquire+0x8c8/0x9b0 [] lock_acquire+0xf0/0x114 [] wait_on_work+0x4c/0x154 [] __cancel_work_timer+0xd4/0x11c [] cancel_delayed_work_sync+0x1c/0x20 [] reg_set_request_processed+0x50/0x78 [cfg80211] [] set_regdom+0x550/0x600 [cfg80211] [] nl80211_set_reg+0x218/0x258 [cfg80211] [] genl_rcv_msg+0x1a8/0x1e8 [] netlink_rcv_skb+0x5c/0xc0 [] genl_rcv+0x28/0x34 [] netlink_unicast+0x15c/0x228 [] netlink_sendmsg+0x218/0x298 [] sock_sendmsg+0xa4/0xc0 [] __sys_sendmsg+0x1e4/0x268 [] sys_sendmsg+0x4c/0x70 [] ret_fast_syscall+0x0/0x3c -> #1 (reg_mutex){+.+.+.}: [] validate_chain+0xb94/0x10f0 [] __lock_acquire+0x8c8/0x9b0 [] lock_acquire+0xf0/0x114 [] mutex_lock_nested+0x48/0x320 [] reg_todo+0x30/0x538 [cfg80211] [] process_one_work+0x2a0/0x480 [] worker_thread+0x1bc/0x2bc [] kthread+0x98/0xa4 [] kernel_thread_exit+0x0/0x8 -> #0 (cfg80211_mutex){+.+.+.}: [] print_circular_bug+0x68/0x2cc [] validate_chain+0x978/0x10f0 [] __lock_acquire+0x8c8/0x9b0 [] lock_acquire+0xf0/0x114 [] mutex_lock_nested+0x48/0x320 [] restore_regulatory_settings+0x34/0x418 [cfg80211] [] reg_timeout_work+0x1c/0x20 [cfg80211] [] process_one_work+0x2a0/0x480 [] worker_thread+0x1bc/0x2bc [] kthread+0x98/0xa4 [] kernel_thread_exit+0x0/0x8 other info that might help us debug this: Chain exists of: cfg80211_mutex --> reg_mutex --> (reg_timeout).work Possible unsafe locking scenario: CPU0 CPU1 ---- ---- lock((reg_timeout).work); lock(reg_mutex); lock((reg_timeout).work); lock(cfg80211_mutex); *** DEADLOCK *** 2 locks held by kworker/0:2/1391: #0: (events){.+.+.+}, at: [] process_one_work+0x1f0/0x480 #1: ((reg_timeout).work){+.+...}, at: [] process_one_work+0x1f0/0x480 stack backtrace: [] (unwind_backtrace+0x0/0x12c) from [] (dump_stack+0x20/0x24) [] (dump_stack+0x20/0x24) from [] (print_circular_bug+0x280/0x2cc) [] (print_circular_bug+0x280/0x2cc) from [] (validate_chain+0x978/0x10f0) [] (validate_chain+0x978/0x10f0) from [] (__lock_acquire+0x8c8/0x9b0) [] (__lock_acquire+0x8c8/0x9b0) from [] (lock_acquire+0xf0/0x114) [] (lock_acquire+0xf0/0x114) from [] (mutex_lock_nested+0x48/0x320) [] (mutex_lock_nested+0x48/0x320) from [] (restore_regulatory_settings+0x34/0x418 [cfg80211]) [] (restore_regulatory_settings+0x34/0x418 [cfg80211]) from [] (reg_timeout_work+0x1c/0x20 [cfg80211]) [] (reg_timeout_work+0x1c/0x20 [cfg80211]) from [] (process_one_work+0x2a0/0x480) [] (process_one_work+0x2a0/0x480) from [] (worker_thread+0x1bc/0x2bc) [] (worker_thread+0x1bc/0x2bc) from [] (kthread+0x98/0xa4) [] (kthread+0x98/0xa4) from [] (kernel_thread_exit+0x0/0x8) cfg80211: Calling CRDA to update world regulatory domain cfg80211: World regulatory domain updated: cfg80211: (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp) cfg80211: (2402000 KHz - 2472000 KHz @ 40000 KHz), (300 mBi, 2000 mBm) cfg80211: (2457000 KHz - 2482000 KHz @ 20000 KHz), (300 mBi, 2000 mBm) cfg80211: (2474000 KHz - 2494000 KHz @ 20000 KHz), (300 mBi, 2000 mBm) cfg80211: (5170000 KHz - 5250000 KHz @ 40000 KHz), (300 mBi, 2000 mBm) cfg80211: (5735000 KHz - 5835000 KHz @ 40000 KHz), (300 mBi, 2000 mBm) Cc: stable@kernel.org Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg --- net/wireless/reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 15f347477a99..baf5704740ee 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1389,7 +1389,7 @@ static void reg_set_request_processed(void) spin_unlock(®_requests_lock); if (last_request->initiator == NL80211_REGDOM_SET_BY_USER) - cancel_delayed_work_sync(®_timeout); + cancel_delayed_work(®_timeout); if (need_more_processing) schedule_work(®_work); -- cgit v1.3-14-g43fede From 554a43d5e77e8256aa9685ffd19ad555e6f77979 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Tue, 12 Jun 2012 12:41:15 +0300 Subject: mac80211: check sdata_running on ieee80211_set_bitrate_mask Otherwise, we might call the driver callback before the interface was uploaded. Solves the following warning: WARNING: at net/mac80211/driver-ops.h:12 ieee80211_set_bitrate_mask+0xbc/0x18c [mac80211]() wlan0: Failed check-sdata-in-driver check, flags: 0x0 Modules linked in: wlcore_sdio wl12xx wl18xx wlcore mac80211 cfg80211 [last unloaded: cfg80211] [] (unwind_backtrace+0x0/0x12c) from [] (dump_stack+0x20/0x24) [] (dump_stack+0x20/0x24) from [] (warn_slowpath_common+0x5c/0x74) [] (warn_slowpath_common+0x5c/0x74) from [] (warn_slowpath_fmt+0x40/0x48) [] (warn_slowpath_fmt+0x40/0x48) from [] (ieee80211_set_bitrate_mask+0xbc/0x18c [mac80211]) [] (ieee80211_set_bitrate_mask+0xbc/0x18c [mac80211]) from [] (nl80211_set_tx_bitrate_mask+0x350/0x358 [cfg80211]) [] (nl80211_set_tx_bitrate_mask+0x350/0x358 [cfg80211]) from [] (genl_rcv_msg+0x1a8/0x1e8) [] (genl_rcv_msg+0x1a8/0x1e8) from [] (netlink_rcv_skb+0x5c/0xc0) [] (netlink_rcv_skb+0x5c/0xc0) from [] (genl_rcv+0x28/0x34) [] (genl_rcv+0x28/0x34) from [] (netlink_unicast+0x158/0x234) [] (netlink_unicast+0x158/0x234) from [] (netlink_sendmsg+0x218/0x298) [] (netlink_sendmsg+0x218/0x298) from [] (sock_sendmsg+0xa4/0xc0) [] (sock_sendmsg+0xa4/0xc0) from [] (__sys_sendmsg+0x1d8/0x254) [] (__sys_sendmsg+0x1d8/0x254) from [] (sys_sendmsg+0x4c/0x70) [] (sys_sendmsg+0x4c/0x70) from [] (ret_fast_syscall+0x0/0x3c) Note that calling the driver can also result in undefined behaviour since it doesn't have to deal with calls while down. Signed-off-by: Eliad Peller [removed timestamps, added note - Johannes] Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net') diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index e9cecca5c44d..7d5108a867ad 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2093,6 +2093,9 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); int i, ret; + if (!ieee80211_sdata_running(sdata)) + return -ENETDOWN; + if (local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) { ret = drv_set_bitrate_mask(local, sdata, mask); if (ret) -- cgit v1.3-14-g43fede From 79543d8eecc0957ac6fe3ec1e2486ad31d4b67a3 Mon Sep 17 00:00:00 2001 From: David Spinadel Date: Tue, 12 Jun 2012 09:59:45 +0300 Subject: mac80211: stop polling in disassociation Stop connection monitor poll during disassociation. This clears the polling flags and if a scan was deferred it will be run. Without this fix, if a scan was deferred due to connection monitoring while disassociation happens, this scan blocks further scan requests until interface down/up which causes problems connecting to another AP. Signed-off-by: David Spinadel Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 91d84cc77bbf..66e4fcdd1c6b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1352,6 +1352,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, if (WARN_ON(!ifmgd->associated)) return; + ieee80211_stop_poll(sdata); + memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); ifmgd->associated = NULL; @@ -2612,8 +2614,6 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[DEAUTH_DISASSOC_LEN]; - ieee80211_stop_poll(sdata); - ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason, false, frame_buf); mutex_unlock(&ifmgd->mtx); -- cgit v1.3-14-g43fede From 047fe3605235888f3ebcda0c728cb31937eadfe6 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 12 Jun 2012 15:24:40 +0200 Subject: splice: fix racy pipe->buffers uses Dave Jones reported a kernel BUG at mm/slub.c:3474! triggered by splice_shrink_spd() called from vmsplice_to_pipe() commit 35f3d14dbbc5 (pipe: add support for shrinking and growing pipes) added capability to adjust pipe->buffers. Problem is some paths don't hold pipe mutex and assume pipe->buffers doesn't change for their duration. Fix this by adding nr_pages_max field in struct splice_pipe_desc, and use it in place of pipe->buffers where appropriate. splice_shrink_spd() loses its struct pipe_inode_info argument. Reported-by: Dave Jones Signed-off-by: Eric Dumazet Cc: Jens Axboe Cc: Alexander Viro Cc: Tom Herbert Cc: stable # 2.6.35 Tested-by: Dave Jones Signed-off-by: Jens Axboe --- fs/splice.c | 35 ++++++++++++++++++++--------------- include/linux/splice.h | 8 ++++---- kernel/relay.c | 5 +++-- kernel/trace/trace.c | 6 ++++-- mm/shmem.c | 3 ++- net/core/skbuff.c | 1 + 6 files changed, 34 insertions(+), 24 deletions(-) (limited to 'net') diff --git a/fs/splice.c b/fs/splice.c index c9f1318a3b82..7bf08fa22ec9 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -273,13 +273,16 @@ void spd_release_page(struct splice_pipe_desc *spd, unsigned int i) * Check if we need to grow the arrays holding pages and partial page * descriptions. */ -int splice_grow_spd(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) +int splice_grow_spd(const struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) { - if (pipe->buffers <= PIPE_DEF_BUFFERS) + unsigned int buffers = ACCESS_ONCE(pipe->buffers); + + spd->nr_pages_max = buffers; + if (buffers <= PIPE_DEF_BUFFERS) return 0; - spd->pages = kmalloc(pipe->buffers * sizeof(struct page *), GFP_KERNEL); - spd->partial = kmalloc(pipe->buffers * sizeof(struct partial_page), GFP_KERNEL); + spd->pages = kmalloc(buffers * sizeof(struct page *), GFP_KERNEL); + spd->partial = kmalloc(buffers * sizeof(struct partial_page), GFP_KERNEL); if (spd->pages && spd->partial) return 0; @@ -289,10 +292,9 @@ int splice_grow_spd(struct pipe_inode_info *pipe, struct splice_pipe_desc *spd) return -ENOMEM; } -void splice_shrink_spd(struct pipe_inode_info *pipe, - struct splice_pipe_desc *spd) +void splice_shrink_spd(struct splice_pipe_desc *spd) { - if (pipe->buffers <= PIPE_DEF_BUFFERS) + if (spd->nr_pages_max <= PIPE_DEF_BUFFERS) return; kfree(spd->pages); @@ -315,6 +317,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &page_cache_pipe_buf_ops, .spd_release = spd_release_page, @@ -326,7 +329,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, index = *ppos >> PAGE_CACHE_SHIFT; loff = *ppos & ~PAGE_CACHE_MASK; req_pages = (len + loff + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - nr_pages = min(req_pages, pipe->buffers); + nr_pages = min(req_pages, spd.nr_pages_max); /* * Lookup the (hopefully) full range of pages we need. @@ -497,7 +500,7 @@ fill_it: if (spd.nr_pages) error = splice_to_pipe(pipe, &spd); - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); return error; } @@ -598,6 +601,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &default_pipe_buf_ops, .spd_release = spd_release_page, @@ -608,8 +612,8 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, res = -ENOMEM; vec = __vec; - if (pipe->buffers > PIPE_DEF_BUFFERS) { - vec = kmalloc(pipe->buffers * sizeof(struct iovec), GFP_KERNEL); + if (spd.nr_pages_max > PIPE_DEF_BUFFERS) { + vec = kmalloc(spd.nr_pages_max * sizeof(struct iovec), GFP_KERNEL); if (!vec) goto shrink_ret; } @@ -617,7 +621,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, offset = *ppos & ~PAGE_CACHE_MASK; nr_pages = (len + offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; - for (i = 0; i < nr_pages && i < pipe->buffers && len; i++) { + for (i = 0; i < nr_pages && i < spd.nr_pages_max && len; i++) { struct page *page; page = alloc_page(GFP_USER); @@ -665,7 +669,7 @@ ssize_t default_file_splice_read(struct file *in, loff_t *ppos, shrink_ret: if (vec != __vec) kfree(vec); - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); return res; err: @@ -1614,6 +1618,7 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &user_page_pipe_buf_ops, .spd_release = spd_release_page, @@ -1629,13 +1634,13 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, spd.nr_pages = get_iovec_page_array(iov, nr_segs, spd.pages, spd.partial, false, - pipe->buffers); + spd.nr_pages_max); if (spd.nr_pages <= 0) ret = spd.nr_pages; else ret = splice_to_pipe(pipe, &spd); - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); return ret; } diff --git a/include/linux/splice.h b/include/linux/splice.h index 26e5b613deda..09a545a7dfa3 100644 --- a/include/linux/splice.h +++ b/include/linux/splice.h @@ -51,7 +51,8 @@ struct partial_page { struct splice_pipe_desc { struct page **pages; /* page map */ struct partial_page *partial; /* pages[] may not be contig */ - int nr_pages; /* number of pages in map */ + int nr_pages; /* number of populated pages in map */ + unsigned int nr_pages_max; /* pages[] & partial[] arrays size */ unsigned int flags; /* splice flags */ const struct pipe_buf_operations *ops;/* ops associated with output pipe */ void (*spd_release)(struct splice_pipe_desc *, unsigned int); @@ -85,9 +86,8 @@ extern ssize_t splice_direct_to_actor(struct file *, struct splice_desc *, /* * for dynamic pipe sizing */ -extern int splice_grow_spd(struct pipe_inode_info *, struct splice_pipe_desc *); -extern void splice_shrink_spd(struct pipe_inode_info *, - struct splice_pipe_desc *); +extern int splice_grow_spd(const struct pipe_inode_info *, struct splice_pipe_desc *); +extern void splice_shrink_spd(struct splice_pipe_desc *); extern void spd_release_page(struct splice_pipe_desc *, unsigned int); extern const struct pipe_buf_operations page_cache_pipe_buf_ops; diff --git a/kernel/relay.c b/kernel/relay.c index ab56a1764d4d..e8cd2027abbd 100644 --- a/kernel/relay.c +++ b/kernel/relay.c @@ -1235,6 +1235,7 @@ static ssize_t subbuf_splice_actor(struct file *in, struct splice_pipe_desc spd = { .pages = pages, .nr_pages = 0, + .nr_pages_max = PIPE_DEF_BUFFERS, .partial = partial, .flags = flags, .ops = &relay_pipe_buf_ops, @@ -1302,8 +1303,8 @@ static ssize_t subbuf_splice_actor(struct file *in, ret += padding; out: - splice_shrink_spd(pipe, &spd); - return ret; + splice_shrink_spd(&spd); + return ret; } static ssize_t relay_file_splice_read(struct file *in, diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 68032c6177db..288488082224 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -3609,6 +3609,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, .pages = pages_def, .partial = partial_def, .nr_pages = 0, /* This gets updated below. */ + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &tracing_pipe_buf_ops, .spd_release = tracing_spd_release_pipe, @@ -3680,7 +3681,7 @@ static ssize_t tracing_splice_read_pipe(struct file *filp, ret = splice_to_pipe(pipe, &spd); out: - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); return ret; out_err: @@ -4231,6 +4232,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, struct splice_pipe_desc spd = { .pages = pages_def, .partial = partial_def, + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &buffer_pipe_buf_ops, .spd_release = buffer_spd_release, @@ -4318,7 +4320,7 @@ tracing_buffers_splice_read(struct file *file, loff_t *ppos, } ret = splice_to_pipe(pipe, &spd); - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); out: return ret; } diff --git a/mm/shmem.c b/mm/shmem.c index 585bd220a21e..c244e93a70fa 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1577,6 +1577,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = PIPE_DEF_BUFFERS, .flags = flags, .ops = &page_cache_pipe_buf_ops, .spd_release = spd_release_page, @@ -1665,7 +1666,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos, if (spd.nr_pages) error = splice_to_pipe(pipe, &spd); - splice_shrink_spd(pipe, &spd); + splice_shrink_spd(&spd); if (error > 0) { *ppos += error; diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 016694d62484..bac3c5756d63 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -1755,6 +1755,7 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset, struct splice_pipe_desc spd = { .pages = pages, .partial = partial, + .nr_pages_max = MAX_SKB_FRAGS, .flags = flags, .ops = &sock_pipe_buf_ops, .spd_release = sock_spd_release, -- cgit v1.3-14-g43fede From f960727e6c98a36018029c0512aa03f1c5faa914 Mon Sep 17 00:00:00 2001 From: Vishal Agarwal Date: Wed, 13 Jun 2012 05:32:43 +0530 Subject: Bluetooth: Fix sending HCI_Disconnect only when connected HCI_Disconnect should only be sent after connection is established. If connection is not yet established and HCI_Disconnect is called then disconnection complete will be received with a handle which does not exist and hence this event will be ignored. But as mgmt.c will not receive this event, its variable for pending command is not cleared.This will result in future Disconnect commands for that BD Address to be blocked with error busy. Signed-off-by: Vishal Agarwal Acked-by: Johan Hedberg Signed-off-by: Gustavo Padovan --- net/bluetooth/mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 991d5b667674..3e5e3362ea00 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1598,7 +1598,7 @@ static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data, else conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); - if (!conn) { + if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) { err = cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT, MGMT_STATUS_NOT_CONNECTED); goto failed; -- cgit v1.3-14-g43fede From 62b1a8ab9b3660bb820d8dfe23148ed6cda38574 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 14 Jun 2012 06:42:44 +0000 Subject: net: remove skb_orphan_try() Orphaning skb in dev_hard_start_xmit() makes bonding behavior unfriendly for applications sending big UDP bursts : Once packets pass the bonding device and come to real device, they might hit a full qdisc and be dropped. Without orphaning, the sender is automatically throttled because sk->sk_wmemalloc reaches sk->sk_sndbuf (assuming sk_sndbuf is not too big) We could try to defer the orphaning adding another test in dev_hard_start_xmit(), but all this seems of little gain, now that BQL tends to make packets more likely to be parked in Qdisc queues instead of NIC TX ring, in cases where performance matters. Reverts commits : fc6055a5ba31 net: Introduce skb_orphan_try() 87fd308cfc6b net: skb_tx_hash() fix relative to skb_orphan_try() and removes SKBTX_DRV_NEEDS_SK_REF flag Reported-and-bisected-by: Jean-Michel Hautbois Signed-off-by: Eric Dumazet Tested-by: Oliver Hartkopp Acked-by: Oliver Hartkopp Signed-off-by: David S. Miller --- include/linux/skbuff.h | 7 ++----- net/can/raw.c | 3 --- net/core/dev.c | 23 +---------------------- net/iucv/af_iucv.c | 1 - 4 files changed, 3 insertions(+), 31 deletions(-) (limited to 'net') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index b534a1be540a..642cb7355df3 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -225,14 +225,11 @@ enum { /* device driver is going to provide hardware time stamp */ SKBTX_IN_PROGRESS = 1 << 2, - /* ensure the originating sk reference is available on driver level */ - SKBTX_DRV_NEEDS_SK_REF = 1 << 3, - /* device driver supports TX zero-copy buffers */ - SKBTX_DEV_ZEROCOPY = 1 << 4, + SKBTX_DEV_ZEROCOPY = 1 << 3, /* generate wifi status information (where possible) */ - SKBTX_WIFI_STATUS = 1 << 5, + SKBTX_WIFI_STATUS = 1 << 4, }; /* diff --git a/net/can/raw.c b/net/can/raw.c index cde1b4a20f75..46cca3a91d19 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -681,9 +681,6 @@ static int raw_sendmsg(struct kiocb *iocb, struct socket *sock, if (err < 0) goto free_skb; - /* to be able to check the received tx sock reference in raw_rcv() */ - skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF; - skb->dev = dev; skb->sk = sk; diff --git a/net/core/dev.c b/net/core/dev.c index cd0981977f5c..6df214041a5e 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2089,25 +2089,6 @@ static int dev_gso_segment(struct sk_buff *skb, netdev_features_t features) return 0; } -/* - * Try to orphan skb early, right before transmission by the device. - * We cannot orphan skb if tx timestamp is requested or the sk-reference - * is needed on driver level for other reasons, e.g. see net/can/raw.c - */ -static inline void skb_orphan_try(struct sk_buff *skb) -{ - struct sock *sk = skb->sk; - - if (sk && !skb_shinfo(skb)->tx_flags) { - /* skb_tx_hash() wont be able to get sk. - * We copy sk_hash into skb->rxhash - */ - if (!skb->rxhash) - skb->rxhash = sk->sk_hash; - skb_orphan(skb); - } -} - static bool can_checksum_protocol(netdev_features_t features, __be16 protocol) { return ((features & NETIF_F_GEN_CSUM) || @@ -2193,8 +2174,6 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, if (!list_empty(&ptype_all)) dev_queue_xmit_nit(skb, dev); - skb_orphan_try(skb); - features = netif_skb_features(skb); if (vlan_tx_tag_present(skb) && @@ -2304,7 +2283,7 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb, if (skb->sk && skb->sk->sk_hash) hash = skb->sk->sk_hash; else - hash = (__force u16) skb->protocol ^ skb->rxhash; + hash = (__force u16) skb->protocol; hash = jhash_1word(hash, hashrnd); return (u16) (((u64) hash * qcount) >> 32) + qoffset; diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 07d7d55a1b93..cd6f7a991d80 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c @@ -372,7 +372,6 @@ static int afiucv_hs_send(struct iucv_message *imsg, struct sock *sock, skb_trim(skb, skb->dev->mtu); } skb->protocol = ETH_P_AF_IUCV; - skb_shinfo(skb)->tx_flags |= SKBTX_DRV_NEEDS_SK_REF; nskb = skb_clone(skb, GFP_ATOMIC); if (!nskb) return -ENOMEM; -- cgit v1.3-14-g43fede From 2a0c451ade8e1783c5d453948289e4a978d417c9 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Thu, 14 Jun 2012 23:00:17 +0000 Subject: ipv6: Prevent access to uninitialized fib_table_hash via /proc/net/ipv6_route /proc/net/ipv6_route reflects the contents of fib_table_hash. The proc handler is installed in ip6_route_net_init() whereas fib_table_hash is allocated in fib6_net_init() _after_ the proc handler has been installed. This opens up a short time frame to access fib_table_hash with its pants down. fib6_init() as a whole can't be moved to an earlier position as it also registers the rtnetlink message handlers which should be registered at the end. Therefore split it into fib6_init() which is run early and fib6_init_late() to register the rtnetlink message handlers. Signed-off-by: Thomas Graf Reviewed-by: Neil Horman Signed-off-by: David S. Miller --- include/net/ip6_fib.h | 2 ++ net/ipv6/ip6_fib.c | 18 +++++++++++------- net/ipv6/route.c | 16 +++++++++++----- 3 files changed, 24 insertions(+), 12 deletions(-) (limited to 'net') diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 0ae759a6c76e..209af13b0336 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -271,6 +271,8 @@ extern void fib6_run_gc(unsigned long expires, extern void fib6_gc_cleanup(void); extern int fib6_init(void); +extern int fib6_init_late(void); +extern void fib6_cleanup_late(void); #ifdef CONFIG_IPV6_MULTIPLE_TABLES extern int fib6_rules_init(void); diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 74c21b924a79..fbd4afff05fa 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1692,21 +1692,25 @@ int __init fib6_init(void) ret = register_pernet_subsys(&fib6_net_ops); if (ret) goto out_kmem_cache_create; - - ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib, - NULL); - if (ret) - goto out_unregister_subsys; out: return ret; -out_unregister_subsys: - unregister_pernet_subsys(&fib6_net_ops); out_kmem_cache_create: kmem_cache_destroy(fib6_node_kmem); goto out; } +int __init fib6_init_late(void) +{ + return __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib, + NULL); +} + +void fib6_cleanup_late(void) +{ + rtnl_unregister(PF_INET6, RTM_GETROUTE); +} + void fib6_gc_cleanup(void) { unregister_pernet_subsys(&fib6_net_ops); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 999a982ad3fd..dc60bf585966 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -3018,10 +3018,14 @@ int __init ip6_route_init(void) if (ret) goto out_kmem_cache; - ret = register_pernet_subsys(&ip6_route_net_ops); + ret = fib6_init(); if (ret) goto out_dst_entries; + ret = register_pernet_subsys(&ip6_route_net_ops); + if (ret) + goto out_fib6_init; + ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; /* Registering of the loopback is done before this portion of code, @@ -3035,13 +3039,13 @@ int __init ip6_route_init(void) init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); #endif - ret = fib6_init(); + ret = fib6_init_late(); if (ret) goto out_register_subsys; ret = xfrm6_init(); if (ret) - goto out_fib6_init; + goto out_fib6_init_late; ret = fib6_rules_init(); if (ret) @@ -3064,10 +3068,12 @@ fib6_rules_init: fib6_rules_cleanup(); xfrm6_init: xfrm6_fini(); -out_fib6_init: - fib6_gc_cleanup(); +out_fib6_init_late: + fib6_cleanup_late(); out_register_subsys: unregister_pernet_subsys(&ip6_route_net_ops); +out_fib6_init: + fib6_gc_cleanup(); out_dst_entries: dst_entries_destroy(&ip6_dst_blackhole_ops); out_kmem_cache: -- cgit v1.3-14-g43fede From e8803b6c387129059e04d9e14d49efda250a7361 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sat, 16 Jun 2012 01:12:19 -0700 Subject: Revert "ipv6: Prevent access to uninitialized fib_table_hash via /proc/net/ipv6_route" This reverts commit 2a0c451ade8e1783c5d453948289e4a978d417c9. It causes crashes, because now ip6_null_entry is used before it is initialized. Signed-off-by: David S. Miller --- include/net/ip6_fib.h | 2 -- net/ipv6/ip6_fib.c | 18 +++++++----------- net/ipv6/route.c | 16 +++++----------- 3 files changed, 12 insertions(+), 24 deletions(-) (limited to 'net') diff --git a/include/net/ip6_fib.h b/include/net/ip6_fib.h index 209af13b0336..0ae759a6c76e 100644 --- a/include/net/ip6_fib.h +++ b/include/net/ip6_fib.h @@ -271,8 +271,6 @@ extern void fib6_run_gc(unsigned long expires, extern void fib6_gc_cleanup(void); extern int fib6_init(void); -extern int fib6_init_late(void); -extern void fib6_cleanup_late(void); #ifdef CONFIG_IPV6_MULTIPLE_TABLES extern int fib6_rules_init(void); diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index fbd4afff05fa..74c21b924a79 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1692,25 +1692,21 @@ int __init fib6_init(void) ret = register_pernet_subsys(&fib6_net_ops); if (ret) goto out_kmem_cache_create; + + ret = __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib, + NULL); + if (ret) + goto out_unregister_subsys; out: return ret; +out_unregister_subsys: + unregister_pernet_subsys(&fib6_net_ops); out_kmem_cache_create: kmem_cache_destroy(fib6_node_kmem); goto out; } -int __init fib6_init_late(void) -{ - return __rtnl_register(PF_INET6, RTM_GETROUTE, NULL, inet6_dump_fib, - NULL); -} - -void fib6_cleanup_late(void) -{ - rtnl_unregister(PF_INET6, RTM_GETROUTE); -} - void fib6_gc_cleanup(void) { unregister_pernet_subsys(&fib6_net_ops); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index dc60bf585966..999a982ad3fd 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -3018,13 +3018,9 @@ int __init ip6_route_init(void) if (ret) goto out_kmem_cache; - ret = fib6_init(); - if (ret) - goto out_dst_entries; - ret = register_pernet_subsys(&ip6_route_net_ops); if (ret) - goto out_fib6_init; + goto out_dst_entries; ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; @@ -3039,13 +3035,13 @@ int __init ip6_route_init(void) init_net.ipv6.ip6_blk_hole_entry->dst.dev = init_net.loopback_dev; init_net.ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(init_net.loopback_dev); #endif - ret = fib6_init_late(); + ret = fib6_init(); if (ret) goto out_register_subsys; ret = xfrm6_init(); if (ret) - goto out_fib6_init_late; + goto out_fib6_init; ret = fib6_rules_init(); if (ret) @@ -3068,12 +3064,10 @@ fib6_rules_init: fib6_rules_cleanup(); xfrm6_init: xfrm6_fini(); -out_fib6_init_late: - fib6_cleanup_late(); -out_register_subsys: - unregister_pernet_subsys(&ip6_route_net_ops); out_fib6_init: fib6_gc_cleanup(); +out_register_subsys: + unregister_pernet_subsys(&ip6_route_net_ops); out_dst_entries: dst_entries_destroy(&ip6_dst_blackhole_ops); out_kmem_cache: -- cgit v1.3-14-g43fede From 31fdc5553b42abd7e29bb7b89f6ba07514eb4763 Mon Sep 17 00:00:00 2001 From: Rémi Denis-Courmont Date: Wed, 13 Jun 2012 22:29:03 +0000 Subject: net: remove my future former mail address MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rémi Denis-Courmont Cc: Sakari Ailus Signed-off-by: David S. Miller --- include/net/phonet/gprs.h | 2 +- net/caif/caif_dev.c | 3 +-- net/phonet/af_phonet.c | 4 ++-- net/phonet/datagram.c | 4 ++-- net/phonet/pep-gprs.c | 2 +- net/phonet/pep.c | 2 +- net/phonet/pn_dev.c | 4 ++-- net/phonet/pn_netlink.c | 4 ++-- net/phonet/socket.c | 4 ++-- net/phonet/sysctl.c | 2 +- 10 files changed, 15 insertions(+), 16 deletions(-) (limited to 'net') diff --git a/include/net/phonet/gprs.h b/include/net/phonet/gprs.h index 928daf595beb..bcd525e39a0b 100644 --- a/include/net/phonet/gprs.h +++ b/include/net/phonet/gprs.h @@ -5,7 +5,7 @@ * * Copyright (C) 2008 Nokia Corporation. * - * Author: Rémi Denis-Courmont + * Author: Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index aa6f716524fd..554b31289607 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -4,8 +4,7 @@ * Author: Sjur Brendeland/sjur.brandeland@stericsson.com * License terms: GNU General Public License (GPL) version 2 * - * Borrowed heavily from file: pn_dev.c. Thanks to - * Remi Denis-Courmont + * Borrowed heavily from file: pn_dev.c. Thanks to Remi Denis-Courmont * and Sakari Ailus */ diff --git a/net/phonet/af_phonet.c b/net/phonet/af_phonet.c index 779ce4ff92ec..5a940dbd74a3 100644 --- a/net/phonet/af_phonet.c +++ b/net/phonet/af_phonet.c @@ -5,8 +5,8 @@ * * Copyright (C) 2008 Nokia Corporation. * - * Contact: Remi Denis-Courmont - * Original author: Sakari Ailus + * Authors: Sakari Ailus + * Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/phonet/datagram.c b/net/phonet/datagram.c index bf35b4e1a14c..12c30f3e643e 100644 --- a/net/phonet/datagram.c +++ b/net/phonet/datagram.c @@ -5,8 +5,8 @@ * * Copyright (C) 2008 Nokia Corporation. * - * Contact: Remi Denis-Courmont - * Original author: Sakari Ailus + * Authors: Sakari Ailus + * Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index d01208968c83..a2fba7edfd1f 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c @@ -5,7 +5,7 @@ * * Copyright (C) 2008 Nokia Corporation. * - * Author: Rémi Denis-Courmont + * Author: Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/phonet/pep.c b/net/phonet/pep.c index 9dd4f926f7d1..576f22c9c76e 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c @@ -5,7 +5,7 @@ * * Copyright (C) 2008 Nokia Corporation. * - * Author: Rémi Denis-Courmont + * Author: Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 36f75a9e2c3d..5bf6341e2dd4 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -5,8 +5,8 @@ * * Copyright (C) 2008 Nokia Corporation. * - * Contact: Remi Denis-Courmont - * Original author: Sakari Ailus + * Authors: Sakari Ailus + * Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index cfdf135fcd69..7dd762a464e5 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c @@ -5,8 +5,8 @@ * * Copyright (C) 2008 Nokia Corporation. * - * Contact: Remi Denis-Courmont - * Original author: Sakari Ailus + * Authors: Sakari Ailus + * Remi Denis-Courmont * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 89cfa9ce4939..0acc943f713a 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c @@ -5,8 +5,8 @@ * * Copyright (C) 2008 Nokia Corporation. * - * Contact: Remi Denis-Courmont - * Original author: Sakari Ailus + * Authors: Sakari Ailus + * Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/net/phonet/sysctl.c b/net/phonet/sysctl.c index 696348fd31a1..d6bbbbd0af18 100644 --- a/net/phonet/sysctl.c +++ b/net/phonet/sysctl.c @@ -5,7 +5,7 @@ * * Copyright (C) 2008 Nokia Corporation. * - * Contact: Remi Denis-Courmont + * Author: Rémi Denis-Courmont * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License -- cgit v1.3-14-g43fede From d189634ecab947c10f6f832258b103d0bbfe73cc Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Mon, 18 Jun 2012 12:08:33 +0000 Subject: ipv6: Move ipv6 proc file registration to end of init order /proc/net/ipv6_route reflects the contents of fib_table_hash. The proc handler is installed in ip6_route_net_init() whereas fib_table_hash is allocated in fib6_net_init() _after_ the proc handler has been installed. This opens up a short time frame to access fib_table_hash with its pants down. Move the registration of the proc files to a later point in the init order to avoid the race. Tested :-) Signed-off-by: Thomas Graf Signed-off-by: David S. Miller --- net/ipv6/route.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) (limited to 'net') diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 999a982ad3fd..becb048d18d4 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -2957,10 +2957,6 @@ static int __net_init ip6_route_net_init(struct net *net) net->ipv6.sysctl.ip6_rt_mtu_expires = 10*60*HZ; net->ipv6.sysctl.ip6_rt_min_advmss = IPV6_MIN_MTU - 20 - 40; -#ifdef CONFIG_PROC_FS - proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); - proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); -#endif net->ipv6.ip6_rt_gc_expire = 30*HZ; ret = 0; @@ -2981,10 +2977,6 @@ out_ip6_dst_ops: static void __net_exit ip6_route_net_exit(struct net *net) { -#ifdef CONFIG_PROC_FS - proc_net_remove(net, "ipv6_route"); - proc_net_remove(net, "rt6_stats"); -#endif kfree(net->ipv6.ip6_null_entry); #ifdef CONFIG_IPV6_MULTIPLE_TABLES kfree(net->ipv6.ip6_prohibit_entry); @@ -2993,11 +2985,33 @@ static void __net_exit ip6_route_net_exit(struct net *net) dst_entries_destroy(&net->ipv6.ip6_dst_ops); } +static int __net_init ip6_route_net_init_late(struct net *net) +{ +#ifdef CONFIG_PROC_FS + proc_net_fops_create(net, "ipv6_route", 0, &ipv6_route_proc_fops); + proc_net_fops_create(net, "rt6_stats", S_IRUGO, &rt6_stats_seq_fops); +#endif + return 0; +} + +static void __net_exit ip6_route_net_exit_late(struct net *net) +{ +#ifdef CONFIG_PROC_FS + proc_net_remove(net, "ipv6_route"); + proc_net_remove(net, "rt6_stats"); +#endif +} + static struct pernet_operations ip6_route_net_ops = { .init = ip6_route_net_init, .exit = ip6_route_net_exit, }; +static struct pernet_operations ip6_route_net_late_ops = { + .init = ip6_route_net_init_late, + .exit = ip6_route_net_exit_late, +}; + static struct notifier_block ip6_route_dev_notifier = { .notifier_call = ip6_route_dev_notify, .priority = 0, @@ -3047,19 +3061,25 @@ int __init ip6_route_init(void) if (ret) goto xfrm6_init; + ret = register_pernet_subsys(&ip6_route_net_late_ops); + if (ret) + goto fib6_rules_init; + ret = -ENOBUFS; if (__rtnl_register(PF_INET6, RTM_NEWROUTE, inet6_rtm_newroute, NULL, NULL) || __rtnl_register(PF_INET6, RTM_DELROUTE, inet6_rtm_delroute, NULL, NULL) || __rtnl_register(PF_INET6, RTM_GETROUTE, inet6_rtm_getroute, NULL, NULL)) - goto fib6_rules_init; + goto out_register_late_subsys; ret = register_netdevice_notifier(&ip6_route_dev_notifier); if (ret) - goto fib6_rules_init; + goto out_register_late_subsys; out: return ret; +out_register_late_subsys: + unregister_pernet_subsys(&ip6_route_net_late_ops); fib6_rules_init: fib6_rules_cleanup(); xfrm6_init: @@ -3078,6 +3098,7 @@ out_kmem_cache: void ip6_route_cleanup(void) { unregister_netdevice_notifier(&ip6_route_dev_notifier); + unregister_pernet_subsys(&ip6_route_net_late_ops); fib6_rules_cleanup(); xfrm6_fini(); fib6_gc_cleanup(); -- cgit v1.3-14-g43fede From 39d84a58ad6290a43e6503acc8b54ebb7e4ecc54 Mon Sep 17 00:00:00 2001 From: Daniel Halperin Date: Mon, 18 Jun 2012 11:04:55 +0000 Subject: sctp: fix warning when compiling without IPv6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit net/sctp/protocol.c: In function ‘sctp_addr_wq_timeout_handler’: net/sctp/protocol.c:676: warning: label ‘free_next’ defined but not used Signed-off-by: Daniel Halperin Signed-off-by: David S. Miller --- net/sctp/protocol.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 5942d27b1444..9c90811d1134 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -673,7 +673,9 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) SCTP_DEBUG_PRINTK("sctp_addrwq_timo_handler: sctp_asconf_mgmt failed\n"); sctp_bh_unlock_sock(sk); } +#if IS_ENABLED(CONFIG_IPV6) free_next: +#endif list_del(&addrw->list); kfree(addrw); } -- cgit v1.3-14-g43fede From 2c995ff892313009e336ecc8ec3411022f5b1c39 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Tue, 19 Jun 2012 09:26:39 +0000 Subject: batman-adv: fix skb->data assignment skb_linearize(skb) possibly rearranges the skb internal data and then changes the skb->data pointer value. For this reason any other pointer in the code that was assigned skb->data before invoking skb_linearise(skb) must be re-assigned. In the current tt_query message handling code this is not done and therefore, in case of skb linearization, the pointer used to handle the packet header ends up in pointing to free'd memory. This bug was introduced by a73105b8d4c765d9ebfb664d0a66802127d8e4c7 (batman-adv: improved client announcement mechanism) Signed-off-by: Antonio Quartulli Cc: Signed-off-by: David S. Miller --- net/batman-adv/routing.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net') diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 840e2c64a301..015471d801b4 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -617,6 +617,8 @@ int recv_tt_query(struct sk_buff *skb, struct hard_iface *recv_if) * changes */ if (skb_linearize(skb) < 0) goto out; + /* skb_linearize() possibly changed skb->data */ + tt_query = (struct tt_query_packet *)skb->data; tt_len = tt_query->tt_data * sizeof(struct tt_change); -- cgit v1.3-14-g43fede From 680584fab05efff732b5ae16ad601ba994d7b505 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Mon, 4 Jun 2012 14:43:32 -0500 Subject: libceph: osd_client: don't drop reply reference too early In ceph_osdc_release_request(), a reference to the r_reply message is dropped. But just after that, that same message is revoked if it was in use to receive an incoming reply. Reorder these so we are sure we hold a reference until we're actually done with the message. Signed-off-by: Alex Elder Reviewed-by: Sage Weil (cherry picked from commit ab8cb34a4b2f60281a4b18b1f1ad23bc2313d91b) --- net/ceph/osd_client.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 1ffebed5ce0f..13538da41dd6 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -139,8 +139,6 @@ void ceph_osdc_release_request(struct kref *kref) if (req->r_request) ceph_msg_put(req->r_request); - if (req->r_reply) - ceph_msg_put(req->r_reply); if (req->r_con_filling_msg) { dout("release_request revoking pages %p from con %p\n", req->r_pages, req->r_con_filling_msg); @@ -148,6 +146,8 @@ void ceph_osdc_release_request(struct kref *kref) req->r_reply); ceph_con_put(req->r_con_filling_msg); } + if (req->r_reply) + ceph_msg_put(req->r_reply); if (req->r_own_pages) ceph_release_page_vector(req->r_pages, req->r_num_pages); -- cgit v1.3-14-g43fede From 88ed6ea0b295f8e2383d599a04027ec596cdf97b Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Thu, 31 May 2012 20:22:18 -0700 Subject: libceph: use con get/put ops from osd_client There were a few direct calls to ceph_con_{get,put}() instead of the con ops from osd_client.c. This is a bug since those ops aren't defined to be ceph_con_get/put. This breaks refcounting on the ceph_osd structs that contain the ceph_connections, and could lead to all manner of strangeness. The purpose of the ->get and ->put methods in a ceph connection are to allow the connection to indicate it has a reference to something external to the messaging system, *not* to indicate something external has a reference to the connection. [elder@inktank.com: added that last sentence] Signed-off-by: Sage Weil Reviewed-by: Alex Elder (cherry picked from commit 0d47766f14211a73eaf54cab234db134ece79f49) --- net/ceph/osd_client.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 13538da41dd6..ca59e66c9787 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c @@ -144,7 +144,7 @@ void ceph_osdc_release_request(struct kref *kref) req->r_pages, req->r_con_filling_msg); ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply); - ceph_con_put(req->r_con_filling_msg); + req->r_con_filling_msg->ops->put(req->r_con_filling_msg); } if (req->r_reply) ceph_msg_put(req->r_reply); @@ -1216,7 +1216,7 @@ static void handle_reply(struct ceph_osd_client *osdc, struct ceph_msg *msg, if (req->r_con_filling_msg == con && req->r_reply == msg) { dout(" dropping con_filling_msg ref %p\n", con); req->r_con_filling_msg = NULL; - ceph_con_put(con); + con->ops->put(con); } if (!req->r_got_reply) { @@ -2028,7 +2028,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, dout("get_reply revoking msg %p from old con %p\n", req->r_reply, req->r_con_filling_msg); ceph_con_revoke_message(req->r_con_filling_msg, req->r_reply); - ceph_con_put(req->r_con_filling_msg); + req->r_con_filling_msg->ops->put(req->r_con_filling_msg); req->r_con_filling_msg = NULL; } @@ -2063,7 +2063,7 @@ static struct ceph_msg *get_reply(struct ceph_connection *con, #endif } *skip = 0; - req->r_con_filling_msg = ceph_con_get(con); + req->r_con_filling_msg = con->ops->get(con); dout("get_reply tid %lld %p\n", tid, m); out: -- cgit v1.3-14-g43fede From b132cf4c733f91bb4dd2277ea049243cf16e8b66 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Wed, 6 Jun 2012 19:35:55 -0500 Subject: rbd: Clear ceph_msg->bio_iter for retransmitted message The bug can cause NULL pointer dereference in write_partial_msg_pages Signed-off-by: Zheng Yan Reviewed-by: Alex Elder (cherry picked from commit 43643528cce60ca184fe8197efa8e8da7c89a037) --- net/ceph/messenger.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net') diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 524f4e4f598b..b332c3d76059 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -563,6 +563,10 @@ static void prepare_write_message(struct ceph_connection *con) m->hdr.seq = cpu_to_le64(++con->out_seq); m->needs_out_seq = false; } +#ifdef CONFIG_BLOCK + else + m->bio_iter = NULL; +#endif dout("prepare_write_message %p seq %lld type %d len %d+%d+%d %d pgs\n", m, con->out_seq, le16_to_cpu(m->hdr.type), -- cgit v1.3-14-g43fede From 642c0dbde32f34baa7886e988a067089992adc8f Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Sun, 10 Jun 2012 20:43:56 -0700 Subject: libceph: flush msgr queue during mon_client shutdown We need to flush the msgr workqueue during mon_client shutdown to ensure that any work affecting our embedded ceph_connection is finished so that we can be safely destroyed. Previously, we were flushing the work queue after osd_client shutdown and before mon_client shutdown to ensure that any osd connection refs to authorizers are flushed. Remove the redundant flush, and document in the comment that the mon_client flush is needed to cover that case as well. Signed-off-by: Sage Weil Reviewed-by: Alex Elder (cherry picked from commit f3dea7edd3d449fe7a6d402c1ce56a294b985261) --- net/ceph/ceph_common.c | 7 ------- net/ceph/mon_client.c | 8 ++++++++ 2 files changed, 8 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index a776f751edbf..ba4323bce0e9 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -504,13 +504,6 @@ void ceph_destroy_client(struct ceph_client *client) /* unmount */ ceph_osdc_stop(&client->osdc); - /* - * make sure osd connections close out before destroying the - * auth module, which is needed to free those connections' - * ceph_authorizers. - */ - ceph_msgr_flush(); - ceph_monc_stop(&client->monc); ceph_debugfs_client_cleanup(client); diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 10d6008d31f2..d0649a9655be 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c @@ -847,6 +847,14 @@ void ceph_monc_stop(struct ceph_mon_client *monc) mutex_unlock(&monc->mutex); + /* + * flush msgr queue before we destroy ourselves to ensure that: + * - any work that references our embedded con is finished. + * - any osd_client or other work that may reference an authorizer + * finishes before we shut down the auth subsystem. + */ + ceph_msgr_flush(); + ceph_auth_destroy(monc->auth); ceph_msg_put(monc->m_auth); -- cgit v1.3-14-g43fede From 88a9e31c506c00c8b7a2f1611406d0e38dcb33b3 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Fri, 1 Jun 2012 11:14:03 +0300 Subject: mac80211: clear ifmgd->bssid only after building DELBA ieee80211_set_disassoc() clears ifmgd->bssid before building DELBA frames, resulting in frames with invalid bssid ("00:00:00:00:00:00"). Fix it by clearing ifmgd->bssid only after building all the needed frames. After this change, we no longer need to save the bssid (before clearing it), so remove the local array. Reported-by: Ido Yariv Cc: stable@vger.kernel.org Signed-off-by: Eliad Peller Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 66e4fcdd1c6b..a4bb856de08f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1342,7 +1342,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, struct ieee80211_local *local = sdata->local; struct sta_info *sta; u32 changed = 0; - u8 bssid[ETH_ALEN]; ASSERT_MGD_MTX(ifmgd); @@ -1354,10 +1353,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, ieee80211_stop_poll(sdata); - memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); - ifmgd->associated = NULL; - memset(ifmgd->bssid, 0, ETH_ALEN); /* * we need to commit the associated = NULL change because the @@ -1377,7 +1373,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, netif_carrier_off(sdata->dev); mutex_lock(&local->sta_mtx); - sta = sta_info_get(sdata, bssid); + sta = sta_info_get(sdata, ifmgd->bssid); if (sta) { set_sta_flag(sta, WLAN_STA_BLOCK_BA); ieee80211_sta_tear_down_BA_sessions(sta, tx); @@ -1386,13 +1382,16 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, /* deauthenticate/disassociate now */ if (tx || frame_buf) - ieee80211_send_deauth_disassoc(sdata, bssid, stype, reason, - tx, frame_buf); + ieee80211_send_deauth_disassoc(sdata, ifmgd->bssid, stype, + reason, tx, frame_buf); /* flush out frame */ if (tx) drv_flush(local, false); + /* clear bssid only after building the needed mgmt frames */ + memset(ifmgd->bssid, 0, ETH_ALEN); + /* remove AP and TDLS peers */ sta_info_flush(local, sdata); -- cgit v1.3-14-g43fede From 5870adc68fc39d81089f1e80efdf64b97e5c37a1 Mon Sep 17 00:00:00 2001 From: Marek Lindner Date: Wed, 20 Jun 2012 17:16:05 +0200 Subject: batman-adv: only drop packets of known wifi clients bug introduced with 59b699cdee039d75915c354da06937102d1f9a84 If the source or destination mac address of an ethernet packet could not be found in the translation table the packet was dropped if AP isolation was turned on. This behavior would make it impossible to send broadcast packets over the mesh as the broadcast address will never enter the translation table. Signed-off-by: Marek Lindner Acked-by: Antonio Quartulli --- net/batman-adv/translation-table.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index a66c2dcd1088..660c40fe13ea 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -2031,10 +2031,10 @@ bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst) { struct tt_local_entry *tt_local_entry = NULL; struct tt_global_entry *tt_global_entry = NULL; - bool ret = true; + bool ret = false; if (!atomic_read(&bat_priv->ap_isolation)) - return false; + goto out; tt_local_entry = tt_local_hash_find(bat_priv, dst); if (!tt_local_entry) @@ -2044,10 +2044,10 @@ bool is_ap_isolated(struct bat_priv *bat_priv, uint8_t *src, uint8_t *dst) if (!tt_global_entry) goto out; - if (_is_ap_isolated(tt_local_entry, tt_global_entry)) + if (!_is_ap_isolated(tt_local_entry, tt_global_entry)) goto out; - ret = false; + ret = true; out: if (tt_global_entry) -- cgit v1.3-14-g43fede From 8b8e4bc0391f8abbcdb9e1c54415bcc0f4f5a2a0 Mon Sep 17 00:00:00 2001 From: Antonio Quartulli Date: Wed, 20 Jun 2012 14:12:56 +0200 Subject: batman-adv: fix race condition in TT full-table replacement bug introduced with cea194d90b11aff7fc289149e4c7f305fad3535a In the current TT code, when a TT_Response containing a full table is received from an originator, first the node purges all the clients for that originator in the global translation-table and then merges the newly received table. During the purging phase each client deletion is done by means of a call_rcu() invocation and at the end of this phase the global entry counter for that originator is set to 0. However the invoked rcu function decreases the global entry counter for that originator by one too and since the rcu invocation is likely to be postponed, the node will end up in first setting the counter to 0 and then decreasing it one by one for each deleted client. This bug leads to having a wrong global entry counter for the related node, say X. Then when the node with the broken counter will answer to a TT_REQUEST on behalf of node X, it will create faulty TT_RESPONSE that will generate an unrecoverable situation on the node that asked for the full table recover. The non-recoverability is given by the fact that the node with the broken counter will keep answering on behalf of X because its knowledge about X's state (ttvn + tt_crc) is correct. To solve this problem the counter is not explicitly set to 0 anymore and the counter decrement is performed right before the invocation of call_rcu(). Signed-off-by: Antonio Quartulli --- net/batman-adv/translation-table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 660c40fe13ea..2ab83d7fb1f8 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -141,13 +141,14 @@ static void tt_orig_list_entry_free_rcu(struct rcu_head *rcu) struct tt_orig_list_entry *orig_entry; orig_entry = container_of(rcu, struct tt_orig_list_entry, rcu); - atomic_dec(&orig_entry->orig_node->tt_size); orig_node_free_ref(orig_entry->orig_node); kfree(orig_entry); } static void tt_orig_list_entry_free_ref(struct tt_orig_list_entry *orig_entry) { + /* to avoid race conditions, immediately decrease the tt counter */ + atomic_dec(&orig_entry->orig_node->tt_size); call_rcu(&orig_entry->rcu, tt_orig_list_entry_free_rcu); } @@ -910,7 +911,6 @@ void tt_global_del_orig(struct bat_priv *bat_priv, } spin_unlock_bh(list_lock); } - atomic_set(&orig_node->tt_size, 0); orig_node->tt_initialised = false; } -- cgit v1.3-14-g43fede From ef5b6e127761667f78d99b7510a3876077fe9abe Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Sun, 17 Jun 2012 09:56:46 +0000 Subject: netfilter: ipset: fix interface comparision in hash-netiface sets ifname_compare() assumes that skb->dev is zero-padded, e.g 'eth1\0\0\0\0\0...'. This isn't always the case. e1000 driver does strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); in e1000_probe(), so once device is registered dev->name memory contains 'eth1\0:0:3\0\0\0' (or something like that), which makes eth1 compare fail. Use plain strcmp() instead. Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipset/ip_set_hash_netiface.c | 32 ++++-------------------------- 1 file changed, 4 insertions(+), 28 deletions(-) (limited to 'net') diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c index ee863943c826..d5d3607ae7bc 100644 --- a/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/net/netfilter/ipset/ip_set_hash_netiface.c @@ -38,30 +38,6 @@ struct iface_node { #define iface_data(n) (rb_entry(n, struct iface_node, node)->iface) -static inline long -ifname_compare(const char *_a, const char *_b) -{ - const long *a = (const long *)_a; - const long *b = (const long *)_b; - - BUILD_BUG_ON(IFNAMSIZ > 4 * sizeof(unsigned long)); - if (a[0] != b[0]) - return a[0] - b[0]; - if (IFNAMSIZ > sizeof(long)) { - if (a[1] != b[1]) - return a[1] - b[1]; - } - if (IFNAMSIZ > 2 * sizeof(long)) { - if (a[2] != b[2]) - return a[2] - b[2]; - } - if (IFNAMSIZ > 3 * sizeof(long)) { - if (a[3] != b[3]) - return a[3] - b[3]; - } - return 0; -} - static void rbtree_destroy(struct rb_root *root) { @@ -99,7 +75,7 @@ iface_test(struct rb_root *root, const char **iface) while (n) { const char *d = iface_data(n); - long res = ifname_compare(*iface, d); + int res = strcmp(*iface, d); if (res < 0) n = n->rb_left; @@ -121,7 +97,7 @@ iface_add(struct rb_root *root, const char **iface) while (*n) { char *ifname = iface_data(*n); - long res = ifname_compare(*iface, ifname); + int res = strcmp(*iface, ifname); p = *n; if (res < 0) @@ -366,7 +342,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], struct hash_netiface4_elem data = { .cidr = HOST_MASK }; u32 ip = 0, ip_to, last; u32 timeout = h->timeout; - char iface[IFNAMSIZ] = {}; + char iface[IFNAMSIZ]; int ret; if (unlikely(!tb[IPSET_ATTR_IP] || @@ -663,7 +639,7 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[], ipset_adtfn adtfn = set->variant->adt[adt]; struct hash_netiface6_elem data = { .cidr = HOST_MASK }; u32 timeout = h->timeout; - char iface[IFNAMSIZ] = {}; + char iface[IFNAMSIZ]; int ret; if (unlikely(!tb[IPSET_ATTR_IP] || -- cgit v1.3-14-g43fede From c24584c028a62900ea6b541b312030f0feac93b8 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 24 Jun 2012 21:58:23 +0000 Subject: netfilter: ipvs: fix dst leak in __ip_vs_addr_is_local_v6 After call to ip6_route_output() we must release dst or we leak it. Also should test dst->error, as ip6_route_output() never returns NULL. Use boolean while we are at it. Signed-off-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipvs/ip_vs_ctl.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index dd811b8dd97c..d43e3c122f7b 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -76,19 +76,19 @@ static void __ip_vs_del_service(struct ip_vs_service *svc); #ifdef CONFIG_IP_VS_IPV6 /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */ -static int __ip_vs_addr_is_local_v6(struct net *net, - const struct in6_addr *addr) +static bool __ip_vs_addr_is_local_v6(struct net *net, + const struct in6_addr *addr) { - struct rt6_info *rt; struct flowi6 fl6 = { .daddr = *addr, }; + struct dst_entry *dst = ip6_route_output(net, NULL, &fl6); + bool is_local; - rt = (struct rt6_info *)ip6_route_output(net, NULL, &fl6); - if (rt && rt->dst.dev && (rt->dst.dev->flags & IFF_LOOPBACK)) - return 1; + is_local = !dst->error && dst->dev && (dst->dev->flags & IFF_LOOPBACK); - return 0; + dst_release(dst); + return is_local; } #endif -- cgit v1.3-14-g43fede From 67de956ff5dc1d4f321e16cfbd63f5be3b691b43 Mon Sep 17 00:00:00 2001 From: Dan Rosenberg Date: Mon, 25 Jun 2012 16:05:27 +0200 Subject: NFC: Prevent multiple buffer overflows in NCI Fix multiple remotely-exploitable stack-based buffer overflows due to the NCI code pulling length fields directly from incoming frames and copying too much data into statically-sized arrays. Signed-off-by: Dan Rosenberg Cc: stable@kernel.org Cc: security@kernel.org Cc: Lauro Ramos Venancio Cc: Aloisio Almeida Jr Cc: Samuel Ortiz Cc: David S. Miller Acked-by: Ilan Elias Signed-off-by: Samuel Ortiz --- net/nfc/nci/ntf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index cb2646179e5f..2ab196a9f228 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c @@ -106,7 +106,7 @@ static __u8 *nci_extract_rf_params_nfca_passive_poll(struct nci_dev *ndev, nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data)); data += 2; - nfca_poll->nfcid1_len = *data++; + nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE); pr_debug("sens_res 0x%x, nfcid1_len %d\n", nfca_poll->sens_res, nfca_poll->nfcid1_len); @@ -130,7 +130,7 @@ static __u8 *nci_extract_rf_params_nfcb_passive_poll(struct nci_dev *ndev, struct rf_tech_specific_params_nfcb_poll *nfcb_poll, __u8 *data) { - nfcb_poll->sensb_res_len = *data++; + nfcb_poll->sensb_res_len = min_t(__u8, *data++, NFC_SENSB_RES_MAXSIZE); pr_debug("sensb_res_len %d\n", nfcb_poll->sensb_res_len); @@ -145,7 +145,7 @@ static __u8 *nci_extract_rf_params_nfcf_passive_poll(struct nci_dev *ndev, __u8 *data) { nfcf_poll->bit_rate = *data++; - nfcf_poll->sensf_res_len = *data++; + nfcf_poll->sensf_res_len = min_t(__u8, *data++, NFC_SENSF_RES_MAXSIZE); pr_debug("bit_rate %d, sensf_res_len %d\n", nfcf_poll->bit_rate, nfcf_poll->sensf_res_len); @@ -331,7 +331,7 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, switch (ntf->activation_rf_tech_and_mode) { case NCI_NFC_A_PASSIVE_POLL_MODE: nfca_poll = &ntf->activation_params.nfca_poll_iso_dep; - nfca_poll->rats_res_len = *data++; + nfca_poll->rats_res_len = min_t(__u8, *data++, 20); pr_debug("rats_res_len %d\n", nfca_poll->rats_res_len); if (nfca_poll->rats_res_len > 0) { memcpy(nfca_poll->rats_res, @@ -341,7 +341,7 @@ static int nci_extract_activation_params_iso_dep(struct nci_dev *ndev, case NCI_NFC_B_PASSIVE_POLL_MODE: nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep; - nfcb_poll->attrib_res_len = *data++; + nfcb_poll->attrib_res_len = min_t(__u8, *data++, 50); pr_debug("attrib_res_len %d\n", nfcb_poll->attrib_res_len); if (nfcb_poll->attrib_res_len > 0) { memcpy(nfcb_poll->attrib_res, -- cgit v1.3-14-g43fede From 1f41a6a9947615dca37d80b044ab81616e956a67 Mon Sep 17 00:00:00 2001 From: Henrik Rydberg Date: Mon, 25 Jun 2012 16:55:41 +0200 Subject: HID: Fix the generic Kconfig options The generic HID driver is obviously not a special driver, so move it outside of the special drivers menu. Explain the usage and make the default follow the HID setting. This should simplify migration from older kernels. While at it, remove the redundant HID_SUPPORT option and modify the HID and USB_HID entries to better explain the bus structure. Reported-by: Jan Beulich Signed-off-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 43 ++++++++++++++++++++----------------------- drivers/hid/usbhid/Kconfig | 8 ++++---- net/bluetooth/hidp/Kconfig | 2 +- 3 files changed, 25 insertions(+), 28 deletions(-) (limited to 'net') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index e9c68fedfcff..3089cd6c5755 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -1,20 +1,11 @@ # # HID driver configuration # -menuconfig HID_SUPPORT - bool "HID Devices" - depends on INPUT - default y - ---help--- - Say Y here to get to see options for various computer-human interface - device drivers. This option alone does not add any kernel code. - - If you say N, all options in this submenu will be skipped and disabled. - -if HID_SUPPORT +menu "HID support" + depends on INPUT config HID - tristate "Generic HID support" + tristate "HID bus support" depends on INPUT default y ---help--- @@ -23,14 +14,17 @@ config HID most commonly used to refer to the USB-HID specification, but other devices (such as, but not strictly limited to, Bluetooth) are designed using HID specification (this involves certain keyboards, - mice, tablets, etc). This option compiles into kernel the generic - HID layer code (parser, usages, etc.), which can then be used by - transport-specific HID implementation (like USB or Bluetooth). + mice, tablets, etc). This option adds the HID bus to the kernel, + together with generic HID layer code. The HID devices are added and + removed from the HID bus by the transport-layer drivers, such as + usbhid (USB_HID) and hidp (BT_HIDP). For docs and specs, see http://www.usb.org/developers/hidpage/ If unsure, say Y. +if HID + config HID_BATTERY_STRENGTH bool "Battery level reporting for HID devices" depends on HID && POWER_SUPPLY && HID = POWER_SUPPLY @@ -59,23 +53,22 @@ config HIDRAW If unsure, say Y. -source "drivers/hid/usbhid/Kconfig" - -menu "Special HID drivers" - depends on HID - config HID_GENERIC tristate "Generic HID driver" depends on HID - default y + default HID ---help--- - Support for generic HID devices. + Support for generic devices on the HID bus. This includes most + keyboards and mice, joysticks, tablets and digitizers. To compile this driver as a module, choose M here: the module will be called hid-generic. If unsure, say Y. +menu "Special HID drivers" + depends on HID + config HID_A4TECH tristate "A4 tech mice" if EXPERT depends on USB_HID @@ -662,4 +655,8 @@ config HID_ZYDACRON endmenu -endif # HID_SUPPORT +endif # HID + +source "drivers/hid/usbhid/Kconfig" + +endmenu diff --git a/drivers/hid/usbhid/Kconfig b/drivers/hid/usbhid/Kconfig index 0f20fd17cf06..0108c5991a04 100644 --- a/drivers/hid/usbhid/Kconfig +++ b/drivers/hid/usbhid/Kconfig @@ -1,13 +1,13 @@ -comment "USB Input Devices" +menu "USB HID support" depends on USB config USB_HID - tristate "USB Human Interface Device (full HID) support" + tristate "USB HID transport layer" default y depends on USB && INPUT select HID ---help--- - Say Y here if you want full HID support to connect USB keyboards, + Say Y here if you want to connect USB keyboards, mice, joysticks, graphic tablets, or any other HID based devices to your computer via USB, as well as Uninterruptible Power Supply (UPS) and monitor control devices. @@ -81,4 +81,4 @@ config USB_MOUSE endmenu - +endmenu diff --git a/net/bluetooth/hidp/Kconfig b/net/bluetooth/hidp/Kconfig index 4deaca78e91e..9332bc7aa851 100644 --- a/net/bluetooth/hidp/Kconfig +++ b/net/bluetooth/hidp/Kconfig @@ -1,6 +1,6 @@ config BT_HIDP tristate "HIDP protocol support" - depends on BT && INPUT && HID_SUPPORT + depends on BT && INPUT select HID help HIDP (Human Interface Device Protocol) is a transport layer -- cgit v1.3-14-g43fede From fa809e2fd6e317226c046202a88520962672eac0 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 25 Jun 2012 15:37:19 -0700 Subject: ipv6: fib: fix fib dump restart Commit 2bec5a369ee79576a3 (ipv6: fib: fix crash when changing large fib while dumping it) introduced ability to restart the dump at tree root, but failed to skip correctly a count of already dumped entries. Code didn't match Patrick intent. We must skip exactly the number of already dumped entries. Note that like other /proc/net files or netlink producers, we could still dump some duplicates entries. Reported-by: Debabrata Banerjee Reported-by: Josh Hunt Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv6/ip6_fib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 74c21b924a79..608327661960 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1349,8 +1349,8 @@ static int fib6_walk_continue(struct fib6_walker_t *w) if (w->leaf && fn->fn_flags & RTN_RTINFO) { int err; - if (w->count < w->skip) { - w->count++; + if (w->skip) { + w->skip--; continue; } -- cgit v1.3-14-g43fede From 437c5b53f63b468996090200df66ef2f3f588c80 Mon Sep 17 00:00:00 2001 From: Neal Cardwell Date: Sat, 23 Jun 2012 19:22:00 +0000 Subject: tcp: heed result of security_inet_conn_request() in tcp_v6_conn_request() If security_inet_conn_request() returns non-zero then TCP/IPv6 should drop the request, just as in TCP/IPv4 and DCCP in both IPv4 and IPv6. Signed-off-by: Neal Cardwell Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv6/tcp_ipv6.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 3a9aec29581a..9df64a50b075 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1212,7 +1212,8 @@ have_isn: tcp_rsk(req)->snt_isn = isn; tcp_rsk(req)->snt_synack = tcp_time_stamp; - security_inet_conn_request(sk, skb, req); + if (security_inet_conn_request(sk, skb, req)) + goto drop_and_release; if (tcp_v6_send_synack(sk, req, (struct request_values *)&tmp_ext, -- cgit v1.3-14-g43fede From eaa8c5f3cf6555294632c176e81439ca420ad07f Mon Sep 17 00:00:00 2001 From: Sjur Brændeland Date: Sun, 24 Jun 2012 11:01:36 +0000 Subject: caif: Clear shutdown mask to zero at reconnect. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clear caif sockets's shutdown mask at (re)connect. Signed-off-by: Sjur Brændeland Signed-off-by: David S. Miller --- net/caif/caif_socket.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index fb8944355264..78f1cdad5b33 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c @@ -220,6 +220,7 @@ static void caif_ctrl_cb(struct cflayer *layr, cfsk_hold, cfsk_put); cf_sk->sk.sk_state = CAIF_CONNECTED; set_tx_flow_on(cf_sk); + cf_sk->sk.sk_shutdown = 0; cf_sk->sk.sk_state_change(&cf_sk->sk); break; -- cgit v1.3-14-g43fede From aa214de0595eecf5079a172a16333fa638b64915 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 25 Jun 2012 00:45:14 +0000 Subject: net: l2tp_eth: fix l2tp_eth_dev_xmit race Its illegal to dereference skb after giving it to l2tp_xmit_skb() as it might be already freed/reused. Signed-off-by: Eric Dumazet Cc: James Chapman Signed-off-by: David S. Miller --- net/l2tp/l2tp_eth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 185f12f4a5fa..c3738f49646a 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -88,12 +88,12 @@ static int l2tp_eth_dev_xmit(struct sk_buff *skb, struct net_device *dev) struct l2tp_eth *priv = netdev_priv(dev); struct l2tp_session *session = priv->session; - l2tp_xmit_skb(session, skb, session->hdr_len); - dev->stats.tx_bytes += skb->len; dev->stats.tx_packets++; - return 0; + l2tp_xmit_skb(session, skb, session->hdr_len); + + return NETDEV_TX_OK; } static struct net_device_ops l2tp_eth_netdev_ops = { -- cgit v1.3-14-g43fede From 03e934f620101ca2cfc9383bd76172dd3e1f8567 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 12 Jun 2012 00:47:58 +0200 Subject: NFC: Return from rawsock_release when sk is NULL Sasha Levin reported following panic : [ 2136.383310] BUG: unable to handle kernel NULL pointer dereference at 00000000000003b0 [ 2136.384022] IP: [] __lock_acquire+0xc0/0x4b0 [ 2136.384022] PGD 131c4067 PUD 11c0c067 PMD 0 [ 2136.388106] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC [ 2136.388106] CPU 1 [ 2136.388106] Pid: 24855, comm: trinity-child1 Tainted: G W 3.5.0-rc2-sasha-00015-g7b268f7 #374 [ 2136.388106] RIP: 0010:[] [] __lock_acquire+0xc0/0x4b0 [ 2136.388106] RSP: 0018:ffff8800130b3ca8 EFLAGS: 00010046 [ 2136.388106] RAX: 0000000000000086 RBX: ffff88001186b000 RCX: 0000000000000000 [ 2136.388106] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 [ 2136.388106] RBP: ffff8800130b3d08 R08: 0000000000000001 R09: 0000000000000000 [ 2136.388106] R10: 0000000000000000 R11: 0000000000000001 R12: 0000000000000002 [ 2136.388106] R13: 00000000000003b0 R14: 0000000000000000 R15: 0000000000000000 [ 2136.388106] FS: 00007fa5b1bd4700(0000) GS:ffff88001b800000(0000) knlGS:0000000000000000 [ 2136.388106] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 2136.388106] CR2: 00000000000003b0 CR3: 0000000011d1f000 CR4: 00000000000406e0 [ 2136.388106] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 2136.388106] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 2136.388106] Process trinity-child1 (pid: 24855, threadinfo ffff8800130b2000, task ffff88001186b000) [ 2136.388106] Stack: [ 2136.388106] ffff8800130b3cd8 ffffffff81121785 ffffffff81236774 000080d000000001 [ 2136.388106] ffff88001b9d6c00 00000000001d6c00 ffffffff130b3d08 ffff88001186b000 [ 2136.388106] 0000000000000000 0000000000000002 0000000000000000 0000000000000000 [ 2136.388106] Call Trace: [ 2136.388106] [] ? sched_clock_local+0x25/0x90 [ 2136.388106] [] ? get_empty_filp+0x74/0x220 [ 2136.388106] [] lock_acquire+0x18a/0x1e0 [ 2136.388106] [] ? rawsock_release+0x4f/0xa0 [ 2136.388106] [] _raw_write_lock_bh+0x40/0x80 [ 2136.388106] [] ? rawsock_release+0x4f/0xa0 [ 2136.388106] [] rawsock_release+0x4f/0xa0 [ 2136.388106] [] sock_release+0x18/0x70 [ 2136.388106] [] sock_close+0x29/0x30 [ 2136.388106] [] __fput+0x11a/0x2c0 [ 2136.388106] [] fput+0x15/0x20 [ 2136.388106] [] sys_accept4+0x1b4/0x200 [ 2136.388106] [] ? _raw_spin_unlock_irq+0x4c/0x80 [ 2136.388106] [] ? _raw_spin_unlock_irq+0x59/0x80 [ 2136.388106] [] ? sysret_check+0x22/0x5d [ 2136.388106] [] sys_accept+0xb/0x10 [ 2136.388106] [] system_call_fastpath+0x16/0x1b [ 2136.388106] Code: ec 04 00 0f 85 ea 03 00 00 be d5 0b 00 00 48 c7 c7 8a c1 40 84 e8 b1 a5 f8 ff 31 c0 e9 d4 03 00 00 66 2e 0f 1f 84 00 00 00 00 00 <49> 81 7d 00 60 73 5e 85 b8 01 00 00 00 44 0f 44 e0 83 fe 01 77 [ 2136.388106] RIP [] __lock_acquire+0xc0/0x4b0 [ 2136.388106] RSP [ 2136.388106] CR2: 00000000000003b0 [ 2136.388106] ---[ end trace 6d450e935ee18982 ]--- [ 2136.388106] Kernel panic - not syncing: Fatal exception in interrupt rawsock_release() should test if sock->sk is NULL before calling sock_orphan()/sock_put() Reported-by: Sasha Levin Tested-by: Sasha Levin Cc: stable@kernel.org Signed-off-by: Eric Dumazet Signed-off-by: Samuel Ortiz --- net/nfc/rawsock.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index ec1134c9e07f..8b8a6a2b2bad 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c @@ -54,7 +54,10 @@ static int rawsock_release(struct socket *sock) { struct sock *sk = sock->sk; - pr_debug("sock=%p\n", sock); + pr_debug("sock=%p sk=%p\n", sock, sk); + + if (!sk) + return 0; sock_orphan(sk); sock_put(sk); -- cgit v1.3-14-g43fede From 8a8e28b8e2c27362f24cf06513c05d5e3a304e03 Mon Sep 17 00:00:00 2001 From: "alex.bluesman.smirnov@gmail.com" Date: Mon, 25 Jun 2012 03:30:13 +0000 Subject: mac802154: add missed braces Add missed braces after 'if' operator. Signed-off-by: Alexander Smirnov Signed-off-by: David S. Miller --- net/mac802154/tx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c index 8781d8f904d9..434b6873b352 100644 --- a/net/mac802154/tx.c +++ b/net/mac802154/tx.c @@ -83,9 +83,10 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb, { struct xmit_work *work; - if (!(priv->phy->channels_supported[page] & (1 << chan))) + if (!(priv->phy->channels_supported[page] & (1 << chan))) { WARN_ON(1); return NETDEV_TX_OK; + } if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) { u16 crc = crc_ccitt(0, skb->data, skb->len); -- cgit v1.3-14-g43fede From a2842a1e66329798d66563b52faec1a299ec4f73 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 25 Jun 2012 05:35:45 +0000 Subject: net: l2tp_eth: use LLTX to avoid LOCKDEP splats Denys Fedoryshchenko reported a LOCKDEP issue with l2tp code. [ 8683.927442] ====================================================== [ 8683.927555] [ INFO: possible circular locking dependency detected ] [ 8683.927672] 3.4.1-build-0061 #14 Not tainted [ 8683.927782] ------------------------------------------------------- [ 8683.927895] swapper/0/0 is trying to acquire lock: [ 8683.928007] (slock-AF_INET){+.-...}, at: [] l2tp_xmit_skb+0x173/0x47e [l2tp_core] [ 8683.928121] [ 8683.928121] but task is already holding lock: [ 8683.928121] (_xmit_ETHER#2){+.-...}, at: [] sch_direct_xmit+0x36/0x119 [ 8683.928121] [ 8683.928121] which lock already depends on the new lock. [ 8683.928121] [ 8683.928121] [ 8683.928121] the existing dependency chain (in reverse order) is: [ 8683.928121] [ 8683.928121] -> #1 (_xmit_ETHER#2){+.-...}: [ 8683.928121] [] lock_acquire+0x71/0x85 [ 8683.928121] [] _raw_spin_lock+0x33/0x40 [ 8683.928121] [] ip_send_reply+0xf2/0x1ce [ 8683.928121] [] tcp_v4_send_reset+0x153/0x16f [ 8683.928121] [] tcp_v4_do_rcv+0x172/0x194 [ 8683.928121] [] tcp_v4_rcv+0x387/0x5a0 [ 8683.928121] [] ip_local_deliver_finish+0x13a/0x1e9 [ 8683.928121] [] NF_HOOK.clone.11+0x46/0x4d [ 8683.928121] [] ip_local_deliver+0x41/0x45 [ 8683.928121] [] ip_rcv_finish+0x31a/0x33c [ 8683.928121] [] NF_HOOK.clone.11+0x46/0x4d [ 8683.928121] [] ip_rcv+0x201/0x23d [ 8683.928121] [] __netif_receive_skb+0x329/0x378 [ 8683.928121] [] netif_receive_skb+0x4e/0x7d [ 8683.928121] [] rtl8139_poll+0x243/0x33d [8139too] [ 8683.928121] [] net_rx_action+0x90/0x15d [ 8683.928121] [] __do_softirq+0x7b/0x118 [ 8683.928121] [ 8683.928121] -> #0 (slock-AF_INET){+.-...}: [ 8683.928121] [] __lock_acquire+0x9a3/0xc27 [ 8683.928121] [] lock_acquire+0x71/0x85 [ 8683.928121] [] _raw_spin_lock+0x33/0x40 [ 8683.928121] [] l2tp_xmit_skb+0x173/0x47e [l2tp_core] [ 8683.928121] [] l2tp_eth_dev_xmit+0x1a/0x2f [l2tp_eth] [ 8683.928121] [] dev_hard_start_xmit+0x333/0x3f2 [ 8683.928121] [] sch_direct_xmit+0x55/0x119 [ 8683.928121] [] dev_queue_xmit+0x282/0x418 [ 8683.928121] [] NF_HOOK.clone.19+0x45/0x4c [ 8683.928121] [] arp_xmit+0x22/0x24 [ 8683.928121] [] arp_send+0x41/0x48 [ 8683.928121] [] arp_process+0x289/0x491 [ 8683.928121] [] NF_HOOK.clone.19+0x45/0x4c [ 8683.928121] [] arp_rcv+0xb1/0xc3 [ 8683.928121] [] __netif_receive_skb+0x329/0x378 [ 8683.928121] [] process_backlog+0x69/0x130 [ 8683.928121] [] net_rx_action+0x90/0x15d [ 8683.928121] [] __do_softirq+0x7b/0x118 [ 8683.928121] [ 8683.928121] other info that might help us debug this: [ 8683.928121] [ 8683.928121] Possible unsafe locking scenario: [ 8683.928121] [ 8683.928121] CPU0 CPU1 [ 8683.928121] ---- ---- [ 8683.928121] lock(_xmit_ETHER#2); [ 8683.928121] lock(slock-AF_INET); [ 8683.928121] lock(_xmit_ETHER#2); [ 8683.928121] lock(slock-AF_INET); [ 8683.928121] [ 8683.928121] *** DEADLOCK *** [ 8683.928121] [ 8683.928121] 3 locks held by swapper/0/0: [ 8683.928121] #0: (rcu_read_lock){.+.+..}, at: [] rcu_lock_acquire+0x0/0x30 [ 8683.928121] #1: (rcu_read_lock_bh){.+....}, at: [] rcu_lock_acquire+0x0/0x30 [ 8683.928121] #2: (_xmit_ETHER#2){+.-...}, at: [] sch_direct_xmit+0x36/0x119 [ 8683.928121] [ 8683.928121] stack backtrace: [ 8683.928121] Pid: 0, comm: swapper/0 Not tainted 3.4.1-build-0061 #14 [ 8683.928121] Call Trace: [ 8683.928121] [] ? printk+0x18/0x1a [ 8683.928121] [] print_circular_bug+0x1ac/0x1b6 [ 8683.928121] [] __lock_acquire+0x9a3/0xc27 [ 8683.928121] [] lock_acquire+0x71/0x85 [ 8683.928121] [] ? l2tp_xmit_skb+0x173/0x47e [l2tp_core] [ 8683.928121] [] _raw_spin_lock+0x33/0x40 [ 8683.928121] [] ? l2tp_xmit_skb+0x173/0x47e [l2tp_core] [ 8683.928121] [] l2tp_xmit_skb+0x173/0x47e [l2tp_core] [ 8683.928121] [] l2tp_eth_dev_xmit+0x1a/0x2f [l2tp_eth] [ 8683.928121] [] dev_hard_start_xmit+0x333/0x3f2 [ 8683.928121] [] sch_direct_xmit+0x55/0x119 [ 8683.928121] [] dev_queue_xmit+0x282/0x418 [ 8683.928121] [] ? dev_hard_start_xmit+0x3f2/0x3f2 [ 8683.928121] [] NF_HOOK.clone.19+0x45/0x4c [ 8683.928121] [] arp_xmit+0x22/0x24 [ 8683.928121] [] ? dev_hard_start_xmit+0x3f2/0x3f2 [ 8683.928121] [] arp_send+0x41/0x48 [ 8683.928121] [] arp_process+0x289/0x491 [ 8683.928121] [] ? __neigh_lookup.clone.20+0x42/0x42 [ 8683.928121] [] NF_HOOK.clone.19+0x45/0x4c [ 8683.928121] [] arp_rcv+0xb1/0xc3 [ 8683.928121] [] ? __neigh_lookup.clone.20+0x42/0x42 [ 8683.928121] [] __netif_receive_skb+0x329/0x378 [ 8683.928121] [] process_backlog+0x69/0x130 [ 8683.928121] [] net_rx_action+0x90/0x15d [ 8683.928121] [] __do_softirq+0x7b/0x118 [ 8683.928121] [] ? local_bh_enable+0xd/0xd [ 8683.928121] [] ? irq_exit+0x41/0x91 [ 8683.928121] [] ? do_IRQ+0x79/0x8d [ 8683.928121] [] ? trace_hardirqs_off_caller+0x2e/0x86 [ 8683.928121] [] ? common_interrupt+0x2e/0x34 [ 8683.928121] [] ? default_idle+0x23/0x38 [ 8683.928121] [] ? cpu_idle+0x55/0x6f [ 8683.928121] [] ? rest_init+0xa1/0xa7 [ 8683.928121] [] ? __read_lock_failed+0x14/0x14 [ 8683.928121] [] ? start_kernel+0x303/0x30a [ 8683.928121] [] ? repair_env_string+0x51/0x51 [ 8683.928121] [] ? i386_start_kernel+0xa8/0xaf It appears that like most virtual devices, l2tp should be converted to LLTX mode. This patch takes care of statistics using atomic_long in both RX and TX paths, and fix a bug in l2tp_eth_dev_recv(), which was caching skb->data before a pskb_may_pull() call. Signed-off-by: Eric Dumazet Reported-by: Denys Fedoryshchenko Cc: James Chapman Cc: Hong zhi guo Cc: Francois Romieu Signed-off-by: David S. Miller --- net/l2tp/l2tp_eth.c | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) (limited to 'net') diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index c3738f49646a..47b259fccd27 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -42,6 +42,11 @@ struct l2tp_eth { struct sock *tunnel_sock; struct l2tp_session *session; struct list_head list; + atomic_long_t tx_bytes; + atomic_long_t tx_packets; + atomic_long_t rx_bytes; + atomic_long_t rx_packets; + atomic_long_t rx_errors; }; /* via l2tp_session_priv() */ @@ -88,24 +93,40 @@ static int l2tp_eth_dev_xmit(struct sk_buff *skb, struct net_device *dev) struct l2tp_eth *priv = netdev_priv(dev); struct l2tp_session *session = priv->session; - dev->stats.tx_bytes += skb->len; - dev->stats.tx_packets++; + atomic_long_add(skb->len, &priv->tx_bytes); + atomic_long_inc(&priv->tx_packets); l2tp_xmit_skb(session, skb, session->hdr_len); return NETDEV_TX_OK; } +static struct rtnl_link_stats64 *l2tp_eth_get_stats64(struct net_device *dev, + struct rtnl_link_stats64 *stats) +{ + struct l2tp_eth *priv = netdev_priv(dev); + + stats->tx_bytes = atomic_long_read(&priv->tx_bytes); + stats->tx_packets = atomic_long_read(&priv->tx_packets); + stats->rx_bytes = atomic_long_read(&priv->rx_bytes); + stats->rx_packets = atomic_long_read(&priv->rx_packets); + stats->rx_errors = atomic_long_read(&priv->rx_errors); + return stats; +} + + static struct net_device_ops l2tp_eth_netdev_ops = { .ndo_init = l2tp_eth_dev_init, .ndo_uninit = l2tp_eth_dev_uninit, .ndo_start_xmit = l2tp_eth_dev_xmit, + .ndo_get_stats64 = l2tp_eth_get_stats64, }; static void l2tp_eth_dev_setup(struct net_device *dev) { ether_setup(dev); - dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->priv_flags &= ~IFF_TX_SKB_SHARING; + dev->features |= NETIF_F_LLTX; dev->netdev_ops = &l2tp_eth_netdev_ops; dev->destructor = free_netdev; } @@ -114,17 +135,17 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, { struct l2tp_eth_sess *spriv = l2tp_session_priv(session); struct net_device *dev = spriv->dev; + struct l2tp_eth *priv = netdev_priv(dev); if (session->debug & L2TP_MSG_DATA) { unsigned int length; - u8 *ptr = skb->data; length = min(32u, skb->len); if (!pskb_may_pull(skb, length)) goto error; pr_debug("%s: eth recv\n", session->name); - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length); + print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, skb->data, length); } if (!pskb_may_pull(skb, sizeof(ETH_HLEN))) @@ -139,15 +160,15 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, nf_reset(skb); if (dev_forward_skb(dev, skb) == NET_RX_SUCCESS) { - dev->stats.rx_packets++; - dev->stats.rx_bytes += data_len; - } else - dev->stats.rx_errors++; - + atomic_long_inc(&priv->rx_packets); + atomic_long_add(data_len, &priv->rx_bytes); + } else { + atomic_long_inc(&priv->rx_errors); + } return; error: - dev->stats.rx_errors++; + atomic_long_inc(&priv->rx_errors); kfree_skb(skb); } -- cgit v1.3-14-g43fede From 149ddd83a92b02c658d6c61f3276eb6500d585e8 Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Tue, 26 Jun 2012 05:48:45 +0000 Subject: bridge: Assign rtnl_link_ops to bridge devices created via ioctl (v2) This ensures that bridges created with brctl(8) or ioctl(2) directly also carry IFLA_LINKINFO when dumped over netlink. This also allows to create a bridge with ioctl(2) and delete it with RTM_DELLINK. Signed-off-by: Thomas Graf Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_if.c | 1 + net/bridge/br_netlink.c | 2 +- net/bridge/br_private.h | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 0a942fbccc9a..e1144e1617be 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -240,6 +240,7 @@ int br_add_bridge(struct net *net, const char *name) return -ENOMEM; dev_net_set(dev, net); + dev->rtnl_link_ops = &br_link_ops; res = register_netdev(dev); if (res) diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 2080485515f1..fe41260fbf38 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c @@ -208,7 +208,7 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[]) return 0; } -static struct rtnl_link_ops br_link_ops __read_mostly = { +struct rtnl_link_ops br_link_ops __read_mostly = { .kind = "bridge", .priv_size = sizeof(struct net_bridge), .setup = br_dev_setup, diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 1a8ad4fb9a6b..a768b2408edf 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -549,6 +549,7 @@ extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr) #endif /* br_netlink.c */ +extern struct rtnl_link_ops br_link_ops; extern int br_netlink_init(void); extern void br_netlink_fini(void); extern void br_ifinfo_notify(int event, struct net_bridge_port *port); -- cgit v1.3-14-g43fede From 4b5ebccc40843104d980f0714bc86bfcd5568941 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 27 Jun 2012 15:38:56 +0200 Subject: mac80211: correct behaviour on unrecognised action frames When receiving an "individually addressed" action frame, the receiver is required to return it to the sender. mac80211 gets this wrong as it also returns group addressed (mcast) frames to the sender. Fix this and update the reference to the new 802.11 standards version since things were shuffled around significantly. Cc: stable@kernel.org Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/rx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 7bcecf73aafb..965e6ec0adb6 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2455,7 +2455,7 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) * frames that we didn't handle, including returning unknown * ones. For all other modes we will return them to the sender, * setting the 0x80 bit in the action category, as required by - * 802.11-2007 7.3.1.11. + * 802.11-2012 9.24.4. * Newer versions of hostapd shall also use the management frame * registration mechanisms, but older ones still use cooked * monitor interfaces so push all frames there. @@ -2465,6 +2465,9 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx) sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) return RX_DROP_MONITOR; + if (is_multicast_ether_addr(mgmt->da)) + return RX_DROP_MONITOR; + /* do not return rejected action frames */ if (mgmt->u.action.category & 0x80) return RX_DROP_UNUSABLE; -- cgit v1.3-14-g43fede From d31bb4f0621756528d11d310c44cd8076b22bc03 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 26 Jun 2012 23:01:41 +0000 Subject: 9p: fix min_t() casting in p9pdu_vwritef() I don't think we're actually likely to hit this limit but if we do then the comparison should be done as size_t. The original code is equivalent to: len = strlen(sptr) % USHRT_MAX; Signed-off-by: Dan Carpenter Signed-off-by: David S. Miller --- net/9p/protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/9p/protocol.c b/net/9p/protocol.c index 9ee48cb30179..3d33ecf13327 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c @@ -368,7 +368,7 @@ p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, const char *sptr = va_arg(ap, const char *); uint16_t len = 0; if (sptr) - len = min_t(uint16_t, strlen(sptr), + len = min_t(size_t, strlen(sptr), USHRT_MAX); errcode = p9pdu_writef(pdu, proto_version, -- cgit v1.3-14-g43fede From 7cecb523adedcaf8acba5e14d47559d8bc3f40d7 Mon Sep 17 00:00:00 2001 From: Vinson Lee Date: Wed, 27 Jun 2012 14:32:07 +0000 Subject: net: Downgrade CAP_SYS_MODULE deprecated message from error to warning. Make logging level consistent with other deprecation messages in net subsystem. Signed-off-by: Vinson Lee Cc: David Mackey Signed-off-by: David S. Miller --- net/core/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/core/dev.c b/net/core/dev.c index 6df214041a5e..84f01ba81a34 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1136,8 +1136,8 @@ void dev_load(struct net *net, const char *name) no_module = request_module("netdev-%s", name); if (no_module && capable(CAP_SYS_MODULE)) { if (!request_module("%s", name)) - pr_err("Loading kernel module for a network device with CAP_SYS_MODULE (deprecated). Use CAP_NET_ADMIN and alias netdev-%s instead.\n", - name); + pr_warn("Loading kernel module for a network device with CAP_SYS_MODULE (deprecated). Use CAP_NET_ADMIN and alias netdev-%s instead.\n", + name); } } EXPORT_SYMBOL(dev_load); -- cgit v1.3-14-g43fede From d31f4d448f7671dc3e6a7a1c92a4c085a36058bb Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Thu, 28 Jun 2012 02:57:48 +0000 Subject: netfilter: ipset: fix crash if IPSET_CMD_NONE command is sent This patch fixes a crash if that ipset command is sent over nfnetlink. Signed-off-by: Tomasz Bursztyka Acked-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipset/ip_set_core.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'net') diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index 819c342f5b30..9730882697aa 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c @@ -639,6 +639,14 @@ find_free_id(const char *name, ip_set_id_t *index, struct ip_set **set) return 0; } +static int +ip_set_none(struct sock *ctnl, struct sk_buff *skb, + const struct nlmsghdr *nlh, + const struct nlattr * const attr[]) +{ + return -EOPNOTSUPP; +} + static int ip_set_create(struct sock *ctnl, struct sk_buff *skb, const struct nlmsghdr *nlh, @@ -1539,6 +1547,10 @@ nlmsg_failure: } static const struct nfnl_callback ip_set_netlink_subsys_cb[IPSET_MSG_MAX] = { + [IPSET_CMD_NONE] = { + .call = ip_set_none, + .attr_count = IPSET_ATTR_CMD_MAX, + }, [IPSET_CMD_CREATE] = { .call = ip_set_create, .attr_count = IPSET_ATTR_CMD_MAX, -- cgit v1.3-14-g43fede From 4009e18851ea555959c6017d848983b3d60bf667 Mon Sep 17 00:00:00 2001 From: Tomasz Bursztyka Date: Thu, 28 Jun 2012 02:57:49 +0000 Subject: netfilter: nfnetlink: fix missing rcu_read_unlock in nfnetlink_rcv_msg Bug added in commit 6b75e3e8d664a9a (netfilter: nfnetlink: add RCU in nfnetlink_rcv_msg()) Signed-off-by: Tomasz Bursztyka Acked-by: Eric Dumazet Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nfnetlink.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 3e797d1fcb94..791d56bbd74a 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -169,8 +169,10 @@ replay: err = nla_parse(cda, ss->cb[cb_id].attr_count, attr, attrlen, ss->cb[cb_id].policy); - if (err < 0) + if (err < 0) { + rcu_read_unlock(); return err; + } if (nc->call_rcu) { err = nc->call_rcu(net->nfnl, skb, nlh, -- cgit v1.3-14-g43fede From 4244854d22bf8f782698c5224b9191c8d2d42610 Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Sat, 30 Jun 2012 03:04:26 +0000 Subject: sctp: be more restrictive in transport selection on bundled sacks It was noticed recently that when we send data on a transport, its possible that we might bundle a sack that arrived on a different transport. While this isn't a major problem, it does go against the SHOULD requirement in section 6.4 of RFC 2960: An endpoint SHOULD transmit reply chunks (e.g., SACK, HEARTBEAT ACK, etc.) to the same destination transport address from which it received the DATA or control chunk to which it is replying. This rule should also be followed if the endpoint is bundling DATA chunks together with the reply chunk. This patch seeks to correct that. It restricts the bundling of sack operations to only those transports which have moved the ctsn of the association forward since the last sack. By doing this we guarantee that we only bundle outbound saks on a transport that has received a chunk since the last sack. This brings us into stricter compliance with the RFC. Vlad had initially suggested that we strictly allow only sack bundling on the transport that last moved the ctsn forward. While this makes sense, I was concerned that doing so prevented us from bundling in the case where we had received chunks that moved the ctsn on multiple transports. In those cases, the RFC allows us to select any of the transports having received chunks to bundle the sack on. so I've modified the approach to allow for that, by adding a state variable to each transport that tracks weather it has moved the ctsn since the last sack. This I think keeps our behavior (and performance), close enough to our current profile that I think we can do this without a sysctl knob to enable/disable it. Signed-off-by: Neil Horman CC: Vlad Yaseivch CC: David S. Miller CC: linux-sctp@vger.kernel.org Reported-by: Michele Baldessari Reported-by: sorin serban Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- include/net/sctp/structs.h | 4 ++++ include/net/sctp/tsnmap.h | 3 ++- net/sctp/associola.c | 1 + net/sctp/output.c | 5 +++++ net/sctp/sm_make_chunk.c | 16 ++++++++++++++++ net/sctp/sm_sideeffect.c | 2 +- net/sctp/transport.c | 2 ++ net/sctp/tsnmap.c | 6 +++++- net/sctp/ulpevent.c | 3 ++- net/sctp/ulpqueue.c | 2 +- 10 files changed, 39 insertions(+), 5 deletions(-) (limited to 'net') diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index e4652fe58958..fecdf31816f2 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -912,6 +912,9 @@ struct sctp_transport { /* Is this structure kfree()able? */ malloced:1; + /* Has this transport moved the ctsn since we last sacked */ + __u32 sack_generation; + struct flowi fl; /* This is the peer's IP address and port. */ @@ -1584,6 +1587,7 @@ struct sctp_association { */ __u8 sack_needed; /* Do we need to sack the peer? */ __u32 sack_cnt; + __u32 sack_generation; /* These are capabilities which our peer advertised. */ __u8 ecn_capable:1, /* Can peer do ECN? */ diff --git a/include/net/sctp/tsnmap.h b/include/net/sctp/tsnmap.h index e7728bc14ccf..2c5d2b4d5d1e 100644 --- a/include/net/sctp/tsnmap.h +++ b/include/net/sctp/tsnmap.h @@ -117,7 +117,8 @@ void sctp_tsnmap_free(struct sctp_tsnmap *map); int sctp_tsnmap_check(const struct sctp_tsnmap *, __u32 tsn); /* Mark this TSN as seen. */ -int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn); +int sctp_tsnmap_mark(struct sctp_tsnmap *, __u32 tsn, + struct sctp_transport *trans); /* Mark this TSN and all lower as seen. */ void sctp_tsnmap_skip(struct sctp_tsnmap *map, __u32 tsn); diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 5bc9ab161b37..b16517ee1aaf 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c @@ -271,6 +271,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a */ asoc->peer.sack_needed = 1; asoc->peer.sack_cnt = 0; + asoc->peer.sack_generation = 1; /* Assume that the peer will tell us if he recognizes ASCONF * as part of INIT exchange. diff --git a/net/sctp/output.c b/net/sctp/output.c index f1b7d4bb591e..6ae47acaaec6 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c @@ -248,6 +248,11 @@ static sctp_xmit_t sctp_packet_bundle_sack(struct sctp_packet *pkt, /* If the SACK timer is running, we have a pending SACK */ if (timer_pending(timer)) { struct sctp_chunk *sack; + + if (pkt->transport->sack_generation != + pkt->transport->asoc->peer.sack_generation) + return retval; + asoc->a_rwnd = asoc->rwnd; sack = sctp_make_sack(asoc); if (sack) { diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index a85eeeb55dd0..b6de71efb140 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -734,8 +734,10 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) int len; __u32 ctsn; __u16 num_gabs, num_dup_tsns; + struct sctp_association *aptr = (struct sctp_association *)asoc; struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; struct sctp_gap_ack_block gabs[SCTP_MAX_GABS]; + struct sctp_transport *trans; memset(gabs, 0, sizeof(gabs)); ctsn = sctp_tsnmap_get_ctsn(map); @@ -805,6 +807,20 @@ struct sctp_chunk *sctp_make_sack(const struct sctp_association *asoc) sctp_addto_chunk(retval, sizeof(__u32) * num_dup_tsns, sctp_tsnmap_get_dups(map)); + /* Once we have a sack generated, check to see what our sack + * generation is, if its 0, reset the transports to 0, and reset + * the association generation to 1 + * + * The idea is that zero is never used as a valid generation for the + * association so no transport will match after a wrap event like this, + * Until the next sack + */ + if (++aptr->peer.sack_generation == 0) { + list_for_each_entry(trans, &asoc->peer.transport_addr_list, + transports) + trans->sack_generation = 0; + aptr->peer.sack_generation = 1; + } nodata: return retval; } diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index c96d1a81cf42..8716da1a8592 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c @@ -1268,7 +1268,7 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, case SCTP_CMD_REPORT_TSN: /* Record the arrival of a TSN. */ error = sctp_tsnmap_mark(&asoc->peer.tsn_map, - cmd->obj.u32); + cmd->obj.u32, NULL); break; case SCTP_CMD_REPORT_FWDTSN: diff --git a/net/sctp/transport.c b/net/sctp/transport.c index b026ba0c6992..1dcceb6e0ce6 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c @@ -68,6 +68,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, peer->af_specific = sctp_get_af_specific(addr->sa.sa_family); memset(&peer->saddr, 0, sizeof(union sctp_addr)); + peer->sack_generation = 0; + /* From 6.3.1 RTO Calculation: * * C1) Until an RTT measurement has been made for a packet sent to the diff --git a/net/sctp/tsnmap.c b/net/sctp/tsnmap.c index f1e40cebc981..b5fb7c409023 100644 --- a/net/sctp/tsnmap.c +++ b/net/sctp/tsnmap.c @@ -114,7 +114,8 @@ int sctp_tsnmap_check(const struct sctp_tsnmap *map, __u32 tsn) /* Mark this TSN as seen. */ -int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn) +int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn, + struct sctp_transport *trans) { u16 gap; @@ -133,6 +134,9 @@ int sctp_tsnmap_mark(struct sctp_tsnmap *map, __u32 tsn) */ map->max_tsn_seen++; map->cumulative_tsn_ack_point++; + if (trans) + trans->sack_generation = + trans->asoc->peer.sack_generation; map->base_tsn++; } else { /* Either we already have a gap, or about to record a gap, so diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 8a84017834c2..33d894776192 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c @@ -715,7 +715,8 @@ struct sctp_ulpevent *sctp_ulpevent_make_rcvmsg(struct sctp_association *asoc, * can mark it as received so the tsn_map is updated correctly. */ if (sctp_tsnmap_mark(&asoc->peer.tsn_map, - ntohl(chunk->subh.data_hdr->tsn))) + ntohl(chunk->subh.data_hdr->tsn), + chunk->transport)) goto fail_mark; /* First calculate the padding, so we don't inadvertently diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index f2d1de7f2ffb..f5a6a4f4faf7 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -1051,7 +1051,7 @@ void sctp_ulpq_renege(struct sctp_ulpq *ulpq, struct sctp_chunk *chunk, if (chunk && (freed >= needed)) { __u32 tsn; tsn = ntohl(chunk->subh.data_hdr->tsn); - sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn); + sctp_tsnmap_mark(&asoc->peer.tsn_map, tsn, chunk->transport); sctp_ulpq_tail_data(ulpq, chunk, gfp); sctp_ulpq_partial_delivery(ulpq, chunk, gfp); -- cgit v1.3-14-g43fede From 2d3f6ccc4ea5c74d4b4af1b47c56b4cff4bbfcb7 Mon Sep 17 00:00:00 2001 From: Simon Wunderlich Date: Wed, 4 Jul 2012 20:38:19 +0200 Subject: batman-adv: check incoming packet type for bla If the gateway functionality is used, some broadcast packets (DHCP requests) may be transmitted as unicast packets. As the bridge loop avoidance code now only considers the payload Ethernet destination, it may drop the DHCP request for clients which are claimed by other backbone gateways, because it falsely infers from the broadcast address that the right backbone gateway should havehandled the broadcast. Fix this by checking and delegating the batman-adv packet type used for transmission. Reported-by: Guido Iribarren Signed-off-by: Simon Wunderlich --- net/batman-adv/bridge_loop_avoidance.c | 15 +++++++++++---- net/batman-adv/bridge_loop_avoidance.h | 5 +++-- net/batman-adv/soft-interface.c | 6 +++++- 3 files changed, 19 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 8bf97515a77d..c5863f499133 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -1351,6 +1351,7 @@ void bla_free(struct bat_priv *bat_priv) * @bat_priv: the bat priv with all the soft interface information * @skb: the frame to be checked * @vid: the VLAN ID of the frame + * @is_bcast: the packet came in a broadcast packet type. * * bla_rx avoidance checks if: * * we have to race for a claim @@ -1361,7 +1362,8 @@ void bla_free(struct bat_priv *bat_priv) * process the skb. * */ -int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid) +int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid, + bool is_bcast) { struct ethhdr *ethhdr; struct claim search_claim, *claim = NULL; @@ -1380,7 +1382,7 @@ int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid) if (unlikely(atomic_read(&bat_priv->bla_num_requests))) /* don't allow broadcasts while requests are in flight */ - if (is_multicast_ether_addr(ethhdr->h_dest)) + if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) goto handled; memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN); @@ -1406,8 +1408,13 @@ int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid) } /* if it is a broadcast ... */ - if (is_multicast_ether_addr(ethhdr->h_dest)) { - /* ... drop it. the responsible gateway is in charge. */ + if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) { + /* ... drop it. the responsible gateway is in charge. + * + * We need to check is_bcast because with the gateway + * feature, broadcasts (like DHCP requests) may be sent + * using a unicast packet type. + */ goto handled; } else { /* seems the client considers us as its best gateway. diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h index e39f93acc28f..dc5227b398d4 100644 --- a/net/batman-adv/bridge_loop_avoidance.h +++ b/net/batman-adv/bridge_loop_avoidance.h @@ -23,7 +23,8 @@ #define _NET_BATMAN_ADV_BLA_H_ #ifdef CONFIG_BATMAN_ADV_BLA -int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid); +int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid, + bool is_bcast); int bla_tx(struct bat_priv *bat_priv, struct sk_buff *skb, short vid); int bla_is_backbone_gw(struct sk_buff *skb, struct orig_node *orig_node, int hdr_size); @@ -41,7 +42,7 @@ void bla_free(struct bat_priv *bat_priv); #else /* ifdef CONFIG_BATMAN_ADV_BLA */ static inline int bla_rx(struct bat_priv *bat_priv, struct sk_buff *skb, - short vid) + short vid, bool is_bcast) { return 0; } diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 6e2530b02043..a0ec0e4ada4c 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c @@ -256,7 +256,11 @@ void interface_rx(struct net_device *soft_iface, struct bat_priv *bat_priv = netdev_priv(soft_iface); struct ethhdr *ethhdr; struct vlan_ethhdr *vhdr; + struct batman_header *batadv_header = (struct batman_header *)skb->data; short vid __maybe_unused = -1; + bool is_bcast; + + is_bcast = (batadv_header->packet_type == BAT_BCAST); /* check if enough space is available for pulling, and pull */ if (!pskb_may_pull(skb, hdr_size)) @@ -302,7 +306,7 @@ void interface_rx(struct net_device *soft_iface, /* Let the bridge loop avoidance check the packet. If will * not handle it, we can safely push it up. */ - if (bla_rx(bat_priv, skb, vid)) + if (bla_rx(bat_priv, skb, vid, is_bcast)) goto out; netif_rx(skb); -- cgit v1.3-14-g43fede From 3da947b2693993d5f6138f005d2625e9387c9618 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 2 Jul 2012 01:29:55 +0000 Subject: ieee802154: verify packet size before trying to allocate it Currently when sending data over datagram, the send function will attempt to allocate any size passed on from the userspace. We should make sure that this size is checked and limited. We'll limit it to the MTU of the device, which is checked later anyway. Signed-off-by: Sasha Levin Signed-off-by: David S. Miller --- net/ieee802154/dgram.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'net') diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 6fbb2ad7bb6d..16705611589a 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c @@ -230,6 +230,12 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, mtu = dev->mtu; pr_debug("name = %s, mtu = %u\n", dev->name, mtu); + if (size > mtu) { + pr_debug("size = %Zu, mtu = %u\n", size, mtu); + err = -EINVAL; + goto out_dev; + } + hlen = LL_RESERVED_SPACE(dev); tlen = dev->needed_tailroom; skb = sock_alloc_send_skb(sk, hlen + tlen + size, @@ -258,12 +264,6 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, if (err < 0) goto out_skb; - if (size > mtu) { - pr_debug("size = %Zu, mtu = %u\n", size, mtu); - err = -EINVAL; - goto out_skb; - } - skb->dev = dev; skb->sk = sk; skb->protocol = htons(ETH_P_IEEE802154); -- cgit v1.3-14-g43fede From 960fb66e520a405dde39ff883f17ff2669c13d85 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 3 Jul 2012 20:55:21 +0000 Subject: netem: add limitation to reordered packets Fix two netem bugs : 1) When a frame was dropped by tfifo_enqueue(), drop counter was incremented twice. 2) When reordering is triggered, we enqueue a packet without checking queue limit. This can OOM pretty fast when this is repeated enough, since skbs are orphaned, no socket limit can help in this situation. Signed-off-by: Eric Dumazet Cc: Mark Gordon Cc: Andreas Terzis Cc: Yuchung Cheng Cc: Hagen Paul Pfeifer Signed-off-by: David S. Miller --- net/sched/sch_netem.c | 42 +++++++++++++++--------------------------- 1 file changed, 15 insertions(+), 27 deletions(-) (limited to 'net') diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index a2a95aabf9c2..c412ad0d0308 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -331,29 +331,22 @@ static psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sche return PSCHED_NS2TICKS(ticks); } -static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) +static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) { struct sk_buff_head *list = &sch->q; psched_time_t tnext = netem_skb_cb(nskb)->time_to_send; - struct sk_buff *skb; - - if (likely(skb_queue_len(list) < sch->limit)) { - skb = skb_peek_tail(list); - /* Optimize for add at tail */ - if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send)) - return qdisc_enqueue_tail(nskb, sch); + struct sk_buff *skb = skb_peek_tail(list); - skb_queue_reverse_walk(list, skb) { - if (tnext >= netem_skb_cb(skb)->time_to_send) - break; - } + /* Optimize for add at tail */ + if (likely(!skb || tnext >= netem_skb_cb(skb)->time_to_send)) + return __skb_queue_tail(list, nskb); - __skb_queue_after(list, skb, nskb); - sch->qstats.backlog += qdisc_pkt_len(nskb); - return NET_XMIT_SUCCESS; + skb_queue_reverse_walk(list, skb) { + if (tnext >= netem_skb_cb(skb)->time_to_send) + break; } - return qdisc_reshape_fail(nskb, sch); + __skb_queue_after(list, skb, nskb); } /* @@ -368,7 +361,6 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) /* We don't fill cb now as skb_unshare() may invalidate it */ struct netem_skb_cb *cb; struct sk_buff *skb2; - int ret; int count = 1; /* Random duplication */ @@ -419,6 +411,11 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) skb->data[net_random() % skb_headlen(skb)] ^= 1<<(net_random() % 8); } + if (unlikely(skb_queue_len(&sch->q) >= sch->limit)) + return qdisc_reshape_fail(skb, sch); + + sch->qstats.backlog += qdisc_pkt_len(skb); + cb = netem_skb_cb(skb); if (q->gap == 0 || /* not doing reordering */ q->counter < q->gap - 1 || /* inside last reordering gap */ @@ -450,7 +447,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) cb->time_to_send = now + delay; ++q->counter; - ret = tfifo_enqueue(skb, sch); + tfifo_enqueue(skb, sch); } else { /* * Do re-ordering by putting one out of N packets at the front @@ -460,16 +457,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) q->counter = 0; __skb_queue_head(&sch->q, skb); - sch->qstats.backlog += qdisc_pkt_len(skb); sch->qstats.requeues++; - ret = NET_XMIT_SUCCESS; - } - - if (ret != NET_XMIT_SUCCESS) { - if (net_xmit_drop_count(ret)) { - sch->qstats.drops++; - return ret; - } } return NET_XMIT_SUCCESS; -- cgit v1.3-14-g43fede From b761c9b1f4f69eb53fb6147547a1ab25237a93b3 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Wed, 4 Jul 2012 23:28:40 +0000 Subject: cgroup: fix panic in netprio_cgroup we set max_prioidx to the first zero bit index of prioidx_map in function get_prioidx. So when we delete the low index netprio cgroup and adding a new netprio cgroup again,the max_prioidx will be set to the low index. when we set the high index cgroup's net_prio.ifpriomap,the function write_priomap will call update_netdev_tables to alloc memory which size is sizeof(struct netprio_map) + sizeof(u32) * (max_prioidx + 1), so the size of array that map->priomap point to is max_prioidx +1, which is low than what we actually need. fix this by adding check in get_prioidx,only set max_prioidx when max_prioidx low than the new prioidx. Signed-off-by: Gao feng Acked-by: Neil Horman Signed-off-by: David S. Miller --- net/core/netprio_cgroup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index 5b8aa2fae48b..aa907ed466ea 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c @@ -49,8 +49,9 @@ static int get_prioidx(u32 *prio) return -ENOSPC; } set_bit(prioidx, prioidx_map); + if (atomic_read(&max_prioidx) < prioidx) + atomic_set(&max_prioidx, prioidx); spin_unlock_irqrestore(&prioidx_map_lock, flags); - atomic_set(&max_prioidx, prioidx); *prio = prioidx; return 0; } -- cgit v1.3-14-g43fede From a73f89a61f92b364f0b4a3be412b5b70553afc23 Mon Sep 17 00:00:00 2001 From: Jozsef Kadlecsik Date: Fri, 29 Jun 2012 09:42:28 +0000 Subject: netfilter: ipset: timeout fixing bug broke SET target special timeout value The patch "127f559 netfilter: ipset: fix timeout value overflow bug" broke the SET target when no timeout was specified. Reported-by: Jean-Philippe Menil Signed-off-by: Jozsef Kadlecsik Signed-off-by: Pablo Neira Ayuso --- net/netfilter/xt_set.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index 035960ec5cb9..c6f7db720d84 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c @@ -16,6 +16,7 @@ #include #include +#include MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik "); @@ -310,7 +311,8 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par) info->del_set.flags, 0, UINT_MAX); /* Normalize to fit into jiffies */ - if (add_opt.timeout > UINT_MAX/MSEC_PER_SEC) + if (add_opt.timeout != IPSET_NO_TIMEOUT && + add_opt.timeout > UINT_MAX/MSEC_PER_SEC) add_opt.timeout = UINT_MAX/MSEC_PER_SEC; if (info->add_set.index != IPSET_INVALID_ID) ip_set_add(info->add_set.index, skb, par, &add_opt); -- cgit v1.3-14-g43fede From 472dd35ccbd999a6cb2994c318ca16edf65c4359 Mon Sep 17 00:00:00 2001 From: Thomas Huehn Date: Fri, 29 Jun 2012 06:26:27 -0700 Subject: mac80211: correct size the argument to kzalloc in minstrel_ht msp has type struct minstrel_ht_sta_priv not struct minstrel_ht_sta. (This incorporates the fixup originally posted as "mac80211: fix kzalloc memory corruption introduced in minstrel_ht". -- JWL) Reported-by: Fengguang Wu Reported-by: Dan Carpenter Signed-off-by: Thomas Huehn Acked-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/rc80211_minstrel_ht.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 2d1acc6c5445..f9e51ef8dfa2 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -809,7 +809,7 @@ minstrel_ht_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) max_rates = sband->n_bitrates; } - msp = kzalloc(sizeof(struct minstrel_ht_sta), gfp); + msp = kzalloc(sizeof(*msp), gfp); if (!msp) return NULL; -- cgit v1.3-14-g43fede From 147f20e316f3949f3f5ffe6c8658e9fe1c6ceb23 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Sat, 30 Jun 2012 11:56:47 +0200 Subject: NFC: Prevent NULL deref when getting socket name llcp_sock_getname can be called without a device attached to the nfc_llcp_sock. This would lead to the following BUG: [ 362.341807] BUG: unable to handle kernel NULL pointer dereference at (null) [ 362.341815] IP: [] llcp_sock_getname+0x75/0xc0 [ 362.341818] PGD 31b35067 PUD 30631067 PMD 0 [ 362.341821] Oops: 0000 [#627] PREEMPT SMP DEBUG_PAGEALLOC [ 362.341826] CPU 3 [ 362.341827] Pid: 7816, comm: trinity-child55 Tainted: G D W 3.5.0-rc4-next-20120628-sasha-00005-g9f23eb7 #479 [ 362.341831] RIP: 0010:[] [] llcp_sock_getname+0x75/0xc0 [ 362.341832] RSP: 0018:ffff8800304fde88 EFLAGS: 00010286 [ 362.341834] RAX: 0000000000000000 RBX: ffff880033cb8000 RCX: 0000000000000001 [ 362.341835] RDX: ffff8800304fdec4 RSI: ffff8800304fdec8 RDI: ffff8800304fdeda [ 362.341836] RBP: ffff8800304fdea8 R08: 7ebcebcb772b7ffb R09: 5fbfcb9c35bdfd53 [ 362.341838] R10: 4220020c54326244 R11: 0000000000000246 R12: ffff8800304fdec8 [ 362.341839] R13: ffff8800304fdec4 R14: ffff8800304fdec8 R15: 0000000000000044 [ 362.341841] FS: 00007effa376e700(0000) GS:ffff880035a00000(0000) knlGS:0000000000000000 [ 362.341843] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 362.341844] CR2: 0000000000000000 CR3: 0000000030438000 CR4: 00000000000406e0 [ 362.341851] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 362.341856] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 [ 362.341858] Process trinity-child55 (pid: 7816, threadinfo ffff8800304fc000, task ffff880031270000) [ 362.341858] Stack: [ 362.341862] ffff8800304fdea8 ffff880035156780 0000000000000000 0000000000001000 [ 362.341865] ffff8800304fdf78 ffffffff83183b40 00000000304fdec8 0000006000000000 [ 362.341868] ffff8800304f0027 ffffffff83729649 ffff8800304fdee8 ffff8800304fdf48 [ 362.341869] Call Trace: [ 362.341874] [] sys_getpeername+0xa0/0x110 [ 362.341877] [] ? _raw_spin_unlock_irq+0x59/0x80 [ 362.341882] [] ? do_setitimer+0x23b/0x290 [ 362.341886] [] ? trace_hardirqs_on_thunk+0x3a/0x3f [ 362.341889] [] system_call_fastpath+0x16/0x1b [ 362.341921] Code: 84 00 00 00 00 00 b8 b3 ff ff ff 48 85 db 74 54 66 41 c7 04 24 27 00 49 8d 7c 24 12 41 c7 45 00 60 00 00 00 48 8b 83 28 05 00 00 <8b> 00 41 89 44 24 04 0f b6 83 41 05 00 00 41 88 44 24 10 0f b6 [ 362.341924] RIP [] llcp_sock_getname+0x75/0xc0 [ 362.341925] RSP [ 362.341926] CR2: 0000000000000000 [ 362.341928] ---[ end trace 6d450e935ee18bf3 ]--- Signed-off-by: Sasha Levin Signed-off-by: John W. Linville --- net/nfc/llcp/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/nfc/llcp/sock.c b/net/nfc/llcp/sock.c index 17a707db40eb..e06d458fc719 100644 --- a/net/nfc/llcp/sock.c +++ b/net/nfc/llcp/sock.c @@ -292,7 +292,7 @@ static int llcp_sock_getname(struct socket *sock, struct sockaddr *addr, pr_debug("%p\n", sk); - if (llcp_sock == NULL) + if (llcp_sock == NULL || llcp_sock->dev == NULL) return -EBADFD; addr->sa_family = AF_NFC; -- cgit v1.3-14-g43fede From 10a9109f2705fdc3caa94d768b2559587a9a050c Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 2 Jul 2012 14:42:03 +0300 Subject: mac80211: destroy assoc_data correctly if assoc fails If association failed due to internal error (e.g. no supported rates IE), we call ieee80211_destroy_assoc_data() with assoc=true, while we actually reject the association. This results in the BSSID not being zeroed out. After passing assoc=false, we no longer have to call sta_info_destroy_addr() explicitly. While on it, move the "associated" message after the assoc_success check. Cc: stable@vger.kernel.org [3.4+] Signed-off-by: Eliad Peller Reviewed-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a4bb856de08f..0db5d34a06b6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -2174,15 +2174,13 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, sdata->name, mgmt->sa, status_code); ieee80211_destroy_assoc_data(sdata, false); } else { - printk(KERN_DEBUG "%s: associated\n", sdata->name); - if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) { /* oops -- internal error -- send timeout for now */ - ieee80211_destroy_assoc_data(sdata, true); - sta_info_destroy_addr(sdata, mgmt->bssid); + ieee80211_destroy_assoc_data(sdata, false); cfg80211_put_bss(*bss); return RX_MGMT_CFG80211_ASSOC_TIMEOUT; } + printk(KERN_DEBUG "%s: associated\n", sdata->name); /* * destroy assoc_data afterwards, as otherwise an idle -- cgit v1.3-14-g43fede From 91c68ce2b26319248a32d7baa1226f819d283758 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 8 Jul 2012 21:45:10 +0000 Subject: net: cgroup: fix out of bounds accesses dev->priomap is allocated by extend_netdev_table() called from update_netdev_tables(). And this is only called if write_priomap() is called. But if write_priomap() is not called, it seems we can have out of bounds accesses in cgrp_destroy(), read_priomap() & skb_update_prio() With help from Gao Feng Signed-off-by: Eric Dumazet Cc: Neil Horman Cc: Gao feng Acked-by: Gao feng Signed-off-by: David S. Miller --- net/core/dev.c | 8 ++++++-- net/core/netprio_cgroup.c | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'net') diff --git a/net/core/dev.c b/net/core/dev.c index 84f01ba81a34..0f28a9e0b8ad 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2444,8 +2444,12 @@ static void skb_update_prio(struct sk_buff *skb) { struct netprio_map *map = rcu_dereference_bh(skb->dev->priomap); - if ((!skb->priority) && (skb->sk) && map) - skb->priority = map->priomap[skb->sk->sk_cgrp_prioidx]; + if (!skb->priority && skb->sk && map) { + unsigned int prioidx = skb->sk->sk_cgrp_prioidx; + + if (prioidx < map->priomap_len) + skb->priority = map->priomap[prioidx]; + } } #else #define skb_update_prio(skb) diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index aa907ed466ea..3e953eaddbfc 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c @@ -142,7 +142,7 @@ static void cgrp_destroy(struct cgroup *cgrp) rtnl_lock(); for_each_netdev(&init_net, dev) { map = rtnl_dereference(dev->priomap); - if (map) + if (map && cs->prioidx < map->priomap_len) map->priomap[cs->prioidx] = 0; } rtnl_unlock(); @@ -166,7 +166,7 @@ static int read_priomap(struct cgroup *cont, struct cftype *cft, rcu_read_lock(); for_each_netdev_rcu(&init_net, dev) { map = rcu_dereference(dev->priomap); - priority = map ? map->priomap[prioidx] : 0; + priority = (map && prioidx < map->priomap_len) ? map->priomap[prioidx] : 0; cb->fill(cb, dev->name, priority); } rcu_read_unlock(); -- cgit v1.3-14-g43fede From cae296c42c94a27e0abdea96eb762752d1ba4908 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 8 Jul 2012 01:37:39 +0000 Subject: net/rxrpc/ar-peer.c: remove invalid reference to list iterator variable If list_for_each_entry, etc complete a traversal of the list, the iterator variable ends up pointing to an address at an offset from the list head, and not a meaningful structure. Thus this value should not be used after the end of the iterator. This seems to be a copy-paste bug from a previous debugging message, and so the meaningless value is just deleted. This problem was found using Coccinelle (http://coccinelle.lip6.fr/). Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- net/rxrpc/ar-peer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/rxrpc/ar-peer.c b/net/rxrpc/ar-peer.c index 2754f098d436..bebaa43484bc 100644 --- a/net/rxrpc/ar-peer.c +++ b/net/rxrpc/ar-peer.c @@ -229,7 +229,7 @@ found_UDP_peer: return peer; new_UDP_peer: - _net("Rx UDP DGRAM from NEW peer %d", peer->debug_id); + _net("Rx UDP DGRAM from NEW peer"); read_unlock_bh(&rxrpc_peer_lock); _leave(" = -EBUSY [new]"); return ERR_PTR(-EBUSY); -- cgit v1.3-14-g43fede From efc73f4bbc238d4f579fb612c04c8e1dd8a82979 Mon Sep 17 00:00:00 2001 From: Amir Hanania Date: Mon, 9 Jul 2012 20:47:19 +0000 Subject: net: Fix memory leak - vlan_info struct In driver reload test there is a memory leak. The structure vlan_info was not freed when the driver was removed. It was not released since the nr_vids var is one after last vlan was removed. The nr_vids is one, since vlan zero is added to the interface when the interface is being set, but the vlan zero is not deleted at unregister. Fix - delete vlan zero when we unregister the device. Signed-off-by: Amir Hanania Acked-by: John Fastabend Tested-by: Aaron Brown Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- net/8021q/vlan.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net') diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 6089f0cf23b4..9096bcb08132 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c @@ -403,6 +403,9 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, break; case NETDEV_DOWN: + if (dev->features & NETIF_F_HW_VLAN_FILTER) + vlan_vid_del(dev, 0); + /* Put all VLANs for this dev in the down state too. */ for (i = 0; i < VLAN_N_VID; i++) { vlandev = vlan_group_get_device(grp, i); -- cgit v1.3-14-g43fede From 7ac2908e4b2edaec60e9090ddb4d9ceb76c05e7d Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 12 Jul 2012 03:39:11 +0000 Subject: sch_sfb: Fix missing NULL check Resolves-bug: https://bugzilla.kernel.org/show_bug.cgi?id=44461 Signed-off-by: Alan Cox Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_sfb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net') diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c index 74305c883bd3..30ea4674cabd 100644 --- a/net/sched/sch_sfb.c +++ b/net/sched/sch_sfb.c @@ -570,6 +570,8 @@ static int sfb_dump(struct Qdisc *sch, struct sk_buff *skb) sch->qstats.backlog = q->qdisc->qstats.backlog; opts = nla_nest_start(skb, TCA_OPTIONS); + if (opts == NULL) + goto nla_put_failure; if (nla_put(skb, TCA_SFB_PARMS, sizeof(opt), &opt)) goto nla_put_failure; return nla_nest_end(skb, opts); -- cgit v1.3-14-g43fede From 310e158cc3b7a6adf41e778d52be746c4dc88561 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 16 Jul 2012 13:15:52 +0200 Subject: net: respect GFP_DMA in __netdev_alloc_skb() Few drivers use GFP_DMA allocations, and netdev_alloc_frag() doesn't allocate pages in DMA zone. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/skbuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 46a3d23d259e..d124306b81fd 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -353,7 +353,7 @@ struct sk_buff *__netdev_alloc_skb(struct net_device *dev, unsigned int fragsz = SKB_DATA_ALIGN(length + NET_SKB_PAD) + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - if (fragsz <= PAGE_SIZE && !(gfp_mask & __GFP_WAIT)) { + if (fragsz <= PAGE_SIZE && !(gfp_mask & (__GFP_WAIT | GFP_DMA))) { void *data = netdev_alloc_frag(fragsz); if (likely(data)) { -- cgit v1.3-14-g43fede From 2eebc1e188e9e45886ee00662519849339884d6d Mon Sep 17 00:00:00 2001 From: Neil Horman Date: Mon, 16 Jul 2012 09:13:51 +0000 Subject: sctp: Fix list corruption resulting from freeing an association on a list A few days ago Dave Jones reported this oops: [22766.294255] general protection fault: 0000 [#1] PREEMPT SMP [22766.295376] CPU 0 [22766.295384] Modules linked in: [22766.387137] ffffffffa169f292 6b6b6b6b6b6b6b6b ffff880147c03a90 ffff880147c03a74 [22766.387135] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 00000000000 [22766.387136] Process trinity-watchdo (pid: 10896, threadinfo ffff88013e7d2000, [22766.387137] Stack: [22766.387140] ffff880147c03a10 [22766.387140] ffffffffa169f2b6 [22766.387140] ffff88013ed95728 [22766.387143] 0000000000000002 [22766.387143] 0000000000000000 [22766.387143] ffff880003fad062 [22766.387144] ffff88013c120000 [22766.387144] [22766.387145] Call Trace: [22766.387145] [22766.387150] [] ? __sctp_lookup_association+0x62/0xd0 [sctp] [22766.387154] [] __sctp_lookup_association+0x86/0xd0 [sctp] [22766.387157] [] sctp_rcv+0x207/0xbb0 [sctp] [22766.387161] [] ? trace_hardirqs_off_caller+0x28/0xd0 [22766.387163] [] ? nf_hook_slow+0x133/0x210 [22766.387166] [] ? ip_local_deliver_finish+0x4c/0x4c0 [22766.387168] [] ip_local_deliver_finish+0x18d/0x4c0 [22766.387169] [] ? ip_local_deliver_finish+0x4c/0x4c0 [22766.387171] [] ip_local_deliver+0x47/0x80 [22766.387172] [] ip_rcv_finish+0x150/0x680 [22766.387174] [] ip_rcv+0x214/0x320 [22766.387176] [] __netif_receive_skb+0x7b7/0x910 [22766.387178] [] ? __netif_receive_skb+0x11c/0x910 [22766.387180] [] ? put_lock_stats.isra.25+0xe/0x40 [22766.387182] [] netif_receive_skb+0x23/0x1f0 [22766.387183] [] ? dev_gro_receive+0x139/0x440 [22766.387185] [] napi_skb_finish+0x70/0xa0 [22766.387187] [] napi_gro_receive+0xf5/0x130 [22766.387218] [] e1000_receive_skb+0x59/0x70 [e1000e] [22766.387242] [] e1000_clean_rx_irq+0x28b/0x460 [e1000e] [22766.387266] [] e1000e_poll+0x78/0x430 [e1000e] [22766.387268] [] net_rx_action+0x1aa/0x3d0 [22766.387270] [] ? account_system_vtime+0x10f/0x130 [22766.387273] [] __do_softirq+0xe0/0x420 [22766.387275] [] call_softirq+0x1c/0x30 [22766.387278] [] do_softirq+0xd5/0x110 [22766.387279] [] irq_exit+0xd5/0xe0 [22766.387281] [] do_IRQ+0x63/0xd0 [22766.387283] [] common_interrupt+0x6f/0x6f [22766.387283] [22766.387284] [22766.387285] [] ? retint_swapgs+0x13/0x1b [22766.387285] Code: c0 90 5d c3 66 0f 1f 44 00 00 4c 89 c8 5d c3 0f 1f 00 55 48 89 e5 48 83 ec 20 48 89 5d e8 4c 89 65 f0 4c 89 6d f8 66 66 66 66 90 <0f> b7 87 98 00 00 00 48 89 fb 49 89 f5 66 c1 c0 08 66 39 46 02 [22766.387307] [22766.387307] RIP [22766.387311] [] sctp_assoc_is_match+0x19/0x90 [sctp] [22766.387311] RSP [22766.387142] ffffffffa16ab120 [22766.599537] ---[ end trace 3f6dae82e37b17f5 ]--- [22766.601221] Kernel panic - not syncing: Fatal exception in interrupt It appears from his analysis and some staring at the code that this is likely occuring because an association is getting freed while still on the sctp_assoc_hashtable. As a result, we get a gpf when traversing the hashtable while a freed node corrupts part of the list. Nominally I would think that an mibalanced refcount was responsible for this, but I can't seem to find any obvious imbalance. What I did note however was that the two places where we create an association using sctp_primitive_ASSOCIATE (__sctp_connect and sctp_sendmsg), have failure paths which free a newly created association after calling sctp_primitive_ASSOCIATE. sctp_primitive_ASSOCIATE brings us into the sctp_sf_do_prm_asoc path, which issues a SCTP_CMD_NEW_ASOC side effect, which in turn adds a new association to the aforementioned hash table. the sctp command interpreter that process side effects has not way to unwind previously processed commands, so freeing the association from the __sctp_connect or sctp_sendmsg error path would lead to a freed association remaining on this hash table. I've fixed this but modifying sctp_[un]hash_established to use hlist_del_init, which allows us to proerly use hlist_unhashed to check if the node is on a hashlist safely during a delete. That in turn alows us to safely call sctp_unhash_established in the __sctp_connect and sctp_sendmsg error paths before freeing them, regardles of what the associations state is on the hash list. I noted, while I was doing this, that the __sctp_unhash_endpoint was using hlist_unhsashed in a simmilar fashion, but never nullified any removed nodes pointers to make that function work properly, so I fixed that up in a simmilar fashion. I attempted to test this using a virtual guest running the SCTP_RR test from netperf in a loop while running the trinity fuzzer, both in a loop. I wasn't able to recreate the problem prior to this fix, nor was I able to trigger the failure after (neither of which I suppose is suprising). Given the trace above however, I think its likely that this is what we hit. Signed-off-by: Neil Horman Reported-by: davej@redhat.com CC: davej@redhat.com CC: "David S. Miller" CC: Vlad Yasevich CC: Sridhar Samudrala CC: linux-sctp@vger.kernel.org Signed-off-by: David S. Miller --- net/sctp/input.c | 7 ++----- net/sctp/socket.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'net') diff --git a/net/sctp/input.c b/net/sctp/input.c index 80564fe03024..8b9b6790a3df 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -736,15 +736,12 @@ static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) epb = &ep->base; - if (hlist_unhashed(&epb->node)) - return; - epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); head = &sctp_ep_hashtable[epb->hashent]; sctp_write_lock(&head->lock); - __hlist_del(&epb->node); + hlist_del_init(&epb->node); sctp_write_unlock(&head->lock); } @@ -825,7 +822,7 @@ static void __sctp_unhash_established(struct sctp_association *asoc) head = &sctp_assoc_hashtable[epb->hashent]; sctp_write_lock(&head->lock); - __hlist_del(&epb->node); + hlist_del_init(&epb->node); sctp_write_unlock(&head->lock); } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index b3b8a8d813eb..31c7bfcd9b58 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1231,8 +1231,14 @@ out_free: SCTP_DEBUG_PRINTK("About to exit __sctp_connect() free asoc: %p" " kaddrs: %p err: %d\n", asoc, kaddrs, err); - if (asoc) + if (asoc) { + /* sctp_primitive_ASSOCIATE may have added this association + * To the hash table, try to unhash it, just in case, its a noop + * if it wasn't hashed so we're safe + */ + sctp_unhash_established(asoc); sctp_association_free(asoc); + } return err; } @@ -1942,8 +1948,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, goto out_unlock; out_free: - if (new_asoc) + if (new_asoc) { + sctp_unhash_established(asoc); sctp_association_free(asoc); + } out_unlock: sctp_release_sock(sk); -- cgit v1.3-14-g43fede From ef209f15980360f6945873df3cd710c5f62f2a3e Mon Sep 17 00:00:00 2001 From: Gao feng Date: Wed, 11 Jul 2012 21:50:15 +0000 Subject: net: cgroup: fix access the unallocated memory in netprio cgroup there are some out of bound accesses in netprio cgroup. now before accessing the dev->priomap.priomap array,we only check if the dev->priomap exist.and because we don't want to see additional bound checkings in fast path, so we should make sure that dev->priomap is null or array size of dev->priomap.priomap is equal to max_prioidx + 1; so in write_priomap logic,we should call extend_netdev_table when dev->priomap is null and dev->priomap.priomap_len < max_len. and in cgrp_create->update_netdev_tables logic,we should call extend_netdev_table only when dev->priomap exist and dev->priomap.priomap_len < max_len. and it's not needed to call update_netdev_tables in write_priomap, we can only allocate the net device's priomap which we change through net_prio.ifpriomap. this patch also add a return value for update_netdev_tables & extend_netdev_table, so when new_priomap is allocated failed, write_priomap will stop to access the priomap,and return -ENOMEM back to the userspace to tell the user what happend. Change From v3: 1. add rtnl protect when reading max_prioidx in write_priomap. 2. only call extend_netdev_table when map->priomap_len < max_len, this will make sure array size of dev->map->priomap always bigger than any prioidx. 3. add a function write_update_netdev_table to make codes clear. Change From v2: 1. protect extend_netdev_table by RTNL. 2. when extend_netdev_table failed,call dev_put to reduce device's refcount. Signed-off-by: Gao feng Cc: Neil Horman Cc: Eric Dumazet Acked-by: Neil Horman Signed-off-by: David S. Miller --- net/core/netprio_cgroup.c | 71 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 54 insertions(+), 17 deletions(-) (limited to 'net') diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index 3e953eaddbfc..b2e9caa1ad1a 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c @@ -65,7 +65,7 @@ static void put_prioidx(u32 idx) spin_unlock_irqrestore(&prioidx_map_lock, flags); } -static void extend_netdev_table(struct net_device *dev, u32 new_len) +static int extend_netdev_table(struct net_device *dev, u32 new_len) { size_t new_size = sizeof(struct netprio_map) + ((sizeof(u32) * new_len)); @@ -77,7 +77,7 @@ static void extend_netdev_table(struct net_device *dev, u32 new_len) if (!new_priomap) { pr_warn("Unable to alloc new priomap!\n"); - return; + return -ENOMEM; } for (i = 0; @@ -90,46 +90,79 @@ static void extend_netdev_table(struct net_device *dev, u32 new_len) rcu_assign_pointer(dev->priomap, new_priomap); if (old_priomap) kfree_rcu(old_priomap, rcu); + return 0; } -static void update_netdev_tables(void) +static int write_update_netdev_table(struct net_device *dev) { + int ret = 0; + u32 max_len; + struct netprio_map *map; + + rtnl_lock(); + max_len = atomic_read(&max_prioidx) + 1; + map = rtnl_dereference(dev->priomap); + if (!map || map->priomap_len < max_len) + ret = extend_netdev_table(dev, max_len); + rtnl_unlock(); + + return ret; +} + +static int update_netdev_tables(void) +{ + int ret = 0; struct net_device *dev; - u32 max_len = atomic_read(&max_prioidx) + 1; + u32 max_len; struct netprio_map *map; rtnl_lock(); + max_len = atomic_read(&max_prioidx) + 1; for_each_netdev(&init_net, dev) { map = rtnl_dereference(dev->priomap); - if ((!map) || - (map->priomap_len < max_len)) - extend_netdev_table(dev, max_len); + /* + * don't allocate priomap if we didn't + * change net_prio.ifpriomap (map == NULL), + * this will speed up skb_update_prio. + */ + if (map && map->priomap_len < max_len) { + ret = extend_netdev_table(dev, max_len); + if (ret < 0) + break; + } } rtnl_unlock(); + return ret; } static struct cgroup_subsys_state *cgrp_create(struct cgroup *cgrp) { struct cgroup_netprio_state *cs; - int ret; + int ret = -EINVAL; cs = kzalloc(sizeof(*cs), GFP_KERNEL); if (!cs) return ERR_PTR(-ENOMEM); - if (cgrp->parent && cgrp_netprio_state(cgrp->parent)->prioidx) { - kfree(cs); - return ERR_PTR(-EINVAL); - } + if (cgrp->parent && cgrp_netprio_state(cgrp->parent)->prioidx) + goto out; ret = get_prioidx(&cs->prioidx); - if (ret != 0) { + if (ret < 0) { pr_warn("No space in priority index array\n"); - kfree(cs); - return ERR_PTR(ret); + goto out; + } + + ret = update_netdev_tables(); + if (ret < 0) { + put_prioidx(cs->prioidx); + goto out; } return &cs->css; +out: + kfree(cs); + return ERR_PTR(ret); } static void cgrp_destroy(struct cgroup *cgrp) @@ -221,13 +254,17 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft, if (!dev) goto out_free_devname; - update_netdev_tables(); - ret = 0; + ret = write_update_netdev_table(dev); + if (ret < 0) + goto out_put_dev; + rcu_read_lock(); map = rcu_dereference(dev->priomap); if (map) map->priomap[prioidx] = priority; rcu_read_unlock(); + +out_put_dev: dev_put(dev); out_free_devname: -- cgit v1.3-14-g43fede From 96f80d123eff05c3cd4701463786b87952a6c3ac Mon Sep 17 00:00:00 2001 From: Sjur Brændeland Date: Sun, 15 Jul 2012 10:10:14 +0000 Subject: caif: Fix access to freed pernet memory MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit unregister_netdevice_notifier() must be called before unregister_pernet_subsys() to avoid accessing already freed pernet memory. This fixes the following oops when doing rmmod: Call Trace: [] caif_device_notify+0x4d/0x5a0 [caif] [] unregister_netdevice_notifier+0xb9/0x100 [] caif_device_exit+0x1c/0x250 [caif] [] sys_delete_module+0x1a4/0x300 [] ? trace_hardirqs_on_caller+0x15d/0x1e0 [] ? trace_hardirqs_on_thunk+0x3a/0x3 [] system_call_fastpath+0x1a/0x1f RIP [] caif_get+0x51/0xb0 [caif] Signed-off-by: Sjur Brændeland Acked-by: "Eric W. Biederman" Signed-off-by: David S. Miller --- net/caif/caif_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index 554b31289607..8c83c175b03a 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -561,9 +561,9 @@ static int __init caif_device_init(void) static void __exit caif_device_exit(void) { - unregister_pernet_subsys(&caif_net_ops); unregister_netdevice_notifier(&caif_device_notifier); dev_remove_pack(&caif_packet_type); + unregister_pernet_subsys(&caif_net_ops); } module_init(caif_device_init); -- cgit v1.3-14-g43fede From ef764a13b8f4bc4b532a51bc37c35b3974831b29 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 13 Jul 2012 06:33:08 +0000 Subject: ax25: Fix missing break At least there seems to be no reason to disallow ROSE sockets when NETROM is loaded. Signed-off-by: Alan Cox Signed-off-by: David S. Miller --- net/ax25/af_ax25.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 051f7abae66d..779095ded689 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -842,6 +842,7 @@ static int ax25_create(struct net *net, struct socket *sock, int protocol, case AX25_P_NETROM: if (ax25_protocol_is_registered(AX25_P_NETROM)) return -ESOCKTNOSUPPORT; + break; #endif #ifdef CONFIG_ROSE_MODULE case AX25_P_ROSE: -- cgit v1.3-14-g43fede From 283283c4da91adc44b03519f434ee1e7e91d6fdb Mon Sep 17 00:00:00 2001 From: Julian Anastasov Date: Sat, 7 Jul 2012 20:30:11 +0300 Subject: ipvs: fix oops in ip_vs_dst_event on rmmod After commit 39f618b4fd95ae243d940ec64c961009c74e3333 (3.4) "ipvs: reset ipvs pointer in netns" we can oops in ip_vs_dst_event on rmmod ip_vs because ip_vs_control_cleanup is called after the ipvs_core_ops subsys is unregistered and net->ipvs is NULL. Fix it by exiting early from ip_vs_dst_event if ipvs is NULL. It is safe because all services and dests for the net are already freed. Signed-off-by: Julian Anastasov Signed-off-by: Simon Horman Signed-off-by: Pablo Neira Ayuso --- net/netfilter/ipvs/ip_vs_ctl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index d43e3c122f7b..84444dda194b 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c @@ -1521,11 +1521,12 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, { struct net_device *dev = ptr; struct net *net = dev_net(dev); + struct netns_ipvs *ipvs = net_ipvs(net); struct ip_vs_service *svc; struct ip_vs_dest *dest; unsigned int idx; - if (event != NETDEV_UNREGISTER) + if (event != NETDEV_UNREGISTER || !ipvs) return NOTIFY_DONE; IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name); EnterFunction(2); @@ -1551,7 +1552,7 @@ static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, } } - list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) { + list_for_each_entry(dest, &ipvs->dest_trash, n_list) { __ip_vs_dev_reset(dest, dev); } mutex_unlock(&__ip_vs_mutex); -- cgit v1.3-14-g43fede From 5bdca4e0768d3e0f4efa43d9a2cc8210aeb91ab9 Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Tue, 10 Jul 2012 11:53:34 -0700 Subject: libceph: fix messenger retry In ancient times, the messenger could both initiate and accept connections. An artifact if that was data structures to store/process an incoming ceph_msg_connect request and send an outgoing ceph_msg_connect_reply. Sadly, the negotiation code was referencing those structures and ignoring important information (like the peer's connect_seq) from the correct ones. Among other things, this fixes tight reconnect loops where the server sends RETRY_SESSION and we (the client) retries with the same connect_seq as last time. This bug pretty easily triggered by injecting socket failures on the MDS and running some fs workload like workunits/direct_io/test_sync_io. Signed-off-by: Sage Weil --- include/linux/ceph/messenger.h | 12 ++---------- net/ceph/messenger.c | 12 ++++++------ 2 files changed, 8 insertions(+), 16 deletions(-) (limited to 'net') diff --git a/include/linux/ceph/messenger.h b/include/linux/ceph/messenger.h index 2521a95fa6d9..44c87e731e9d 100644 --- a/include/linux/ceph/messenger.h +++ b/include/linux/ceph/messenger.h @@ -163,16 +163,8 @@ struct ceph_connection { /* connection negotiation temps */ char in_banner[CEPH_BANNER_MAX_LEN]; - union { - struct { /* outgoing connection */ - struct ceph_msg_connect out_connect; - struct ceph_msg_connect_reply in_reply; - }; - struct { /* incoming */ - struct ceph_msg_connect in_connect; - struct ceph_msg_connect_reply out_reply; - }; - }; + struct ceph_msg_connect out_connect; + struct ceph_msg_connect_reply in_reply; struct ceph_entity_addr actual_peer_addr; /* message out temps */ diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index b332c3d76059..10255e81be79 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -1423,7 +1423,7 @@ static int process_connect(struct ceph_connection *con) * dropped messages. */ dout("process_connect got RESET peer seq %u\n", - le32_to_cpu(con->in_connect.connect_seq)); + le32_to_cpu(con->in_reply.connect_seq)); pr_err("%s%lld %s connection reset\n", ENTITY_NAME(con->peer_name), ceph_pr_addr(&con->peer_addr.in_addr)); @@ -1450,10 +1450,10 @@ static int process_connect(struct ceph_connection *con) * If we sent a smaller connect_seq than the peer has, try * again with a larger value. */ - dout("process_connect got RETRY my seq = %u, peer_seq = %u\n", + dout("process_connect got RETRY_SESSION my seq %u, peer %u\n", le32_to_cpu(con->out_connect.connect_seq), - le32_to_cpu(con->in_connect.connect_seq)); - con->connect_seq = le32_to_cpu(con->in_connect.connect_seq); + le32_to_cpu(con->in_reply.connect_seq)); + con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); ceph_con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) @@ -1468,9 +1468,9 @@ static int process_connect(struct ceph_connection *con) */ dout("process_connect got RETRY_GLOBAL my %u peer_gseq %u\n", con->peer_global_seq, - le32_to_cpu(con->in_connect.global_seq)); + le32_to_cpu(con->in_reply.global_seq)); get_global_seq(con->msgr, - le32_to_cpu(con->in_connect.global_seq)); + le32_to_cpu(con->in_reply.global_seq)); ceph_con_out_kvec_reset(con); ret = prepare_write_connect(con); if (ret < 0) -- cgit v1.3-14-g43fede From 89d7ae34cdda4195809a5a987f697a517a2a3177 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 17 Jul 2012 11:07:47 +0000 Subject: cipso: don't follow a NULL pointer when setsockopt() is called As reported by Alan Cox, and verified by Lin Ming, when a user attempts to add a CIPSO option to a socket using the CIPSO_V4_TAG_LOCAL tag the kernel dies a terrible death when it attempts to follow a NULL pointer (the skb argument to cipso_v4_validate() is NULL when called via the setsockopt() syscall). This patch fixes this by first checking to ensure that the skb is non-NULL before using it to find the incoming network interface. In the unlikely case where the skb is NULL and the user attempts to add a CIPSO option with the _TAG_LOCAL tag we return an error as this is not something we want to allow. A simple reproducer, kindly supplied by Lin Ming, although you must have the CIPSO DOI #3 configure on the system first or you will be caught early in cipso_v4_validate(): #include #include #include #include #include struct local_tag { char type; char length; char info[4]; }; struct cipso { char type; char length; char doi[4]; struct local_tag local; }; int main(int argc, char **argv) { int sockfd; struct cipso cipso = { .type = IPOPT_CIPSO, .length = sizeof(struct cipso), .local = { .type = 128, .length = sizeof(struct local_tag), }, }; memset(cipso.doi, 0, 4); cipso.doi[3] = 3; sockfd = socket(AF_INET, SOCK_DGRAM, 0); #define SOL_IP 0 setsockopt(sockfd, SOL_IP, IP_OPTIONS, &cipso, sizeof(struct cipso)); return 0; } CC: Lin Ming Reported-by: Alan Cox Signed-off-by: Paul Moore Signed-off-by: David S. Miller --- net/ipv4/cipso_ipv4.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index c48adc565e92..667c1d4ca984 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1725,8 +1725,10 @@ int cipso_v4_validate(const struct sk_buff *skb, unsigned char **option) case CIPSO_V4_TAG_LOCAL: /* This is a non-standard tag that we only allow for * local connections, so if the incoming interface is - * not the loopback device drop the packet. */ - if (!(skb->dev->flags & IFF_LOOPBACK)) { + * not the loopback device drop the packet. Further, + * there is no legitimate reason for setting this from + * userspace so reject it if skb is NULL. */ + if (skb == NULL || !(skb->dev->flags & IFF_LOOPBACK)) { err_offset = opt_iter; goto validate_return_locked; } -- cgit v1.3-14-g43fede From 734b65417b24d6eea3e3d7457e1f11493890ee1d Mon Sep 17 00:00:00 2001 From: "Rustad, Mark D" Date: Wed, 18 Jul 2012 09:06:07 +0000 Subject: net: Statically initialize init_net.dev_base_head This change eliminates an initialization-order hazard most recently seen when netprio_cgroup is built into the kernel. With thanks to Eric Dumazet for catching a bug. Signed-off-by: Mark Rustad Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/core/dev.c | 3 ++- net/core/net_namespace.c | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'net') diff --git a/net/core/dev.c b/net/core/dev.c index 0f28a9e0b8ad..1cb0d8a6aa6c 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6283,7 +6283,8 @@ static struct hlist_head *netdev_create_hash(void) /* Initialize per network namespace state */ static int __net_init netdev_init(struct net *net) { - INIT_LIST_HEAD(&net->dev_base_head); + if (net != &init_net) + INIT_LIST_HEAD(&net->dev_base_head); net->dev_name_head = netdev_create_hash(); if (net->dev_name_head == NULL) diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index dddbacb8f28c..42f1e1c7514f 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c @@ -27,7 +27,9 @@ static DEFINE_MUTEX(net_mutex); LIST_HEAD(net_namespace_list); EXPORT_SYMBOL_GPL(net_namespace_list); -struct net init_net; +struct net init_net = { + .dev_base_head = LIST_HEAD_INIT(init_net.dev_base_head), +}; EXPORT_SYMBOL(init_net); #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ -- cgit v1.3-14-g43fede