]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 Nov 2020 09:40:00 +0000 (10:40 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 Nov 2020 09:40:00 +0000 (10:40 +0100)
added patches:
ipv6-set-sit-tunnel-hard_header_len-to-zero.patch
net-af_iucv-fix-null-pointer-dereference-on-shutdown.patch
net-update-window_clamp-if-sock_rcvbuf-is-set.patch
net-x25-fix-null-ptr-deref-in-x25_connect.patch
r8169-fix-potential-skb-double-free-in-an-error-path.patch
vrf-fix-fast-path-output-packet-handling-with-async-netfilter-rules.patch

queue-4.14/btrfs-fix-potential-overflow-in-cluster_pages_for_defrag-on-32bit-arch.patch [deleted file]
queue-4.14/ipv6-set-sit-tunnel-hard_header_len-to-zero.patch [new file with mode: 0644]
queue-4.14/net-af_iucv-fix-null-pointer-dereference-on-shutdown.patch [new file with mode: 0644]
queue-4.14/net-update-window_clamp-if-sock_rcvbuf-is-set.patch [new file with mode: 0644]
queue-4.14/net-x25-fix-null-ptr-deref-in-x25_connect.patch [new file with mode: 0644]
queue-4.14/r8169-fix-potential-skb-double-free-in-an-error-path.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/vrf-fix-fast-path-output-packet-handling-with-async-netfilter-rules.patch [new file with mode: 0644]

diff --git a/queue-4.14/btrfs-fix-potential-overflow-in-cluster_pages_for_defrag-on-32bit-arch.patch b/queue-4.14/btrfs-fix-potential-overflow-in-cluster_pages_for_defrag-on-32bit-arch.patch
deleted file mode 100644 (file)
index c1b5c37..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-From a1fbc6750e212c5675a4e48d7f51d44607eb8756 Mon Sep 17 00:00:00 2001
-From: "Matthew Wilcox (Oracle)" <willy@infradead.org>
-Date: Sun, 4 Oct 2020 19:04:26 +0100
-Subject: btrfs: fix potential overflow in cluster_pages_for_defrag on 32bit arch
-
-From: Matthew Wilcox (Oracle) <willy@infradead.org>
-
-commit a1fbc6750e212c5675a4e48d7f51d44607eb8756 upstream.
-
-On 32-bit systems, this shift will overflow for files larger than 4GB as
-start_index is unsigned long while the calls to btrfs_delalloc_*_space
-expect u64.
-
-CC: stable@vger.kernel.org # 4.4+
-Fixes: df480633b891 ("btrfs: extent-tree: Switch to new delalloc space reserve and release")
-Reviewed-by: Josef Bacik <josef@toxicpanda.com>
-Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
-Reviewed-by: David Sterba <dsterba@suse.com>
-[ define the variable instead of repeating the shift ]
-Signed-off-by: David Sterba <dsterba@suse.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-
-
-
-diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
-index 63394b450afc..4e3b71ec7492 100644
---- a/fs/btrfs/ioctl.c
-+++ b/fs/btrfs/ioctl.c
-@@ -1255,6 +1255,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
-       u64 page_start;
-       u64 page_end;
-       u64 page_cnt;
-+      u64 start = (u64)start_index << PAGE_SHIFT;
-       int ret;
-       int i;
-       int i_done;
-@@ -1271,8 +1272,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
-       page_cnt = min_t(u64, (u64)num_pages, (u64)file_end - start_index + 1);
-       ret = btrfs_delalloc_reserve_space(inode, &data_reserved,
--                      start_index << PAGE_SHIFT,
--                      page_cnt << PAGE_SHIFT);
-+                      start, page_cnt << PAGE_SHIFT);
-       if (ret)
-               return ret;
-       i_done = 0;
-@@ -1361,8 +1361,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
-               btrfs_mod_outstanding_extents(BTRFS_I(inode), 1);
-               spin_unlock(&BTRFS_I(inode)->lock);
-               btrfs_delalloc_release_space(inode, data_reserved,
--                              start_index << PAGE_SHIFT,
--                              (page_cnt - i_done) << PAGE_SHIFT, true);
-+                              start, (page_cnt - i_done) << PAGE_SHIFT, true);
-       }
-@@ -1389,8 +1388,7 @@ static int cluster_pages_for_defrag(struct inode *inode,
-               put_page(pages[i]);
-       }
-       btrfs_delalloc_release_space(inode, data_reserved,
--                      start_index << PAGE_SHIFT,
--                      page_cnt << PAGE_SHIFT, true);
-+                      start, page_cnt << PAGE_SHIFT, true);
-       btrfs_delalloc_release_extents(BTRFS_I(inode), page_cnt << PAGE_SHIFT);
-       extent_changeset_free(data_reserved);
-       return ret;
diff --git a/queue-4.14/ipv6-set-sit-tunnel-hard_header_len-to-zero.patch b/queue-4.14/ipv6-set-sit-tunnel-hard_header_len-to-zero.patch
new file mode 100644 (file)
index 0000000..b3e73a7
--- /dev/null
@@ -0,0 +1,52 @@
+From foo@baz Tue Nov 17 10:36:22 AM CET 2020
+From: Oliver Herms <oliver.peter.herms@gmail.com>
+Date: Tue, 3 Nov 2020 11:41:33 +0100
+Subject: IPv6: Set SIT tunnel hard_header_len to zero
+
+From: Oliver Herms <oliver.peter.herms@gmail.com>
+
+[ Upstream commit 8ef9ba4d666614497a057d09b0a6eafc1e34eadf ]
+
+Due to the legacy usage of hard_header_len for SIT tunnels while
+already using infrastructure from net/ipv4/ip_tunnel.c the
+calculation of the path MTU in tnl_update_pmtu is incorrect.
+This leads to unnecessary creation of MTU exceptions for any
+flow going over a SIT tunnel.
+
+As SIT tunnels do not have a header themsevles other than their
+transport (L3, L2) headers we're leaving hard_header_len set to zero
+as tnl_update_pmtu is already taking care of the transport headers
+sizes.
+
+This will also help avoiding unnecessary IPv6 GC runs and spinlock
+contention seen when using SIT tunnels and for more than
+net.ipv6.route.gc_thresh flows.
+
+Fixes: c54419321455 ("GRE: Refactor GRE tunneling code.")
+Signed-off-by: Oliver Herms <oliver.peter.herms@gmail.com>
+Acked-by: Willem de Bruijn <willemb@google.com>
+Link: https://lore.kernel.org/r/20201103104133.GA1573211@tws
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv6/sit.c |    2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/net/ipv6/sit.c
++++ b/net/ipv6/sit.c
+@@ -1073,7 +1073,6 @@ static void ipip6_tunnel_bind_dev(struct
+       if (tdev && !netif_is_l3_master(tdev)) {
+               int t_hlen = tunnel->hlen + sizeof(struct iphdr);
+-              dev->hard_header_len = tdev->hard_header_len + sizeof(struct iphdr);
+               dev->mtu = tdev->mtu - t_hlen;
+               if (dev->mtu < IPV6_MIN_MTU)
+                       dev->mtu = IPV6_MIN_MTU;
+@@ -1363,7 +1362,6 @@ static void ipip6_tunnel_setup(struct ne
+       dev->priv_destructor    = ipip6_dev_free;
+       dev->type               = ARPHRD_SIT;
+-      dev->hard_header_len    = LL_MAX_HEADER + t_hlen;
+       dev->mtu                = ETH_DATA_LEN - t_hlen;
+       dev->min_mtu            = IPV6_MIN_MTU;
+       dev->max_mtu            = IP6_MAX_MTU - t_hlen;
diff --git a/queue-4.14/net-af_iucv-fix-null-pointer-dereference-on-shutdown.patch b/queue-4.14/net-af_iucv-fix-null-pointer-dereference-on-shutdown.patch
new file mode 100644 (file)
index 0000000..c27943e
--- /dev/null
@@ -0,0 +1,61 @@
+From foo@baz Tue Nov 17 10:36:22 AM CET 2020
+From: Ursula Braun <ubraun@linux.ibm.com>
+Date: Mon, 9 Nov 2020 08:57:05 +0100
+Subject: net/af_iucv: fix null pointer dereference on shutdown
+
+From: Ursula Braun <ubraun@linux.ibm.com>
+
+[ Upstream commit 4031eeafa71eaf22ae40a15606a134ae86345daf ]
+
+syzbot reported the following KASAN finding:
+
+BUG: KASAN: nullptr-dereference in iucv_send_ctrl+0x390/0x3f0 net/iucv/af_iucv.c:385
+Read of size 2 at addr 000000000000021e by task syz-executor907/519
+
+CPU: 0 PID: 519 Comm: syz-executor907 Not tainted 5.9.0-syzkaller-07043-gbcf9877ad213 #0
+Hardware name: IBM 3906 M04 701 (KVM/Linux)
+Call Trace:
+ [<00000000c576af60>] unwind_start arch/s390/include/asm/unwind.h:65 [inline]
+ [<00000000c576af60>] show_stack+0x180/0x228 arch/s390/kernel/dumpstack.c:135
+ [<00000000c9dcd1f8>] __dump_stack lib/dump_stack.c:77 [inline]
+ [<00000000c9dcd1f8>] dump_stack+0x268/0x2f0 lib/dump_stack.c:118
+ [<00000000c5fed016>] print_address_description.constprop.0+0x5e/0x218 mm/kasan/report.c:383
+ [<00000000c5fec82a>] __kasan_report mm/kasan/report.c:517 [inline]
+ [<00000000c5fec82a>] kasan_report+0x11a/0x168 mm/kasan/report.c:534
+ [<00000000c98b5b60>] iucv_send_ctrl+0x390/0x3f0 net/iucv/af_iucv.c:385
+ [<00000000c98b6262>] iucv_sock_shutdown+0x44a/0x4c0 net/iucv/af_iucv.c:1457
+ [<00000000c89d3a54>] __sys_shutdown+0x12c/0x1c8 net/socket.c:2204
+ [<00000000c89d3b70>] __do_sys_shutdown net/socket.c:2212 [inline]
+ [<00000000c89d3b70>] __s390x_sys_shutdown+0x38/0x48 net/socket.c:2210
+ [<00000000c9e36eac>] system_call+0xe0/0x28c arch/s390/kernel/entry.S:415
+
+There is nothing to shutdown if a connection has never been established.
+Besides that iucv->hs_dev is not yet initialized if a socket is in
+IUCV_OPEN state and iucv->path is not yet initialized if socket is in
+IUCV_BOUND state.
+So, just skip the shutdown calls for a socket in these states.
+
+Fixes: eac3731bd04c ("[S390]: Add AF_IUCV socket support")
+Fixes: 82492a355fac ("af_iucv: add shutdown for HS transport")
+Reviewed-by: Vasily Gorbik <gor@linux.ibm.com>
+Signed-off-by: Ursula Braun <ubraun@linux.ibm.com>
+[jwi: correct one Fixes tag]
+Signed-off-by: Julian Wiedmann <jwi@linux.ibm.com>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/iucv/af_iucv.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/iucv/af_iucv.c
++++ b/net/iucv/af_iucv.c
+@@ -1552,7 +1552,8 @@ static int iucv_sock_shutdown(struct soc
+               break;
+       }
+-      if (how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) {
++      if ((how == SEND_SHUTDOWN || how == SHUTDOWN_MASK) &&
++          sk->sk_state == IUCV_CONNECTED) {
+               if (iucv->transport == AF_IUCV_TRANS_IUCV) {
+                       txmsg.class = 0;
+                       txmsg.tag = 0;
diff --git a/queue-4.14/net-update-window_clamp-if-sock_rcvbuf-is-set.patch b/queue-4.14/net-update-window_clamp-if-sock_rcvbuf-is-set.patch
new file mode 100644 (file)
index 0000000..86b7ca8
--- /dev/null
@@ -0,0 +1,82 @@
+From foo@baz Tue Nov 17 10:36:22 AM CET 2020
+From: Mao Wenan <wenan.mao@linux.alibaba.com>
+Date: Tue, 10 Nov 2020 08:16:31 +0800
+Subject: net: Update window_clamp if SOCK_RCVBUF is set
+
+From: Mao Wenan <wenan.mao@linux.alibaba.com>
+
+[ Upstream commit 909172a149749242990a6e64cb55d55460d4e417 ]
+
+When net.ipv4.tcp_syncookies=1 and syn flood is happened,
+cookie_v4_check or cookie_v6_check tries to redo what
+tcp_v4_send_synack or tcp_v6_send_synack did,
+rsk_window_clamp will be changed if SOCK_RCVBUF is set,
+which will make rcv_wscale is different, the client
+still operates with initial window scale and can overshot
+granted window, the client use the initial scale but local
+server use new scale to advertise window value, and session
+work abnormally.
+
+Fixes: e88c64f0a425 ("tcp: allow effective reduction of TCP's rcv-buffer via setsockopt")
+Signed-off-by: Mao Wenan <wenan.mao@linux.alibaba.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Link: https://lore.kernel.org/r/1604967391-123737-1-git-send-email-wenan.mao@linux.alibaba.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/ipv4/syncookies.c |    9 +++++++--
+ net/ipv6/syncookies.c |   10 ++++++++--
+ 2 files changed, 15 insertions(+), 4 deletions(-)
+
+--- a/net/ipv4/syncookies.c
++++ b/net/ipv4/syncookies.c
+@@ -296,7 +296,7 @@ struct sock *cookie_v4_check(struct sock
+       __u32 cookie = ntohl(th->ack_seq) - 1;
+       struct sock *ret = sk;
+       struct request_sock *req;
+-      int mss;
++      int full_space, mss;
+       struct rtable *rt;
+       __u8 rcv_wscale;
+       struct flowi4 fl4;
+@@ -389,8 +389,13 @@ struct sock *cookie_v4_check(struct sock
+       /* Try to redo what tcp_v4_send_synack did. */
+       req->rsk_window_clamp = tp->window_clamp ? :dst_metric(&rt->dst, RTAX_WINDOW);
++      /* limit the window selection if the user enforce a smaller rx buffer */
++      full_space = tcp_full_space(sk);
++      if (sk->sk_userlocks & SOCK_RCVBUF_LOCK &&
++          (req->rsk_window_clamp > full_space || req->rsk_window_clamp == 0))
++              req->rsk_window_clamp = full_space;
+-      tcp_select_initial_window(tcp_full_space(sk), req->mss,
++      tcp_select_initial_window(full_space, req->mss,
+                                 &req->rsk_rcv_wnd, &req->rsk_window_clamp,
+                                 ireq->wscale_ok, &rcv_wscale,
+                                 dst_metric(&rt->dst, RTAX_INITRWND));
+--- a/net/ipv6/syncookies.c
++++ b/net/ipv6/syncookies.c
+@@ -141,7 +141,7 @@ struct sock *cookie_v6_check(struct sock
+       __u32 cookie = ntohl(th->ack_seq) - 1;
+       struct sock *ret = sk;
+       struct request_sock *req;
+-      int mss;
++      int full_space, mss;
+       struct dst_entry *dst;
+       __u8 rcv_wscale;
+       u32 tsoff = 0;
+@@ -244,7 +244,13 @@ struct sock *cookie_v6_check(struct sock
+       }
+       req->rsk_window_clamp = tp->window_clamp ? :dst_metric(dst, RTAX_WINDOW);
+-      tcp_select_initial_window(tcp_full_space(sk), req->mss,
++      /* limit the window selection if the user enforce a smaller rx buffer */
++      full_space = tcp_full_space(sk);
++      if (sk->sk_userlocks & SOCK_RCVBUF_LOCK &&
++          (req->rsk_window_clamp > full_space || req->rsk_window_clamp == 0))
++              req->rsk_window_clamp = full_space;
++
++      tcp_select_initial_window(full_space, req->mss,
+                                 &req->rsk_rcv_wnd, &req->rsk_window_clamp,
+                                 ireq->wscale_ok, &rcv_wscale,
+                                 dst_metric(dst, RTAX_INITRWND));
diff --git a/queue-4.14/net-x25-fix-null-ptr-deref-in-x25_connect.patch b/queue-4.14/net-x25-fix-null-ptr-deref-in-x25_connect.patch
new file mode 100644 (file)
index 0000000..0c66236
--- /dev/null
@@ -0,0 +1,39 @@
+From foo@baz Tue Nov 17 10:36:22 AM CET 2020
+From: Martin Schiller <ms@dev.tdt.de>
+Date: Mon, 9 Nov 2020 07:54:49 +0100
+Subject: net/x25: Fix null-ptr-deref in x25_connect
+
+From: Martin Schiller <ms@dev.tdt.de>
+
+[ Upstream commit 361182308766a265b6c521879b34302617a8c209 ]
+
+This fixes a regression for blocking connects introduced by commit
+4becb7ee5b3d ("net/x25: Fix x25_neigh refcnt leak when x25 disconnect").
+
+The x25->neighbour is already set to "NULL" by x25_disconnect() now,
+while a blocking connect is waiting in
+x25_wait_for_connection_establishment(). Therefore x25->neighbour must
+not be accessed here again and x25->state is also already set to
+X25_STATE_0 by x25_disconnect().
+
+Fixes: 4becb7ee5b3d ("net/x25: Fix x25_neigh refcnt leak when x25 disconnect")
+Signed-off-by: Martin Schiller <ms@dev.tdt.de>
+Reviewed-by: Xie He <xie.he.0141@gmail.com>
+Link: https://lore.kernel.org/r/20201109065449.9014-1-ms@dev.tdt.de
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/x25/af_x25.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/x25/af_x25.c
++++ b/net/x25/af_x25.c
+@@ -823,7 +823,7 @@ static int x25_connect(struct socket *so
+       sock->state = SS_CONNECTED;
+       rc = 0;
+ out_put_neigh:
+-      if (rc) {
++      if (rc && x25->neighbour) {
+               read_lock_bh(&x25_list_lock);
+               x25_neigh_put(x25->neighbour);
+               x25->neighbour = NULL;
diff --git a/queue-4.14/r8169-fix-potential-skb-double-free-in-an-error-path.patch b/queue-4.14/r8169-fix-potential-skb-double-free-in-an-error-path.patch
new file mode 100644 (file)
index 0000000..9eec7c4
--- /dev/null
@@ -0,0 +1,36 @@
+From foo@baz Tue Nov 17 10:23:12 AM CET 2020
+From: Heiner Kallweit <hkallweit1@gmail.com>
+Date: Thu, 5 Nov 2020 15:28:42 +0100
+Subject: r8169: fix potential skb double free in an error path
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit cc6528bc9a0c901c83b8220a2e2617f3354d6dd9 ]
+
+The caller of rtl8169_tso_csum_v2() frees the skb if false is returned.
+eth_skb_pad() internally frees the skb on error what would result in a
+double free. Therefore use __skb_put_padto() directly and instruct it
+to not free the skb on error.
+
+Fixes: b423e9ae49d7 ("r8169: fix offloaded tx checksum for small packets.")
+Reported-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Link: https://lore.kernel.org/r/f7e68191-acff-9ded-4263-c016428a8762@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/ethernet/realtek/r8169.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/realtek/r8169.c
++++ b/drivers/net/ethernet/realtek/r8169.c
+@@ -7143,7 +7143,8 @@ static bool rtl8169_tso_csum_v2(struct r
+               opts[1] |= transport_offset << TCPHO_SHIFT;
+       } else {
+               if (unlikely(rtl_test_hw_pad_bug(tp, skb)))
+-                      return !eth_skb_pad(skb);
++                      /* eth_skb_pad would free the skb on error */
++                      return !__skb_put_padto(skb, ETH_ZLEN, false);
+       }
+       return true;
index fdc799cd966a1b31700dc184b1ecffb4a83a9634..9a2235346bc5d56b18317b0650a6976c7988bbed 100644 (file)
@@ -55,4 +55,9 @@ drm-gma500-fix-out-of-bounds-access-to-struct-drm_device.vblank.patch
 pinctrl-amd-use-higher-precision-for-512-rtcclk.patch
 pinctrl-amd-fix-incorrect-way-to-disable-debounce-filter.patch
 swiotlb-fix-x86-don-t-panic-if-can-not-alloc-buffer-for-swiotlb.patch
-btrfs-fix-potential-overflow-in-cluster_pages_for_defrag-on-32bit-arch.patch
+ipv6-set-sit-tunnel-hard_header_len-to-zero.patch
+net-af_iucv-fix-null-pointer-dereference-on-shutdown.patch
+net-x25-fix-null-ptr-deref-in-x25_connect.patch
+vrf-fix-fast-path-output-packet-handling-with-async-netfilter-rules.patch
+r8169-fix-potential-skb-double-free-in-an-error-path.patch
+net-update-window_clamp-if-sock_rcvbuf-is-set.patch
diff --git a/queue-4.14/vrf-fix-fast-path-output-packet-handling-with-async-netfilter-rules.patch b/queue-4.14/vrf-fix-fast-path-output-packet-handling-with-async-netfilter-rules.patch
new file mode 100644 (file)
index 0000000..e4f3eb8
--- /dev/null
@@ -0,0 +1,192 @@
+From foo@baz Tue Nov 17 10:23:12 AM CET 2020
+From: Martin Willi <martin@strongswan.org>
+Date: Fri, 6 Nov 2020 08:30:30 +0100
+Subject: vrf: Fix fast path output packet handling with async Netfilter rules
+
+From: Martin Willi <martin@strongswan.org>
+
+[ Upstream commit 9e2b7fa2df4365e99934901da4fb4af52d81e820 ]
+
+VRF devices use an optimized direct path on output if a default qdisc
+is involved, calling Netfilter hooks directly. This path, however, does
+not consider Netfilter rules completing asynchronously, such as with
+NFQUEUE. The Netfilter okfn() is called for asynchronously accepted
+packets, but the VRF never passes that packet down the stack to send
+it out over the slave device. Using the slower redirect path for this
+seems not feasible, as we do not know beforehand if a Netfilter hook
+has asynchronously completing rules.
+
+Fix the use of asynchronously completing Netfilter rules in OUTPUT and
+POSTROUTING by using a special completion function that additionally
+calls dst_output() to pass the packet down the stack. Also, slightly
+adjust the use of nf_reset_ct() so that is called in the asynchronous
+case, too.
+
+Fixes: dcdd43c41e60 ("net: vrf: performance improvements for IPv4")
+Fixes: a9ec54d1b0cd ("net: vrf: performance improvements for IPv6")
+Signed-off-by: Martin Willi <martin@strongswan.org>
+Link: https://lore.kernel.org/r/20201106073030.3974927-1-martin@strongswan.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/vrf.c |   92 ++++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 69 insertions(+), 23 deletions(-)
+
+--- a/drivers/net/vrf.c
++++ b/drivers/net/vrf.c
+@@ -334,8 +334,7 @@ static netdev_tx_t vrf_xmit(struct sk_bu
+       return ret;
+ }
+-static int vrf_finish_direct(struct net *net, struct sock *sk,
+-                           struct sk_buff *skb)
++static void vrf_finish_direct(struct sk_buff *skb)
+ {
+       struct net_device *vrf_dev = skb->dev;
+@@ -354,7 +353,8 @@ static int vrf_finish_direct(struct net
+               skb_pull(skb, ETH_HLEN);
+       }
+-      return 1;
++      /* reset skb device */
++      nf_reset(skb);
+ }
+ #if IS_ENABLED(CONFIG_IPV6)
+@@ -433,15 +433,41 @@ static struct sk_buff *vrf_ip6_out_redir
+       return skb;
+ }
++static int vrf_output6_direct_finish(struct net *net, struct sock *sk,
++                                   struct sk_buff *skb)
++{
++      vrf_finish_direct(skb);
++
++      return vrf_ip6_local_out(net, sk, skb);
++}
++
+ static int vrf_output6_direct(struct net *net, struct sock *sk,
+                             struct sk_buff *skb)
+ {
++      int err = 1;
++
+       skb->protocol = htons(ETH_P_IPV6);
+-      return NF_HOOK_COND(NFPROTO_IPV6, NF_INET_POST_ROUTING,
+-                          net, sk, skb, NULL, skb->dev,
+-                          vrf_finish_direct,
+-                          !(IPCB(skb)->flags & IPSKB_REROUTED));
++      if (!(IPCB(skb)->flags & IPSKB_REROUTED))
++              err = nf_hook(NFPROTO_IPV6, NF_INET_POST_ROUTING, net, sk, skb,
++                            NULL, skb->dev, vrf_output6_direct_finish);
++
++      if (likely(err == 1))
++              vrf_finish_direct(skb);
++
++      return err;
++}
++
++static int vrf_ip6_out_direct_finish(struct net *net, struct sock *sk,
++                                   struct sk_buff *skb)
++{
++      int err;
++
++      err = vrf_output6_direct(net, sk, skb);
++      if (likely(err == 1))
++              err = vrf_ip6_local_out(net, sk, skb);
++
++      return err;
+ }
+ static struct sk_buff *vrf_ip6_out_direct(struct net_device *vrf_dev,
+@@ -454,18 +480,15 @@ static struct sk_buff *vrf_ip6_out_direc
+       skb->dev = vrf_dev;
+       err = nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk,
+-                    skb, NULL, vrf_dev, vrf_output6_direct);
++                    skb, NULL, vrf_dev, vrf_ip6_out_direct_finish);
+       if (likely(err == 1))
+               err = vrf_output6_direct(net, sk, skb);
+-      /* reset skb device */
+       if (likely(err == 1))
+-              nf_reset(skb);
+-      else
+-              skb = NULL;
++              return skb;
+-      return skb;
++      return NULL;
+ }
+ static struct sk_buff *vrf_ip6_out(struct net_device *vrf_dev,
+@@ -649,15 +672,41 @@ static struct sk_buff *vrf_ip_out_redire
+       return skb;
+ }
++static int vrf_output_direct_finish(struct net *net, struct sock *sk,
++                                  struct sk_buff *skb)
++{
++      vrf_finish_direct(skb);
++
++      return vrf_ip_local_out(net, sk, skb);
++}
++
+ static int vrf_output_direct(struct net *net, struct sock *sk,
+                            struct sk_buff *skb)
+ {
++      int err = 1;
++
+       skb->protocol = htons(ETH_P_IP);
+-      return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING,
+-                          net, sk, skb, NULL, skb->dev,
+-                          vrf_finish_direct,
+-                          !(IPCB(skb)->flags & IPSKB_REROUTED));
++      if (!(IPCB(skb)->flags & IPSKB_REROUTED))
++              err = nf_hook(NFPROTO_IPV4, NF_INET_POST_ROUTING, net, sk, skb,
++                            NULL, skb->dev, vrf_output_direct_finish);
++
++      if (likely(err == 1))
++              vrf_finish_direct(skb);
++
++      return err;
++}
++
++static int vrf_ip_out_direct_finish(struct net *net, struct sock *sk,
++                                  struct sk_buff *skb)
++{
++      int err;
++
++      err = vrf_output_direct(net, sk, skb);
++      if (likely(err == 1))
++              err = vrf_ip_local_out(net, sk, skb);
++
++      return err;
+ }
+ static struct sk_buff *vrf_ip_out_direct(struct net_device *vrf_dev,
+@@ -670,18 +719,15 @@ static struct sk_buff *vrf_ip_out_direct
+       skb->dev = vrf_dev;
+       err = nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT, net, sk,
+-                    skb, NULL, vrf_dev, vrf_output_direct);
++                    skb, NULL, vrf_dev, vrf_ip_out_direct_finish);
+       if (likely(err == 1))
+               err = vrf_output_direct(net, sk, skb);
+-      /* reset skb device */
+       if (likely(err == 1))
+-              nf_reset(skb);
+-      else
+-              skb = NULL;
++              return skb;
+-      return skb;
++      return NULL;
+ }
+ static struct sk_buff *vrf_ip_out(struct net_device *vrf_dev,