]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
xfrm: Log input direction mismatch error in one place
authorAntony Antony <antony.antony@secunet.com>
Tue, 11 Jun 2024 06:32:15 +0000 (08:32 +0200)
committerSteffen Klassert <steffen.klassert@secunet.com>
Mon, 17 Jun 2024 11:53:19 +0000 (13:53 +0200)
Previously, the offload data path decrypted the packet before checking
the direction, leading to error logging and packet dropping. However,
dropped packets wouldn't be visible in tcpdump or audit log.

With this fix, the offload path, upon noticing SA direction mismatch,
will pass the packet to the stack without decrypting it. The L3 layer
will then log the error, audit, and drop ESP without decrypting or
decapsulating it.

This also ensures that the slow path records the error and audit log,
making dropped packets visible in tcpdump.

Fixes: 304b44f0d5a4 ("xfrm: Add dir validation to "in" data path lookup")
Signed-off-by: Antony Antony <antony.antony@secunet.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
net/ipv4/esp4_offload.c
net/ipv6/esp6_offload.c
net/xfrm/xfrm_input.c

index b3271957ad9a0c3230496786cf0e864da83ec8da..3f28ecbdcaef1f8032d4bf25b66b05629a1fc024 100644 (file)
@@ -56,6 +56,13 @@ static struct sk_buff *esp4_gro_receive(struct list_head *head,
                x = xfrm_state_lookup(dev_net(skb->dev), skb->mark,
                                      (xfrm_address_t *)&ip_hdr(skb)->daddr,
                                      spi, IPPROTO_ESP, AF_INET);
+
+               if (unlikely(x && x->dir && x->dir != XFRM_SA_DIR_IN)) {
+                       /* non-offload path will record the error and audit log */
+                       xfrm_state_put(x);
+                       x = NULL;
+               }
+
                if (!x)
                        goto out_reset;
 
index 527b7caddbc68d9d10f98cb879e2baa8fa8535c8..919ebfabbe4ee272e268d93586b9d06ec35588ea 100644 (file)
@@ -83,6 +83,13 @@ static struct sk_buff *esp6_gro_receive(struct list_head *head,
                x = xfrm_state_lookup(dev_net(skb->dev), skb->mark,
                                      (xfrm_address_t *)&ipv6_hdr(skb)->daddr,
                                      spi, IPPROTO_ESP, AF_INET6);
+
+               if (unlikely(x && x->dir && x->dir != XFRM_SA_DIR_IN)) {
+                       /* non-offload path will record the error and audit log */
+                       xfrm_state_put(x);
+                       x = NULL;
+               }
+
                if (!x)
                        goto out_reset;
 
index 63c00410391204b6f071bea00dd6e82663483ce6..e95462b982b0fd6b485a204e036dca849a59bb80 100644 (file)
@@ -474,11 +474,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
        if (encap_type < 0 || (xo && xo->flags & XFRM_GRO)) {
                x = xfrm_input_state(skb);
 
-               if (unlikely(x->dir && x->dir != XFRM_SA_DIR_IN)) {
-                       XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEDIRERROR);
-                       goto drop;
-               }
-
                if (unlikely(x->km.state != XFRM_STATE_VALID)) {
                        if (x->km.state == XFRM_STATE_ACQ)
                                XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR);