From: Greg Kroah-Hartman Date: Wed, 27 Jan 2016 06:29:58 +0000 (-0800) Subject: 4.4-stable patches X-Git-Tag: v3.10.96~20 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4b6a61bb1284b4ea50507f3644b4a50cba0fccee;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: batman-adv-avoid-recursive-call_rcu-for-batadv_bla_claim.patch batman-adv-avoid-recursive-call_rcu-for-batadv_nc_node.patch batman-adv-drop-immediate-batadv_hard_iface-free-function.patch batman-adv-drop-immediate-batadv_neigh_node-free-function.patch batman-adv-drop-immediate-batadv_orig_ifinfo-free-function.patch batman-adv-drop-immediate-neigh_ifinfo-free-function.patch batman-adv-drop-immediate-orig_node-free-function.patch bonding-prevent-ipv6-link-local-address-on-enslaved-devices.patch bridge-fix-lockdep-addr_list_lock-false-positive-splat.patch dwc_eth_qos-fix-dma-address-for-multi-fragment-skbs.patch ipv6-tcp-add-rcu-locking-in-tcp_v6_send_synack.patch ipv6-update-skb-csum-when-ce-mark-is-propagated.patch net-bpf-reject-invalid-shifts.patch net-mlx5_core-fix-trimming-down-irq-number.patch net-pktgen-fix-null-ptr-deref-in-skb-allocation.patch net-preserve-ip-control-block-during-gso-segmentation.patch net-sctp-prevent-writes-to-cookie_hmac_alg-from-accessing-invalid-memory.patch phonet-properly-unshare-skbs-in-phonet_rcv.patch sched-cls_flower-set-key-address-type-when-present.patch tcp_yeah-don-t-set-ssthresh-below-2.patch team-replace-rcu_read_lock-with-a-mutex-in-team_vlan_rx_kill_vid.patch udp-disallow-ufo-for-sockets-with-so_no_check-option.patch unix-properly-account-for-fds-passed-over-unix-sockets.patch vxlan-fix-test-which-detect-duplicate-vxlan-iface.patch --- diff --git a/queue-4.4/batman-adv-avoid-recursive-call_rcu-for-batadv_bla_claim.patch b/queue-4.4/batman-adv-avoid-recursive-call_rcu-for-batadv_bla_claim.patch new file mode 100644 index 00000000000..b2a9848147f --- /dev/null +++ b/queue-4.4/batman-adv-avoid-recursive-call_rcu-for-batadv_bla_claim.patch @@ -0,0 +1,61 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Sven Eckelmann +Date: Thu, 14 Jan 2016 15:28:19 +0100 +Subject: batman-adv: Avoid recursive call_rcu for batadv_bla_claim + +From: Sven Eckelmann + +[ Upstream commit 63b399272294e7a939cde41792dca38c549f0484 ] + +The batadv_claim_free_ref function uses call_rcu to delay the free of the +batadv_bla_claim object until no (already started) rcu_read_lock is enabled +anymore. This makes sure that no context is still trying to access the +object which should be removed. But batadv_bla_claim also contains a +reference to backbone_gw which must be removed. + +The reference drop of backbone_gw was done in the call_rcu function +batadv_claim_free_rcu but should actually be done in the +batadv_claim_release function to avoid nested call_rcus. This is important +because rcu_barrier (e.g. batadv_softif_free or batadv_exit) will not +detect the inner call_rcu as relevant for its execution. Otherwise this +barrier will most likely be inserted in the queue before the callback of +the first call_rcu was executed. The caller of rcu_barrier will therefore +continue to run before the inner call_rcu callback finished. + +Fixes: 23721387c409 ("batman-adv: add basic bridge loop avoidance code") +Signed-off-by: Sven Eckelmann +Acked-by: Simon Wunderlich +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/bridge_loop_avoidance.c | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +--- a/net/batman-adv/bridge_loop_avoidance.c ++++ b/net/batman-adv/bridge_loop_avoidance.c +@@ -127,21 +127,17 @@ batadv_backbone_gw_free_ref(struct batad + } + + /* finally deinitialize the claim */ +-static void batadv_claim_free_rcu(struct rcu_head *rcu) ++static void batadv_claim_release(struct batadv_bla_claim *claim) + { +- struct batadv_bla_claim *claim; +- +- claim = container_of(rcu, struct batadv_bla_claim, rcu); +- + batadv_backbone_gw_free_ref(claim->backbone_gw); +- kfree(claim); ++ kfree_rcu(claim, rcu); + } + + /* free a claim, call claim_free_rcu if its the last reference */ + static void batadv_claim_free_ref(struct batadv_bla_claim *claim) + { + if (atomic_dec_and_test(&claim->refcount)) +- call_rcu(&claim->rcu, batadv_claim_free_rcu); ++ batadv_claim_release(claim); + } + + /** diff --git a/queue-4.4/batman-adv-avoid-recursive-call_rcu-for-batadv_nc_node.patch b/queue-4.4/batman-adv-avoid-recursive-call_rcu-for-batadv_nc_node.patch new file mode 100644 index 00000000000..a91a5ceb5ab --- /dev/null +++ b/queue-4.4/batman-adv-avoid-recursive-call_rcu-for-batadv_nc_node.patch @@ -0,0 +1,72 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Sven Eckelmann +Date: Tue, 5 Jan 2016 12:06:19 +0100 +Subject: batman-adv: Avoid recursive call_rcu for batadv_nc_node + +From: Sven Eckelmann + +[ Upstream commit 44e8e7e91d6c7c7ab19688750f7257292640d1a0 ] + +The batadv_nc_node_free_ref function uses call_rcu to delay the free of the +batadv_nc_node object until no (already started) rcu_read_lock is enabled +anymore. This makes sure that no context is still trying to access the +object which should be removed. But batadv_nc_node also contains a +reference to orig_node which must be removed. + +The reference drop of orig_node was done in the call_rcu function +batadv_nc_node_free_rcu but should actually be done in the +batadv_nc_node_release function to avoid nested call_rcus. This is +important because rcu_barrier (e.g. batadv_softif_free or batadv_exit) will +not detect the inner call_rcu as relevant for its execution. Otherwise this +barrier will most likely be inserted in the queue before the callback of +the first call_rcu was executed. The caller of rcu_barrier will therefore +continue to run before the inner call_rcu callback finished. + +Fixes: d56b1705e28c ("batman-adv: network coding - detect coding nodes and remove these after timeout") +Signed-off-by: Sven Eckelmann +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/network-coding.c | 19 ++++++++----------- + 1 file changed, 8 insertions(+), 11 deletions(-) + +--- a/net/batman-adv/network-coding.c ++++ b/net/batman-adv/network-coding.c +@@ -203,28 +203,25 @@ void batadv_nc_init_orig(struct batadv_o + } + + /** +- * batadv_nc_node_free_rcu - rcu callback to free an nc node and remove +- * its refcount on the orig_node +- * @rcu: rcu pointer of the nc node ++ * batadv_nc_node_release - release nc_node from lists and queue for free after ++ * rcu grace period ++ * @nc_node: the nc node to free + */ +-static void batadv_nc_node_free_rcu(struct rcu_head *rcu) ++static void batadv_nc_node_release(struct batadv_nc_node *nc_node) + { +- struct batadv_nc_node *nc_node; +- +- nc_node = container_of(rcu, struct batadv_nc_node, rcu); + batadv_orig_node_free_ref(nc_node->orig_node); +- kfree(nc_node); ++ kfree_rcu(nc_node, rcu); + } + + /** +- * batadv_nc_node_free_ref - decrements the nc node refcounter and possibly +- * frees it ++ * batadv_nc_node_free_ref - decrement the nc node refcounter and possibly ++ * release it + * @nc_node: the nc node to free + */ + static void batadv_nc_node_free_ref(struct batadv_nc_node *nc_node) + { + if (atomic_dec_and_test(&nc_node->refcount)) +- call_rcu(&nc_node->rcu, batadv_nc_node_free_rcu); ++ batadv_nc_node_release(nc_node); + } + + /** diff --git a/queue-4.4/batman-adv-drop-immediate-batadv_hard_iface-free-function.patch b/queue-4.4/batman-adv-drop-immediate-batadv_hard_iface-free-function.patch new file mode 100644 index 00000000000..93c4d6a9736 --- /dev/null +++ b/queue-4.4/batman-adv-drop-immediate-batadv_hard_iface-free-function.patch @@ -0,0 +1,95 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Sven Eckelmann +Date: Tue, 5 Jan 2016 12:06:25 +0100 +Subject: batman-adv: Drop immediate batadv_hard_iface free function + +From: Sven Eckelmann + +[ Upstream commit b4d922cfc9c08318eeb77d53b7633740e6b0efb0 ] + +It is not allowed to free the memory of an object which is part of a list +which is protected by rcu-read-side-critical sections without making sure +that no other context is accessing the object anymore. This usually happens +by removing the references to this object and then waiting until the rcu +grace period is over and no one (allowedly) accesses it anymore. + +But the _now functions ignore this completely. They free the object +directly even when a different context still tries to access it. This has +to be avoided and thus these functions must be removed and all functions +have to use batadv_hardif_free_ref. + +Fixes: 89652331c00f ("batman-adv: split tq information in neigh_node struct") +Signed-off-by: Sven Eckelmann +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/hard-interface.h | 12 ------------ + net/batman-adv/originator.c | 14 +++++++------- + 2 files changed, 7 insertions(+), 19 deletions(-) + +--- a/net/batman-adv/hard-interface.h ++++ b/net/batman-adv/hard-interface.h +@@ -75,18 +75,6 @@ batadv_hardif_free_ref(struct batadv_har + call_rcu(&hard_iface->rcu, batadv_hardif_free_rcu); + } + +-/** +- * batadv_hardif_free_ref_now - decrement the hard interface refcounter and +- * possibly free it (without rcu callback) +- * @hard_iface: the hard interface to free +- */ +-static inline void +-batadv_hardif_free_ref_now(struct batadv_hard_iface *hard_iface) +-{ +- if (atomic_dec_and_test(&hard_iface->refcount)) +- batadv_hardif_free_rcu(&hard_iface->rcu); +-} +- + static inline struct batadv_hard_iface * + batadv_primary_if_get_selected(struct batadv_priv *bat_priv) + { +--- a/net/batman-adv/originator.c ++++ b/net/batman-adv/originator.c +@@ -189,16 +189,16 @@ void batadv_neigh_ifinfo_free_ref(struct + + /** + * batadv_neigh_node_free_rcu - free the neigh_node +- * @rcu: rcu pointer of the neigh_node ++ * batadv_neigh_node_release - release neigh_node from lists and queue for ++ * free after rcu grace period ++ * @neigh_node: neigh neighbor to free + */ +-static void batadv_neigh_node_free_rcu(struct rcu_head *rcu) ++static void batadv_neigh_node_release(struct batadv_neigh_node *neigh_node) + { + struct hlist_node *node_tmp; +- struct batadv_neigh_node *neigh_node; + struct batadv_neigh_ifinfo *neigh_ifinfo; + struct batadv_algo_ops *bao; + +- neigh_node = container_of(rcu, struct batadv_neigh_node, rcu); + bao = neigh_node->orig_node->bat_priv->bat_algo_ops; + + hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, +@@ -209,9 +209,9 @@ static void batadv_neigh_node_free_rcu(s + if (bao->bat_neigh_free) + bao->bat_neigh_free(neigh_node); + +- batadv_hardif_free_ref_now(neigh_node->if_incoming); ++ batadv_hardif_free_ref(neigh_node->if_incoming); + +- kfree(neigh_node); ++ kfree_rcu(neigh_node, rcu); + } + + /** +@@ -222,7 +222,7 @@ static void batadv_neigh_node_free_rcu(s + void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) + { + if (atomic_dec_and_test(&neigh_node->refcount)) +- call_rcu(&neigh_node->rcu, batadv_neigh_node_free_rcu); ++ batadv_neigh_node_release(neigh_node); + } + + /** diff --git a/queue-4.4/batman-adv-drop-immediate-batadv_neigh_node-free-function.patch b/queue-4.4/batman-adv-drop-immediate-batadv_neigh_node-free-function.patch new file mode 100644 index 00000000000..b838ca7086c --- /dev/null +++ b/queue-4.4/batman-adv-drop-immediate-batadv_neigh_node-free-function.patch @@ -0,0 +1,95 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Sven Eckelmann +Date: Tue, 5 Jan 2016 12:06:22 +0100 +Subject: batman-adv: Drop immediate batadv_neigh_node free function + +From: Sven Eckelmann + +[ Upstream commit 2baa753c276f27f8e844637561ad597867aa6fb6 ] + +It is not allowed to free the memory of an object which is part of a list +which is protected by rcu-read-side-critical sections without making sure +that no other context is accessing the object anymore. This usually happens +by removing the references to this object and then waiting until the rcu +grace period is over and no one (allowedly) accesses it anymore. + +But the _now functions ignore this completely. They free the object +directly even when a different context still tries to access it. This has +to be avoided and thus these functions must be removed and all functions +have to use batadv_neigh_node_free_ref. + +Fixes: 89652331c00f ("batman-adv: split tq information in neigh_node struct") +Signed-off-by: Sven Eckelmann +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/originator.c | 33 ++++++++++----------------------- + 1 file changed, 10 insertions(+), 23 deletions(-) + +--- a/net/batman-adv/originator.c ++++ b/net/batman-adv/originator.c +@@ -229,20 +229,8 @@ static void batadv_neigh_node_free_rcu(s + } + + /** +- * batadv_neigh_node_free_ref_now - decrement the neighbors refcounter +- * and possibly free it (without rcu callback) +- * @neigh_node: neigh neighbor to free +- */ +-static void +-batadv_neigh_node_free_ref_now(struct batadv_neigh_node *neigh_node) +-{ +- if (atomic_dec_and_test(&neigh_node->refcount)) +- batadv_neigh_node_free_rcu(&neigh_node->rcu); +-} +- +-/** + * batadv_neigh_node_free_ref - decrement the neighbors refcounter +- * and possibly free it ++ * and possibly release it + * @neigh_node: neigh neighbor to free + */ + void batadv_neigh_node_free_ref(struct batadv_neigh_node *neigh_node) +@@ -532,24 +520,23 @@ out: + } + + /** +- * batadv_orig_ifinfo_free_rcu - free the orig_ifinfo object +- * @rcu: rcu pointer of the orig_ifinfo object ++ * batadv_orig_ifinfo_release - release orig_ifinfo from lists and queue for ++ * free after rcu grace period ++ * @orig_ifinfo: the orig_ifinfo object to release + */ +-static void batadv_orig_ifinfo_free_rcu(struct rcu_head *rcu) ++static void batadv_orig_ifinfo_release(struct batadv_orig_ifinfo *orig_ifinfo) + { +- struct batadv_orig_ifinfo *orig_ifinfo; + struct batadv_neigh_node *router; + +- orig_ifinfo = container_of(rcu, struct batadv_orig_ifinfo, rcu); +- + if (orig_ifinfo->if_outgoing != BATADV_IF_DEFAULT) +- batadv_hardif_free_ref_now(orig_ifinfo->if_outgoing); ++ batadv_hardif_free_ref(orig_ifinfo->if_outgoing); + + /* this is the last reference to this object */ + router = rcu_dereference_protected(orig_ifinfo->router, true); + if (router) +- batadv_neigh_node_free_ref_now(router); +- kfree(orig_ifinfo); ++ batadv_neigh_node_free_ref(router); ++ ++ kfree_rcu(orig_ifinfo, rcu); + } + + /** +@@ -560,7 +547,7 @@ static void batadv_orig_ifinfo_free_rcu( + void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo) + { + if (atomic_dec_and_test(&orig_ifinfo->refcount)) +- call_rcu(&orig_ifinfo->rcu, batadv_orig_ifinfo_free_rcu); ++ batadv_orig_ifinfo_release(orig_ifinfo); + } + + /** diff --git a/queue-4.4/batman-adv-drop-immediate-batadv_orig_ifinfo-free-function.patch b/queue-4.4/batman-adv-drop-immediate-batadv_orig_ifinfo-free-function.patch new file mode 100644 index 00000000000..249d9e6ddee --- /dev/null +++ b/queue-4.4/batman-adv-drop-immediate-batadv_orig_ifinfo-free-function.patch @@ -0,0 +1,139 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Sven Eckelmann +Date: Tue, 5 Jan 2016 12:06:21 +0100 +Subject: batman-adv: Drop immediate batadv_orig_ifinfo free function + +From: Sven Eckelmann + +[ Upstream commit deed96605f5695cb945e0b3d79429581857a2b9d ] + +It is not allowed to free the memory of an object which is part of a list +which is protected by rcu-read-side-critical sections without making sure +that no other context is accessing the object anymore. This usually happens +by removing the references to this object and then waiting until the rcu +grace period is over and no one (allowedly) accesses it anymore. + +But the _now functions ignore this completely. They free the object +directly even when a different context still tries to access it. This has +to be avoided and thus these functions must be removed and all functions +have to use batadv_orig_ifinfo_free_ref. + +Fixes: 7351a4822d42 ("batman-adv: split out router from orig_node") +Signed-off-by: Sven Eckelmann +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/originator.c | 59 +++++++++++++++++++++++--------------------- + 1 file changed, 31 insertions(+), 28 deletions(-) + +--- a/net/batman-adv/originator.c ++++ b/net/batman-adv/originator.c +@@ -553,76 +553,79 @@ static void batadv_orig_ifinfo_free_rcu( + } + + /** +- * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free +- * the orig_ifinfo (without rcu callback) ++ * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly release ++ * the orig_ifinfo + * @orig_ifinfo: the orig_ifinfo object to release + */ +-static void +-batadv_orig_ifinfo_free_ref_now(struct batadv_orig_ifinfo *orig_ifinfo) ++void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo) + { + if (atomic_dec_and_test(&orig_ifinfo->refcount)) +- batadv_orig_ifinfo_free_rcu(&orig_ifinfo->rcu); ++ call_rcu(&orig_ifinfo->rcu, batadv_orig_ifinfo_free_rcu); + } + + /** +- * batadv_orig_ifinfo_free_ref - decrement the refcounter and possibly free +- * the orig_ifinfo +- * @orig_ifinfo: the orig_ifinfo object to release ++ * batadv_orig_node_free_rcu - free the orig_node ++ * @rcu: rcu pointer of the orig_node + */ +-void batadv_orig_ifinfo_free_ref(struct batadv_orig_ifinfo *orig_ifinfo) ++static void batadv_orig_node_free_rcu(struct rcu_head *rcu) + { +- if (atomic_dec_and_test(&orig_ifinfo->refcount)) +- call_rcu(&orig_ifinfo->rcu, batadv_orig_ifinfo_free_rcu); ++ struct batadv_orig_node *orig_node; ++ ++ orig_node = container_of(rcu, struct batadv_orig_node, rcu); ++ ++ batadv_mcast_purge_orig(orig_node); ++ ++ batadv_frag_purge_orig(orig_node, NULL); ++ ++ if (orig_node->bat_priv->bat_algo_ops->bat_orig_free) ++ orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node); ++ ++ kfree(orig_node->tt_buff); ++ kfree(orig_node); + } + +-static void batadv_orig_node_free_rcu(struct rcu_head *rcu) ++/** ++ * batadv_orig_node_release - release orig_node from lists and queue for ++ * free after rcu grace period ++ * @orig_node: the orig node to free ++ */ ++static void batadv_orig_node_release(struct batadv_orig_node *orig_node) + { + struct hlist_node *node_tmp; + struct batadv_neigh_node *neigh_node; +- struct batadv_orig_node *orig_node; + struct batadv_orig_ifinfo *orig_ifinfo; + +- orig_node = container_of(rcu, struct batadv_orig_node, rcu); +- + spin_lock_bh(&orig_node->neigh_list_lock); + + /* for all neighbors towards this originator ... */ + hlist_for_each_entry_safe(neigh_node, node_tmp, + &orig_node->neigh_list, list) { + hlist_del_rcu(&neigh_node->list); +- batadv_neigh_node_free_ref_now(neigh_node); ++ batadv_neigh_node_free_ref(neigh_node); + } + + hlist_for_each_entry_safe(orig_ifinfo, node_tmp, + &orig_node->ifinfo_list, list) { + hlist_del_rcu(&orig_ifinfo->list); +- batadv_orig_ifinfo_free_ref_now(orig_ifinfo); ++ batadv_orig_ifinfo_free_ref(orig_ifinfo); + } + spin_unlock_bh(&orig_node->neigh_list_lock); + +- batadv_mcast_purge_orig(orig_node); +- + /* Free nc_nodes */ + batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL); + +- batadv_frag_purge_orig(orig_node, NULL); +- +- if (orig_node->bat_priv->bat_algo_ops->bat_orig_free) +- orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node); +- +- kfree(orig_node->tt_buff); +- kfree(orig_node); ++ call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu); + } + + /** + * batadv_orig_node_free_ref - decrement the orig node refcounter and possibly +- * schedule an rcu callback for freeing it ++ * release it + * @orig_node: the orig node to free + */ + void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node) + { + if (atomic_dec_and_test(&orig_node->refcount)) +- call_rcu(&orig_node->rcu, batadv_orig_node_free_rcu); ++ batadv_orig_node_release(orig_node); + } + + /** diff --git a/queue-4.4/batman-adv-drop-immediate-neigh_ifinfo-free-function.patch b/queue-4.4/batman-adv-drop-immediate-neigh_ifinfo-free-function.patch new file mode 100644 index 00000000000..ace881c0baf --- /dev/null +++ b/queue-4.4/batman-adv-drop-immediate-neigh_ifinfo-free-function.patch @@ -0,0 +1,92 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Sven Eckelmann +Date: Tue, 5 Jan 2016 12:06:24 +0100 +Subject: batman-adv: Drop immediate neigh_ifinfo free function + +From: Sven Eckelmann + +[ Upstream commit ae3e1e36e3cb6c686a7a2725af20ca86aa46d62a ] + +It is not allowed to free the memory of an object which is part of a list +which is protected by rcu-read-side-critical sections without making sure +that no other context is accessing the object anymore. This usually happens +by removing the references to this object and then waiting until the rcu +grace period is over and no one (allowedly) accesses it anymore. + +But the _now functions ignore this completely. They free the object +directly even when a different context still tries to access it. This has +to be avoided and thus these functions must be removed and all functions +have to use batadv_neigh_ifinfo_free_ref. + +Fixes: 89652331c00f ("batman-adv: split tq information in neigh_node struct") +Signed-off-by: Sven Eckelmann +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/originator.c | 34 ++++++++++------------------------ + 1 file changed, 10 insertions(+), 24 deletions(-) + +--- a/net/batman-adv/originator.c ++++ b/net/batman-adv/originator.c +@@ -163,42 +163,28 @@ err: + } + + /** +- * batadv_neigh_ifinfo_free_rcu - free the neigh_ifinfo object +- * @rcu: rcu pointer of the neigh_ifinfo object +- */ +-static void batadv_neigh_ifinfo_free_rcu(struct rcu_head *rcu) +-{ +- struct batadv_neigh_ifinfo *neigh_ifinfo; +- +- neigh_ifinfo = container_of(rcu, struct batadv_neigh_ifinfo, rcu); +- +- if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT) +- batadv_hardif_free_ref_now(neigh_ifinfo->if_outgoing); +- +- kfree(neigh_ifinfo); +-} +- +-/** +- * batadv_neigh_ifinfo_free_now - decrement the refcounter and possibly free +- * the neigh_ifinfo (without rcu callback) ++ * batadv_neigh_ifinfo_release - release neigh_ifinfo from lists and queue for ++ * free after rcu grace period + * @neigh_ifinfo: the neigh_ifinfo object to release + */ + static void +-batadv_neigh_ifinfo_free_ref_now(struct batadv_neigh_ifinfo *neigh_ifinfo) ++batadv_neigh_ifinfo_release(struct batadv_neigh_ifinfo *neigh_ifinfo) + { +- if (atomic_dec_and_test(&neigh_ifinfo->refcount)) +- batadv_neigh_ifinfo_free_rcu(&neigh_ifinfo->rcu); ++ if (neigh_ifinfo->if_outgoing != BATADV_IF_DEFAULT) ++ batadv_hardif_free_ref(neigh_ifinfo->if_outgoing); ++ ++ kfree_rcu(neigh_ifinfo, rcu); + } + + /** +- * batadv_neigh_ifinfo_free_ref - decrement the refcounter and possibly free ++ * batadv_neigh_ifinfo_free_ref - decrement the refcounter and possibly release + * the neigh_ifinfo + * @neigh_ifinfo: the neigh_ifinfo object to release + */ + void batadv_neigh_ifinfo_free_ref(struct batadv_neigh_ifinfo *neigh_ifinfo) + { + if (atomic_dec_and_test(&neigh_ifinfo->refcount)) +- call_rcu(&neigh_ifinfo->rcu, batadv_neigh_ifinfo_free_rcu); ++ batadv_neigh_ifinfo_release(neigh_ifinfo); + } + + /** +@@ -217,7 +203,7 @@ static void batadv_neigh_node_free_rcu(s + + hlist_for_each_entry_safe(neigh_ifinfo, node_tmp, + &neigh_node->ifinfo_list, list) { +- batadv_neigh_ifinfo_free_ref_now(neigh_ifinfo); ++ batadv_neigh_ifinfo_free_ref(neigh_ifinfo); + } + + if (bao->bat_neigh_free) diff --git a/queue-4.4/batman-adv-drop-immediate-orig_node-free-function.patch b/queue-4.4/batman-adv-drop-immediate-orig_node-free-function.patch new file mode 100644 index 00000000000..81131dded73 --- /dev/null +++ b/queue-4.4/batman-adv-drop-immediate-orig_node-free-function.patch @@ -0,0 +1,111 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Sven Eckelmann +Date: Tue, 5 Jan 2016 12:06:20 +0100 +Subject: batman-adv: Drop immediate orig_node free function + +From: Sven Eckelmann + +[ Upstream commit 42eff6a617e23b691f8e4467f4687ed7245a92db ] + +It is not allowed to free the memory of an object which is part of a list +which is protected by rcu-read-side-critical sections without making sure +that no other context is accessing the object anymore. This usually happens +by removing the references to this object and then waiting until the rcu +grace period is over and no one (allowedly) accesses it anymore. + +But the _now functions ignore this completely. They free the object +directly even when a different context still tries to access it. This has +to be avoided and thus these functions must be removed and all functions +have to use batadv_orig_node_free_ref. + +Fixes: 72822225bd41 ("batman-adv: Fix rcu_barrier() miss due to double call_rcu() in TT code") +Signed-off-by: Sven Eckelmann +Signed-off-by: Marek Lindner +Signed-off-by: Antonio Quartulli +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/originator.c | 11 ----------- + net/batman-adv/originator.h | 1 - + net/batman-adv/translation-table.c | 28 +++++++++++++--------------- + 3 files changed, 13 insertions(+), 27 deletions(-) + +--- a/net/batman-adv/originator.c ++++ b/net/batman-adv/originator.c +@@ -601,17 +601,6 @@ void batadv_orig_node_free_ref(struct ba + batadv_orig_node_release(orig_node); + } + +-/** +- * batadv_orig_node_free_ref_now - decrement the orig node refcounter and +- * possibly free it (without rcu callback) +- * @orig_node: the orig node to free +- */ +-void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node) +-{ +- if (atomic_dec_and_test(&orig_node->refcount)) +- batadv_orig_node_free_rcu(&orig_node->rcu); +-} +- + void batadv_originator_free(struct batadv_priv *bat_priv) + { + struct batadv_hashtable *hash = bat_priv->orig_hash; +--- a/net/batman-adv/originator.h ++++ b/net/batman-adv/originator.h +@@ -38,7 +38,6 @@ int batadv_originator_init(struct batadv + void batadv_originator_free(struct batadv_priv *bat_priv); + void batadv_purge_orig_ref(struct batadv_priv *bat_priv); + void batadv_orig_node_free_ref(struct batadv_orig_node *orig_node); +-void batadv_orig_node_free_ref_now(struct batadv_orig_node *orig_node); + struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, + const u8 *addr); + struct batadv_neigh_node * +--- a/net/batman-adv/translation-table.c ++++ b/net/batman-adv/translation-table.c +@@ -240,20 +240,6 @@ int batadv_tt_global_hash_count(struct b + return count; + } + +-static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) +-{ +- struct batadv_tt_orig_list_entry *orig_entry; +- +- orig_entry = container_of(rcu, struct batadv_tt_orig_list_entry, rcu); +- +- /* We are in an rcu callback here, therefore we cannot use +- * batadv_orig_node_free_ref() and its call_rcu(): +- * An rcu_barrier() wouldn't wait for that to finish +- */ +- batadv_orig_node_free_ref_now(orig_entry->orig_node); +- kfree(orig_entry); +-} +- + /** + * batadv_tt_local_size_mod - change the size by v of the local table identified + * by vid +@@ -349,13 +335,25 @@ static void batadv_tt_global_size_dec(st + batadv_tt_global_size_mod(orig_node, vid, -1); + } + ++/** ++ * batadv_tt_orig_list_entry_release - release tt orig entry from lists and ++ * queue for free after rcu grace period ++ * @orig_entry: tt orig entry to be free'd ++ */ ++static void ++batadv_tt_orig_list_entry_release(struct batadv_tt_orig_list_entry *orig_entry) ++{ ++ batadv_orig_node_free_ref(orig_entry->orig_node); ++ kfree_rcu(orig_entry, rcu); ++} ++ + static void + batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) + { + if (!atomic_dec_and_test(&orig_entry->refcount)) + return; + +- call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); ++ batadv_tt_orig_list_entry_release(orig_entry); + } + + /** diff --git a/queue-4.4/bonding-prevent-ipv6-link-local-address-on-enslaved-devices.patch b/queue-4.4/bonding-prevent-ipv6-link-local-address-on-enslaved-devices.patch new file mode 100644 index 00000000000..1c4d9f0a1c4 --- /dev/null +++ b/queue-4.4/bonding-prevent-ipv6-link-local-address-on-enslaved-devices.patch @@ -0,0 +1,58 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Karl Heiss +Date: Mon, 11 Jan 2016 08:28:43 -0500 +Subject: bonding: Prevent IPv6 link local address on enslaved devices + +From: Karl Heiss + +[ Upstream commit 03d84a5f83a67e692af00a3d3901e7820e3e84d5 ] + +Commit 1f718f0f4f97 ("bonding: populate neighbour's private on enslave") +undoes the fix provided by commit c2edacf80e15 ("bonding / ipv6: no addrconf +for slaves separately from master") by effectively setting the slave flag +after the slave has been opened. If the slave comes up quickly enough, it +will go through the IPv6 addrconf before the slave flag has been set and +will get a link local IPv6 address. + +In order to ensure that addrconf knows to ignore the slave devices on state +change, set IFF_SLAVE before dev_open() during bonding enslavement. + +Fixes: 1f718f0f4f97 ("bonding: populate neighbour's private on enslave") +Signed-off-by: Karl Heiss +Signed-off-by: Jay Vosburgh +Reviewed-by: Jarod Wilson +Signed-off-by: Andy Gospodarek +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/bonding/bond_main.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/net/bonding/bond_main.c ++++ b/drivers/net/bonding/bond_main.c +@@ -1207,7 +1207,6 @@ static int bond_master_upper_dev_link(st + err = netdev_master_upper_dev_link_private(slave_dev, bond_dev, slave); + if (err) + return err; +- slave_dev->flags |= IFF_SLAVE; + rtmsg_ifinfo(RTM_NEWLINK, slave_dev, IFF_SLAVE, GFP_KERNEL); + return 0; + } +@@ -1465,6 +1464,9 @@ int bond_enslave(struct net_device *bond + } + } + ++ /* set slave flag before open to prevent IPv6 addrconf */ ++ slave_dev->flags |= IFF_SLAVE; ++ + /* open the slave since the application closed it */ + res = dev_open(slave_dev); + if (res) { +@@ -1725,6 +1727,7 @@ err_close: + dev_close(slave_dev); + + err_restore_mac: ++ slave_dev->flags &= ~IFF_SLAVE; + if (!bond->params.fail_over_mac || + BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) { + /* XXX TODO - fom follow mode needs to change master's diff --git a/queue-4.4/bridge-fix-lockdep-addr_list_lock-false-positive-splat.patch b/queue-4.4/bridge-fix-lockdep-addr_list_lock-false-positive-splat.patch new file mode 100644 index 00000000000..c63c9afbfca --- /dev/null +++ b/queue-4.4/bridge-fix-lockdep-addr_list_lock-false-positive-splat.patch @@ -0,0 +1,133 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Nikolay Aleksandrov +Date: Fri, 15 Jan 2016 19:03:54 +0100 +Subject: bridge: fix lockdep addr_list_lock false positive splat + +From: Nikolay Aleksandrov + +[ Upstream commit c6894dec8ea9ae05747124dce98b3b5c2e69b168 ] + +After promisc mode management was introduced a bridge device could do +dev_set_promiscuity from its ndo_change_rx_flags() callback which in +turn can be called after the bridge's addr_list_lock has been taken +(e.g. by dev_uc_add). This causes a false positive lockdep splat because +the port interfaces' addr_list_lock is taken when br_manage_promisc() +runs after the bridge's addr list lock was already taken. +To remove the false positive introduce a custom bridge addr_list_lock +class and set it on bridge init. +A simple way to reproduce this is with the following: +$ brctl addbr br0 +$ ip l add l br0 br0.100 type vlan id 100 +$ ip l set br0 up +$ ip l set br0.100 up +$ echo 1 > /sys/class/net/br0/bridge/vlan_filtering +$ brctl addif br0 eth0 +Splat: +[ 43.684325] ============================================= +[ 43.684485] [ INFO: possible recursive locking detected ] +[ 43.684636] 4.4.0-rc8+ #54 Not tainted +[ 43.684755] --------------------------------------------- +[ 43.684906] brctl/1187 is trying to acquire lock: +[ 43.685047] (_xmit_ETHER){+.....}, at: [] dev_set_rx_mode+0x1e/0x40 +[ 43.685460] but task is already holding lock: +[ 43.685618] (_xmit_ETHER){+.....}, at: [] dev_uc_add+0x27/0x80 +[ 43.686015] other info that might help us debug this: +[ 43.686316] Possible unsafe locking scenario: + +[ 43.686743] CPU0 +[ 43.686967] ---- +[ 43.687197] lock(_xmit_ETHER); +[ 43.687544] lock(_xmit_ETHER); +[ 43.687886] *** DEADLOCK *** + +[ 43.688438] May be due to missing lock nesting notation + +[ 43.688882] 2 locks held by brctl/1187: +[ 43.689134] #0: (rtnl_mutex){+.+.+.}, at: [] rtnl_lock+0x17/0x20 +[ 43.689852] #1: (_xmit_ETHER){+.....}, at: [] dev_uc_add+0x27/0x80 +[ 43.690575] stack backtrace: +[ 43.690970] CPU: 0 PID: 1187 Comm: brctl Not tainted 4.4.0-rc8+ #54 +[ 43.691270] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.8.1-20150318_183358- 04/01/2014 +[ 43.691770] ffffffff826a25c0 ffff8800369fb8e0 ffffffff81360ceb ffffffff826a25c0 +[ 43.692425] ffff8800369fb9b8 ffffffff810d0466 ffff8800369fb968 ffffffff81537139 +[ 43.693071] ffff88003a08c880 0000000000000000 00000000ffffffff 0000000002080020 +[ 43.693709] Call Trace: +[ 43.693931] [] dump_stack+0x4b/0x70 +[ 43.694199] [] __lock_acquire+0x1e46/0x1e90 +[ 43.694483] [] ? netlink_broadcast_filtered+0x139/0x3e0 +[ 43.694789] [] ? nlmsg_notify+0x5a/0xc0 +[ 43.695064] [] lock_acquire+0xe5/0x1f0 +[ 43.695340] [] ? dev_set_rx_mode+0x1e/0x40 +[ 43.695623] [] _raw_spin_lock_bh+0x45/0x80 +[ 43.695901] [] ? dev_set_rx_mode+0x1e/0x40 +[ 43.696180] [] dev_set_rx_mode+0x1e/0x40 +[ 43.696460] [] dev_set_promiscuity+0x3c/0x50 +[ 43.696750] [] br_port_set_promisc+0x25/0x50 [bridge] +[ 43.697052] [] br_manage_promisc+0x8a/0xe0 [bridge] +[ 43.697348] [] br_dev_change_rx_flags+0x1e/0x20 [bridge] +[ 43.697655] [] __dev_set_promiscuity+0x132/0x1f0 +[ 43.697943] [] __dev_set_rx_mode+0x82/0x90 +[ 43.698223] [] dev_uc_add+0x5e/0x80 +[ 43.698498] [] vlan_device_event+0x542/0x650 [8021q] +[ 43.698798] [] notifier_call_chain+0x5d/0x80 +[ 43.699083] [] raw_notifier_call_chain+0x16/0x20 +[ 43.699374] [] call_netdevice_notifiers_info+0x6e/0x80 +[ 43.699678] [] call_netdevice_notifiers+0x16/0x20 +[ 43.699973] [] br_add_if+0x47e/0x4c0 [bridge] +[ 43.700259] [] add_del_if+0x6e/0x80 [bridge] +[ 43.700548] [] br_dev_ioctl+0xaf/0xc0 [bridge] +[ 43.700836] [] dev_ifsioc+0x30c/0x3c0 +[ 43.701106] [] dev_ioctl+0xf9/0x6f0 +[ 43.701379] [] ? mntput_no_expire+0x5/0x450 +[ 43.701665] [] ? mntput_no_expire+0xae/0x450 +[ 43.701947] [] sock_do_ioctl+0x42/0x50 +[ 43.702219] [] sock_ioctl+0x1e5/0x290 +[ 43.702500] [] do_vfs_ioctl+0x2cb/0x5c0 +[ 43.702771] [] SyS_ioctl+0x79/0x90 +[ 43.703033] [] entry_SYSCALL_64_fastpath+0x16/0x7a + +CC: Vlad Yasevich +CC: Stephen Hemminger +CC: Bridge list +CC: Andy Gospodarek +CC: Roopa Prabhu +Fixes: 2796d0c648c9 ("bridge: Automatically manage port promiscuous mode.") +Reported-by: Andy Gospodarek +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/bridge/br_device.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/net/bridge/br_device.c ++++ b/net/bridge/br_device.c +@@ -28,6 +28,8 @@ + const struct nf_br_ops __rcu *nf_br_ops __read_mostly; + EXPORT_SYMBOL_GPL(nf_br_ops); + ++static struct lock_class_key bridge_netdev_addr_lock_key; ++ + /* net device transmit always called with BH disabled */ + netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) + { +@@ -87,6 +89,11 @@ out: + return NETDEV_TX_OK; + } + ++static void br_set_lockdep_class(struct net_device *dev) ++{ ++ lockdep_set_class(&dev->addr_list_lock, &bridge_netdev_addr_lock_key); ++} ++ + static int br_dev_init(struct net_device *dev) + { + struct net_bridge *br = netdev_priv(dev); +@@ -99,6 +106,7 @@ static int br_dev_init(struct net_device + err = br_vlan_init(br); + if (err) + free_percpu(br->stats); ++ br_set_lockdep_class(dev); + + return err; + } diff --git a/queue-4.4/dwc_eth_qos-fix-dma-address-for-multi-fragment-skbs.patch b/queue-4.4/dwc_eth_qos-fix-dma-address-for-multi-fragment-skbs.patch new file mode 100644 index 00000000000..0ecefa3c348 --- /dev/null +++ b/queue-4.4/dwc_eth_qos-fix-dma-address-for-multi-fragment-skbs.patch @@ -0,0 +1,31 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Lars Persson +Date: Tue, 12 Jan 2016 15:28:13 +0100 +Subject: dwc_eth_qos: Fix dma address for multi-fragment skbs + +From: Lars Persson + +[ Upstream commit d461873272169a3fc3a8d155d7b1c92e9d97b419 ] + +The offset inside the fragment was not used for the dma address and +silent data corruption resulted because TSO makes the checksum match. + +Fixes: 077742dac2c7 ("dwc_eth_qos: Add support for Synopsys DWC Ethernet QoS") +Signed-off-by: Lars Persson +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/synopsys/dwc_eth_qos.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/synopsys/dwc_eth_qos.c ++++ b/drivers/net/ethernet/synopsys/dwc_eth_qos.c +@@ -2107,7 +2107,7 @@ static int dwceqos_tx_frags(struct sk_bu + dd = &lp->tx_descs[lp->tx_next]; + + /* Set DMA Descriptor fields */ +- dd->des0 = dma_handle; ++ dd->des0 = dma_handle + consumed_size; + dd->des1 = 0; + dd->des2 = dma_size; + diff --git a/queue-4.4/ipv6-tcp-add-rcu-locking-in-tcp_v6_send_synack.patch b/queue-4.4/ipv6-tcp-add-rcu-locking-in-tcp_v6_send_synack.patch new file mode 100644 index 00000000000..5928c66bc12 --- /dev/null +++ b/queue-4.4/ipv6-tcp-add-rcu-locking-in-tcp_v6_send_synack.patch @@ -0,0 +1,35 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Eric Dumazet +Date: Fri, 8 Jan 2016 09:35:51 -0800 +Subject: ipv6: tcp: add rcu locking in tcp_v6_send_synack() + +From: Eric Dumazet + +[ Upstream commit 3e4006f0b86a5ae5eb0e8215f9a9e1db24506977 ] + +When first SYNACK is sent, we already hold rcu_read_lock(), but this +is not true if a SYNACK is retransmitted, as a timer (soft) interrupt +does not hold rcu_read_lock() + +Fixes: 45f6fad84cc30 ("ipv6: add complete rcu protection around np->opt") +Reported-by: Dave Jones +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/tcp_ipv6.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -462,8 +462,10 @@ static int tcp_v6_send_synack(const stru + if (np->repflow && ireq->pktopts) + fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts)); + ++ rcu_read_lock(); + err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt), + np->tclass); ++ rcu_read_unlock(); + err = net_xmit_eval(err); + } + diff --git a/queue-4.4/ipv6-update-skb-csum-when-ce-mark-is-propagated.patch b/queue-4.4/ipv6-update-skb-csum-when-ce-mark-is-propagated.patch new file mode 100644 index 00000000000..986fa22f546 --- /dev/null +++ b/queue-4.4/ipv6-update-skb-csum-when-ce-mark-is-propagated.patch @@ -0,0 +1,74 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Eric Dumazet +Date: Fri, 15 Jan 2016 04:56:56 -0800 +Subject: ipv6: update skb->csum when CE mark is propagated + +From: Eric Dumazet + +[ Upstream commit 34ae6a1aa0540f0f781dd265366036355fdc8930 ] + +When a tunnel decapsulates the outer header, it has to comply +with RFC 6080 and eventually propagate CE mark into inner header. + +It turns out IP6_ECN_set_ce() does not correctly update skb->csum +for CHECKSUM_COMPLETE packets, triggering infamous "hw csum failure" +messages and stack traces. + +Signed-off-by: Eric Dumazet +Acked-by: Herbert Xu +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/inet_ecn.h | 19 ++++++++++++++++--- + net/ipv6/xfrm6_mode_tunnel.c | 2 +- + 2 files changed, 17 insertions(+), 4 deletions(-) + +--- a/include/net/inet_ecn.h ++++ b/include/net/inet_ecn.h +@@ -111,11 +111,24 @@ static inline void ipv4_copy_dscp(unsign + + struct ipv6hdr; + +-static inline int IP6_ECN_set_ce(struct ipv6hdr *iph) ++/* Note: ++ * IP_ECN_set_ce() has to tweak IPV4 checksum when setting CE, ++ * meaning both changes have no effect on skb->csum if/when CHECKSUM_COMPLETE ++ * In IPv6 case, no checksum compensates the change in IPv6 header, ++ * so we have to update skb->csum. ++ */ ++static inline int IP6_ECN_set_ce(struct sk_buff *skb, struct ipv6hdr *iph) + { ++ __be32 from, to; ++ + if (INET_ECN_is_not_ect(ipv6_get_dsfield(iph))) + return 0; +- *(__be32*)iph |= htonl(INET_ECN_CE << 20); ++ ++ from = *(__be32 *)iph; ++ to = from | htonl(INET_ECN_CE << 20); ++ *(__be32 *)iph = to; ++ if (skb->ip_summed == CHECKSUM_COMPLETE) ++ skb->csum = csum_add(csum_sub(skb->csum, from), to); + return 1; + } + +@@ -142,7 +155,7 @@ static inline int INET_ECN_set_ce(struct + case cpu_to_be16(ETH_P_IPV6): + if (skb_network_header(skb) + sizeof(struct ipv6hdr) <= + skb_tail_pointer(skb)) +- return IP6_ECN_set_ce(ipv6_hdr(skb)); ++ return IP6_ECN_set_ce(skb, ipv6_hdr(skb)); + break; + } + +--- a/net/ipv6/xfrm6_mode_tunnel.c ++++ b/net/ipv6/xfrm6_mode_tunnel.c +@@ -23,7 +23,7 @@ static inline void ipip6_ecn_decapsulate + struct ipv6hdr *inner_iph = ipipv6_hdr(skb); + + if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos)) +- IP6_ECN_set_ce(inner_iph); ++ IP6_ECN_set_ce(skb, inner_iph); + } + + /* Add encapsulation header. diff --git a/queue-4.4/net-bpf-reject-invalid-shifts.patch b/queue-4.4/net-bpf-reject-invalid-shifts.patch new file mode 100644 index 00000000000..01b0efc8580 --- /dev/null +++ b/queue-4.4/net-bpf-reject-invalid-shifts.patch @@ -0,0 +1,59 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Rabin Vincent +Date: Tue, 12 Jan 2016 20:17:08 +0100 +Subject: net: bpf: reject invalid shifts + +From: Rabin Vincent + +[ Upstream commit 229394e8e62a4191d592842cf67e80c62a492937 ] + +On ARM64, a BUG() is triggered in the eBPF JIT if a filter with a +constant shift that can't be encoded in the immediate field of the +UBFM/SBFM instructions is passed to the JIT. Since these shifts +amounts, which are negative or >= regsize, are invalid, reject them in +the eBPF verifier and the classic BPF filter checker, for all +architectures. + +Signed-off-by: Rabin Vincent +Acked-by: Alexei Starovoitov +Acked-by: Daniel Borkmann +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 10 ++++++++++ + net/core/filter.c | 5 +++++ + 2 files changed, 15 insertions(+) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -1121,6 +1121,16 @@ static int check_alu_op(struct verifier_ + return -EINVAL; + } + ++ if ((opcode == BPF_LSH || opcode == BPF_RSH || ++ opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) { ++ int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32; ++ ++ if (insn->imm < 0 || insn->imm >= size) { ++ verbose("invalid shift %d\n", insn->imm); ++ return -EINVAL; ++ } ++ } ++ + /* pattern match 'bpf_add Rx, imm' instruction */ + if (opcode == BPF_ADD && BPF_CLASS(insn->code) == BPF_ALU64 && + regs[insn->dst_reg].type == FRAME_PTR && +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -777,6 +777,11 @@ static int bpf_check_classic(const struc + if (ftest->k == 0) + return -EINVAL; + break; ++ case BPF_ALU | BPF_LSH | BPF_K: ++ case BPF_ALU | BPF_RSH | BPF_K: ++ if (ftest->k >= 32) ++ return -EINVAL; ++ break; + case BPF_LD | BPF_MEM: + case BPF_LDX | BPF_MEM: + case BPF_ST: diff --git a/queue-4.4/net-mlx5_core-fix-trimming-down-irq-number.patch b/queue-4.4/net-mlx5_core-fix-trimming-down-irq-number.patch new file mode 100644 index 00000000000..5cf9b9ec1ca --- /dev/null +++ b/queue-4.4/net-mlx5_core-fix-trimming-down-irq-number.patch @@ -0,0 +1,124 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Doron Tsur +Date: Sun, 17 Jan 2016 11:25:47 +0200 +Subject: net/mlx5_core: Fix trimming down IRQ number + +From: Doron Tsur + +[ Upstream commit 0b6e26ce89391327d955a756a7823272238eb867 ] + +With several ConnectX-4 cards installed on a server, one may receive +irqn > 255 from the kernel API, which we mistakenly trim to 8bit. + +This causes EQ creation failure with the following stack trace: +[] dump_stack+0x48/0x64 +[] __setup_irq+0x3a1/0x4f0 +[] request_threaded_irq+0x120/0x180 +[] ? mlx5_eq_int+0x450/0x450 [mlx5_core] +[] mlx5_create_map_eq+0x1e4/0x2b0 [mlx5_core] +[] alloc_comp_eqs+0xb1/0x180 [mlx5_core] +[] mlx5_dev_init+0x5e9/0x6e0 [mlx5_core] +[] init_one+0x99/0x1c0 [mlx5_core] +[] local_pci_probe+0x4c/0xa0 + +Fixing it by changing of the irqn type from u8 to unsigned int to +support values > 255 + +Fixes: 61d0e73e0a5a ('net/mlx5_core: Use the the real irqn in eq->irqn') +Reported-by: Jiri Pirko +Signed-off-by: Doron Tsur +Signed-off-by: Matan Barak +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/infiniband/hw/mlx5/cq.c | 2 +- + drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 6 +++--- + drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 ++- + include/linux/mlx5/cq.h | 2 +- + include/linux/mlx5/driver.h | 5 +++-- + 5 files changed, 10 insertions(+), 8 deletions(-) + +--- a/drivers/infiniband/hw/mlx5/cq.c ++++ b/drivers/infiniband/hw/mlx5/cq.c +@@ -756,7 +756,7 @@ struct ib_cq *mlx5_ib_create_cq(struct i + int uninitialized_var(index); + int uninitialized_var(inlen); + int cqe_size; +- int irqn; ++ unsigned int irqn; + int eqn; + int err; + +--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +@@ -746,7 +746,7 @@ static int mlx5e_create_cq(struct mlx5e_ + struct mlx5_core_dev *mdev = priv->mdev; + struct mlx5_core_cq *mcq = &cq->mcq; + int eqn_not_used; +- int irqn; ++ unsigned int irqn; + int err; + u32 i; + +@@ -800,7 +800,7 @@ static int mlx5e_enable_cq(struct mlx5e_ + void *in; + void *cqc; + int inlen; +- int irqn_not_used; ++ unsigned int irqn_not_used; + int eqn; + int err; + +@@ -1504,7 +1504,7 @@ static int mlx5e_create_drop_cq(struct m + struct mlx5_core_dev *mdev = priv->mdev; + struct mlx5_core_cq *mcq = &cq->mcq; + int eqn_not_used; +- int irqn; ++ unsigned int irqn; + int err; + + err = mlx5_cqwq_create(mdev, ¶m->wq, param->cqc, &cq->wq, +--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c ++++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c +@@ -568,7 +568,8 @@ static void mlx5_irq_clear_affinity_hint + mlx5_irq_clear_affinity_hint(mdev, i); + } + +-int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int *irqn) ++int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, ++ unsigned int *irqn) + { + struct mlx5_eq_table *table = &dev->priv.eq_table; + struct mlx5_eq *eq, *n; +--- a/include/linux/mlx5/cq.h ++++ b/include/linux/mlx5/cq.h +@@ -45,7 +45,7 @@ struct mlx5_core_cq { + atomic_t refcount; + struct completion free; + unsigned vector; +- int irqn; ++ unsigned int irqn; + void (*comp) (struct mlx5_core_cq *); + void (*event) (struct mlx5_core_cq *, enum mlx5_event); + struct mlx5_uar *uar; +--- a/include/linux/mlx5/driver.h ++++ b/include/linux/mlx5/driver.h +@@ -303,7 +303,7 @@ struct mlx5_eq { + u32 cons_index; + struct mlx5_buf buf; + int size; +- u8 irqn; ++ unsigned int irqn; + u8 eqn; + int nent; + u64 mask; +@@ -762,7 +762,8 @@ int mlx5_create_map_eq(struct mlx5_core_ + int mlx5_destroy_unmap_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq); + int mlx5_start_eqs(struct mlx5_core_dev *dev); + int mlx5_stop_eqs(struct mlx5_core_dev *dev); +-int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, int *irqn); ++int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn, ++ unsigned int *irqn); + int mlx5_core_attach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn); + int mlx5_core_detach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn); + diff --git a/queue-4.4/net-pktgen-fix-null-ptr-deref-in-skb-allocation.patch b/queue-4.4/net-pktgen-fix-null-ptr-deref-in-skb-allocation.patch new file mode 100644 index 00000000000..7cbc3bc9a63 --- /dev/null +++ b/queue-4.4/net-pktgen-fix-null-ptr-deref-in-skb-allocation.patch @@ -0,0 +1,33 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: John Fastabend +Date: Sun, 10 Jan 2016 21:38:44 -0800 +Subject: net: pktgen: fix null ptr deref in skb allocation + +From: John Fastabend + +[ Upstream commit 3de03596dfeee48bc803c1d1a6daf60a459929f3 ] + +Fix possible null pointer dereference that may occur when calling +skb_reserve() on a null skb. + +Fixes: 879c7220e82 ("net: pktgen: Observe needed_headroom of the device") +Signed-off-by: John Fastabend +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/pktgen.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/net/core/pktgen.c ++++ b/net/core/pktgen.c +@@ -2787,7 +2787,9 @@ static struct sk_buff *pktgen_alloc_skb( + } else { + skb = __netdev_alloc_skb(dev, size, GFP_NOWAIT); + } +- skb_reserve(skb, LL_RESERVED_SPACE(dev)); ++ ++ if (likely(skb)) ++ skb_reserve(skb, LL_RESERVED_SPACE(dev)); + + return skb; + } diff --git a/queue-4.4/net-preserve-ip-control-block-during-gso-segmentation.patch b/queue-4.4/net-preserve-ip-control-block-during-gso-segmentation.patch new file mode 100644 index 00000000000..baee9026d0e --- /dev/null +++ b/queue-4.4/net-preserve-ip-control-block-during-gso-segmentation.patch @@ -0,0 +1,107 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Konstantin Khlebnikov +Date: Fri, 8 Jan 2016 15:21:46 +0300 +Subject: net: preserve IP control block during GSO segmentation + +From: Konstantin Khlebnikov + +[ Upstream commit 9207f9d45b0ad071baa128e846d7e7ed85016df3 ] + +Skb_gso_segment() uses skb control block during segmentation. +This patch adds 32-bytes room for previous control block which +will be copied into all resulting segments. + +This patch fixes kernel crash during fragmenting forwarded packets. +Fragmentation requires valid IP CB in skb for clearing ip options. +Also patch removes custom save/restore in ovs code, now it's redundant. + +Signed-off-by: Konstantin Khlebnikov +Link: http://lkml.kernel.org/r/CALYGNiP-0MZ-FExV2HutTvE9U-QQtkKSoE--KN=JQE5STYsjAA@mail.gmail.com +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/skbuff.h | 3 ++- + net/core/dev.c | 5 +++++ + net/ipv4/ip_output.c | 1 + + net/openvswitch/datapath.c | 5 +---- + net/xfrm/xfrm_output.c | 2 ++ + 5 files changed, 11 insertions(+), 5 deletions(-) + +--- a/include/linux/skbuff.h ++++ b/include/linux/skbuff.h +@@ -3446,7 +3446,8 @@ struct skb_gso_cb { + int encap_level; + __u16 csum_start; + }; +-#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)(skb)->cb) ++#define SKB_SGO_CB_OFFSET 32 ++#define SKB_GSO_CB(skb) ((struct skb_gso_cb *)((skb)->cb + SKB_SGO_CB_OFFSET)) + + static inline int skb_tnl_header_len(const struct sk_buff *inner_skb) + { +--- a/net/core/dev.c ++++ b/net/core/dev.c +@@ -2542,6 +2542,8 @@ static inline bool skb_needs_check(struc + * + * It may return NULL if the skb requires no segmentation. This is + * only possible when GSO is used for verifying header integrity. ++ * ++ * Segmentation preserves SKB_SGO_CB_OFFSET bytes of previous skb cb. + */ + struct sk_buff *__skb_gso_segment(struct sk_buff *skb, + netdev_features_t features, bool tx_path) +@@ -2556,6 +2558,9 @@ struct sk_buff *__skb_gso_segment(struct + return ERR_PTR(err); + } + ++ BUILD_BUG_ON(SKB_SGO_CB_OFFSET + ++ sizeof(*SKB_GSO_CB(skb)) > sizeof(skb->cb)); ++ + SKB_GSO_CB(skb)->mac_offset = skb_headroom(skb); + SKB_GSO_CB(skb)->encap_level = 0; + +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -240,6 +240,7 @@ static int ip_finish_output_gso(struct n + * from host network stack. + */ + features = netif_skb_features(skb); ++ BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_SGO_CB_OFFSET); + segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK); + if (IS_ERR_OR_NULL(segs)) { + kfree_skb(skb); +--- a/net/openvswitch/datapath.c ++++ b/net/openvswitch/datapath.c +@@ -336,12 +336,10 @@ static int queue_gso_packets(struct data + unsigned short gso_type = skb_shinfo(skb)->gso_type; + struct sw_flow_key later_key; + struct sk_buff *segs, *nskb; +- struct ovs_skb_cb ovs_cb; + int err; + +- ovs_cb = *OVS_CB(skb); ++ BUILD_BUG_ON(sizeof(*OVS_CB(skb)) > SKB_SGO_CB_OFFSET); + segs = __skb_gso_segment(skb, NETIF_F_SG, false); +- *OVS_CB(skb) = ovs_cb; + if (IS_ERR(segs)) + return PTR_ERR(segs); + if (segs == NULL) +@@ -359,7 +357,6 @@ static int queue_gso_packets(struct data + /* Queue all of the segments. */ + skb = segs; + do { +- *OVS_CB(skb) = ovs_cb; + if (gso_type & SKB_GSO_UDP && skb != segs) + key = &later_key; + +--- a/net/xfrm/xfrm_output.c ++++ b/net/xfrm/xfrm_output.c +@@ -167,6 +167,8 @@ static int xfrm_output_gso(struct net *n + { + struct sk_buff *segs; + ++ BUILD_BUG_ON(sizeof(*IPCB(skb)) > SKB_SGO_CB_OFFSET); ++ BUILD_BUG_ON(sizeof(*IP6CB(skb)) > SKB_SGO_CB_OFFSET); + segs = skb_gso_segment(skb, 0); + kfree_skb(skb); + if (IS_ERR(segs)) diff --git a/queue-4.4/net-sctp-prevent-writes-to-cookie_hmac_alg-from-accessing-invalid-memory.patch b/queue-4.4/net-sctp-prevent-writes-to-cookie_hmac_alg-from-accessing-invalid-memory.patch new file mode 100644 index 00000000000..242216fe08a --- /dev/null +++ b/queue-4.4/net-sctp-prevent-writes-to-cookie_hmac_alg-from-accessing-invalid-memory.patch @@ -0,0 +1,34 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Sasha Levin +Date: Thu, 7 Jan 2016 14:52:43 -0500 +Subject: net: sctp: prevent writes to cookie_hmac_alg from accessing invalid memory + +From: Sasha Levin + +[ Upstream commit 320f1a4a175e7cd5d3f006f92b4d4d3e2cbb7bb5 ] + +proc_dostring() needs an initialized destination string, while the one +provided in proc_sctp_do_hmac_alg() contains stack garbage. + +Thus, writing to cookie_hmac_alg would strlen() that garbage and end up +accessing invalid memory. + +Fixes: 3c68198e7 ("sctp: Make hmac algorithm selection for cookie generation dynamic") +Signed-off-by: Sasha Levin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/sysctl.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/sctp/sysctl.c ++++ b/net/sctp/sysctl.c +@@ -320,7 +320,7 @@ static int proc_sctp_do_hmac_alg(struct + struct ctl_table tbl; + bool changed = false; + char *none = "none"; +- char tmp[8]; ++ char tmp[8] = {0}; + int ret; + + memset(&tbl, 0, sizeof(struct ctl_table)); diff --git a/queue-4.4/phonet-properly-unshare-skbs-in-phonet_rcv.patch b/queue-4.4/phonet-properly-unshare-skbs-in-phonet_rcv.patch new file mode 100644 index 00000000000..9c9bae333be --- /dev/null +++ b/queue-4.4/phonet-properly-unshare-skbs-in-phonet_rcv.patch @@ -0,0 +1,45 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Eric Dumazet +Date: Tue, 12 Jan 2016 08:58:00 -0800 +Subject: phonet: properly unshare skbs in phonet_rcv() + +From: Eric Dumazet + +[ Upstream commit 7aaed57c5c2890634cfadf725173c7c68ea4cb4f ] + +Ivaylo Dimitrov reported a regression caused by commit 7866a621043f +("dev: add per net_device packet type chains"). + +skb->dev becomes NULL and we crash in __netif_receive_skb_core(). + +Before above commit, different kind of bugs or corruptions could happen +without major crash. + +But the root cause is that phonet_rcv() can queue skb without checking +if skb is shared or not. + +Many thanks to Ivaylo Dimitrov for his help, diagnosis and tests. + +Reported-by: Ivaylo Dimitrov +Tested-by: Ivaylo Dimitrov +Signed-off-by: Eric Dumazet +Cc: Remi Denis-Courmont +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/phonet/af_phonet.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/net/phonet/af_phonet.c ++++ b/net/phonet/af_phonet.c +@@ -377,6 +377,10 @@ static int phonet_rcv(struct sk_buff *sk + struct sockaddr_pn sa; + u16 len; + ++ skb = skb_share_check(skb, GFP_ATOMIC); ++ if (!skb) ++ return NET_RX_DROP; ++ + /* check we have at least a full Phonet header */ + if (!pskb_pull(skb, sizeof(struct phonethdr))) + goto out; diff --git a/queue-4.4/sched-cls_flower-set-key-address-type-when-present.patch b/queue-4.4/sched-cls_flower-set-key-address-type-when-present.patch new file mode 100644 index 00000000000..2ff82db1c39 --- /dev/null +++ b/queue-4.4/sched-cls_flower-set-key-address-type-when-present.patch @@ -0,0 +1,61 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Jamal Hadi Salim +Date: Sun, 10 Jan 2016 11:47:01 -0500 +Subject: sched,cls_flower: set key address type when present + +From: Jamal Hadi Salim + +[ Upstream commit 66530bdf85eb1d72a0c399665e09a2c2298501c6 ] + +only when user space passes the addresses should we consider their +presence + +Signed-off-by: Jamal Hadi Salim +Acked-by: Jiri Pirko +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/cls_flower.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +--- a/net/sched/cls_flower.c ++++ b/net/sched/cls_flower.c +@@ -252,23 +252,28 @@ static int fl_set_key(struct net *net, s + fl_set_key_val(tb, key->eth.src, TCA_FLOWER_KEY_ETH_SRC, + mask->eth.src, TCA_FLOWER_KEY_ETH_SRC_MASK, + sizeof(key->eth.src)); ++ + fl_set_key_val(tb, &key->basic.n_proto, TCA_FLOWER_KEY_ETH_TYPE, + &mask->basic.n_proto, TCA_FLOWER_UNSPEC, + sizeof(key->basic.n_proto)); ++ + if (key->basic.n_proto == htons(ETH_P_IP) || + key->basic.n_proto == htons(ETH_P_IPV6)) { + fl_set_key_val(tb, &key->basic.ip_proto, TCA_FLOWER_KEY_IP_PROTO, + &mask->basic.ip_proto, TCA_FLOWER_UNSPEC, + sizeof(key->basic.ip_proto)); + } +- if (key->control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) { ++ ++ if (tb[TCA_FLOWER_KEY_IPV4_SRC] || tb[TCA_FLOWER_KEY_IPV4_DST]) { ++ key->control.addr_type = FLOW_DISSECTOR_KEY_IPV4_ADDRS; + fl_set_key_val(tb, &key->ipv4.src, TCA_FLOWER_KEY_IPV4_SRC, + &mask->ipv4.src, TCA_FLOWER_KEY_IPV4_SRC_MASK, + sizeof(key->ipv4.src)); + fl_set_key_val(tb, &key->ipv4.dst, TCA_FLOWER_KEY_IPV4_DST, + &mask->ipv4.dst, TCA_FLOWER_KEY_IPV4_DST_MASK, + sizeof(key->ipv4.dst)); +- } else if (key->control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) { ++ } else if (tb[TCA_FLOWER_KEY_IPV6_SRC] || tb[TCA_FLOWER_KEY_IPV6_DST]) { ++ key->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS; + fl_set_key_val(tb, &key->ipv6.src, TCA_FLOWER_KEY_IPV6_SRC, + &mask->ipv6.src, TCA_FLOWER_KEY_IPV6_SRC_MASK, + sizeof(key->ipv6.src)); +@@ -276,6 +281,7 @@ static int fl_set_key(struct net *net, s + &mask->ipv6.dst, TCA_FLOWER_KEY_IPV6_DST_MASK, + sizeof(key->ipv6.dst)); + } ++ + if (key->basic.ip_proto == IPPROTO_TCP) { + fl_set_key_val(tb, &key->tp.src, TCA_FLOWER_KEY_TCP_SRC, + &mask->tp.src, TCA_FLOWER_UNSPEC, diff --git a/queue-4.4/series b/queue-4.4/series index ec86b1b72c6..fd73bf0df46 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -33,3 +33,27 @@ rtlwifi-fix-memory-leak-for-usb-device.patch usb-cp210x-add-id-for-elv-marble-sound-board-1.patch usb-core-lpm-fix-usb3_hardware_lpm-sysfs-node.patch xhci-refuse-loading-if-nousb-is-used.patch +unix-properly-account-for-fds-passed-over-unix-sockets.patch +vxlan-fix-test-which-detect-duplicate-vxlan-iface.patch +net-sctp-prevent-writes-to-cookie_hmac_alg-from-accessing-invalid-memory.patch +ipv6-tcp-add-rcu-locking-in-tcp_v6_send_synack.patch +tcp_yeah-don-t-set-ssthresh-below-2.patch +sched-cls_flower-set-key-address-type-when-present.patch +net-pktgen-fix-null-ptr-deref-in-skb-allocation.patch +udp-disallow-ufo-for-sockets-with-so_no_check-option.patch +net-preserve-ip-control-block-during-gso-segmentation.patch +bonding-prevent-ipv6-link-local-address-on-enslaved-devices.patch +dwc_eth_qos-fix-dma-address-for-multi-fragment-skbs.patch +phonet-properly-unshare-skbs-in-phonet_rcv.patch +net-bpf-reject-invalid-shifts.patch +ipv6-update-skb-csum-when-ce-mark-is-propagated.patch +bridge-fix-lockdep-addr_list_lock-false-positive-splat.patch +net-mlx5_core-fix-trimming-down-irq-number.patch +team-replace-rcu_read_lock-with-a-mutex-in-team_vlan_rx_kill_vid.patch +batman-adv-avoid-recursive-call_rcu-for-batadv_bla_claim.patch +batman-adv-avoid-recursive-call_rcu-for-batadv_nc_node.patch +batman-adv-drop-immediate-batadv_orig_ifinfo-free-function.patch +batman-adv-drop-immediate-batadv_neigh_node-free-function.patch +batman-adv-drop-immediate-neigh_ifinfo-free-function.patch +batman-adv-drop-immediate-batadv_hard_iface-free-function.patch +batman-adv-drop-immediate-orig_node-free-function.patch diff --git a/queue-4.4/tcp_yeah-don-t-set-ssthresh-below-2.patch b/queue-4.4/tcp_yeah-don-t-set-ssthresh-below-2.patch new file mode 100644 index 00000000000..15bd1c172f1 --- /dev/null +++ b/queue-4.4/tcp_yeah-don-t-set-ssthresh-below-2.patch @@ -0,0 +1,46 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Neal Cardwell +Date: Mon, 11 Jan 2016 13:42:43 -0500 +Subject: tcp_yeah: don't set ssthresh below 2 + +From: Neal Cardwell + +[ Upstream commit 83d15e70c4d8909d722c0d64747d8fb42e38a48f ] + +For tcp_yeah, use an ssthresh floor of 2, the same floor used by Reno +and CUBIC, per RFC 5681 (equation 4). + +tcp_yeah_ssthresh() was sometimes returning a 0 or negative ssthresh +value if the intended reduction is as big or bigger than the current +cwnd. Congestion control modules should never return a zero or +negative ssthresh. A zero ssthresh generally results in a zero cwnd, +causing the connection to stall. A negative ssthresh value will be +interpreted as a u32 and will set a target cwnd for PRR near 4 +billion. + +Oleksandr Natalenko reported that a system using tcp_yeah with ECN +could see a warning about a prior_cwnd of 0 in +tcp_cwnd_reduction(). Testing verified that this was due to +tcp_yeah_ssthresh() misbehaving in this way. + +Reported-by: Oleksandr Natalenko +Signed-off-by: Neal Cardwell +Signed-off-by: Yuchung Cheng +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp_yeah.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/ipv4/tcp_yeah.c ++++ b/net/ipv4/tcp_yeah.c +@@ -219,7 +219,7 @@ static u32 tcp_yeah_ssthresh(struct sock + yeah->fast_count = 0; + yeah->reno_count = max(yeah->reno_count>>1, 2U); + +- return tp->snd_cwnd - reduction; ++ return max_t(int, tp->snd_cwnd - reduction, 2); + } + + static struct tcp_congestion_ops tcp_yeah __read_mostly = { diff --git a/queue-4.4/team-replace-rcu_read_lock-with-a-mutex-in-team_vlan_rx_kill_vid.patch b/queue-4.4/team-replace-rcu_read_lock-with-a-mutex-in-team_vlan_rx_kill_vid.patch new file mode 100644 index 00000000000..07ccc414f6d --- /dev/null +++ b/queue-4.4/team-replace-rcu_read_lock-with-a-mutex-in-team_vlan_rx_kill_vid.patch @@ -0,0 +1,39 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Ido Schimmel +Date: Mon, 18 Jan 2016 17:30:22 +0200 +Subject: team: Replace rcu_read_lock with a mutex in team_vlan_rx_kill_vid + +From: Ido Schimmel + +[ Upstream commit 60a6531bfe49555581ccd65f66a350cc5693fcde ] + +We can't be within an RCU read-side critical section when deleting +VLANs, as underlying drivers might sleep during the hardware operation. +Therefore, replace the RCU critical section with a mutex. This is +consistent with team_vlan_rx_add_vid. + +Fixes: 3d249d4ca7d0 ("net: introduce ethernet teaming device") +Acked-by: Jiri Pirko +Signed-off-by: Ido Schimmel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/team/team.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/net/team/team.c ++++ b/drivers/net/team/team.c +@@ -1845,10 +1845,10 @@ static int team_vlan_rx_kill_vid(struct + struct team *team = netdev_priv(dev); + struct team_port *port; + +- rcu_read_lock(); +- list_for_each_entry_rcu(port, &team->port_list, list) ++ mutex_lock(&team->lock); ++ list_for_each_entry(port, &team->port_list, list) + vlan_vid_del(port->dev, proto, vid); +- rcu_read_unlock(); ++ mutex_unlock(&team->lock); + + return 0; + } diff --git a/queue-4.4/udp-disallow-ufo-for-sockets-with-so_no_check-option.patch b/queue-4.4/udp-disallow-ufo-for-sockets-with-so_no_check-option.patch new file mode 100644 index 00000000000..b3c603bf3f1 --- /dev/null +++ b/queue-4.4/udp-disallow-ufo-for-sockets-with-so_no_check-option.patch @@ -0,0 +1,51 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: =?UTF-8?q?Michal=20Kube=C4=8Dek?= +Date: Mon, 11 Jan 2016 07:50:30 +0100 +Subject: udp: disallow UFO for sockets with SO_NO_CHECK option + +From: =?UTF-8?q?Michal=20Kube=C4=8Dek?= + +[ Upstream commit 40ba330227ad00b8c0cdf2f425736ff9549cc423 ] + +Commit acf8dd0a9d0b ("udp: only allow UFO for packets from SOCK_DGRAM +sockets") disallows UFO for packets sent from raw sockets. We need to do +the same also for SOCK_DGRAM sockets with SO_NO_CHECK options, even if +for a bit different reason: while such socket would override the +CHECKSUM_PARTIAL set by ip_ufo_append_data(), gso_size is still set and +bad offloading flags warning is triggered in __skb_gso_segment(). + +In the IPv6 case, SO_NO_CHECK option is ignored but we need to disallow +UFO for packets sent by sockets with UDP_NO_CHECK6_TX option. + +Signed-off-by: Michal Kubecek +Tested-by: Shannon Nelson +Acked-by: Hannes Frederic Sowa +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/ip_output.c | 2 +- + net/ipv6/ip6_output.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -921,7 +921,7 @@ static int __ip_append_data(struct sock + if (((length > mtu) || (skb && skb_is_gso(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && + (rt->dst.dev->features & NETIF_F_UFO) && !rt->dst.header_len && +- (sk->sk_type == SOCK_DGRAM)) { ++ (sk->sk_type == SOCK_DGRAM) && !sk->sk_no_check_tx) { + err = ip_ufo_append_data(sk, queue, getfrag, from, length, + hh_len, fragheaderlen, transhdrlen, + maxfraglen, flags); +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1353,7 +1353,7 @@ emsgsize: + (skb && skb_is_gso(skb))) && + (sk->sk_protocol == IPPROTO_UDP) && + (rt->dst.dev->features & NETIF_F_UFO) && +- (sk->sk_type == SOCK_DGRAM)) { ++ (sk->sk_type == SOCK_DGRAM) && !udp_get_no_check6_tx(sk)) { + err = ip6_ufo_append_data(sk, queue, getfrag, from, length, + hh_len, fragheaderlen, + transhdrlen, mtu, flags, fl6); diff --git a/queue-4.4/unix-properly-account-for-fds-passed-over-unix-sockets.patch b/queue-4.4/unix-properly-account-for-fds-passed-over-unix-sockets.patch new file mode 100644 index 00000000000..e36ae0a7337 --- /dev/null +++ b/queue-4.4/unix-properly-account-for-fds-passed-over-unix-sockets.patch @@ -0,0 +1,136 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: willy tarreau +Date: Sun, 10 Jan 2016 07:54:56 +0100 +Subject: unix: properly account for FDs passed over unix sockets + +From: willy tarreau + +[ Upstream commit 712f4aad406bb1ed67f3f98d04c044191f0ff593 ] + +It is possible for a process to allocate and accumulate far more FDs than +the process' limit by sending them over a unix socket then closing them +to keep the process' fd count low. + +This change addresses this problem by keeping track of the number of FDs +in flight per user and preventing non-privileged processes from having +more FDs in flight than their configured FD limit. + +Reported-by: socketpair@gmail.com +Reported-by: Tetsuo Handa +Mitigates: CVE-2013-4312 (Linux 2.0+) +Suggested-by: Linus Torvalds +Acked-by: Hannes Frederic Sowa +Signed-off-by: Willy Tarreau +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/sched.h | 1 + + net/unix/af_unix.c | 24 ++++++++++++++++++++---- + net/unix/garbage.c | 13 ++++++++----- + 3 files changed, 29 insertions(+), 9 deletions(-) + +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -830,6 +830,7 @@ struct user_struct { + unsigned long mq_bytes; /* How many bytes can be allocated to mqueue? */ + #endif + unsigned long locked_shm; /* How many pages of mlocked shm ? */ ++ unsigned long unix_inflight; /* How many files in flight in unix sockets */ + + #ifdef CONFIG_KEYS + struct key *uid_keyring; /* UID specific keyring */ +--- a/net/unix/af_unix.c ++++ b/net/unix/af_unix.c +@@ -1513,6 +1513,21 @@ static void unix_destruct_scm(struct sk_ + sock_wfree(skb); + } + ++/* ++ * The "user->unix_inflight" variable is protected by the garbage ++ * collection lock, and we just read it locklessly here. If you go ++ * over the limit, there might be a tiny race in actually noticing ++ * it across threads. Tough. ++ */ ++static inline bool too_many_unix_fds(struct task_struct *p) ++{ ++ struct user_struct *user = current_user(); ++ ++ if (unlikely(user->unix_inflight > task_rlimit(p, RLIMIT_NOFILE))) ++ return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN); ++ return false; ++} ++ + #define MAX_RECURSION_LEVEL 4 + + static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb) +@@ -1521,6 +1536,9 @@ static int unix_attach_fds(struct scm_co + unsigned char max_level = 0; + int unix_sock_count = 0; + ++ if (too_many_unix_fds(current)) ++ return -ETOOMANYREFS; ++ + for (i = scm->fp->count - 1; i >= 0; i--) { + struct sock *sk = unix_get_socket(scm->fp->fp[i]); + +@@ -1542,10 +1560,8 @@ static int unix_attach_fds(struct scm_co + if (!UNIXCB(skb).fp) + return -ENOMEM; + +- if (unix_sock_count) { +- for (i = scm->fp->count - 1; i >= 0; i--) +- unix_inflight(scm->fp->fp[i]); +- } ++ for (i = scm->fp->count - 1; i >= 0; i--) ++ unix_inflight(scm->fp->fp[i]); + return max_level; + } + +--- a/net/unix/garbage.c ++++ b/net/unix/garbage.c +@@ -120,11 +120,11 @@ void unix_inflight(struct file *fp) + { + struct sock *s = unix_get_socket(fp); + ++ spin_lock(&unix_gc_lock); ++ + if (s) { + struct unix_sock *u = unix_sk(s); + +- spin_lock(&unix_gc_lock); +- + if (atomic_long_inc_return(&u->inflight) == 1) { + BUG_ON(!list_empty(&u->link)); + list_add_tail(&u->link, &gc_inflight_list); +@@ -132,25 +132,28 @@ void unix_inflight(struct file *fp) + BUG_ON(list_empty(&u->link)); + } + unix_tot_inflight++; +- spin_unlock(&unix_gc_lock); + } ++ fp->f_cred->user->unix_inflight++; ++ spin_unlock(&unix_gc_lock); + } + + void unix_notinflight(struct file *fp) + { + struct sock *s = unix_get_socket(fp); + ++ spin_lock(&unix_gc_lock); ++ + if (s) { + struct unix_sock *u = unix_sk(s); + +- spin_lock(&unix_gc_lock); + BUG_ON(list_empty(&u->link)); + + if (atomic_long_dec_and_test(&u->inflight)) + list_del_init(&u->link); + unix_tot_inflight--; +- spin_unlock(&unix_gc_lock); + } ++ fp->f_cred->user->unix_inflight--; ++ spin_unlock(&unix_gc_lock); + } + + static void scan_inflight(struct sock *x, void (*func)(struct unix_sock *), diff --git a/queue-4.4/vxlan-fix-test-which-detect-duplicate-vxlan-iface.patch b/queue-4.4/vxlan-fix-test-which-detect-duplicate-vxlan-iface.patch new file mode 100644 index 00000000000..b325aa9937e --- /dev/null +++ b/queue-4.4/vxlan-fix-test-which-detect-duplicate-vxlan-iface.patch @@ -0,0 +1,62 @@ +From foo@baz Tue Jan 26 21:31:27 PST 2016 +From: Nicolas Dichtel +Date: Thu, 7 Jan 2016 11:26:53 +0100 +Subject: vxlan: fix test which detect duplicate vxlan iface + +From: Nicolas Dichtel + +[ Upstream commit 07b9b37c227cb8d88d478b4a9c5634fee514ede1 ] + +When a vxlan interface is created, the driver checks that there is not +another vxlan interface with the same properties. To do this, it checks +the existing vxlan udp socket. Since commit 1c51a9159dde, the creation of +the vxlan socket is done only when the interface is set up, thus it breaks +that test. + +Example: +$ ip l a vxlan10 type vxlan id 10 group 239.0.0.10 dev eth0 dstport 0 +$ ip l a vxlan11 type vxlan id 10 group 239.0.0.10 dev eth0 dstport 0 +$ ip -br l | grep vxlan +vxlan10 DOWN f2:55:1c:6a:fb:00 +vxlan11 DOWN 7a:cb:b9:38:59:0d + +Instead of checking sockets, let's loop over the vxlan iface list. + +Fixes: 1c51a9159dde ("vxlan: fix race caused by dropping rtnl_unlock") +Reported-by: Thomas Faivre +Signed-off-by: Nicolas Dichtel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/vxlan.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +--- a/drivers/net/vxlan.c ++++ b/drivers/net/vxlan.c +@@ -2751,7 +2751,7 @@ static int vxlan_dev_configure(struct ne + struct vxlan_config *conf) + { + struct vxlan_net *vn = net_generic(src_net, vxlan_net_id); +- struct vxlan_dev *vxlan = netdev_priv(dev); ++ struct vxlan_dev *vxlan = netdev_priv(dev), *tmp; + struct vxlan_rdst *dst = &vxlan->default_dst; + unsigned short needed_headroom = ETH_HLEN; + int err; +@@ -2817,9 +2817,15 @@ static int vxlan_dev_configure(struct ne + if (!vxlan->cfg.age_interval) + vxlan->cfg.age_interval = FDB_AGE_DEFAULT; + +- if (vxlan_find_vni(src_net, conf->vni, use_ipv6 ? AF_INET6 : AF_INET, +- vxlan->cfg.dst_port, vxlan->flags)) ++ list_for_each_entry(tmp, &vn->vxlan_list, next) { ++ if (tmp->cfg.vni == conf->vni && ++ (tmp->default_dst.remote_ip.sa.sa_family == AF_INET6 || ++ tmp->cfg.saddr.sa.sa_family == AF_INET6) == use_ipv6 && ++ tmp->cfg.dst_port == vxlan->cfg.dst_port && ++ (tmp->flags & VXLAN_F_RCV_FLAGS) == ++ (vxlan->flags & VXLAN_F_RCV_FLAGS)) + return -EEXIST; ++ } + + dev->ethtool_ops = &vxlan_ethtool_ops; +