Commit 304b44f0 authored by Antony Antony's avatar Antony Antony Committed by Steffen Klassert

xfrm: Add dir validation to "in" data path lookup

Introduces validation for the x->dir attribute within the XFRM input
data lookup path. If the configured direction does not match the
expected direction, input, increment the XfrmInStateDirError counter
and drop the packet to ensure data integrity and correct flow handling.

grep -vw 0 /proc/net/xfrm_stat
XfrmInStateDirError     	1
Signed-off-by: default avatarAntony Antony <antony.antony@secunet.com>
Reviewed-by: default avatarSabrina Dubroca <sd@queasysnail.net>
Reviewed-by: default avatarNicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 601a0867
......@@ -73,6 +73,9 @@ XfrmAcquireError:
XfrmFwdHdrError:
Forward routing of a packet is not allowed
XfrmInStateDirError:
State direction mismatch (lookup found an output state on the input path, expected input or no direction)
Outbound errors
~~~~~~~~~~~~~~~
XfrmOutError:
......
......@@ -338,6 +338,7 @@ enum
LINUX_MIB_XFRMOUTSTATEINVALID, /* XfrmOutStateInvalid */
LINUX_MIB_XFRMACQUIREERROR, /* XfrmAcquireError */
LINUX_MIB_XFRMOUTSTATEDIRERROR, /* XfrmOutStateDirError */
LINUX_MIB_XFRMINSTATEDIRERROR, /* XfrmInStateDirError */
__LINUX_MIB_XFRMMAX
};
......
......@@ -266,6 +266,13 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
if (!x)
continue;
if (unlikely(x->dir && x->dir != XFRM_SA_DIR_IN)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEDIRERROR);
xfrm_state_put(x);
x = NULL;
continue;
}
spin_lock(&x->lock);
if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) &&
......
......@@ -466,6 +466,11 @@ 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);
......@@ -571,6 +576,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
goto drop;
}
if (unlikely(x->dir && x->dir != XFRM_SA_DIR_IN)) {
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEDIRERROR);
xfrm_state_put(x);
goto drop;
}
skb->mark = xfrm_smark_get(skb->mark, x);
sp->xvec[sp->len++] = x;
......
......@@ -42,6 +42,7 @@ static const struct snmp_mib xfrm_mib_list[] = {
SNMP_MIB_ITEM("XfrmOutStateInvalid", LINUX_MIB_XFRMOUTSTATEINVALID),
SNMP_MIB_ITEM("XfrmAcquireError", LINUX_MIB_XFRMACQUIREERROR),
SNMP_MIB_ITEM("XfrmOutStateDirError", LINUX_MIB_XFRMOUTSTATEDIRERROR),
SNMP_MIB_ITEM("XfrmInStateDirError", LINUX_MIB_XFRMINSTATEDIRERROR),
SNMP_MIB_SENTINEL
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment