--- /dev/null
+From 94f999fdfc5d3072ac861e608620a8c70c19b54e Mon Sep 17 00:00:00 2001
+From: Antonio Quartulli <ordex@autistici.org>
+Date: Tue, 2 Oct 2012 06:14:17 +0000
+Subject: 8021q: fix mac_len recomputation in vlan_untag()
+
+
+From: Antonio Quartulli <ordex@autistici.org>
+
+[ Upstream commit 5316cf9a5197eb80b2800e1acadde287924ca975 ]
+
+skb_reset_mac_len() relies on the value of the skb->network_header pointer,
+therefore we must wait for such pointer to be recalculated before computing
+the new mac_len value.
+
+Signed-off-by: Antonio Quartulli <ordex@autistici.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/8021q/vlan_core.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/8021q/vlan_core.c
++++ b/net/8021q/vlan_core.c
+@@ -106,7 +106,6 @@ static struct sk_buff *vlan_reorder_head
+ return NULL;
+ memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN);
+ skb->mac_header += VLAN_HLEN;
+- skb_reset_mac_len(skb);
+ return skb;
+ }
+
+@@ -140,6 +139,8 @@ struct sk_buff *vlan_untag(struct sk_buf
+
+ skb_reset_network_header(skb);
+ skb_reset_transport_header(skb);
++ skb_reset_mac_len(skb);
++
+ return skb;
+
+ err_free:
--- /dev/null
+From 776d2d0e9f7d49cdd7592bdf5bf86e89abb56d4a Mon Sep 17 00:00:00 2001
+From: Ed Cashin <ecashin@coraid.com>
+Date: Wed, 19 Sep 2012 15:46:39 +0000
+Subject: aoe: assert AoE packets marked as requiring no checksum
+
+
+From: Ed Cashin <ecashin@coraid.com>
+
+[ Upstream commit 8babe8cc6570ed896b7b596337eb8fe730c3ff45 ]
+
+In order for the network layer to see that AoE requires
+no checksumming in a generic way, the packets must be
+marked as requiring no checksum, so we make this requirement
+explicit with the assertion.
+
+Signed-off-by: Ed Cashin <ecashin@coraid.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/aoe/aoecmd.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/block/aoe/aoecmd.c
++++ b/drivers/block/aoe/aoecmd.c
+@@ -35,6 +35,7 @@ new_skb(ulong len)
+ skb_reset_mac_header(skb);
+ skb_reset_network_header(skb);
+ skb->protocol = __constant_htons(ETH_P_AOE);
++ skb_checksum_none_assert(skb);
+ }
+ return skb;
+ }
--- /dev/null
+From 77e5e5854b8cbf52576ee43edd1d054ce9da3df4 Mon Sep 17 00:00:00 2001
+From: Michal Schmidt <mschmidt@redhat.com>
+Date: Thu, 13 Sep 2012 12:59:44 +0000
+Subject: bnx2x: fix rx checksum validation for IPv6
+
+
+From: Michal Schmidt <mschmidt@redhat.com>
+
+[ Upstream commit e488921f44765e8ab6c48ca35e3f6b78df9819df ]
+
+Commit d6cb3e41 "bnx2x: fix checksum validation" caused a performance
+regression for IPv6. Rx checksum offload does not work. IPv6 packets
+are passed to the stack with CHECKSUM_NONE.
+
+The hardware obviously cannot perform IP checksum validation for IPv6,
+because there is no checksum in the IPv6 header. This should not prevent
+us from setting CHECKSUM_UNNECESSARY.
+
+Tested on BCM57711.
+
+Signed-off-by: Michal Schmidt <mschmidt@redhat.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Acked-by: Eilon Greenstein <eilong@broadcom.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
++++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+@@ -571,14 +571,16 @@ drop:
+ static void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe,
+ struct bnx2x_fastpath *fp)
+ {
+- /* Do nothing if no IP/L4 csum validation was done */
+-
++ /* Do nothing if no L4 csum validation was done.
++ * We do not check whether IP csum was validated. For IPv4 we assume
++ * that if the card got as far as validating the L4 csum, it also
++ * validated the IP csum. IPv6 has no IP csum.
++ */
+ if (cqe->fast_path_cqe.status_flags &
+- (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG |
+- ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG))
++ ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)
+ return;
+
+- /* If both IP/L4 validation were done, check if an error was found. */
++ /* If L4 validation was done, check if an error was found. */
+
+ if (cqe->fast_path_cqe.type_error_flags &
+ (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG |
--- /dev/null
+From d19817c05c51e99af4dca75caf15ba5a8b043680 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Sat, 22 Sep 2012 00:08:29 +0000
+Subject: ipv4: raw: fix icmp_filter()
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit ab43ed8b7490cb387782423ecf74aeee7237e591 ]
+
+icmp_filter() should not modify its input, or else its caller
+would need to recompute ip_hdr() if skb->head is reallocated.
+
+Use skb_header_pointer() instead of pskb_may_pull() and
+change the prototype to make clear both sk and skb are const.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/raw.c | 14 ++++++++------
+ 1 file changed, 8 insertions(+), 6 deletions(-)
+
+--- a/net/ipv4/raw.c
++++ b/net/ipv4/raw.c
+@@ -131,18 +131,20 @@ found:
+ * 0 - deliver
+ * 1 - block
+ */
+-static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
++static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
+ {
+- int type;
++ struct icmphdr _hdr;
++ const struct icmphdr *hdr;
+
+- if (!pskb_may_pull(skb, sizeof(struct icmphdr)))
++ hdr = skb_header_pointer(skb, skb_transport_offset(skb),
++ sizeof(_hdr), &_hdr);
++ if (!hdr)
+ return 1;
+
+- type = icmp_hdr(skb)->type;
+- if (type < 32) {
++ if (hdr->type < 32) {
+ __u32 data = raw_sk(sk)->filter.data;
+
+- return ((1 << type) & data) != 0;
++ return ((1U << hdr->type) & data) != 0;
+ }
+
+ /* Do not block unknown ICMP types */
--- /dev/null
+From 6439745e063e7621a864707226615329a93cecb5 Mon Sep 17 00:00:00 2001
+From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Date: Wed, 26 Sep 2012 00:04:55 +0000
+Subject: ipv6: del unreachable route when an addr is deleted on lo
+
+
+From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+
+[ Upstream commit 64c6d08e6490fb18cea09bb03686c149946bd818 ]
+
+When an address is added on loopback (ip -6 a a 2002::1/128 dev lo), two routes
+are added:
+ - one in the local table:
+ local 2002::1 via :: dev lo proto none metric 0
+ - one the in main table (for the prefix):
+ unreachable 2002::1 dev lo proto kernel metric 256 error -101
+
+When the address is deleted, the route inserted in the main table remains
+because we use rt6_lookup(), which returns NULL when dst->error is set, which
+is the case here! Thus, it is better to use ip6_route_lookup() to avoid this
+kind of filter.
+
+Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/addrconf.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -793,10 +793,16 @@ static void ipv6_del_addr(struct inet6_i
+ struct in6_addr prefix;
+ struct rt6_info *rt;
+ struct net *net = dev_net(ifp->idev->dev);
++ struct flowi6 fl6 = {};
++
+ ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
+- rt = rt6_lookup(net, &prefix, NULL, ifp->idev->dev->ifindex, 1);
++ fl6.flowi6_oif = ifp->idev->dev->ifindex;
++ fl6.daddr = prefix;
++ rt = (struct rt6_info *)ip6_route_lookup(net, &fl6,
++ RT6_LOOKUP_F_IFACE);
+
+- if (rt && addrconf_is_prefix_route(rt)) {
++ if (rt != net->ipv6.ip6_null_entry &&
++ addrconf_is_prefix_route(rt)) {
+ if (onlink == 0) {
+ ip6_del_rt(rt);
+ rt = NULL;
--- /dev/null
+From 072661538f835eb7fd7a01beb1abacc9459368bd Mon Sep 17 00:00:00 2001
+From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
+Date: Thu, 20 Sep 2012 18:29:56 +0000
+Subject: ipv6: fix return value check in fib6_add()
+
+
+From: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
+
+[ Upstream commit f950c0ecc78f745e490d615280e031de4dbb1306 ]
+
+In case of error, the function fib6_add_1() returns ERR_PTR()
+or NULL pointer. The ERR_PTR() case check is missing in fib6_add().
+
+dpatch engine is used to generated this patch.
+(https://github.com/weiyj/dpatch)
+
+Signed-off-by: Wei Yongjun <yongjun_wei@trendmicro.com.cn>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ip6_fib.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -818,6 +818,10 @@ int fib6_add(struct fib6_node *root, str
+ offsetof(struct rt6_info, rt6i_src),
+ allow_create, replace_required);
+
++ if (IS_ERR(sn)) {
++ err = PTR_ERR(sn);
++ sn = NULL;
++ }
+ if (!sn) {
+ /* If it is failed, discard just allocated
+ root, and then (in st_failure) stale node
--- /dev/null
+From 2943773e918a8f9cc79a2b14edd9c0590e4dfe74 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 25 Sep 2012 22:01:28 +0200
+Subject: ipv6: mip6: fix mip6_mh_filter()
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 96af69ea2a83d292238bdba20e4508ee967cf8cb ]
+
+mip6_mh_filter() should not modify its input, or else its caller
+would need to recompute ipv6_hdr() if skb->head is reallocated.
+
+Use skb_header_pointer() instead of pskb_may_pull()
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/mip6.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/net/ipv6/mip6.c
++++ b/net/ipv6/mip6.c
+@@ -84,28 +84,30 @@ static int mip6_mh_len(int type)
+
+ static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
+ {
+- struct ip6_mh *mh;
++ struct ip6_mh _hdr;
++ const struct ip6_mh *mh;
+
+- if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) ||
+- !pskb_may_pull(skb, (skb_transport_offset(skb) +
+- ((skb_transport_header(skb)[1] + 1) << 3))))
++ mh = skb_header_pointer(skb, skb_transport_offset(skb),
++ sizeof(_hdr), &_hdr);
++ if (!mh)
+ return -1;
+
+- mh = (struct ip6_mh *)skb_transport_header(skb);
++ if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len)
++ return -1;
+
+ if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {
+ LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",
+ mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type));
+- mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) -
+- skb_network_header(skb)));
++ mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) +
++ skb_network_header_len(skb));
+ return -1;
+ }
+
+ if (mh->ip6mh_proto != IPPROTO_NONE) {
+ LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
+ mh->ip6mh_proto);
+- mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) -
+- skb_network_header(skb)));
++ mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) +
++ skb_network_header_len(skb));
+ return -1;
+ }
+
--- /dev/null
+From 34c0451ce1badf75dfa49594a515b8a208cbc7b4 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 25 Sep 2012 07:03:40 +0000
+Subject: ipv6: raw: fix icmpv6_filter()
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 1b05c4b50edbddbdde715c4a7350629819f6655e ]
+
+icmpv6_filter() should not modify its input, or else its caller
+would need to recompute ipv6_hdr() if skb->head is reallocated.
+
+Use skb_header_pointer() instead of pskb_may_pull() and
+change the prototype to make clear both sk and skb are const.
+
+Also, if icmpv6 header cannot be found, do not deliver the packet,
+as we do in IPv4.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/raw.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+--- a/net/ipv6/raw.c
++++ b/net/ipv6/raw.c
+@@ -107,21 +107,20 @@ found:
+ * 0 - deliver
+ * 1 - block
+ */
+-static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
++static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)
+ {
+- struct icmp6hdr *icmph;
+- struct raw6_sock *rp = raw6_sk(sk);
++ struct icmp6hdr *_hdr;
++ const struct icmp6hdr *hdr;
+
+- if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) {
+- __u32 *data = &rp->filter.data[0];
+- int bit_nr;
++ hdr = skb_header_pointer(skb, skb_transport_offset(skb),
++ sizeof(_hdr), &_hdr);
++ if (hdr) {
++ const __u32 *data = &raw6_sk(sk)->filter.data[0];
++ unsigned int type = hdr->icmp6_type;
+
+- icmph = (struct icmp6hdr *) skb->data;
+- bit_nr = icmph->icmp6_type;
+-
+- return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0;
++ return (data[type >> 5] & (1U << (type & 31))) != 0;
+ }
+- return 0;
++ return 1;
+ }
+
+ #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
--- /dev/null
+From 1aafcc429d6fd940fd85c66d83a92cb1d396591d Mon Sep 17 00:00:00 2001
+From: Gao feng <gaofeng@cn.fujitsu.com>
+Date: Wed, 19 Sep 2012 19:25:34 +0000
+Subject: ipv6: release reference of ip6_null_entry's dst entry in __ip6_del_rt
+
+
+From: Gao feng <gaofeng@cn.fujitsu.com>
+
+[ Upstream commit 6825a26c2dc21eb4f8df9c06d3786ddec97cf53b ]
+
+as we hold dst_entry before we call __ip6_del_rt,
+so we should alse call dst_release not only return
+-ENOENT when the rt6_info is ip6_null_entry.
+
+and we already hold the dst entry, so I think it's
+safe to call dst_release out of the write-read lock.
+
+Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/route.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/net/ipv6/route.c
++++ b/net/ipv6/route.c
+@@ -1485,17 +1485,18 @@ static int __ip6_del_rt(struct rt6_info
+ struct fib6_table *table;
+ struct net *net = dev_net(rt->dst.dev);
+
+- if (rt == net->ipv6.ip6_null_entry)
+- return -ENOENT;
++ if (rt == net->ipv6.ip6_null_entry) {
++ err = -ENOENT;
++ goto out;
++ }
+
+ table = rt->rt6i_table;
+ write_lock_bh(&table->tb6_lock);
+-
+ err = fib6_del(rt, info);
+- dst_release(&rt->dst);
+-
+ write_unlock_bh(&table->tb6_lock);
+
++out:
++ dst_release(&rt->dst);
+ return err;
+ }
+
--- /dev/null
+From 868cecfc3977770b373c366a3d22110163c0121f Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <florian@openwrt.org>
+Date: Mon, 10 Sep 2012 14:06:58 +0200
+Subject: ixp4xx_hss: fix build failure due to missing linux/module.h inclusion
+
+
+From: Florian Fainelli <florian@openwrt.org>
+
+[ Upstream commit 0b836ddde177bdd5790ade83772860940bd481ea ]
+
+Commit 36a1211970193ce215de50ed1e4e1272bc814df1 (netprio_cgroup.h:
+dont include module.h from other includes) made the following build
+error on ixp4xx_hss pop up:
+
+ CC [M] drivers/net/wan/ixp4xx_hss.o
+ drivers/net/wan/ixp4xx_hss.c:1412:20: error: expected ';', ',' or ')'
+ before string constant
+ drivers/net/wan/ixp4xx_hss.c:1413:25: error: expected ';', ',' or ')'
+ before string constant
+ drivers/net/wan/ixp4xx_hss.c:1414:21: error: expected ';', ',' or ')'
+ before string constant
+ drivers/net/wan/ixp4xx_hss.c:1415:19: error: expected ';', ',' or ')'
+ before string constant
+ make[8]: *** [drivers/net/wan/ixp4xx_hss.o] Error 1
+
+This was previously hidden because ixp4xx_hss includes linux/hdlc.h which
+includes linux/netdevice.h which includes linux/netprio_cgroup.h which
+used to include linux/module.h. The real issue was actually present since
+the initial commit that added this driver since it uses macros from
+linux/module.h without including this file.
+
+Signed-off-by: Florian Fainelli <florian@openwrt.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wan/ixp4xx_hss.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wan/ixp4xx_hss.c
++++ b/drivers/net/wan/ixp4xx_hss.c
+@@ -10,6 +10,7 @@
+
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
++#include <linux/module.h>
+ #include <linux/bitops.h>
+ #include <linux/cdev.h>
+ #include <linux/dma-mapping.h>
--- /dev/null
+From 6a2ffa4f6523b80530ee613fc30492657471e86f Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 4 Sep 2012 15:54:55 -0400
+Subject: l2tp: fix a typo in l2tp_eth_dev_recv()
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit c0cc88a7627c333de50b07b7c60b1d49d9d2e6cc ]
+
+While investigating l2tp bug, I hit a bug in eth_type_trans(),
+because not enough bytes were pulled in skb head.
+
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/l2tp/l2tp_eth.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/l2tp/l2tp_eth.c
++++ b/net/l2tp/l2tp_eth.c
+@@ -132,7 +132,7 @@ static void l2tp_eth_dev_recv(struct l2t
+ printk("\n");
+ }
+
+- if (!pskb_may_pull(skb, sizeof(ETH_HLEN)))
++ if (!pskb_may_pull(skb, ETH_HLEN))
+ goto error;
+
+ secpath_reset(skb);
--- /dev/null
+From f182e53c6b53a4691a475a5af77636cadca210f0 Mon Sep 17 00:00:00 2001
+From: Ed Cashin <ecashin@coraid.com>
+Date: Wed, 19 Sep 2012 15:49:00 +0000
+Subject: net: do not disable sg for packets requiring no checksum
+
+
+From: Ed Cashin <ecashin@coraid.com>
+
+[ Upstream commit c0d680e577ff171e7b37dbdb1b1bf5451e851f04 ]
+
+A change in a series of VLAN-related changes appears to have
+inadvertently disabled the use of the scatter gather feature of
+network cards for transmission of non-IP ethernet protocols like ATA
+over Ethernet (AoE). Below is a reference to the commit that
+introduces a "harmonize_features" function that turns off scatter
+gather when the NIC does not support hardware checksumming for the
+ethernet protocol of an sk buff.
+
+ commit f01a5236bd4b140198fbcc550f085e8361fd73fa
+ Author: Jesse Gross <jesse@nicira.com>
+ Date: Sun Jan 9 06:23:31 2011 +0000
+
+ net offloading: Generalize netif_get_vlan_features().
+
+The can_checksum_protocol function is not equipped to consider a
+protocol that does not require checksumming. Calling it for a
+protocol that requires no checksum is inappropriate.
+
+The patch below has harmonize_features call can_checksum_protocol when
+the protocol needs a checksum, so that the network layer is not forced
+to perform unnecessary skb linearization on the transmission of AoE
+packets. Unnecessary linearization results in decreased performance
+and increased memory pressure, as reported here:
+
+ http://www.spinics.net/lists/linux-mm/msg15184.html
+
+The problem has probably not been widely experienced yet, because
+only recently has the kernel.org-distributed aoe driver acquired the
+ability to use payloads of over a page in size, with the patchset
+recently included in the mm tree:
+
+ https://lkml.org/lkml/2012/8/28/140
+
+The coraid.com-distributed aoe driver already could use payloads of
+greater than a page in size, but its users generally do not use the
+newest kernels.
+
+Signed-off-by: Ed Cashin <ecashin@coraid.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/dev.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2121,7 +2121,8 @@ static bool can_checksum_protocol(netdev
+ static netdev_features_t harmonize_features(struct sk_buff *skb,
+ __be16 protocol, netdev_features_t features)
+ {
+- if (!can_checksum_protocol(features, protocol)) {
++ if (skb->ip_summed != CHECKSUM_NONE &&
++ !can_checksum_protocol(features, protocol)) {
+ features &= ~NETIF_F_ALL_CSUM;
+ features &= ~NETIF_F_SG;
+ } else if (illegal_highdma(skb->dev, skb)) {
--- /dev/null
+From f73b1c62797dfd36aebda0f8f7305ae9d12c09f5 Mon Sep 17 00:00:00 2001
+From: htbegin <hotforest@gmail.com>
+Date: Mon, 1 Oct 2012 16:42:43 +0000
+Subject: net: ethernet: davinci_cpdma: decrease the desc count when cleaning up the remaining packets
+
+
+From: htbegin <hotforest@gmail.com>
+
+[ Upstream commit ffb5ba90017505a19e238e986e6d33f09e4df765 ]
+
+chan->count is used by rx channel. If the desc count is not updated by
+the clean up loop in cpdma_chan_stop, the value written to the rxfree
+register in cpdma_chan_start will be incorrect.
+
+Signed-off-by: Tao Hou <hotforest@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/ti/davinci_cpdma.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/ethernet/ti/davinci_cpdma.c
++++ b/drivers/net/ethernet/ti/davinci_cpdma.c
+@@ -851,6 +851,7 @@ int cpdma_chan_stop(struct cpdma_chan *c
+
+ next_dma = desc_read(desc, hw_next);
+ chan->head = desc_from_phys(pool, next_dma);
++ chan->count--;
+ chan->stats.teardown_dequeue++;
+
+ /* issue callback without locks held */
--- /dev/null
+From 11a14deab9f8381abfbdb0763f4e4f416fb8710f Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Mon, 24 Sep 2012 07:00:11 +0000
+Subject: net: guard tcp_set_keepalive() to tcp sockets
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 3e10986d1d698140747fcfc2761ec9cb64c1d582 ]
+
+Its possible to use RAW sockets to get a crash in
+tcp_set_keepalive() / sk_reset_timer()
+
+Fix is to make sure socket is a SOCK_STREAM one.
+
+Reported-by: Dave Jones <davej@redhat.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/sock.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/core/sock.c
++++ b/net/core/sock.c
+@@ -644,7 +644,8 @@ set_rcvbuf:
+
+ case SO_KEEPALIVE:
+ #ifdef CONFIG_INET
+- if (sk->sk_protocol == IPPROTO_TCP)
++ if (sk->sk_protocol == IPPROTO_TCP &&
++ sk->sk_type == SOCK_STREAM)
+ tcp_set_keepalive(sk, valbool);
+ #endif
+ sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
--- /dev/null
+From 7a5697725ebf1f5b8c73b6f5f5eecd71d9fa9f4f Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <edumazet@google.com>
+Date: Tue, 11 Sep 2012 13:11:12 +0000
+Subject: net-sched: sch_cbq: avoid infinite loop
+
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit bdfc87f7d1e253e0a61e2fc6a75ea9d76f7fc03a ]
+
+Its possible to setup a bad cbq configuration leading to
+an infinite loop in cbq_classify()
+
+DEV_OUT=eth0
+ICMP="match ip protocol 1 0xff"
+U32="protocol ip u32"
+DST="match ip dst"
+tc qdisc add dev $DEV_OUT root handle 1: cbq avpkt 1000 \
+ bandwidth 100mbit
+tc class add dev $DEV_OUT parent 1: classid 1:1 cbq \
+ rate 512kbit allot 1500 prio 5 bounded isolated
+tc filter add dev $DEV_OUT parent 1: prio 3 $U32 \
+ $ICMP $DST 192.168.3.234 flowid 1:
+
+Reported-by: Denys Fedoryschenko <denys@visp.net.lb>
+Tested-by: Denys Fedoryschenko <denys@visp.net.lb>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sched/sch_cbq.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/net/sched/sch_cbq.c
++++ b/net/sched/sch_cbq.c
+@@ -250,10 +250,11 @@ cbq_classify(struct sk_buff *skb, struct
+ else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL)
+ cl = defmap[TC_PRIO_BESTEFFORT];
+
+- if (cl == NULL || cl->level >= head->level)
++ if (cl == NULL)
+ goto fallback;
+ }
+-
++ if (cl->level >= head->level)
++ goto fallback;
+ #ifdef CONFIG_NET_CLS_ACT
+ switch (result) {
+ case TC_ACT_QUEUED:
--- /dev/null
+From 5e1ad74e5323596a8970a62bcee874422ba1d15e Mon Sep 17 00:00:00 2001
+From: Chema Gonzalez <chema@google.com>
+Date: Fri, 7 Sep 2012 13:40:50 +0000
+Subject: net: small bug on rxhash calculation
+
+
+From: Chema Gonzalez <chema@google.com>
+
+[ Upstream commit 6862234238e84648c305526af2edd98badcad1e0 ]
+
+In the current rxhash calculation function, while the
+sorting of the ports/addrs is coherent (you get the
+same rxhash for packets sharing the same 4-tuple, in
+both directions), ports and addrs are sorted
+independently. This implies packets from a connection
+between the same addresses but crossed ports hash to
+the same rxhash.
+
+For example, traffic between A=S:l and B=L:s is hashed
+(in both directions) from {L, S, {s, l}}. The same
+rxhash is obtained for packets between C=S:s and D=L:l.
+
+This patch ensures that you either swap both addrs and ports,
+or you swap none. Traffic between A and B, and traffic
+between C and D, get their rxhash from different sources
+({L, S, {l, s}} for A<->B, and {L, S, {s, l}} for C<->D)
+
+The patch is co-written with Eric Dumazet <edumazet@google.com>
+
+Signed-off-by: Chema Gonzalez <chema@google.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/dev.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2617,15 +2617,16 @@ void __skb_get_rxhash(struct sk_buff *sk
+ if (!skb_flow_dissect(skb, &keys))
+ return;
+
+- if (keys.ports) {
+- if ((__force u16)keys.port16[1] < (__force u16)keys.port16[0])
+- swap(keys.port16[0], keys.port16[1]);
++ if (keys.ports)
+ skb->l4_rxhash = 1;
+- }
+
+ /* get a consistent hash (same value on both flow directions) */
+- if ((__force u32)keys.dst < (__force u32)keys.src)
++ if (((__force u32)keys.dst < (__force u32)keys.src) ||
++ (((__force u32)keys.dst == (__force u32)keys.src) &&
++ ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) {
+ swap(keys.dst, keys.src);
++ swap(keys.port16[0], keys.port16[1]);
++ }
+
+ hash = jhash_3words((__force u32)keys.dst,
+ (__force u32)keys.src,
--- /dev/null
+From 74d16a708fec25588e3ccf559d6406d88213605c Mon Sep 17 00:00:00 2001
+From: Alan Cox <alan@linux.intel.com>
+Date: Tue, 4 Sep 2012 04:13:18 +0000
+Subject: netrom: copy_datagram_iovec can fail
+
+
+From: Alan Cox <alan@linux.intel.com>
+
+[ Upstream commit 6cf5c951175abcec4da470c50565cc0afe6cd11d ]
+
+Check for an error from this and if so bail properly.
+
+Signed-off-by: Alan Cox <alan@linux.intel.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netrom/af_netrom.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/net/netrom/af_netrom.c
++++ b/net/netrom/af_netrom.c
+@@ -1169,7 +1169,12 @@ static int nr_recvmsg(struct kiocb *iocb
+ msg->msg_flags |= MSG_TRUNC;
+ }
+
+- skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
++ er = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
++ if (er < 0) {
++ skb_free_datagram(sk, skb);
++ release_sock(sk);
++ return er;
++ }
+
+ if (sax != NULL) {
+ sax->sax25_family = AF_NETROM;
--- /dev/null
+From 7cc8e3aa760c59ae4c22e5f459a895e2eaf64f3c Mon Sep 17 00:00:00 2001
+From: Nikolay Aleksandrov <nikolay@redhat.com>
+Date: Fri, 14 Sep 2012 05:50:03 +0000
+Subject: netxen: check for root bus in netxen_mask_aer_correctable
+
+
+From: Nikolay Aleksandrov <nikolay@redhat.com>
+
+[ Upstream commit e4d1aa40e363ed3e0486aeeeb0d173f7f822737e ]
+
+Add a check if pdev->bus->self == NULL (root bus). When attaching
+a netxen NIC to a VM it can be on the root bus and the guest would
+crash in netxen_mask_aer_correctable() because of a NULL pointer
+dereference if CONFIG_PCIEAER is present.
+
+Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
++++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+@@ -1370,6 +1370,10 @@ static void netxen_mask_aer_correctable(
+ struct pci_dev *root = pdev->bus->self;
+ u32 aer_pos;
+
++ /* root bus? */
++ if (!root)
++ return;
++
+ if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM &&
+ adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP)
+ return;
--- /dev/null
+From d7801416cc1ec6b72872fcfae807fd6ace95e410 Mon Sep 17 00:00:00 2001
+From: Paolo Valente <paolo.valente@unimore.it>
+Date: Sat, 15 Sep 2012 00:41:35 +0000
+Subject: pkt_sched: fix virtual-start-time update in QFQ
+
+
+From: Paolo Valente <paolo.valente@unimore.it>
+
+[ Upstream commit 71261956973ba9e0637848a5adb4a5819b4bae83 ]
+
+If the old timestamps of a class, say cl, are stale when the class
+becomes active, then QFQ may assign to cl a much higher start time
+than the maximum value allowed. This may happen when QFQ assigns to
+the start time of cl the finish time of a group whose classes are
+characterized by a higher value of the ratio
+max_class_pkt/weight_of_the_class with respect to that of
+cl. Inserting a class with a too high start time into the bucket list
+corrupts the data structure and may eventually lead to crashes.
+This patch limits the maximum start time assigned to a class.
+
+Signed-off-by: Paolo Valente <paolo.valente@unimore.it>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sched/sch_qfq.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/net/sched/sch_qfq.c
++++ b/net/sched/sch_qfq.c
+@@ -830,7 +830,10 @@ static void qfq_update_start(struct qfq_
+ if (mask) {
+ struct qfq_group *next = qfq_ffs(q, mask);
+ if (qfq_gt(roundedF, next->F)) {
+- cl->S = next->F;
++ if (qfq_gt(limit, next->F))
++ cl->S = next->F;
++ else /* preserve timestamp correctness */
++ cl->S = limit;
+ return;
+ }
+ }
--- /dev/null
+From 56434040eb3864a7341dfd31364271db26e76eff Mon Sep 17 00:00:00 2001
+From: Xiaodong Xu <stid.smth@gmail.com>
+Date: Sat, 22 Sep 2012 00:09:32 +0000
+Subject: pppoe: drop PPPOX_ZOMBIEs in pppoe_release
+
+
+From: Xiaodong Xu <stid.smth@gmail.com>
+
+[ Upstream commit 2b018d57ff18e5405823e5cb59651a5b4d946d7b ]
+
+When PPPOE is running over a virtual ethernet interface (e.g., a
+bonding interface) and the user tries to delete the interface in case
+the PPPOE state is ZOMBIE, the kernel will loop forever while
+unregistering net_device for the reference count is not decreased to
+zero which should have been done with dev_put().
+
+Signed-off-by: Xiaodong Xu <stid.smth@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ppp/pppoe.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/ppp/pppoe.c
++++ b/drivers/net/ppp/pppoe.c
+@@ -576,7 +576,7 @@ static int pppoe_release(struct socket *
+
+ po = pppox_sk(sk);
+
+- if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
++ if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
+ dev_put(po->pppoe_dev);
+ po->pppoe_dev = NULL;
+ }
--- /dev/null
+From 117427496fc6588e63807b59c72c7f2d464c27bc Mon Sep 17 00:00:00 2001
+From: Thomas Graf <tgraf@suug.ch>
+Date: Mon, 3 Sep 2012 04:27:42 +0000
+Subject: sctp: Don't charge for data in sndbuf again when transmitting packet
+
+
+From: Thomas Graf <tgraf@suug.ch>
+
+[ Upstream commit 4c3a5bdae293f75cdf729c6c00124e8489af2276 ]
+
+SCTP charges wmem_alloc via sctp_set_owner_w() in sctp_sendmsg() and via
+skb_set_owner_w() in sctp_packet_transmit(). If a sender runs out of
+sndbuf it will sleep in sctp_wait_for_sndbuf() and expects to be waken up
+by __sctp_write_space().
+
+Buffer space charged via sctp_set_owner_w() is released in sctp_wfree()
+which calls __sctp_write_space() directly.
+
+Buffer space charged via skb_set_owner_w() is released via sock_wfree()
+which calls sk->sk_write_space() _if_ SOCK_USE_WRITE_QUEUE is not set.
+sctp_endpoint_init() sets SOCK_USE_WRITE_QUEUE on all sockets.
+
+Therefore if sctp_packet_transmit() manages to queue up more than sndbuf
+bytes, sctp_wait_for_sndbuf() will never be woken up again unless it is
+interrupted by a signal.
+
+This could be fixed by clearing the SOCK_USE_WRITE_QUEUE flag but ...
+
+Charging for the data twice does not make sense in the first place, it
+leads to overcharging sndbuf by a factor 2. Therefore this patch only
+charges a single byte in wmem_alloc when transmitting an SCTP packet to
+ensure that the socket stays alive until the packet has been released.
+
+This means that control chunks are no longer accounted for in wmem_alloc
+which I believe is not a problem as skb->truesize will typically lead
+to overcharging anyway and thus compensates for any control overhead.
+
+Signed-off-by: Thomas Graf <tgraf@suug.ch>
+CC: Vlad Yasevich <vyasevic@redhat.com>
+CC: Neil Horman <nhorman@tuxdriver.com>
+CC: David Miller <davem@davemloft.net>
+Acked-by: Vlad Yasevich <vyasevich@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/output.c | 21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/net/sctp/output.c
++++ b/net/sctp/output.c
+@@ -334,6 +334,25 @@ finish:
+ return retval;
+ }
+
++static void sctp_packet_release_owner(struct sk_buff *skb)
++{
++ sk_free(skb->sk);
++}
++
++static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk)
++{
++ skb_orphan(skb);
++ skb->sk = sk;
++ skb->destructor = sctp_packet_release_owner;
++
++ /*
++ * The data chunks have already been accounted for in sctp_sendmsg(),
++ * therefore only reserve a single byte to keep socket around until
++ * the packet has been transmitted.
++ */
++ atomic_inc(&sk->sk_wmem_alloc);
++}
++
+ /* All packets are sent to the network through this function from
+ * sctp_outq_tail().
+ *
+@@ -375,7 +394,7 @@ int sctp_packet_transmit(struct sctp_pac
+ /* Set the owning socket so that we know where to get the
+ * destination IP address.
+ */
+- skb_set_owner_w(nskb, sk);
++ sctp_packet_set_owner_w(nskb, sk);
+
+ if (!sctp_transport_dst_check(tp)) {
+ sctp_transport_route(tp, NULL, sctp_sk(sk));
workqueue-add-missing-smp_wmb-in-process_one_work.patch
jbd2-don-t-write-superblock-when-if-its-empty.patch
localmodconfig-fix-localyesconfig-to-set-to-y-not-m.patch
+bnx2x-fix-rx-checksum-validation-for-ipv6.patch
+xfrm-workaround-incompatibility-of-esn-and-async-crypto.patch
+xfrm_user-return-error-pointer-instead-of-null.patch
+xfrm_user-return-error-pointer-instead-of-null-2.patch
+xfrm-fix-a-read-lock-imbalance-in-make_blackhole.patch
+xfrm_user-fix-info-leak-in-copy_to_user_auth.patch
+xfrm_user-fix-info-leak-in-copy_to_user_state.patch
+xfrm_user-fix-info-leak-in-copy_to_user_policy.patch
+xfrm_user-fix-info-leak-in-copy_to_user_tmpl.patch
+xfrm_user-don-t-copy-esn-replay-window-twice-for-new-states.patch
+xfrm_user-ensure-user-supplied-esn-replay-window-is-valid.patch
+net-ethernet-davinci_cpdma-decrease-the-desc-count-when-cleaning-up-the-remaining-packets.patch
+ixp4xx_hss-fix-build-failure-due-to-missing-linux-module.h-inclusion.patch
+netxen-check-for-root-bus-in-netxen_mask_aer_correctable.patch
+net-sched-sch_cbq-avoid-infinite-loop.patch
+pkt_sched-fix-virtual-start-time-update-in-qfq.patch
+sierra_net-endianess-bug-fix.patch
+8021q-fix-mac_len-recomputation-in-vlan_untag.patch
+ipv6-release-reference-of-ip6_null_entry-s-dst-entry-in-__ip6_del_rt.patch
+ipv6-del-unreachable-route-when-an-addr-is-deleted-on-lo.patch
+ipv6-fix-return-value-check-in-fib6_add.patch
+tcp-flush-dma-queue-before-sk_wait_data-if-rcv_wnd-is-zero.patch
+sctp-don-t-charge-for-data-in-sndbuf-again-when-transmitting-packet.patch
+pppoe-drop-pppox_zombies-in-pppoe_release.patch
+net-small-bug-on-rxhash-calculation.patch
+net-guard-tcp_set_keepalive-to-tcp-sockets.patch
+ipv4-raw-fix-icmp_filter.patch
+ipv6-raw-fix-icmpv6_filter.patch
+ipv6-mip6-fix-mip6_mh_filter.patch
+l2tp-fix-a-typo-in-l2tp_eth_dev_recv.patch
+netrom-copy_datagram_iovec-can-fail.patch
+net-do-not-disable-sg-for-packets-requiring-no-checksum.patch
+aoe-assert-aoe-packets-marked-as-requiring-no-checksum.patch
--- /dev/null
+From 3c4f394d7a96efa30d19317c2b1904c6011f2987 Mon Sep 17 00:00:00 2001
+From: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
+Date: Fri, 7 Sep 2012 12:14:02 +0000
+Subject: sierra_net: Endianess bug fix.
+
+
+From: Lennart Sorensen <lsorense@csclub.uwaterloo.ca>
+
+[ Upstream commit 2120c52da6fe741454a60644018ad2a6abd957ac ]
+
+I discovered I couldn't get sierra_net to work on a powerpc. Turns out
+the firmware attribute check assumes the system is little endian and
+hence fails because the attributes is a 16 bit value.
+
+Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/usb/sierra_net.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/usb/sierra_net.c
++++ b/drivers/net/usb/sierra_net.c
+@@ -678,7 +678,7 @@ static int sierra_net_get_fw_attr(struct
+ return -EIO;
+ }
+
+- *datap = *attrdata;
++ *datap = le16_to_cpu(*attrdata);
+
+ kfree(attrdata);
+ return result;
--- /dev/null
+From 317dd28e97aa4541612669110217c871ff8c8529 Mon Sep 17 00:00:00 2001
+From: Michal Kubeček <mkubecek@suse.cz>
+Date: Fri, 14 Sep 2012 04:59:52 +0000
+Subject: tcp: flush DMA queue before sk_wait_data if rcv_wnd is zero
+
+
+From: =?UTF-8?q?Michal=20Kube=C4=8Dek?= <mkubecek@suse.cz>
+
+[ Upstream commit 15c041759bfcd9ab0a4e43f1c16e2644977d0467 ]
+
+If recv() syscall is called for a TCP socket so that
+ - IOAT DMA is used
+ - MSG_WAITALL flag is used
+ - requested length is bigger than sk_rcvbuf
+ - enough data has already arrived to bring rcv_wnd to zero
+then when tcp_recvmsg() gets to calling sk_wait_data(), receive
+window can be still zero while sk_async_wait_queue exhausts
+enough space to keep it zero. As this queue isn't cleaned until
+the tcp_service_net_dma() call, sk_wait_data() cannot receive
+any data and blocks forever.
+
+If zero receive window and non-empty sk_async_wait_queue is
+detected before calling sk_wait_data(), process the queue first.
+
+Signed-off-by: Michal Kubecek <mkubecek@suse.cz>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -1594,8 +1594,14 @@ int tcp_recvmsg(struct kiocb *iocb, stru
+ }
+
+ #ifdef CONFIG_NET_DMA
+- if (tp->ucopy.dma_chan)
+- dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
++ if (tp->ucopy.dma_chan) {
++ if (tp->rcv_wnd == 0 &&
++ !skb_queue_empty(&sk->sk_async_wait_queue)) {
++ tcp_service_net_dma(sk, true);
++ tcp_cleanup_rbuf(sk, copied);
++ } else
++ dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
++ }
+ #endif
+ if (copied >= target) {
+ /* Do not sleep, just process backlog. */
--- /dev/null
+From e615a446c6bb2dad2e5dcec849b84789e610e611 Mon Sep 17 00:00:00 2001
+From: Li RongQing <roy.qing.li@gmail.com>
+Date: Mon, 17 Sep 2012 22:40:10 +0000
+Subject: xfrm: fix a read lock imbalance in make_blackhole
+
+
+From: Li RongQing <roy.qing.li@gmail.com>
+
+[ Upstream commit 433a19548061bb5457b6ab77ed7ea58ca6e43ddb ]
+
+if xfrm_policy_get_afinfo returns 0, it has already released the read
+lock, xfrm_policy_put_afinfo should not be called again.
+
+Signed-off-by: Li RongQing <roy.qing.li@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xfrm/xfrm_policy.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -1761,7 +1761,7 @@ static struct dst_entry *make_blackhole(
+
+ if (!afinfo) {
+ dst_release(dst_orig);
+- ret = ERR_PTR(-EINVAL);
++ return ERR_PTR(-EINVAL);
+ } else {
+ ret = afinfo->blackhole_route(net, dst_orig);
+ }
--- /dev/null
+From 2b39f4e40b6874b5301195c72416ec5c16e81545 Mon Sep 17 00:00:00 2001
+From: Steffen Klassert <steffen.klassert@secunet.com>
+Date: Tue, 4 Sep 2012 00:03:29 +0000
+Subject: xfrm: Workaround incompatibility of ESN and async crypto
+
+
+From: Steffen Klassert <steffen.klassert@secunet.com>
+
+[ Upstream commit 3b59df46a449ec9975146d71318c4777ad086744 ]
+
+ESN for esp is defined in RFC 4303. This RFC assumes that the
+sequence number counters are always up to date. However,
+this is not true if an async crypto algorithm is employed.
+
+If the sequence number counters are not up to date on sequence
+number check, we may incorrectly update the upper 32 bit of
+the sequence number. This leads to a DOS.
+
+We workaround this by comparing the upper sequence number,
+(used for authentication) with the upper sequence number
+computed after the async processing. We drop the packet
+if these numbers are different.
+
+To do this, we introduce a recheck function that does this
+check in the ESN case.
+
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/xfrm.h | 3 +++
+ net/xfrm/xfrm_input.c | 2 +-
+ net/xfrm/xfrm_replay.c | 15 +++++++++++++++
+ 3 files changed, 19 insertions(+), 1 deletion(-)
+
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -269,6 +269,9 @@ struct xfrm_replay {
+ int (*check)(struct xfrm_state *x,
+ struct sk_buff *skb,
+ __be32 net_seq);
++ int (*recheck)(struct xfrm_state *x,
++ struct sk_buff *skb,
++ __be32 net_seq);
+ void (*notify)(struct xfrm_state *x, int event);
+ int (*overflow)(struct xfrm_state *x, struct sk_buff *skb);
+ };
+--- a/net/xfrm/xfrm_input.c
++++ b/net/xfrm/xfrm_input.c
+@@ -212,7 +212,7 @@ resume:
+ /* only the first xfrm gets the encap type */
+ encap_type = 0;
+
+- if (async && x->repl->check(x, skb, seq)) {
++ if (async && x->repl->recheck(x, skb, seq)) {
+ XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR);
+ goto drop_unlock;
+ }
+--- a/net/xfrm/xfrm_replay.c
++++ b/net/xfrm/xfrm_replay.c
+@@ -420,6 +420,18 @@ err:
+ return -EINVAL;
+ }
+
++static int xfrm_replay_recheck_esn(struct xfrm_state *x,
++ struct sk_buff *skb, __be32 net_seq)
++{
++ if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi !=
++ htonl(xfrm_replay_seqhi(x, net_seq)))) {
++ x->stats.replay_window++;
++ return -EINVAL;
++ }
++
++ return xfrm_replay_check_esn(x, skb, net_seq);
++}
++
+ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
+ {
+ unsigned int bitnr, nr, i;
+@@ -479,6 +491,7 @@ static void xfrm_replay_advance_esn(stru
+ static struct xfrm_replay xfrm_replay_legacy = {
+ .advance = xfrm_replay_advance,
+ .check = xfrm_replay_check,
++ .recheck = xfrm_replay_check,
+ .notify = xfrm_replay_notify,
+ .overflow = xfrm_replay_overflow,
+ };
+@@ -486,6 +499,7 @@ static struct xfrm_replay xfrm_replay_le
+ static struct xfrm_replay xfrm_replay_bmp = {
+ .advance = xfrm_replay_advance_bmp,
+ .check = xfrm_replay_check_bmp,
++ .recheck = xfrm_replay_check_bmp,
+ .notify = xfrm_replay_notify_bmp,
+ .overflow = xfrm_replay_overflow_bmp,
+ };
+@@ -493,6 +507,7 @@ static struct xfrm_replay xfrm_replay_bm
+ static struct xfrm_replay xfrm_replay_esn = {
+ .advance = xfrm_replay_advance_esn,
+ .check = xfrm_replay_check_esn,
++ .recheck = xfrm_replay_recheck_esn,
+ .notify = xfrm_replay_notify_bmp,
+ .overflow = xfrm_replay_overflow_esn,
+ };
--- /dev/null
+From a265c226015f392507655a57cd6e5acaf4c5b4bf Mon Sep 17 00:00:00 2001
+From: Mathias Krause <minipli@googlemail.com>
+Date: Wed, 19 Sep 2012 11:33:43 +0000
+Subject: xfrm_user: don't copy esn replay window twice for new states
+
+
+From: Mathias Krause <minipli@googlemail.com>
+
+[ Upstream commit e3ac104d41a97b42316915020ba228c505447d21 ]
+
+The ESN replay window was already fully initialized in
+xfrm_alloc_replay_state_esn(). No need to copy it again.
+
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xfrm/xfrm_user.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -442,10 +442,11 @@ static void copy_from_user_state(struct
+ * somehow made shareable and move it to xfrm_state.c - JHS
+ *
+ */
+-static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
++static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
++ int update_esn)
+ {
+ struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
+- struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
++ struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL;
+ struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
+ struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
+ struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
+@@ -555,7 +556,7 @@ static struct xfrm_state *xfrm_state_con
+ goto error;
+
+ /* override default values from above */
+- xfrm_update_ae_params(x, attrs);
++ xfrm_update_ae_params(x, attrs, 0);
+
+ return x;
+
+@@ -1801,7 +1802,7 @@ static int xfrm_new_ae(struct sk_buff *s
+ goto out;
+
+ spin_lock_bh(&x->lock);
+- xfrm_update_ae_params(x, attrs);
++ xfrm_update_ae_params(x, attrs, 1);
+ spin_unlock_bh(&x->lock);
+
+ c.event = nlh->nlmsg_type;
--- /dev/null
+From e1e1bafcb338bd9a4a44a6b1b0e625f5f749658b Mon Sep 17 00:00:00 2001
+From: Mathias Krause <minipli@googlemail.com>
+Date: Thu, 20 Sep 2012 10:01:49 +0000
+Subject: xfrm_user: ensure user supplied esn replay window is valid
+
+
+From: Mathias Krause <minipli@googlemail.com>
+
+[ Upstream commit ecd7918745234e423dd87fcc0c077da557909720 ]
+
+The current code fails to ensure that the netlink message actually
+contains as many bytes as the header indicates. If a user creates a new
+state or updates an existing one but does not supply the bytes for the
+whole ESN replay window, the kernel copies random heap bytes into the
+replay bitmap, the ones happen to follow the XFRMA_REPLAY_ESN_VAL
+netlink attribute. This leads to following issues:
+
+1. The replay window has random bits set confusing the replay handling
+ code later on.
+
+2. A malicious user could use this flaw to leak up to ~3.5kB of heap
+ memory when she has access to the XFRM netlink interface (requires
+ CAP_NET_ADMIN).
+
+Known users of the ESN replay window are strongSwan and Steffen's
+iproute2 patch (<http://patchwork.ozlabs.org/patch/85962/>). The latter
+uses the interface with a bitmap supplied while the former does not.
+strongSwan is therefore prone to run into issue 1.
+
+To fix both issues without breaking existing userland allow using the
+XFRMA_REPLAY_ESN_VAL netlink attribute with either an empty bitmap or a
+fully specified one. For the former case we initialize the in-kernel
+bitmap with zero, for the latter we copy the user supplied bitmap. For
+state updates the full bitmap must be supplied.
+
+To prevent overflows in the bitmap length calculation the maximum size
+of bmp_len is limited to 128 by this patch -- resulting in a maximum
+replay window of 4096 packets. This should be sufficient for all real
+life scenarios (RFC 4303 recommends a default replay window size of 64).
+
+Cc: Steffen Klassert <steffen.klassert@secunet.com>
+Cc: Martin Willi <martin@revosec.ch>
+Cc: Ben Hutchings <bhutchings@solarflare.com>
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/xfrm.h | 2 ++
+ net/xfrm/xfrm_user.c | 31 +++++++++++++++++++++++++------
+ 2 files changed, 27 insertions(+), 6 deletions(-)
+
+--- a/include/linux/xfrm.h
++++ b/include/linux/xfrm.h
+@@ -84,6 +84,8 @@ struct xfrm_replay_state {
+ __u32 bitmap;
+ };
+
++#define XFRMA_REPLAY_ESN_MAX 4096
++
+ struct xfrm_replay_state_esn {
+ unsigned int bmp_len;
+ __u32 oseq;
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -123,9 +123,21 @@ static inline int verify_replay(struct x
+ struct nlattr **attrs)
+ {
+ struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
++ struct xfrm_replay_state_esn *rs;
+
+- if ((p->flags & XFRM_STATE_ESN) && !rt)
+- return -EINVAL;
++ if (p->flags & XFRM_STATE_ESN) {
++ if (!rt)
++ return -EINVAL;
++
++ rs = nla_data(rt);
++
++ if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8)
++ return -EINVAL;
++
++ if (nla_len(rt) < xfrm_replay_state_esn_len(rs) &&
++ nla_len(rt) != sizeof(*rs))
++ return -EINVAL;
++ }
+
+ if (!rt)
+ return 0;
+@@ -370,14 +382,15 @@ static inline int xfrm_replay_verify_len
+ struct nlattr *rp)
+ {
+ struct xfrm_replay_state_esn *up;
++ int ulen;
+
+ if (!replay_esn || !rp)
+ return 0;
+
+ up = nla_data(rp);
++ ulen = xfrm_replay_state_esn_len(up);
+
+- if (xfrm_replay_state_esn_len(replay_esn) !=
+- xfrm_replay_state_esn_len(up))
++ if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
+ return -EINVAL;
+
+ return 0;
+@@ -388,22 +401,28 @@ static int xfrm_alloc_replay_state_esn(s
+ struct nlattr *rta)
+ {
+ struct xfrm_replay_state_esn *p, *pp, *up;
++ int klen, ulen;
+
+ if (!rta)
+ return 0;
+
+ up = nla_data(rta);
++ klen = xfrm_replay_state_esn_len(up);
++ ulen = nla_len(rta) >= klen ? klen : sizeof(*up);
+
+- p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
++ p = kzalloc(klen, GFP_KERNEL);
+ if (!p)
+ return -ENOMEM;
+
+- pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
++ pp = kzalloc(klen, GFP_KERNEL);
+ if (!pp) {
+ kfree(p);
+ return -ENOMEM;
+ }
+
++ memcpy(p, up, ulen);
++ memcpy(pp, up, ulen);
++
+ *replay_esn = p;
+ *preplay_esn = pp;
+
--- /dev/null
+From 56a9ba68b6ed284901636b1be7b12d8017bec5b6 Mon Sep 17 00:00:00 2001
+From: Mathias Krause <minipli@googlemail.com>
+Date: Wed, 19 Sep 2012 11:33:38 +0000
+Subject: xfrm_user: fix info leak in copy_to_user_auth()
+
+
+From: Mathias Krause <minipli@googlemail.com>
+
+[ Upstream commit 4c87308bdea31a7b4828a51f6156e6f721a1fcc9 ]
+
+copy_to_user_auth() fails to initialize the remainder of alg_name and
+therefore discloses up to 54 bytes of heap memory via netlink to
+userland.
+
+Use strncpy() instead of strcpy() to fill the trailing bytes of alg_name
+with null bytes.
+
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xfrm/xfrm_user.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -742,7 +742,7 @@ static int copy_to_user_auth(struct xfrm
+ return -EMSGSIZE;
+
+ algo = nla_data(nla);
+- strcpy(algo->alg_name, auth->alg_name);
++ strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name));
+ memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8);
+ algo->alg_key_len = auth->alg_key_len;
+
--- /dev/null
+From cad2200c059fbfc3eed90f741af389aed3afcb43 Mon Sep 17 00:00:00 2001
+From: Mathias Krause <minipli@googlemail.com>
+Date: Wed, 19 Sep 2012 11:33:40 +0000
+Subject: xfrm_user: fix info leak in copy_to_user_policy()
+
+
+From: Mathias Krause <minipli@googlemail.com>
+
+[ Upstream commit 7b789836f434c87168eab067cfbed1ec4783dffd ]
+
+The memory reserved to dump the xfrm policy includes multiple padding
+bytes added by the compiler for alignment (padding bytes in struct
+xfrm_selector and struct xfrm_userpolicy_info). Add an explicit
+memset(0) before filling the buffer to avoid the heap info leak.
+
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xfrm/xfrm_user.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -1300,6 +1300,7 @@ static void copy_from_user_policy(struct
+
+ static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir)
+ {
++ memset(p, 0, sizeof(*p));
+ memcpy(&p->sel, &xp->selector, sizeof(p->sel));
+ memcpy(&p->lft, &xp->lft, sizeof(p->lft));
+ memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft));
--- /dev/null
+From eadcdb9928c9f3d18ba73bf2b15414c2d8a23633 Mon Sep 17 00:00:00 2001
+From: Mathias Krause <minipli@googlemail.com>
+Date: Wed, 19 Sep 2012 11:33:39 +0000
+Subject: xfrm_user: fix info leak in copy_to_user_state()
+
+
+From: Mathias Krause <minipli@googlemail.com>
+
+[ Upstream commit f778a636713a435d3a922c60b1622a91136560c1 ]
+
+The memory reserved to dump the xfrm state includes the padding bytes of
+struct xfrm_usersa_info added by the compiler for alignment (7 for
+amd64, 3 for i386). Add an explicit memset(0) before filling the buffer
+to avoid the info leak.
+
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xfrm/xfrm_user.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -689,6 +689,7 @@ out:
+
+ static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
+ {
++ memset(p, 0, sizeof(*p));
+ memcpy(&p->id, &x->id, sizeof(p->id));
+ memcpy(&p->sel, &x->sel, sizeof(p->sel));
+ memcpy(&p->lft, &x->lft, sizeof(p->lft));
--- /dev/null
+From 83c45a0a9b36b8f6832a622f7322b638d87a16fa Mon Sep 17 00:00:00 2001
+From: Mathias Krause <minipli@googlemail.com>
+Date: Wed, 19 Sep 2012 11:33:41 +0000
+Subject: xfrm_user: fix info leak in copy_to_user_tmpl()
+
+
+From: Mathias Krause <minipli@googlemail.com>
+
+[ Upstream commit 1f86840f897717f86d523a13e99a447e6a5d2fa5 ]
+
+The memory used for the template copy is a local stack variable. As
+struct xfrm_user_tmpl contains multiple holes added by the compiler for
+alignment, not initializing the memory will lead to leaking stack bytes
+to userland. Add an explicit memset(0) to avoid the info leak.
+
+Initial version of the patch by Brad Spengler.
+
+Cc: Brad Spengler <spender@grsecurity.net>
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xfrm/xfrm_user.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -1405,6 +1405,7 @@ static int copy_to_user_tmpl(struct xfrm
+ struct xfrm_user_tmpl *up = &vec[i];
+ struct xfrm_tmpl *kp = &xp->xfrm_vec[i];
+
++ memset(up, 0, sizeof(*up));
+ memcpy(&up->id, &kp->id, sizeof(up->id));
+ up->family = kp->encap_family;
+ memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr));
--- /dev/null
+From d8b8025a3ed096b73a177fc15af98c49ca39eccf Mon Sep 17 00:00:00 2001
+From: Mathias Krause <minipli@googlemail.com>
+Date: Fri, 14 Sep 2012 09:58:32 +0000
+Subject: xfrm_user: return error pointer instead of NULL #2
+
+
+From: Mathias Krause <minipli@googlemail.com>
+
+[ Upstream commit c25463722509fef0ed630b271576a8c9a70236f3 ]
+
+When dump_one_policy() returns an error, e.g. because of a too small
+buffer to dump the whole xfrm policy, xfrm_policy_netlink() returns
+NULL instead of an error pointer. But its caller expects an error
+pointer and therefore continues to operate on a NULL skbuff.
+
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xfrm/xfrm_user.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -1531,6 +1531,7 @@ static struct sk_buff *xfrm_policy_netli
+ {
+ struct xfrm_dump_info info;
+ struct sk_buff *skb;
++ int err;
+
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!skb)
+@@ -1541,9 +1542,10 @@ static struct sk_buff *xfrm_policy_netli
+ info.nlmsg_seq = seq;
+ info.nlmsg_flags = 0;
+
+- if (dump_one_policy(xp, dir, 0, &info) < 0) {
++ err = dump_one_policy(xp, dir, 0, &info);
++ if (err) {
+ kfree_skb(skb);
+- return NULL;
++ return ERR_PTR(err);
+ }
+
+ return skb;
--- /dev/null
+From 6b8aa091463b9a9fdebd9070bd711a88ad60f44b Mon Sep 17 00:00:00 2001
+From: Mathias Krause <minipli@googlemail.com>
+Date: Thu, 13 Sep 2012 11:41:26 +0000
+Subject: xfrm_user: return error pointer instead of NULL
+
+
+From: Mathias Krause <minipli@googlemail.com>
+
+[ Upstream commit 864745d291b5ba80ea0bd0edcbe67273de368836 ]
+
+When dump_one_state() returns an error, e.g. because of a too small
+buffer to dump the whole xfrm state, xfrm_state_netlink() returns NULL
+instead of an error pointer. But its callers expect an error pointer
+and therefore continue to operate on a NULL skbuff.
+
+This could lead to a privilege escalation (execution of user code in
+kernel context) if the attacker has CAP_NET_ADMIN and is able to map
+address 0.
+
+Signed-off-by: Mathias Krause <minipli@googlemail.com>
+Acked-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/xfrm/xfrm_user.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -862,6 +862,7 @@ static struct sk_buff *xfrm_state_netlin
+ {
+ struct xfrm_dump_info info;
+ struct sk_buff *skb;
++ int err;
+
+ skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
+ if (!skb)
+@@ -872,9 +873,10 @@ static struct sk_buff *xfrm_state_netlin
+ info.nlmsg_seq = seq;
+ info.nlmsg_flags = 0;
+
+- if (dump_one_state(x, 0, &info)) {
++ err = dump_one_state(x, 0, &info);
++ if (err) {
+ kfree_skb(skb);
+- return NULL;
++ return ERR_PTR(err);
+ }
+
+ return skb;