]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 20 Nov 2012 18:49:06 +0000 (10:49 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 20 Nov 2012 18:49:06 +0000 (10:49 -0800)
added patches:
ipv4-avoid-undefined-behavior-in-do_ip_setsockopt.patch
ipv4-ip_vti.c-vti-fix-post-decryption-forwarding.patch
ipv6-setsockopt-ipipproto_ipv6-ipv6_minhopcount-forgot-to-set-return-value.patch
net-correct-check-in-dev_addr_del.patch
net-rps-fix-brokeness-causing-ooo-packets.patch
sctp-fix-proc-net-sctp-memory-leak.patch
tcp-fix-retransmission-in-repair-mode.patch
tcp-handle-tcp_net_metrics_init-order-5-memory-allocation-failures.patch

queue-3.6/ipv4-avoid-undefined-behavior-in-do_ip_setsockopt.patch [new file with mode: 0644]
queue-3.6/ipv4-ip_vti.c-vti-fix-post-decryption-forwarding.patch [new file with mode: 0644]
queue-3.6/ipv6-setsockopt-ipipproto_ipv6-ipv6_minhopcount-forgot-to-set-return-value.patch [new file with mode: 0644]
queue-3.6/net-correct-check-in-dev_addr_del.patch [new file with mode: 0644]
queue-3.6/net-rps-fix-brokeness-causing-ooo-packets.patch [new file with mode: 0644]
queue-3.6/sctp-fix-proc-net-sctp-memory-leak.patch [new file with mode: 0644]
queue-3.6/series
queue-3.6/tcp-fix-retransmission-in-repair-mode.patch [new file with mode: 0644]
queue-3.6/tcp-handle-tcp_net_metrics_init-order-5-memory-allocation-failures.patch [new file with mode: 0644]

diff --git a/queue-3.6/ipv4-avoid-undefined-behavior-in-do_ip_setsockopt.patch b/queue-3.6/ipv4-avoid-undefined-behavior-in-do_ip_setsockopt.patch
new file mode 100644 (file)
index 0000000..df58f73
--- /dev/null
@@ -0,0 +1,69 @@
+From 2a7ee5c346a18a46f119a455e0f3116bd7d8a476 Mon Sep 17 00:00:00 2001
+From: Xi Wang <xi.wang@gmail.com>
+Date: Sun, 11 Nov 2012 11:20:01 +0000
+Subject: ipv4: avoid undefined behavior in do_ip_setsockopt()
+
+
+From: Xi Wang <xi.wang@gmail.com>
+
+[ Upstream commit 0c9f79be295c99ac7e4b569ca493d75fdcc19e4e ]
+
+(1<<optname) is undefined behavior in C with a negative optname or
+optname larger than 31.  In those cases the result of the shift is
+not necessarily zero (e.g., on x86).
+
+This patch simplifies the code with a switch statement on optname.
+It also allows the compiler to generate better code (e.g., using a
+64-bit mask).
+
+Signed-off-by: Xi Wang <xi.wang@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ip_sockglue.c |   35 ++++++++++++++++++++++-------------
+ 1 file changed, 22 insertions(+), 13 deletions(-)
+
+--- a/net/ipv4/ip_sockglue.c
++++ b/net/ipv4/ip_sockglue.c
+@@ -457,19 +457,28 @@ static int do_ip_setsockopt(struct sock
+       struct inet_sock *inet = inet_sk(sk);
+       int val = 0, err;
+-      if (((1<<optname) & ((1<<IP_PKTINFO) | (1<<IP_RECVTTL) |
+-                           (1<<IP_RECVOPTS) | (1<<IP_RECVTOS) |
+-                           (1<<IP_RETOPTS) | (1<<IP_TOS) |
+-                           (1<<IP_TTL) | (1<<IP_HDRINCL) |
+-                           (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
+-                           (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
+-                           (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT) |
+-                           (1<<IP_MINTTL) | (1<<IP_NODEFRAG))) ||
+-          optname == IP_UNICAST_IF ||
+-          optname == IP_MULTICAST_TTL ||
+-          optname == IP_MULTICAST_ALL ||
+-          optname == IP_MULTICAST_LOOP ||
+-          optname == IP_RECVORIGDSTADDR) {
++      switch (optname) {
++      case IP_PKTINFO:
++      case IP_RECVTTL:
++      case IP_RECVOPTS:
++      case IP_RECVTOS:
++      case IP_RETOPTS:
++      case IP_TOS:
++      case IP_TTL:
++      case IP_HDRINCL:
++      case IP_MTU_DISCOVER:
++      case IP_RECVERR:
++      case IP_ROUTER_ALERT:
++      case IP_FREEBIND:
++      case IP_PASSSEC:
++      case IP_TRANSPARENT:
++      case IP_MINTTL:
++      case IP_NODEFRAG:
++      case IP_UNICAST_IF:
++      case IP_MULTICAST_TTL:
++      case IP_MULTICAST_ALL:
++      case IP_MULTICAST_LOOP:
++      case IP_RECVORIGDSTADDR:
+               if (optlen >= sizeof(int)) {
+                       if (get_user(val, (int __user *) optval))
+                               return -EFAULT;
diff --git a/queue-3.6/ipv4-ip_vti.c-vti-fix-post-decryption-forwarding.patch b/queue-3.6/ipv4-ip_vti.c-vti-fix-post-decryption-forwarding.patch
new file mode 100644 (file)
index 0000000..22de805
--- /dev/null
@@ -0,0 +1,49 @@
+From e031b84387a863855999d681f922fd7094c76009 Mon Sep 17 00:00:00 2001
+From: Saurabh Mohan <saurabh.mohan@vyatta.com>
+Date: Wed, 14 Nov 2012 18:08:15 -0800
+Subject: ipv4/ip_vti.c: VTI fix post-decryption forwarding
+
+
+From: Saurabh Mohan <saurabh.mohan@vyatta.com>
+
+[ Upstream commit b2942004fb5c9f3304b77e187b8a1977b3626c9b ]
+
+With the latest kernel there are two things that must be done post decryption
+ so that the packet are forwarded.
+ 1. Remove the mark from the packet. This will cause the packet to not match
+ the ipsec-policy again. However doing this causes the post-decryption check to
+ fail also and the packet will get dropped. (cat /proc/net/xfrm_stat).
+ 2. Remove the sp association in the skbuff so that no policy check is done on
+ the packet for VTI tunnels.
+
+Due to #2 above we must now do a security-policy check in the vti rcv path
+prior to resetting the mark in the skbuff.
+
+Signed-off-by: Saurabh Mohan <saurabh.mohan@vyatta.com>
+Reported-by: Ruben Herold <ruben@puettmann.net>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/ip_vti.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/net/ipv4/ip_vti.c
++++ b/net/ipv4/ip_vti.c
+@@ -341,12 +341,17 @@ static int vti_rcv(struct sk_buff *skb)
+       if (tunnel != NULL) {
+               struct pcpu_tstats *tstats;
++              if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
++                      return -1;
++
+               tstats = this_cpu_ptr(tunnel->dev->tstats);
+               u64_stats_update_begin(&tstats->syncp);
+               tstats->rx_packets++;
+               tstats->rx_bytes += skb->len;
+               u64_stats_update_end(&tstats->syncp);
++              skb->mark = 0;
++              secpath_reset(skb);
+               skb->dev = tunnel->dev;
+               rcu_read_unlock();
+               return 1;
diff --git a/queue-3.6/ipv6-setsockopt-ipipproto_ipv6-ipv6_minhopcount-forgot-to-set-return-value.patch b/queue-3.6/ipv6-setsockopt-ipipproto_ipv6-ipv6_minhopcount-forgot-to-set-return-value.patch
new file mode 100644 (file)
index 0000000..ef7dcc1
--- /dev/null
@@ -0,0 +1,28 @@
+From 513a4430184bb9f058832c9b462037737d9c33b9 Mon Sep 17 00:00:00 2001
+From: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Date: Sat, 10 Nov 2012 19:52:34 +0000
+Subject: ipv6: setsockopt(IPIPPROTO_IPV6, IPV6_MINHOPCOUNT) forgot to set return value
+
+
+From: Hannes Frederic Sowa <hannes@stressinduktion.org>
+
+[ Upstream commit d4596bad2a713fcd0def492b1960e6d899d5baa8 ]
+
+Cc: Stephen Hemminger <shemminger@vyatta.com>
+Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/ipv6_sockglue.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/net/ipv6/ipv6_sockglue.c
++++ b/net/ipv6/ipv6_sockglue.c
+@@ -827,6 +827,7 @@ pref_skip_coa:
+               if (val < 0 || val > 255)
+                       goto e_inval;
+               np->min_hopcount = val;
++              retv = 0;
+               break;
+       case IPV6_DONTFRAG:
+               np->dontfrag = valbool;
diff --git a/queue-3.6/net-correct-check-in-dev_addr_del.patch b/queue-3.6/net-correct-check-in-dev_addr_del.patch
new file mode 100644 (file)
index 0000000..27784c1
--- /dev/null
@@ -0,0 +1,32 @@
+From 3e168a2aebeef824b7de16af9914a41bb43a7a7e Mon Sep 17 00:00:00 2001
+From: Jiri Pirko <jiri@resnulli.us>
+Date: Wed, 14 Nov 2012 02:51:04 +0000
+Subject: net: correct check in dev_addr_del()
+
+
+From: Jiri Pirko <jiri@resnulli.us>
+
+[ Upstream commit a652208e0b52c190e57f2a075ffb5e897fe31c3b ]
+
+Check (ha->addr == dev->dev_addr) is always true because dev_addr_init()
+sets this. Correct the check to behave properly on addr removal.
+
+Signed-off-by: Jiri Pirko <jiri@resnulli.us>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/dev_addr_lists.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/core/dev_addr_lists.c
++++ b/net/core/dev_addr_lists.c
+@@ -317,7 +317,8 @@ int dev_addr_del(struct net_device *dev,
+        */
+       ha = list_first_entry(&dev->dev_addrs.list,
+                             struct netdev_hw_addr, list);
+-      if (ha->addr == dev->dev_addr && ha->refcount == 1)
++      if (!memcmp(ha->addr, addr, dev->addr_len) &&
++          ha->type == addr_type && ha->refcount == 1)
+               return -ENOENT;
+       err = __hw_addr_del(&dev->dev_addrs, addr, dev->addr_len,
diff --git a/queue-3.6/net-rps-fix-brokeness-causing-ooo-packets.patch b/queue-3.6/net-rps-fix-brokeness-causing-ooo-packets.patch
new file mode 100644 (file)
index 0000000..7eac936
--- /dev/null
@@ -0,0 +1,37 @@
+From 5e26fb0e61c630f44d4cdd09e5c190647e4aa0f3 Mon Sep 17 00:00:00 2001
+From: Tom Herbert <therbert@google.com>
+Date: Fri, 16 Nov 2012 09:04:15 +0000
+Subject: net-rps: Fix brokeness causing OOO packets
+
+
+From: Tom Herbert <therbert@google.com>
+
+[ Upstream commit baefa31db2f2b13a05d1b81bdf2d20d487f58b0a ]
+
+In commit c445477d74ab3779 which adds aRFS to the kernel, the CPU
+selected for RFS is not set correctly when CPU is changing.
+This is causing OOO packets and probably other issues.
+
+Signed-off-by: Tom Herbert <therbert@google.com>
+Acked-by: Eric Dumazet <edumazet@google.com>
+Acked-by: Ben Hutchings <bhutchings@solarflare.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/core/dev.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/net/core/dev.c
++++ b/net/core/dev.c
+@@ -2793,8 +2793,10 @@ static int get_rps_cpu(struct net_device
+               if (unlikely(tcpu != next_cpu) &&
+                   (tcpu == RPS_NO_CPU || !cpu_online(tcpu) ||
+                    ((int)(per_cpu(softnet_data, tcpu).input_queue_head -
+-                    rflow->last_qtail)) >= 0))
++                    rflow->last_qtail)) >= 0)) {
++                      tcpu = next_cpu;
+                       rflow = set_rps_cpu(dev, skb, rflow, next_cpu);
++              }
+               if (tcpu != RPS_NO_CPU && cpu_online(tcpu)) {
+                       *rflowp = rflow;
diff --git a/queue-3.6/sctp-fix-proc-net-sctp-memory-leak.patch b/queue-3.6/sctp-fix-proc-net-sctp-memory-leak.patch
new file mode 100644 (file)
index 0000000..95a56bc
--- /dev/null
@@ -0,0 +1,66 @@
+From 92732269096b1737ebb14b5cd98c1721fd5cbc15 Mon Sep 17 00:00:00 2001
+From: Tommi Rantala <tt.rantala@gmail.com>
+Date: Thu, 15 Nov 2012 03:49:05 +0000
+Subject: sctp: fix /proc/net/sctp/ memory leak
+
+
+From: Tommi Rantala <tt.rantala@gmail.com>
+
+[ Upstream commit 0da9a0c2638c8476b4a5021841912f249e3187dc ]
+
+Commit 13d782f ("sctp: Make the proc files per network namespace.")
+changed the /proc/net/sctp/ struct file_operations opener functions to
+use single_open_net() and seq_open_net().
+
+Avoid leaking memory by using single_release_net() and seq_release_net()
+as the release functions.
+
+Discovered with Trinity (the syscall fuzzer).
+
+Signed-off-by: Tommi Rantala <tt.rantala@gmail.com>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Cc: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/sctp/proc.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/net/sctp/proc.c
++++ b/net/sctp/proc.c
+@@ -101,7 +101,7 @@ static const struct file_operations sctp
+       .open    = sctp_snmp_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+-      .release = single_release,
++      .release = single_release_net,
+ };
+ /* Set up the proc fs entry for 'snmp' object. */
+@@ -245,7 +245,7 @@ static const struct file_operations sctp
+       .open    = sctp_eps_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+-      .release = seq_release,
++      .release = seq_release_net,
+ };
+ /* Set up the proc fs entry for 'eps' object. */
+@@ -361,7 +361,7 @@ static const struct file_operations sctp
+       .open    = sctp_assocs_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+-      .release = seq_release,
++      .release = seq_release_net,
+ };
+ /* Set up the proc fs entry for 'assocs' object. */
+@@ -503,7 +503,7 @@ static const struct file_operations sctp
+       .open = sctp_remaddr_seq_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+-      .release = seq_release,
++      .release = seq_release_net,
+ };
+ int __init sctp_remaddr_proc_init(void)
index 135519fc1c8a92a21b795508878bb712e1def77f..41f59938defd58c9e2ee9f720f66f70dd876ce2a 100644 (file)
@@ -29,3 +29,11 @@ asoc-dapm-use-card_list-during-dapm-shutdown.patch
 asoc-core-double-control-update-err-for-snd_soc_put_volsw_sx.patch
 ubifs-fix-mounting-problems-after-power-cuts.patch
 ubifs-introduce-categorized-lprops-counter.patch
+ipv4-avoid-undefined-behavior-in-do_ip_setsockopt.patch
+ipv4-ip_vti.c-vti-fix-post-decryption-forwarding.patch
+ipv6-setsockopt-ipipproto_ipv6-ipv6_minhopcount-forgot-to-set-return-value.patch
+net-correct-check-in-dev_addr_del.patch
+net-rps-fix-brokeness-causing-ooo-packets.patch
+sctp-fix-proc-net-sctp-memory-leak.patch
+tcp-fix-retransmission-in-repair-mode.patch
+tcp-handle-tcp_net_metrics_init-order-5-memory-allocation-failures.patch
diff --git a/queue-3.6/tcp-fix-retransmission-in-repair-mode.patch b/queue-3.6/tcp-fix-retransmission-in-repair-mode.patch
new file mode 100644 (file)
index 0000000..2d4347f
--- /dev/null
@@ -0,0 +1,84 @@
+From 9e6a7cc684ebf922e7e402c4972e6f8ea1dfa0aa Mon Sep 17 00:00:00 2001
+From: Andrew Vagin <avagin@openvz.org>
+Date: Thu, 15 Nov 2012 04:03:17 +0000
+Subject: tcp: fix retransmission in repair mode
+
+
+From: Andrew Vagin <avagin@openvz.org>
+
+[ Upstream commit ec34232575083fd0f43d3a101e8ebb041b203761 ]
+
+Currently if a socket was repaired with a few packet in a write queue,
+a kernel bug may be triggered:
+
+kernel BUG at net/ipv4/tcp_output.c:2330!
+RIP: 0010:[<ffffffff8155784f>] tcp_retransmit_skb+0x5ff/0x610
+
+According to the initial realization v3.4-rc2-963-gc0e88ff,
+all skb-s should look like already posted. This patch fixes code
+according with this sentence.
+
+Here are three points, which were not done in the initial patch:
+1. A tcp send head should not be changed
+2. Initialize TSO state of a skb
+3. Reset the retransmission time
+
+This patch moves logic from tcp_sendmsg to tcp_write_xmit. A packet
+passes the ussual way, but isn't sent to network. This patch solves
+all described problems and handles tcp_sendpages.
+
+Cc: Pavel Emelyanov <xemul@parallels.com>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
+Cc: James Morris <jmorris@namei.org>
+Cc: Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
+Cc: Patrick McHardy <kaber@trash.net>
+Signed-off-by: Andrey Vagin <avagin@openvz.org>
+Acked-by: Pavel Emelyanov <xemul@parallels.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/tcp.c        |    4 ++--
+ net/ipv4/tcp_output.c |    4 ++++
+ 2 files changed, 6 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/tcp.c
++++ b/net/ipv4/tcp.c
+@@ -1236,7 +1236,7 @@ new_segment:
+ wait_for_sndbuf:
+                       set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+ wait_for_memory:
+-                      if (copied && likely(!tp->repair))
++                      if (copied)
+                               tcp_push(sk, flags & ~MSG_MORE, mss_now, TCP_NAGLE_PUSH);
+                       if ((err = sk_stream_wait_memory(sk, &timeo)) != 0)
+@@ -1247,7 +1247,7 @@ wait_for_memory:
+       }
+ out:
+-      if (copied && likely(!tp->repair))
++      if (copied)
+               tcp_push(sk, flags, mss_now, tp->nonagle);
+       release_sock(sk);
+       return copied + copied_syn;
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -1977,6 +1977,9 @@ static bool tcp_write_xmit(struct sock *
+               tso_segs = tcp_init_tso_segs(sk, skb, mss_now);
+               BUG_ON(!tso_segs);
++              if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE)
++                      goto repair; /* Skip network transmission */
++
+               cwnd_quota = tcp_cwnd_test(tp, skb);
+               if (!cwnd_quota)
+                       break;
+@@ -2017,6 +2020,7 @@ static bool tcp_write_xmit(struct sock *
+               if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
+                       break;
++repair:
+               /* Advance the send_head.  This one is sent out.
+                * This call will increment packets_out.
+                */
diff --git a/queue-3.6/tcp-handle-tcp_net_metrics_init-order-5-memory-allocation-failures.patch b/queue-3.6/tcp-handle-tcp_net_metrics_init-order-5-memory-allocation-failures.patch
new file mode 100644 (file)
index 0000000..c4b4575
--- /dev/null
@@ -0,0 +1,62 @@
+From e7510275aa8b8ff6bda0ff3cd9461a7bf461aa3d Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Fri, 16 Nov 2012 05:31:53 +0000
+Subject: tcp: handle tcp_net_metrics_init() order-5 memory allocation failures
+
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+[ Upstream commit 976a702ac9eeacea09e588456ab165dc06f9ee83 ]
+
+order-5 allocations can fail with current kernels, we should
+try vmalloc() as well.
+
+Reported-by: Julien Tinnes <jln@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/ipv4/tcp_metrics.c |   12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+--- a/net/ipv4/tcp_metrics.c
++++ b/net/ipv4/tcp_metrics.c
+@@ -1,13 +1,13 @@
+ #include <linux/rcupdate.h>
+ #include <linux/spinlock.h>
+ #include <linux/jiffies.h>
+-#include <linux/bootmem.h>
+ #include <linux/module.h>
+ #include <linux/cache.h>
+ #include <linux/slab.h>
+ #include <linux/init.h>
+ #include <linux/tcp.h>
+ #include <linux/hash.h>
++#include <linux/vmalloc.h>
+ #include <net/inet_connection_sock.h>
+ #include <net/net_namespace.h>
+@@ -722,7 +722,10 @@ static int __net_init tcp_net_metrics_in
+       net->ipv4.tcp_metrics_hash_log = order_base_2(slots);
+       size = sizeof(struct tcpm_hash_bucket) << net->ipv4.tcp_metrics_hash_log;
+-      net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL);
++      net->ipv4.tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
++      if (!net->ipv4.tcp_metrics_hash)
++              net->ipv4.tcp_metrics_hash = vzalloc(size);
++
+       if (!net->ipv4.tcp_metrics_hash)
+               return -ENOMEM;
+@@ -743,7 +746,10 @@ static void __net_exit tcp_net_metrics_e
+                       tm = next;
+               }
+       }
+-      kfree(net->ipv4.tcp_metrics_hash);
++      if (is_vmalloc_addr(net->ipv4.tcp_metrics_hash))
++              vfree(net->ipv4.tcp_metrics_hash);
++      else
++              kfree(net->ipv4.tcp_metrics_hash);
+ }
+ static __net_initdata struct pernet_operations tcp_net_metrics_ops = {