mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-28 07:03:56 +00:00
d540725871
Without this patch, the chacha block counter is not incremented on neon rounds, resulting in incorrect calculations and corrupt packets. This also switches to using `--no-numbered --zero-commit` so that future diffs are smaller. Reported-by: Hans Geiblinger <cybrnook2002@yahoo.com> Reviewed-by: Ilya Lipnitskiy <ilya.lipnitskiy@gmail.com> Cc: David Bauer <mail@david-bauer.net> Cc: Petr Štetiar <ynezz@true.cz> Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
149 lines
4.3 KiB
Diff
149 lines
4.3 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: "Jason A. Donenfeld" <Jason@zx2c4.com>
|
|
Date: Tue, 11 Feb 2020 20:47:05 +0100
|
|
Subject: [PATCH] icmp: introduce helper for nat'd source address in network
|
|
device context
|
|
|
|
commit 0b41713b606694257b90d61ba7e2712d8457648b upstream.
|
|
|
|
This introduces a helper function to be called only by network drivers
|
|
that wraps calls to icmp[v6]_send in a conntrack transformation, in case
|
|
NAT has been used. We don't want to pollute the non-driver path, though,
|
|
so we introduce this as a helper to be called by places that actually
|
|
make use of this, as suggested by Florian.
|
|
|
|
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
|
Cc: Florian Westphal <fw@strlen.de>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
|
|
---
|
|
include/linux/icmpv6.h | 10 ++++++++++
|
|
include/net/icmp.h | 6 ++++++
|
|
net/ipv4/icmp.c | 33 +++++++++++++++++++++++++++++++++
|
|
net/ipv6/ip6_icmp.c | 34 ++++++++++++++++++++++++++++++++++
|
|
4 files changed, 83 insertions(+)
|
|
|
|
--- a/include/linux/icmpv6.h
|
|
+++ b/include/linux/icmpv6.h
|
|
@@ -22,12 +22,22 @@ extern int inet6_unregister_icmp_sender(
|
|
int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type,
|
|
unsigned int data_len);
|
|
|
|
+#if IS_ENABLED(CONFIG_NF_NAT)
|
|
+void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info);
|
|
+#else
|
|
+#define icmpv6_ndo_send icmpv6_send
|
|
+#endif
|
|
+
|
|
#else
|
|
|
|
static inline void icmpv6_send(struct sk_buff *skb,
|
|
u8 type, u8 code, __u32 info)
|
|
{
|
|
+}
|
|
|
|
+static inline void icmpv6_ndo_send(struct sk_buff *skb,
|
|
+ u8 type, u8 code, __u32 info)
|
|
+{
|
|
}
|
|
#endif
|
|
|
|
--- a/include/net/icmp.h
|
|
+++ b/include/net/icmp.h
|
|
@@ -43,6 +43,12 @@ static inline void icmp_send(struct sk_b
|
|
__icmp_send(skb_in, type, code, info, &IPCB(skb_in)->opt);
|
|
}
|
|
|
|
+#if IS_ENABLED(CONFIG_NF_NAT)
|
|
+void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info);
|
|
+#else
|
|
+#define icmp_ndo_send icmp_send
|
|
+#endif
|
|
+
|
|
int icmp_rcv(struct sk_buff *skb);
|
|
int icmp_err(struct sk_buff *skb, u32 info);
|
|
int icmp_init(void);
|
|
--- a/net/ipv4/icmp.c
|
|
+++ b/net/ipv4/icmp.c
|
|
@@ -750,6 +750,39 @@ out:;
|
|
}
|
|
EXPORT_SYMBOL(__icmp_send);
|
|
|
|
+#if IS_ENABLED(CONFIG_NF_NAT)
|
|
+#include <net/netfilter/nf_conntrack.h>
|
|
+void icmp_ndo_send(struct sk_buff *skb_in, int type, int code, __be32 info)
|
|
+{
|
|
+ struct sk_buff *cloned_skb = NULL;
|
|
+ enum ip_conntrack_info ctinfo;
|
|
+ struct nf_conn *ct;
|
|
+ __be32 orig_ip;
|
|
+
|
|
+ ct = nf_ct_get(skb_in, &ctinfo);
|
|
+ if (!ct || !(ct->status & IPS_SRC_NAT)) {
|
|
+ icmp_send(skb_in, type, code, info);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (skb_shared(skb_in))
|
|
+ skb_in = cloned_skb = skb_clone(skb_in, GFP_ATOMIC);
|
|
+
|
|
+ if (unlikely(!skb_in || skb_network_header(skb_in) < skb_in->head ||
|
|
+ (skb_network_header(skb_in) + sizeof(struct iphdr)) >
|
|
+ skb_tail_pointer(skb_in) || skb_ensure_writable(skb_in,
|
|
+ skb_network_offset(skb_in) + sizeof(struct iphdr))))
|
|
+ goto out;
|
|
+
|
|
+ orig_ip = ip_hdr(skb_in)->saddr;
|
|
+ ip_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.ip;
|
|
+ icmp_send(skb_in, type, code, info);
|
|
+ ip_hdr(skb_in)->saddr = orig_ip;
|
|
+out:
|
|
+ consume_skb(cloned_skb);
|
|
+}
|
|
+EXPORT_SYMBOL(icmp_ndo_send);
|
|
+#endif
|
|
|
|
static void icmp_socket_deliver(struct sk_buff *skb, u32 info)
|
|
{
|
|
--- a/net/ipv6/ip6_icmp.c
|
|
+++ b/net/ipv6/ip6_icmp.c
|
|
@@ -45,4 +45,38 @@ out:
|
|
rcu_read_unlock();
|
|
}
|
|
EXPORT_SYMBOL(icmpv6_send);
|
|
+
|
|
+#if IS_ENABLED(CONFIG_NF_NAT)
|
|
+#include <net/netfilter/nf_conntrack.h>
|
|
+void icmpv6_ndo_send(struct sk_buff *skb_in, u8 type, u8 code, __u32 info)
|
|
+{
|
|
+ struct sk_buff *cloned_skb = NULL;
|
|
+ enum ip_conntrack_info ctinfo;
|
|
+ struct in6_addr orig_ip;
|
|
+ struct nf_conn *ct;
|
|
+
|
|
+ ct = nf_ct_get(skb_in, &ctinfo);
|
|
+ if (!ct || !(ct->status & IPS_SRC_NAT)) {
|
|
+ icmpv6_send(skb_in, type, code, info);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (skb_shared(skb_in))
|
|
+ skb_in = cloned_skb = skb_clone(skb_in, GFP_ATOMIC);
|
|
+
|
|
+ if (unlikely(!skb_in || skb_network_header(skb_in) < skb_in->head ||
|
|
+ (skb_network_header(skb_in) + sizeof(struct ipv6hdr)) >
|
|
+ skb_tail_pointer(skb_in) || skb_ensure_writable(skb_in,
|
|
+ skb_network_offset(skb_in) + sizeof(struct ipv6hdr))))
|
|
+ goto out;
|
|
+
|
|
+ orig_ip = ipv6_hdr(skb_in)->saddr;
|
|
+ ipv6_hdr(skb_in)->saddr = ct->tuplehash[0].tuple.src.u3.in6;
|
|
+ icmpv6_send(skb_in, type, code, info);
|
|
+ ipv6_hdr(skb_in)->saddr = orig_ip;
|
|
+out:
|
|
+ consume_skb(cloned_skb);
|
|
+}
|
|
+EXPORT_SYMBOL(icmpv6_ndo_send);
|
|
+#endif
|
|
#endif
|