af_packet: Introduce egress hook
authorPablo Neira Ayuso <pablo@netfilter.org>
Fri, 8 Oct 2021 20:06:04 +0000 (22:06 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Thu, 14 Oct 2021 21:06:44 +0000 (23:06 +0200)
Add egress hook for AF_PACKET sockets that have the PACKET_QDISC_BYPASS
socket option set to on, which allows packets to escape without being
filtered in the egress path.

This patch only updates the AF_PACKET path, it does not update
dev_direct_xmit() so the XDP infrastructure has a chance to bypass
Netfilter.

[lukas: acquire rcu_read_lock, fix typos, rebase]
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
net/packet/af_packet.c

index 2a2bc64..46943a1 100644 (file)
@@ -91,6 +91,7 @@
 #endif
 #include <linux/bpf.h>
 #include <net/compat.h>
+#include <linux/netfilter_netdev.h>
 
 #include "internal.h"
 
@@ -241,8 +242,42 @@ struct packet_skb_cb {
 static void __fanout_unlink(struct sock *sk, struct packet_sock *po);
 static void __fanout_link(struct sock *sk, struct packet_sock *po);
 
+#ifdef CONFIG_NETFILTER_EGRESS
+static noinline struct sk_buff *nf_hook_direct_egress(struct sk_buff *skb)
+{
+       struct sk_buff *next, *head = NULL, *tail;
+       int rc;
+
+       rcu_read_lock();
+       for (; skb != NULL; skb = next) {
+               next = skb->next;
+               skb_mark_not_on_list(skb);
+
+               if (!nf_hook_egress(skb, &rc, skb->dev))
+                       continue;
+
+               if (!head)
+                       head = skb;
+               else
+                       tail->next = skb;
+
+               tail = skb;
+       }
+       rcu_read_unlock();
+
+       return head;
+}
+#endif
+
 static int packet_direct_xmit(struct sk_buff *skb)
 {
+#ifdef CONFIG_NETFILTER_EGRESS
+       if (nf_hook_egress_active()) {
+               skb = nf_hook_direct_egress(skb);
+               if (!skb)
+                       return NET_XMIT_DROP;
+       }
+#endif
        return dev_direct_xmit(skb, packet_pick_tx_queue(skb));
 }