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: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Wed, 14 Jun 2017 14:47:56 +0200
From:   Jan Grashöfer <jan.grashoefer@...il.com>
To:     netdev@...r.kernel.org
Cc:     aeppert@...il.com
Subject: Receiving raw packets (incl. VLAN tags) on raw sockets

Hello,

trying to ingest packets to a network monitoring tool using AF_Packet, I
noticed that VLAN tags are stripped off even if VLAN offloading is
disabled. As described in [1] the tags are stripped that early in the
receive path that raw sockets do not receive the packets as seen on the
wire. However, the man pages [2] state:

> SOCK_RAW packets are passed to and from the device driver without any
> changes in the packet data.

So at least the docs are wrong here. While the VLAN information is
present in the tpacket_hdr, the packets themselves are manipulated by
the kernel. In my case, for example, I need to pass on each packet (in
form of a packet) and thus would have to reinsert the tag manually,
which is definitely undesirable.

As I am dealing with a monitoring application, the following patch that
disables untagging VLANs in promisc mode fixes the issue for me:

diff --git a/net/core/dev.c b/net/core/dev.c
index 54f8c16..ec5b1c5 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4104,8 +4104,9 @@ static int __netif_receive_skb_core(struct sk_buff
*skb, bool pfmemalloc)

        __this_cpu_inc(softnet_data.processed);

-       if (skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
-           skb->protocol == cpu_to_be16(ETH_P_8021AD)) {
+       if ((skb->protocol == cpu_to_be16(ETH_P_8021Q) ||
+           skb->protocol == cpu_to_be16(ETH_P_8021AD)) &&
+           skb->dev->promiscuity < 1) {
                skb = skb_vlan_untag(skb);
                if (unlikely(!skb))
                        goto out;
--

I tested the patch with tcpdump and suricata. As they are designed to
handle VLAN tags anyway, both work as expected. Still there are two
caveats regarding this patch: First, there might be software out there
that does not work as expected anymore. Second, the semantics of raw
sockets are even more cluttered than before. I could imagine the
following solutions:

1) Disable VLAN untagging done by the kernel or move it up the receive
path - probably least practicable.

2) Parse VLAN info into the tpacket_hdr but keep the packet as is (at
least in promisc mode) - still, seems clumsy and error-prone to me.

3) Introduce a new socket option to disable VLAN untagging for raw
sockets - maybe overkill.

I would be happy to receive some feedback!

Best regards,
Jan

[1] https://www.spinics.net/lists/netdev/msg244668.html
[2] http://man7.org/linux/man-pages/man7/ip.7.html

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ