lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20200626201330.325840-1-ndev@hwipl.net>
Date:   Fri, 26 Jun 2020 22:13:30 +0200
From:   Hans Wippel <ndev@...pl.net>
To:     "Jason A . Donenfeld" <Jason@...c4.com>, wireguard@...ts.zx2c4.com,
        netdev@...r.kernel.org
Cc:     Hans Wippel <ndev@...pl.net>
Subject: wireguard: problem sending via libpcap's packet socket

Hi,

while toying around with sending packets with libpcap, I noticed that it
did not work with a wireguard interface in contrast to my regular
ethernet interface.

It seems like libpcap does not set a protocol on the packet socket and
the following checks

  "skb->protocol == real_protocol",
  "skb->protocol == htons(ETH_P_IP)" and
  "skb->protocol == htons(ETH_P_IPV6)"

in the functions

  wg_check_packet_protocol(),
  wg_xmit() and
  wg_allowedips_lookup_dst()

fail because skb->protocol is 0.

Is this intended behaviour? Should these checks be changed in the kernel
or should this rather be reported to libpcap? Just in case, you can find
changes that made it work for me below (probably not the best solution).

Again, if this is not the right place to ask, just let me know and I am
sorry for the noise.
  Hans

Signed-off-by: Hans Wippel <ndev@...pl.net>
---
 drivers/net/wireguard/allowedips.c | 5 +++--
 drivers/net/wireguard/device.c     | 4 ++--
 drivers/net/wireguard/queueing.h   | 3 ++-
 3 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireguard/allowedips.c b/drivers/net/wireguard/allowedips.c
index 3725e9cd85f4..08e16907fde5 100644
--- a/drivers/net/wireguard/allowedips.c
+++ b/drivers/net/wireguard/allowedips.c
@@ -5,6 +5,7 @@
 
 #include "allowedips.h"
 #include "peer.h"
+#include "queueing.h"
 
 static void swap_endian(u8 *dst, const u8 *src, u8 bits)
 {
@@ -356,9 +357,9 @@ int wg_allowedips_read_node(struct allowedips_node *node, u8 ip[16], u8 *cidr)
 struct wg_peer *wg_allowedips_lookup_dst(struct allowedips *table,
 					 struct sk_buff *skb)
 {
-	if (skb->protocol == htons(ETH_P_IP))
+	if (wg_examine_packet_protocol(skb) == htons(ETH_P_IP))
 		return lookup(table->root4, 32, &ip_hdr(skb)->daddr);
-	else if (skb->protocol == htons(ETH_P_IPV6))
+	else if (wg_examine_packet_protocol(skb) == htons(ETH_P_IPV6))
 		return lookup(table->root6, 128, &ipv6_hdr(skb)->daddr);
 	return NULL;
 }
diff --git a/drivers/net/wireguard/device.c b/drivers/net/wireguard/device.c
index a8f151b1b5fa..baed429b2ed1 100644
--- a/drivers/net/wireguard/device.c
+++ b/drivers/net/wireguard/device.c
@@ -132,10 +132,10 @@ static netdev_tx_t wg_xmit(struct sk_buff *skb, struct net_device *dev)
 	peer = wg_allowedips_lookup_dst(&wg->peer_allowedips, skb);
 	if (unlikely(!peer)) {
 		ret = -ENOKEY;
-		if (skb->protocol == htons(ETH_P_IP))
+		if (wg_examine_packet_protocol(skb) == htons(ETH_P_IP))
 			net_dbg_ratelimited("%s: No peer has allowed IPs matching %pI4\n",
 					    dev->name, &ip_hdr(skb)->daddr);
-		else if (skb->protocol == htons(ETH_P_IPV6))
+		else if (wg_examine_packet_protocol(skb) == htons(ETH_P_IPV6))
 			net_dbg_ratelimited("%s: No peer has allowed IPs matching %pI6\n",
 					    dev->name, &ipv6_hdr(skb)->daddr);
 		goto err;
diff --git a/drivers/net/wireguard/queueing.h b/drivers/net/wireguard/queueing.h
index c58df439dbbe..36badcf8a11d 100644
--- a/drivers/net/wireguard/queueing.h
+++ b/drivers/net/wireguard/queueing.h
@@ -84,7 +84,8 @@ static inline __be16 wg_examine_packet_protocol(struct sk_buff *skb)
 static inline bool wg_check_packet_protocol(struct sk_buff *skb)
 {
 	__be16 real_protocol = wg_examine_packet_protocol(skb);
-	return real_protocol && skb->protocol == real_protocol;
+	return real_protocol == htons(ETH_P_IP) ||
+		real_protocol == htons(ETH_P_IPV6);
 }
 
 static inline void wg_reset_packet(struct sk_buff *skb, bool encapsulating)
-- 
2.27.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ