From: Greg Kroah-Hartman Date: Sat, 17 Oct 2015 21:07:25 +0000 (-0700) Subject: 4.1-stable patches X-Git-Tag: v3.10.91~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=7c7d23e89f417fea012854518fc82f00812ff140;p=thirdparty%2Fkernel%2Fstable-queue.git 4.1-stable patches added patches: batman-adv-fix-kernel-crash-due-to-missing-null-checks.patch batman-adv-make-dat-capability-changes-atomic.patch batman-adv-protect-tt_local_entry-from-concurrent-delete-events.patch fbdev-select-versatile-helpers-for-the-integrator.patch initialize-msg-shm-ipc-objects-before-doing-ipc_addid.patch ipvs-call-skb_sender_cpu_clear.patch ipvs-do-not-use-random-local-source-address-for-tunnels.patch ipvs-fix-crash-if-scheduler-is-changed.patch ipvs-fix-crash-with-sync-protocol-v0-and-ftp.patch ipvs-skb_orphan-in-case-of-forwarding.patch sched-fair-prevent-throttling-in-early-pick_next_task_fair.patch serial-amba-pl011-disable-interrupts-around-tx-softirq.patch --- diff --git a/queue-4.1/batman-adv-fix-kernel-crash-due-to-missing-null-checks.patch b/queue-4.1/batman-adv-fix-kernel-crash-due-to-missing-null-checks.patch new file mode 100644 index 00000000000..6e310eb096b --- /dev/null +++ b/queue-4.1/batman-adv-fix-kernel-crash-due-to-missing-null-checks.patch @@ -0,0 +1,83 @@ +From 354136bcc3c4f40a2813bba8f57ca5267d812d15 Mon Sep 17 00:00:00 2001 +From: Marek Lindner +Date: Tue, 9 Jun 2015 21:24:36 +0800 +Subject: batman-adv: fix kernel crash due to missing NULL checks + +From: Marek Lindner + +commit 354136bcc3c4f40a2813bba8f57ca5267d812d15 upstream. + +batadv_softif_vlan_get() may return NULL which has to be verified +by the caller. + +Fixes: 35df3b298fc8 ("batman-adv: fix TT VLAN inconsistency on VLAN re-add") +Reported-by: Ryan Thompson +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman + +--- + net/batman-adv/soft-interface.c | 3 +++ + net/batman-adv/translation-table.c | 18 ++++++++++++++---- + 2 files changed, 17 insertions(+), 4 deletions(-) + +--- a/net/batman-adv/soft-interface.c ++++ b/net/batman-adv/soft-interface.c +@@ -449,6 +449,9 @@ out: + */ + void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) + { ++ if (!vlan) ++ return; ++ + if (atomic_dec_and_test(&vlan->refcount)) { + spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock); + hlist_del_rcu(&vlan->list); +--- a/net/batman-adv/translation-table.c ++++ b/net/batman-adv/translation-table.c +@@ -575,6 +575,9 @@ bool batadv_tt_local_add(struct net_devi + + /* increase the refcounter of the related vlan */ + vlan = batadv_softif_vlan_get(bat_priv, vid); ++ if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d", ++ addr, BATADV_PRINT_VID(vid))) ++ goto out; + + batadv_dbg(BATADV_DBG_TT, bat_priv, + "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n", +@@ -1047,6 +1050,9 @@ uint16_t batadv_tt_local_remove(struct b + + /* decrease the reference held for this vlan */ + vlan = batadv_softif_vlan_get(bat_priv, vid); ++ if (!vlan) ++ goto out; ++ + batadv_softif_vlan_free_ref(vlan); + batadv_softif_vlan_free_ref(vlan); + +@@ -1147,8 +1153,10 @@ static void batadv_tt_local_table_free(s + /* decrease the reference held for this vlan */ + vlan = batadv_softif_vlan_get(bat_priv, + tt_common_entry->vid); +- batadv_softif_vlan_free_ref(vlan); +- batadv_softif_vlan_free_ref(vlan); ++ if (vlan) { ++ batadv_softif_vlan_free_ref(vlan); ++ batadv_softif_vlan_free_ref(vlan); ++ } + + batadv_tt_local_entry_free_ref(tt_local); + } +@@ -3188,8 +3196,10 @@ static void batadv_tt_local_purge_pendin + + /* decrease the reference held for this vlan */ + vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid); +- batadv_softif_vlan_free_ref(vlan); +- batadv_softif_vlan_free_ref(vlan); ++ if (vlan) { ++ batadv_softif_vlan_free_ref(vlan); ++ batadv_softif_vlan_free_ref(vlan); ++ } + + batadv_tt_local_entry_free_ref(tt_local); + } diff --git a/queue-4.1/batman-adv-make-dat-capability-changes-atomic.patch b/queue-4.1/batman-adv-make-dat-capability-changes-atomic.patch new file mode 100644 index 00000000000..f06cb6beb28 --- /dev/null +++ b/queue-4.1/batman-adv-make-dat-capability-changes-atomic.patch @@ -0,0 +1,80 @@ +From 65d7d46050704bcdb8121ddbf4110bfbf2b38baa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Linus=20L=C3=BCssing?= +Date: Tue, 16 Jun 2015 17:10:22 +0200 +Subject: batman-adv: Make DAT capability changes atomic +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: =?UTF-8?q?Linus=20L=C3=BCssing?= + +commit 65d7d46050704bcdb8121ddbf4110bfbf2b38baa upstream. + +Bitwise OR/AND assignments in C aren't guaranteed to be atomic. One +OGM handler might undo the set/clear of a specific bit from another +handler run in between. + +Fix this by using the atomic set_bit()/clear_bit()/test_bit() functions. + +Fixes: 17cf0ea455f1 ("batman-adv: tvlv - add distributed arp table container") +Signed-off-by: Linus Lüssing +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman + +--- + net/batman-adv/distributed-arp-table.c | 7 ++++--- + net/batman-adv/types.h | 4 ++-- + 2 files changed, 6 insertions(+), 5 deletions(-) + +--- a/net/batman-adv/distributed-arp-table.c ++++ b/net/batman-adv/distributed-arp-table.c +@@ -15,6 +15,7 @@ + * along with this program; if not, see . + */ + ++#include + #include + #include + #include +@@ -422,7 +423,7 @@ static bool batadv_is_orig_node_eligible + int j; + + /* check if orig node candidate is running DAT */ +- if (!(candidate->capabilities & BATADV_ORIG_CAPA_HAS_DAT)) ++ if (!test_bit(BATADV_ORIG_CAPA_HAS_DAT, &candidate->capabilities)) + goto out; + + /* Check if this node has already been selected... */ +@@ -682,9 +683,9 @@ static void batadv_dat_tvlv_ogm_handler_ + uint16_t tvlv_value_len) + { + if (flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND) +- orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_DAT; ++ clear_bit(BATADV_ORIG_CAPA_HAS_DAT, &orig->capabilities); + else +- orig->capabilities |= BATADV_ORIG_CAPA_HAS_DAT; ++ set_bit(BATADV_ORIG_CAPA_HAS_DAT, &orig->capabilities); + } + + /** +--- a/net/batman-adv/types.h ++++ b/net/batman-adv/types.h +@@ -256,7 +256,7 @@ struct batadv_orig_node { + struct hlist_node mcast_want_all_ipv4_node; + struct hlist_node mcast_want_all_ipv6_node; + #endif +- uint8_t capabilities; ++ unsigned long capabilities; + uint8_t capa_initialized; + atomic_t last_ttvn; + unsigned char *tt_buff; +@@ -296,7 +296,7 @@ struct batadv_orig_node { + * (= orig node announces a tvlv of type BATADV_TVLV_MCAST) + */ + enum batadv_orig_capabilities { +- BATADV_ORIG_CAPA_HAS_DAT = BIT(0), ++ BATADV_ORIG_CAPA_HAS_DAT, + BATADV_ORIG_CAPA_HAS_NC = BIT(1), + BATADV_ORIG_CAPA_HAS_TT = BIT(2), + BATADV_ORIG_CAPA_HAS_MCAST = BIT(3), diff --git a/queue-4.1/batman-adv-protect-tt_local_entry-from-concurrent-delete-events.patch b/queue-4.1/batman-adv-protect-tt_local_entry-from-concurrent-delete-events.patch new file mode 100644 index 00000000000..98e70d1869d --- /dev/null +++ b/queue-4.1/batman-adv-protect-tt_local_entry-from-concurrent-delete-events.patch @@ -0,0 +1,54 @@ +From ef72706a0543d0c3a5ab29bd6378fdfb368118d9 Mon Sep 17 00:00:00 2001 +From: Marek Lindner +Date: Wed, 17 Jun 2015 20:01:36 +0800 +Subject: batman-adv: protect tt_local_entry from concurrent delete events + +From: Marek Lindner + +commit ef72706a0543d0c3a5ab29bd6378fdfb368118d9 upstream. + +The tt_local_entry deletion performed in batadv_tt_local_remove() was neither +protecting against simultaneous deletes nor checking whether the element was +still part of the list before calling hlist_del_rcu(). + +Replacing the hlist_del_rcu() call with batadv_hash_remove() provides adequate +protection via hash spinlocks as well as an is-element-still-in-hash check to +avoid 'blind' hash removal. + +Fixes: 068ee6e204e1 ("batman-adv: roaming handling mechanism redesign") +Reported-by: alfonsname@web.de +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman + +--- + net/batman-adv/translation-table.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/net/batman-adv/translation-table.c ++++ b/net/batman-adv/translation-table.c +@@ -1018,6 +1018,7 @@ uint16_t batadv_tt_local_remove(struct b + struct batadv_tt_local_entry *tt_local_entry; + uint16_t flags, curr_flags = BATADV_NO_FLAGS; + struct batadv_softif_vlan *vlan; ++ void *tt_entry_exists; + + tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid); + if (!tt_local_entry) +@@ -1045,7 +1046,15 @@ uint16_t batadv_tt_local_remove(struct b + * immediately purge it + */ + batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL); +- hlist_del_rcu(&tt_local_entry->common.hash_entry); ++ ++ tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash, ++ batadv_compare_tt, ++ batadv_choose_tt, ++ &tt_local_entry->common); ++ if (!tt_entry_exists) ++ goto out; ++ ++ /* extra call to free the local tt entry */ + batadv_tt_local_entry_free_ref(tt_local_entry); + + /* decrease the reference held for this vlan */ diff --git a/queue-4.1/fbdev-select-versatile-helpers-for-the-integrator.patch b/queue-4.1/fbdev-select-versatile-helpers-for-the-integrator.patch new file mode 100644 index 00000000000..7d4fa13548b --- /dev/null +++ b/queue-4.1/fbdev-select-versatile-helpers-for-the-integrator.patch @@ -0,0 +1,36 @@ +From 2701fa0864ecb9e49d47a4aa1c02f172ab79639a Mon Sep 17 00:00:00 2001 +From: Linus Walleij +Date: Tue, 28 Jul 2015 15:31:12 +0200 +Subject: fbdev: select versatile helpers for the integrator + +From: Linus Walleij + +commit 2701fa0864ecb9e49d47a4aa1c02f172ab79639a upstream. + +Commit 11c32d7b6274cb0f554943d65bd4a126c4a86dcd +"video: move Versatile CLCD helpers" missed the fact +that the Integrator/CP is also using the helper, and +as a result the platform got only stubs and no graphics. +Add this as a default selection to Kconfig so we have +graphics again. + +Fixes: 11c32d7b6274 (video: move Versatile CLCD helpers) +Signed-off-by: Linus Walleij +Signed-off-by: Tomi Valkeinen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/video/fbdev/Kconfig | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/video/fbdev/Kconfig ++++ b/drivers/video/fbdev/Kconfig +@@ -298,7 +298,7 @@ config FB_ARMCLCD + + # Helper logic selected only by the ARM Versatile platform family. + config PLAT_VERSATILE_CLCD +- def_bool ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS ++ def_bool ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS || ARCH_INTEGRATOR + depends on ARM + depends on FB_ARMCLCD && FB=y + diff --git a/queue-4.1/initialize-msg-shm-ipc-objects-before-doing-ipc_addid.patch b/queue-4.1/initialize-msg-shm-ipc-objects-before-doing-ipc_addid.patch new file mode 100644 index 00000000000..7ca020be87f --- /dev/null +++ b/queue-4.1/initialize-msg-shm-ipc-objects-before-doing-ipc_addid.patch @@ -0,0 +1,113 @@ +From b9a532277938798b53178d5a66af6e2915cb27cf Mon Sep 17 00:00:00 2001 +From: Linus Torvalds +Date: Wed, 30 Sep 2015 12:48:40 -0400 +Subject: Initialize msg/shm IPC objects before doing ipc_addid() + +From: Linus Torvalds + +commit b9a532277938798b53178d5a66af6e2915cb27cf upstream. + +As reported by Dmitry Vyukov, we really shouldn't do ipc_addid() before +having initialized the IPC object state. Yes, we initialize the IPC +object in a locked state, but with all the lockless RCU lookup work, +that IPC object lock no longer means that the state cannot be seen. + +We already did this for the IPC semaphore code (see commit e8577d1f0329: +"ipc/sem.c: fully initialize sem_array before making it visible") but we +clearly forgot about msg and shm. + +Reported-by: Dmitry Vyukov +Cc: Manfred Spraul +Cc: Davidlohr Bueso +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + ipc/msg.c | 14 +++++++------- + ipc/shm.c | 13 +++++++------ + ipc/util.c | 8 ++++---- + 3 files changed, 18 insertions(+), 17 deletions(-) + +--- a/ipc/msg.c ++++ b/ipc/msg.c +@@ -137,13 +137,6 @@ static int newque(struct ipc_namespace * + return retval; + } + +- /* ipc_addid() locks msq upon success. */ +- id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni); +- if (id < 0) { +- ipc_rcu_putref(msq, msg_rcu_free); +- return id; +- } +- + msq->q_stime = msq->q_rtime = 0; + msq->q_ctime = get_seconds(); + msq->q_cbytes = msq->q_qnum = 0; +@@ -153,6 +146,13 @@ static int newque(struct ipc_namespace * + INIT_LIST_HEAD(&msq->q_receivers); + INIT_LIST_HEAD(&msq->q_senders); + ++ /* ipc_addid() locks msq upon success. */ ++ id = ipc_addid(&msg_ids(ns), &msq->q_perm, ns->msg_ctlmni); ++ if (id < 0) { ++ ipc_rcu_putref(msq, msg_rcu_free); ++ return id; ++ } ++ + ipc_unlock_object(&msq->q_perm); + rcu_read_unlock(); + +--- a/ipc/shm.c ++++ b/ipc/shm.c +@@ -550,12 +550,6 @@ static int newseg(struct ipc_namespace * + if (IS_ERR(file)) + goto no_file; + +- id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); +- if (id < 0) { +- error = id; +- goto no_id; +- } +- + shp->shm_cprid = task_tgid_vnr(current); + shp->shm_lprid = 0; + shp->shm_atim = shp->shm_dtim = 0; +@@ -564,6 +558,13 @@ static int newseg(struct ipc_namespace * + shp->shm_nattch = 0; + shp->shm_file = file; + shp->shm_creator = current; ++ ++ id = ipc_addid(&shm_ids(ns), &shp->shm_perm, ns->shm_ctlmni); ++ if (id < 0) { ++ error = id; ++ goto no_id; ++ } ++ + list_add(&shp->shm_clist, ¤t->sysvshm.shm_clist); + + /* +--- a/ipc/util.c ++++ b/ipc/util.c +@@ -237,6 +237,10 @@ int ipc_addid(struct ipc_ids *ids, struc + rcu_read_lock(); + spin_lock(&new->lock); + ++ current_euid_egid(&euid, &egid); ++ new->cuid = new->uid = euid; ++ new->gid = new->cgid = egid; ++ + id = idr_alloc(&ids->ipcs_idr, new, + (next_id < 0) ? 0 : ipcid_to_idx(next_id), 0, + GFP_NOWAIT); +@@ -249,10 +253,6 @@ int ipc_addid(struct ipc_ids *ids, struc + + ids->in_use++; + +- current_euid_egid(&euid, &egid); +- new->cuid = new->uid = euid; +- new->gid = new->cgid = egid; +- + if (next_id < 0) { + new->seq = ids->seq++; + if (ids->seq > IPCID_SEQ_MAX) diff --git a/queue-4.1/ipvs-call-skb_sender_cpu_clear.patch b/queue-4.1/ipvs-call-skb_sender_cpu_clear.patch new file mode 100644 index 00000000000..7ad79774886 --- /dev/null +++ b/queue-4.1/ipvs-call-skb_sender_cpu_clear.patch @@ -0,0 +1,49 @@ +From e3895c0334d0ef46e80f22eaf2a52401ff6d5a67 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Thu, 9 Jul 2015 11:15:27 +0300 +Subject: ipvs: call skb_sender_cpu_clear + +From: Julian Anastasov + +commit e3895c0334d0ef46e80f22eaf2a52401ff6d5a67 upstream. + +Reset XPS's sender_cpu on forwarding. + +Signed-off-by: Julian Anastasov +Fixes: 2bd82484bb4c ("xps: fix xps for stacked devices") +Signed-off-by: Simon Horman +Signed-off-by: Greg Kroah-Hartman + +--- + net/netfilter/ipvs/ip_vs_xmit.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -518,6 +518,8 @@ static inline int ip_vs_tunnel_xmit_prep + if (ret == NF_ACCEPT) { + nf_reset(skb); + skb_forward_csum(skb); ++ if (!skb->sk) ++ skb_sender_cpu_clear(skb); + } + return ret; + } +@@ -558,6 +560,8 @@ static inline int ip_vs_nat_send_or_cont + + if (!local) { + skb_forward_csum(skb); ++ if (!skb->sk) ++ skb_sender_cpu_clear(skb); + NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, + NULL, skb_dst(skb)->dev, dst_output_sk); + } else +@@ -578,6 +582,8 @@ static inline int ip_vs_send_or_cont(int + if (!local) { + ip_vs_drop_early_demux_sk(skb); + skb_forward_csum(skb); ++ if (!skb->sk) ++ skb_sender_cpu_clear(skb); + NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, + NULL, skb_dst(skb)->dev, dst_output_sk); + } else diff --git a/queue-4.1/ipvs-do-not-use-random-local-source-address-for-tunnels.patch b/queue-4.1/ipvs-do-not-use-random-local-source-address-for-tunnels.patch new file mode 100644 index 00000000000..c76e4b569b4 --- /dev/null +++ b/queue-4.1/ipvs-do-not-use-random-local-source-address-for-tunnels.patch @@ -0,0 +1,43 @@ +From 4754957f04f5f368792a0eb7dab0ae89fb93dcfd Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Sat, 27 Jun 2015 14:39:30 +0300 +Subject: ipvs: do not use random local source address for tunnels + +From: Julian Anastasov + +commit 4754957f04f5f368792a0eb7dab0ae89fb93dcfd upstream. + +Michael Vallaly reports about wrong source address used +in rare cases for tunneled traffic. Looks like +__ip_vs_get_out_rt in 3.10+ is providing uninitialized +dest_dst->dst_saddr.ip because ip_vs_dest_dst_alloc uses +kmalloc. While we retry after seeing EINVAL from routing +for data that does not look like valid local address, it +still succeeded when this memory was previously used from +other dests and with different local addresses. As result, +we can use valid local address that is not suitable for +our real server. + +Fix it by providing 0.0.0.0 every time our cache is refreshed. +By this way we will get preferred source address from routing. + +Reported-by: Michael Vallaly +Fixes: 026ace060dfe ("ipvs: optimize dst usage for real server") +Signed-off-by: Julian Anastasov +Signed-off-by: Simon Horman +Signed-off-by: Greg Kroah-Hartman + +--- + net/netfilter/ipvs/ip_vs_xmit.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -130,7 +130,6 @@ static struct rtable *do_output_route4(s + + memset(&fl4, 0, sizeof(fl4)); + fl4.daddr = daddr; +- fl4.saddr = (rt_mode & IP_VS_RT_MODE_CONNECT) ? *saddr : 0; + fl4.flowi4_flags = (rt_mode & IP_VS_RT_MODE_KNOWN_NH) ? + FLOWI_FLAG_KNOWN_NH : 0; + diff --git a/queue-4.1/ipvs-fix-crash-if-scheduler-is-changed.patch b/queue-4.1/ipvs-fix-crash-if-scheduler-is-changed.patch new file mode 100644 index 00000000000..7f8af1a579a --- /dev/null +++ b/queue-4.1/ipvs-fix-crash-if-scheduler-is-changed.patch @@ -0,0 +1,293 @@ +From 05f00505a89acd21f5d0d20f5797dfbc4cf85243 Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Mon, 29 Jun 2015 21:51:40 +0300 +Subject: ipvs: fix crash if scheduler is changed + +From: Julian Anastasov + +commit 05f00505a89acd21f5d0d20f5797dfbc4cf85243 upstream. + +I overlooked the svc->sched_data usage from schedulers +when the services were converted to RCU in 3.10. Now +the rare ipvsadm -E command can change the scheduler +but due to the reverse order of ip_vs_bind_scheduler +and ip_vs_unbind_scheduler we provide new sched_data +to the old scheduler resulting in a crash. + +To fix it without changing the scheduler methods we +have to use synchronize_rcu() only for the editing case. +It means all svc->scheduler readers should expect a +NULL value. To avoid breakage for the service listing +and ipvsadm -R we can use the "none" name to indicate +that scheduler is not assigned, a state when we drop +new connections. + +Reported-by: Alexander Vasiliev +Fixes: ceec4c381681 ("ipvs: convert services to rcu") +Signed-off-by: Julian Anastasov +Signed-off-by: Simon Horman +Signed-off-by: Greg Kroah-Hartman + +--- + net/netfilter/ipvs/ip_vs_core.c | 16 +++++++- + net/netfilter/ipvs/ip_vs_ctl.c | 78 ++++++++++++++++++++++++--------------- + net/netfilter/ipvs/ip_vs_sched.c | 12 +++--- + 3 files changed, 69 insertions(+), 37 deletions(-) + +--- a/net/netfilter/ipvs/ip_vs_core.c ++++ b/net/netfilter/ipvs/ip_vs_core.c +@@ -319,7 +319,13 @@ ip_vs_sched_persist(struct ip_vs_service + * return *ignored=0 i.e. ICMP and NF_DROP + */ + sched = rcu_dereference(svc->scheduler); +- dest = sched->schedule(svc, skb, iph); ++ if (sched) { ++ /* read svc->sched_data after svc->scheduler */ ++ smp_rmb(); ++ dest = sched->schedule(svc, skb, iph); ++ } else { ++ dest = NULL; ++ } + if (!dest) { + IP_VS_DBG(1, "p-schedule: no dest found.\n"); + kfree(param.pe_data); +@@ -467,7 +473,13 @@ ip_vs_schedule(struct ip_vs_service *svc + } + + sched = rcu_dereference(svc->scheduler); +- dest = sched->schedule(svc, skb, iph); ++ if (sched) { ++ /* read svc->sched_data after svc->scheduler */ ++ smp_rmb(); ++ dest = sched->schedule(svc, skb, iph); ++ } else { ++ dest = NULL; ++ } + if (dest == NULL) { + IP_VS_DBG(1, "Schedule: no dest found.\n"); + return NULL; +--- a/net/netfilter/ipvs/ip_vs_ctl.c ++++ b/net/netfilter/ipvs/ip_vs_ctl.c +@@ -842,15 +842,16 @@ __ip_vs_update_dest(struct ip_vs_service + __ip_vs_dst_cache_reset(dest); + spin_unlock_bh(&dest->dst_lock); + +- sched = rcu_dereference_protected(svc->scheduler, 1); + if (add) { + ip_vs_start_estimator(svc->net, &dest->stats); + list_add_rcu(&dest->n_list, &svc->destinations); + svc->num_dests++; +- if (sched->add_dest) ++ sched = rcu_dereference_protected(svc->scheduler, 1); ++ if (sched && sched->add_dest) + sched->add_dest(svc, dest); + } else { +- if (sched->upd_dest) ++ sched = rcu_dereference_protected(svc->scheduler, 1); ++ if (sched && sched->upd_dest) + sched->upd_dest(svc, dest); + } + } +@@ -1084,7 +1085,7 @@ static void __ip_vs_unlink_dest(struct i + struct ip_vs_scheduler *sched; + + sched = rcu_dereference_protected(svc->scheduler, 1); +- if (sched->del_dest) ++ if (sched && sched->del_dest) + sched->del_dest(svc, dest); + } + } +@@ -1175,11 +1176,14 @@ ip_vs_add_service(struct net *net, struc + ip_vs_use_count_inc(); + + /* Lookup the scheduler by 'u->sched_name' */ +- sched = ip_vs_scheduler_get(u->sched_name); +- if (sched == NULL) { +- pr_info("Scheduler module ip_vs_%s not found\n", u->sched_name); +- ret = -ENOENT; +- goto out_err; ++ if (strcmp(u->sched_name, "none")) { ++ sched = ip_vs_scheduler_get(u->sched_name); ++ if (!sched) { ++ pr_info("Scheduler module ip_vs_%s not found\n", ++ u->sched_name); ++ ret = -ENOENT; ++ goto out_err; ++ } + } + + if (u->pe_name && *u->pe_name) { +@@ -1240,10 +1244,12 @@ ip_vs_add_service(struct net *net, struc + spin_lock_init(&svc->stats.lock); + + /* Bind the scheduler */ +- ret = ip_vs_bind_scheduler(svc, sched); +- if (ret) +- goto out_err; +- sched = NULL; ++ if (sched) { ++ ret = ip_vs_bind_scheduler(svc, sched); ++ if (ret) ++ goto out_err; ++ sched = NULL; ++ } + + /* Bind the ct retriever */ + RCU_INIT_POINTER(svc->pe, pe); +@@ -1291,17 +1297,20 @@ ip_vs_add_service(struct net *net, struc + static int + ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u) + { +- struct ip_vs_scheduler *sched, *old_sched; ++ struct ip_vs_scheduler *sched = NULL, *old_sched; + struct ip_vs_pe *pe = NULL, *old_pe = NULL; + int ret = 0; + + /* + * Lookup the scheduler, by 'u->sched_name' + */ +- sched = ip_vs_scheduler_get(u->sched_name); +- if (sched == NULL) { +- pr_info("Scheduler module ip_vs_%s not found\n", u->sched_name); +- return -ENOENT; ++ if (strcmp(u->sched_name, "none")) { ++ sched = ip_vs_scheduler_get(u->sched_name); ++ if (!sched) { ++ pr_info("Scheduler module ip_vs_%s not found\n", ++ u->sched_name); ++ return -ENOENT; ++ } + } + old_sched = sched; + +@@ -1329,14 +1338,20 @@ ip_vs_edit_service(struct ip_vs_service + + old_sched = rcu_dereference_protected(svc->scheduler, 1); + if (sched != old_sched) { ++ if (old_sched) { ++ ip_vs_unbind_scheduler(svc, old_sched); ++ RCU_INIT_POINTER(svc->scheduler, NULL); ++ /* Wait all svc->sched_data users */ ++ synchronize_rcu(); ++ } + /* Bind the new scheduler */ +- ret = ip_vs_bind_scheduler(svc, sched); +- if (ret) { +- old_sched = sched; +- goto out; ++ if (sched) { ++ ret = ip_vs_bind_scheduler(svc, sched); ++ if (ret) { ++ ip_vs_scheduler_put(sched); ++ goto out; ++ } + } +- /* Unbind the old scheduler on success */ +- ip_vs_unbind_scheduler(svc, old_sched); + } + + /* +@@ -1982,6 +1997,7 @@ static int ip_vs_info_seq_show(struct se + const struct ip_vs_iter *iter = seq->private; + const struct ip_vs_dest *dest; + struct ip_vs_scheduler *sched = rcu_dereference(svc->scheduler); ++ char *sched_name = sched ? sched->name : "none"; + + if (iter->table == ip_vs_svc_table) { + #ifdef CONFIG_IP_VS_IPV6 +@@ -1990,18 +2006,18 @@ static int ip_vs_info_seq_show(struct se + ip_vs_proto_name(svc->protocol), + &svc->addr.in6, + ntohs(svc->port), +- sched->name); ++ sched_name); + else + #endif + seq_printf(seq, "%s %08X:%04X %s %s ", + ip_vs_proto_name(svc->protocol), + ntohl(svc->addr.ip), + ntohs(svc->port), +- sched->name, ++ sched_name, + (svc->flags & IP_VS_SVC_F_ONEPACKET)?"ops ":""); + } else { + seq_printf(seq, "FWM %08X %s %s", +- svc->fwmark, sched->name, ++ svc->fwmark, sched_name, + (svc->flags & IP_VS_SVC_F_ONEPACKET)?"ops ":""); + } + +@@ -2427,13 +2443,15 @@ ip_vs_copy_service(struct ip_vs_service_ + { + struct ip_vs_scheduler *sched; + struct ip_vs_kstats kstats; ++ char *sched_name; + + sched = rcu_dereference_protected(src->scheduler, 1); ++ sched_name = sched ? sched->name : "none"; + dst->protocol = src->protocol; + dst->addr = src->addr.ip; + dst->port = src->port; + dst->fwmark = src->fwmark; +- strlcpy(dst->sched_name, sched->name, sizeof(dst->sched_name)); ++ strlcpy(dst->sched_name, sched_name, sizeof(dst->sched_name)); + dst->flags = src->flags; + dst->timeout = src->timeout / HZ; + dst->netmask = src->netmask; +@@ -2892,6 +2910,7 @@ static int ip_vs_genl_fill_service(struc + struct ip_vs_flags flags = { .flags = svc->flags, + .mask = ~0 }; + struct ip_vs_kstats kstats; ++ char *sched_name; + + nl_service = nla_nest_start(skb, IPVS_CMD_ATTR_SERVICE); + if (!nl_service) +@@ -2910,8 +2929,9 @@ static int ip_vs_genl_fill_service(struc + } + + sched = rcu_dereference_protected(svc->scheduler, 1); ++ sched_name = sched ? sched->name : "none"; + pe = rcu_dereference_protected(svc->pe, 1); +- if (nla_put_string(skb, IPVS_SVC_ATTR_SCHED_NAME, sched->name) || ++ if (nla_put_string(skb, IPVS_SVC_ATTR_SCHED_NAME, sched_name) || + (pe && nla_put_string(skb, IPVS_SVC_ATTR_PE_NAME, pe->name)) || + nla_put(skb, IPVS_SVC_ATTR_FLAGS, sizeof(flags), &flags) || + nla_put_u32(skb, IPVS_SVC_ATTR_TIMEOUT, svc->timeout / HZ) || +--- a/net/netfilter/ipvs/ip_vs_sched.c ++++ b/net/netfilter/ipvs/ip_vs_sched.c +@@ -74,7 +74,7 @@ void ip_vs_unbind_scheduler(struct ip_vs + + if (sched->done_service) + sched->done_service(svc); +- /* svc->scheduler can not be set to NULL */ ++ /* svc->scheduler can be set to NULL only by caller */ + } + + +@@ -147,21 +147,21 @@ void ip_vs_scheduler_put(struct ip_vs_sc + + void ip_vs_scheduler_err(struct ip_vs_service *svc, const char *msg) + { +- struct ip_vs_scheduler *sched; ++ struct ip_vs_scheduler *sched = rcu_dereference(svc->scheduler); ++ char *sched_name = sched ? sched->name : "none"; + +- sched = rcu_dereference(svc->scheduler); + if (svc->fwmark) { + IP_VS_ERR_RL("%s: FWM %u 0x%08X - %s\n", +- sched->name, svc->fwmark, svc->fwmark, msg); ++ sched_name, svc->fwmark, svc->fwmark, msg); + #ifdef CONFIG_IP_VS_IPV6 + } else if (svc->af == AF_INET6) { + IP_VS_ERR_RL("%s: %s [%pI6c]:%d - %s\n", +- sched->name, ip_vs_proto_name(svc->protocol), ++ sched_name, ip_vs_proto_name(svc->protocol), + &svc->addr.in6, ntohs(svc->port), msg); + #endif + } else { + IP_VS_ERR_RL("%s: %s %pI4:%d - %s\n", +- sched->name, ip_vs_proto_name(svc->protocol), ++ sched_name, ip_vs_proto_name(svc->protocol), + &svc->addr.ip, ntohs(svc->port), msg); + } + } diff --git a/queue-4.1/ipvs-fix-crash-with-sync-protocol-v0-and-ftp.patch b/queue-4.1/ipvs-fix-crash-with-sync-protocol-v0-and-ftp.patch new file mode 100644 index 00000000000..6f6338e9692 --- /dev/null +++ b/queue-4.1/ipvs-fix-crash-with-sync-protocol-v0-and-ftp.patch @@ -0,0 +1,32 @@ +From 56184858d1fc95c46723436b455cb7261cd8be6f Mon Sep 17 00:00:00 2001 +From: Julian Anastasov +Date: Wed, 8 Jul 2015 08:31:33 +0300 +Subject: ipvs: fix crash with sync protocol v0 and FTP + +From: Julian Anastasov + +commit 56184858d1fc95c46723436b455cb7261cd8be6f upstream. + +Fix crash in 3.5+ if FTP is used after switching +sync_version to 0. + +Fixes: 749c42b620a9 ("ipvs: reduce sync rate with time thresholds") +Signed-off-by: Julian Anastasov +Signed-off-by: Simon Horman +Signed-off-by: Greg Kroah-Hartman + +--- + net/netfilter/ipvs/ip_vs_sync.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/netfilter/ipvs/ip_vs_sync.c ++++ b/net/netfilter/ipvs/ip_vs_sync.c +@@ -612,7 +612,7 @@ static void ip_vs_sync_conn_v0(struct ne + pkts = atomic_add_return(1, &cp->in_pkts); + else + pkts = sysctl_sync_threshold(ipvs); +- ip_vs_sync_conn(net, cp->control, pkts); ++ ip_vs_sync_conn(net, cp, pkts); + } + } + diff --git a/queue-4.1/ipvs-skb_orphan-in-case-of-forwarding.patch b/queue-4.1/ipvs-skb_orphan-in-case-of-forwarding.patch new file mode 100644 index 00000000000..435b91fb5c6 --- /dev/null +++ b/queue-4.1/ipvs-skb_orphan-in-case-of-forwarding.patch @@ -0,0 +1,88 @@ +From 71563f3414e917c62acd8e0fb0edf8ed6af63e4b Mon Sep 17 00:00:00 2001 +From: Alex Gartrell +Date: Sun, 5 Jul 2015 14:28:26 -0700 +Subject: ipvs: skb_orphan in case of forwarding + +From: Alex Gartrell + +commit 71563f3414e917c62acd8e0fb0edf8ed6af63e4b upstream. + +It is possible that we bind against a local socket in early_demux when we +are actually going to want to forward it. In this case, the socket serves +no purpose and only serves to confuse things (particularly functions which +implicitly expect sk_fullsock to be true, like ip_local_out). +Additionally, skb_set_owner_w is totally broken for non full-socks. + +Signed-off-by: Alex Gartrell +Fixes: 41063e9dd119 ("ipv4: Early TCP socket demux.") +Acked-by: Julian Anastasov +Signed-off-by: Simon Horman +Signed-off-by: Greg Kroah-Hartman + +--- + net/netfilter/ipvs/ip_vs_xmit.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +--- a/net/netfilter/ipvs/ip_vs_xmit.c ++++ b/net/netfilter/ipvs/ip_vs_xmit.c +@@ -522,6 +522,21 @@ static inline int ip_vs_tunnel_xmit_prep + return ret; + } + ++/* In the event of a remote destination, it's possible that we would have ++ * matches against an old socket (particularly a TIME-WAIT socket). This ++ * causes havoc down the line (ip_local_out et. al. expect regular sockets ++ * and invalid memory accesses will happen) so simply drop the association ++ * in this case. ++*/ ++static inline void ip_vs_drop_early_demux_sk(struct sk_buff *skb) ++{ ++ /* If dev is set, the packet came from the LOCAL_IN callback and ++ * not from a local TCP socket. ++ */ ++ if (skb->dev) ++ skb_orphan(skb); ++} ++ + /* return NF_STOLEN (sent) or NF_ACCEPT if local=1 (not sent) */ + static inline int ip_vs_nat_send_or_cont(int pf, struct sk_buff *skb, + struct ip_vs_conn *cp, int local) +@@ -533,12 +548,21 @@ static inline int ip_vs_nat_send_or_cont + ip_vs_notrack(skb); + else + ip_vs_update_conntrack(skb, cp, 1); ++ ++ /* Remove the early_demux association unless it's bound for the ++ * exact same port and address on this host after translation. ++ */ ++ if (!local || cp->vport != cp->dport || ++ !ip_vs_addr_equal(cp->af, &cp->vaddr, &cp->daddr)) ++ ip_vs_drop_early_demux_sk(skb); ++ + if (!local) { + skb_forward_csum(skb); + NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, + NULL, skb_dst(skb)->dev, dst_output_sk); + } else + ret = NF_ACCEPT; ++ + return ret; + } + +@@ -552,6 +576,7 @@ static inline int ip_vs_send_or_cont(int + if (likely(!(cp->flags & IP_VS_CONN_F_NFCT))) + ip_vs_notrack(skb); + if (!local) { ++ ip_vs_drop_early_demux_sk(skb); + skb_forward_csum(skb); + NF_HOOK(pf, NF_INET_LOCAL_OUT, NULL, skb, + NULL, skb_dst(skb)->dev, dst_output_sk); +@@ -840,6 +865,8 @@ ip_vs_prepare_tunneled_skb(struct sk_buf + struct ipv6hdr *old_ipv6h = NULL; + #endif + ++ ip_vs_drop_early_demux_sk(skb); ++ + if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) { + new_skb = skb_realloc_headroom(skb, max_headroom); + if (!new_skb) diff --git a/queue-4.1/sched-fair-prevent-throttling-in-early-pick_next_task_fair.patch b/queue-4.1/sched-fair-prevent-throttling-in-early-pick_next_task_fair.patch new file mode 100644 index 00000000000..d9fc5f77dbd --- /dev/null +++ b/queue-4.1/sched-fair-prevent-throttling-in-early-pick_next_task_fair.patch @@ -0,0 +1,86 @@ +From 54d27365cae88fbcc853b391dcd561e71acb81fa Mon Sep 17 00:00:00 2001 +From: Ben Segall +Date: Mon, 6 Apr 2015 15:28:10 -0700 +Subject: sched/fair: Prevent throttling in early pick_next_task_fair() + +From: Ben Segall + +commit 54d27365cae88fbcc853b391dcd561e71acb81fa upstream. + +The optimized task selection logic optimistically selects a new task +to run without first doing a full put_prev_task(). This is so that we +can avoid a put/set on the common ancestors of the old and new task. + +Similarly, we should only call check_cfs_rq_runtime() to throttle +eligible groups if they're part of the common ancestry, otherwise it +is possible to end up with no eligible task in the simple task +selection. + +Imagine: + /root + /prev /next + /A /B + +If our optimistic selection ends up throttling /next, we goto simple +and our put_prev_task() ends up throttling /prev, after which we're +going to bug out in set_next_entity() because there aren't any tasks +left. + +Avoid this scenario by only throttling common ancestors. + +Reported-by: Mohammed Naser +Reported-by: Konstantin Khlebnikov +Signed-off-by: Ben Segall +[ munged Changelog ] +Signed-off-by: Peter Zijlstra (Intel) +Cc: Andrew Morton +Cc: H. Peter Anvin +Cc: Linus Torvalds +Cc: Peter Zijlstra +Cc: Roman Gushchin +Cc: Thomas Gleixner +Cc: pjt@google.com +Fixes: 678d5718d8d0 ("sched/fair: Optimize cgroup pick_next_task_fair()") +Link: http://lkml.kernel.org/r/xm26wq1oswoq.fsf@sword-of-the-dawn.mtv.corp.google.com +Signed-off-by: Ingo Molnar +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/sched/fair.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -5126,18 +5126,21 @@ again: + * entity, update_curr() will update its vruntime, otherwise + * forget we've ever seen it. + */ +- if (curr && curr->on_rq) +- update_curr(cfs_rq); +- else +- curr = NULL; ++ if (curr) { ++ if (curr->on_rq) ++ update_curr(cfs_rq); ++ else ++ curr = NULL; + +- /* +- * This call to check_cfs_rq_runtime() will do the throttle and +- * dequeue its entity in the parent(s). Therefore the 'simple' +- * nr_running test will indeed be correct. +- */ +- if (unlikely(check_cfs_rq_runtime(cfs_rq))) +- goto simple; ++ /* ++ * This call to check_cfs_rq_runtime() will do the ++ * throttle and dequeue its entity in the parent(s). ++ * Therefore the 'simple' nr_running test will indeed ++ * be correct. ++ */ ++ if (unlikely(check_cfs_rq_runtime(cfs_rq))) ++ goto simple; ++ } + + se = pick_next_entity(cfs_rq, curr); + cfs_rq = group_cfs_rq(se); diff --git a/queue-4.1/serial-amba-pl011-disable-interrupts-around-tx-softirq.patch b/queue-4.1/serial-amba-pl011-disable-interrupts-around-tx-softirq.patch new file mode 100644 index 00000000000..6a0488d7b8e --- /dev/null +++ b/queue-4.1/serial-amba-pl011-disable-interrupts-around-tx-softirq.patch @@ -0,0 +1,60 @@ +From Dave.Martin@arm.com Sat Oct 17 13:59:05 2015 +From: Dave Martin +Date: Fri, 24 Jul 2015 17:39:21 +0100 +Subject: [PATCH REPOST] serial/amba-pl011: Disable interrupts around TX softirq +To: linux-serial@vger.kernel.org, Greg Kroah-Hartman +Cc: Russell King , Robin Murphy , linux-arm-kernel@lists.infradead.org, Jakub Kiciński , Andrew Jackson , Graeme Gregory , Andre Przywara , Jorge Ramirez-Ortiz , popcorn mix , stable +Message-ID: <1437755961-15403-1-git-send-email-Dave.Martin@arm.com> + +From: Dave Martin + +pl011_tx_softirq() currently uses spin_{,un}lock(), which are not +sufficient to inhibit pl011_int() from being triggered by a local +IRQ and trying to re-take the same lock. This can lead to +deadlocks. + +This patch uses the _irq() locking variants instead to ensure that +pl011_int() handling for a given port is deferred until any +pl011_tx_softirq() work for that port is complete. + + +Notes for stable: + +This patch fixes an issue that is fixed by the following upstream +commit, which is a more substantial rewrite of the affected code, +fixing multiple, mostly more minor issues: + + 1e84d22322ceed4767db1e5342c830dd60c8210f + serial/amba-pl011: Refactor and simplify TX FIFO handling + +The upstream patch was rejected for stable on the reasonable grounds +that it was too big and complex a patch. The original buggy code was +merged in v4.1, and the rewrite was merged in v4.2, leaving only v4.1 +affected. + + +This patch replaces the 1e84d22, for 4.1.x only. + +Fixes: 734745caeb9f serial/amba-pl011: Activate TX IRQ passively +Signed-off-by: Dave Martin +Tested-by: Robin Murphy +Tested-by: Stefan Wahren +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/amba-pl011.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/tty/serial/amba-pl011.c ++++ b/drivers/tty/serial/amba-pl011.c +@@ -1360,9 +1360,9 @@ static void pl011_tx_softirq(struct work + struct uart_amba_port *uap = + container_of(dwork, struct uart_amba_port, tx_softirq_work); + +- spin_lock(&uap->port.lock); ++ spin_lock_irq(&uap->port.lock); + while (pl011_tx_chars(uap)) ; +- spin_unlock(&uap->port.lock); ++ spin_unlock_irq(&uap->port.lock); + } + + static void pl011_tx_irq_seen(struct uart_amba_port *uap) diff --git a/queue-4.1/series b/queue-4.1/series index 1783b6b8b98..21b2d79dc7f 100644 --- a/queue-4.1/series +++ b/queue-4.1/series @@ -113,3 +113,15 @@ usb-xhci-exit-early-in-xhci_setup_device-if-we-re-halted-or-dying.patch xhci-change-xhci-1.0-only-restrictions-to-support-xhci-1.1.patch xhci-init-command-timeout-timer-earlier-to-avoid-deleting-it-uninitialized.patch usb-xhci-add-support-for-urb_zero_packet-to-bulk-sg-transfers.patch +initialize-msg-shm-ipc-objects-before-doing-ipc_addid.patch +sched-fair-prevent-throttling-in-early-pick_next_task_fair.patch +serial-amba-pl011-disable-interrupts-around-tx-softirq.patch +ipvs-do-not-use-random-local-source-address-for-tunnels.patch +ipvs-fix-crash-if-scheduler-is-changed.patch +ipvs-skb_orphan-in-case-of-forwarding.patch +ipvs-fix-crash-with-sync-protocol-v0-and-ftp.patch +ipvs-call-skb_sender_cpu_clear.patch +fbdev-select-versatile-helpers-for-the-integrator.patch +batman-adv-fix-kernel-crash-due-to-missing-null-checks.patch +batman-adv-protect-tt_local_entry-from-concurrent-delete-events.patch +batman-adv-make-dat-capability-changes-atomic.patch