xfrm: Add dir validation to "out" data path lookup
authorAntony Antony <antony.antony@secunet.com>
Tue, 30 Apr 2024 07:09:09 +0000 (09:09 +0200)
committerSteffen Klassert <steffen.klassert@secunet.com>
Wed, 1 May 2024 08:05:52 +0000 (10:05 +0200)
Introduces validation for the x->dir attribute within the XFRM output
data lookup path. If the configured direction does not match the expected
direction, output, increment the XfrmOutStateDirError counter and drop
the packet to ensure data integrity and correct flow handling.

grep -vw 0 /proc/net/xfrm_stat
XfrmOutPolError          1
XfrmOutStateDirError     1

Signed-off-by: Antony Antony <antony.antony@secunet.com>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Reviewed-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Documentation/networking/xfrm_proc.rst
include/uapi/linux/snmp.h
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_proc.c

index 0a771c5a7399b558be69a7e1ae3c95e7547864f4..5ac3acf4cf51c32161cf9b608bf64f04315c520d 100644 (file)
@@ -111,3 +111,6 @@ XfrmOutPolError:
 
 XfrmOutStateInvalid:
        State is invalid, perhaps expired
+
+XfrmOutStateDirError:
+        State direction mismatch (lookup found an input state on the output path, expected output or no direction)
index a0819c6a5988fc97b14fc23cac3911e70a14cbff..23792b8412bd2890fc69090bc6d9db9f28cf1339 100644 (file)
@@ -337,6 +337,7 @@ enum
        LINUX_MIB_XFRMFWDHDRERROR,              /* XfrmFwdHdrError*/
        LINUX_MIB_XFRMOUTSTATEINVALID,          /* XfrmOutStateInvalid */
        LINUX_MIB_XFRMACQUIREERROR,             /* XfrmAcquireError */
+       LINUX_MIB_XFRMOUTSTATEDIRERROR,         /* XfrmOutStateDirError */
        __LINUX_MIB_XFRMMAX
 };
 
index 6affe5cd85d8f14fb1689b830422eaea56d0dafc..298b3a9eb48d2502aa082da6cf871fecbf443958 100644 (file)
@@ -2489,6 +2489,12 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
 
                x = xfrm_state_find(remote, local, fl, tmpl, policy, &error,
                                    family, policy->if_id);
+               if (x && x->dir && x->dir != XFRM_SA_DIR_OUT) {
+                       XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEDIRERROR);
+                       xfrm_state_put(x);
+                       error = -EINVAL;
+                       goto fail;
+               }
 
                if (x && x->km.state == XFRM_STATE_VALID) {
                        xfrm[nx++] = x;
index 5f9bf8e5c9338f4337b308f06edb25612c68a3fa..98606f1078f70a9a30fe5fd06850c36c0e73b225 100644 (file)
@@ -41,6 +41,7 @@ static const struct snmp_mib xfrm_mib_list[] = {
        SNMP_MIB_ITEM("XfrmFwdHdrError", LINUX_MIB_XFRMFWDHDRERROR),
        SNMP_MIB_ITEM("XfrmOutStateInvalid", LINUX_MIB_XFRMOUTSTATEINVALID),
        SNMP_MIB_ITEM("XfrmAcquireError", LINUX_MIB_XFRMACQUIREERROR),
+       SNMP_MIB_ITEM("XfrmOutStateDirError", LINUX_MIB_XFRMOUTSTATEDIRERROR),
        SNMP_MIB_SENTINEL
 };