tag packets going out a sec interface to prevent route/encap loops.
authordlg <dlg@openbsd.org>
Wed, 24 Jan 2024 00:17:01 +0000 (00:17 +0000)
committerdlg <dlg@openbsd.org>
Wed, 24 Jan 2024 00:17:01 +0000 (00:17 +0000)
sec(4) was already looking for this mbuf tag so it could drop packets
that had already been sent out on the same interface, but i forgot
the code that adds the tag.

this was reported by jason tubnor who experienced spins/lockups
when using sec and a physical interface was disconnected. rather
than being a locking problem like we initially assumed, it turned
out that unplugging a physical interface caused a route for ipsec
encapsulated traffic to go out over sec(4), causing the packet to
loop in the stack.

the fix was also tested and verified by jason. sorry for taking so
long to look at it.

sys/net/if_sec.c

index 99e79b5..7e4e5f5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: if_sec.c,v 1.9 2023/12/23 10:52:54 bluhm Exp $ */
+/*     $OpenBSD: if_sec.c,v 1.10 2024/01/24 00:17:01 dlg Exp $ */
 
 /*
  * Copyright (c) 2022 The University of Queensland
@@ -315,6 +315,14 @@ sec_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
                }
        }
 
+       mtag = m_tag_get(PACKET_TAG_GRE, sizeof(ifp->if_index), M_NOWAIT);
+       if (mtag == NULL) {
+               error = ENOBUFS;
+               goto drop;
+       }
+       *(int *)(mtag + 1) = ifp->if_index;
+       m_tag_prepend(m, mtag);
+
        m->m_pkthdr.ph_family = dst->sa_family;
 
        error = if_enqueue(ifp, m);