Skip to content

Commit

Permalink
xfrm: Add dir validation to "in" data path lookup
Browse files Browse the repository at this point in the history
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: Antony Antony <[email protected]>
Reviewed-by: Sabrina Dubroca <[email protected]>
Reviewed-by: Nicolas Dichtel <[email protected]>
Signed-off-by: Steffen Klassert <[email protected]>
  • Loading branch information
antonyantony authored and klassert committed May 1, 2024
1 parent 601a086 commit 304b44f
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Documentation/networking/xfrm_proc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions include/uapi/linux/snmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ enum
LINUX_MIB_XFRMOUTSTATEINVALID, /* XfrmOutStateInvalid */
LINUX_MIB_XFRMACQUIREERROR, /* XfrmAcquireError */
LINUX_MIB_XFRMOUTSTATEDIRERROR, /* XfrmOutStateDirError */
LINUX_MIB_XFRMINSTATEDIRERROR, /* XfrmInStateDirError */
__LINUX_MIB_XFRMMAX
};

Expand Down
7 changes: 7 additions & 0 deletions net/ipv6/xfrm6_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)) &&
Expand Down
11 changes: 11 additions & 0 deletions net/xfrm/xfrm_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions net/xfrm/xfrm_proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
};

Expand Down

0 comments on commit 304b44f

Please sign in to comment.