Skip to content

Commit 304b44f

Browse files
antonyantonyklassert
authored andcommitted
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: Antony Antony <[email protected]> Reviewed-by: Sabrina Dubroca <[email protected]> Reviewed-by: Nicolas Dichtel <[email protected]> Signed-off-by: Steffen Klassert <[email protected]>
1 parent 601a086 commit 304b44f

File tree

5 files changed

+23
-0
lines changed

5 files changed

+23
-0
lines changed

Documentation/networking/xfrm_proc.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ XfrmAcquireError:
7373
XfrmFwdHdrError:
7474
Forward routing of a packet is not allowed
7575

76+
XfrmInStateDirError:
77+
State direction mismatch (lookup found an output state on the input path, expected input or no direction)
78+
7679
Outbound errors
7780
~~~~~~~~~~~~~~~
7881
XfrmOutError:

include/uapi/linux/snmp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ enum
338338
LINUX_MIB_XFRMOUTSTATEINVALID, /* XfrmOutStateInvalid */
339339
LINUX_MIB_XFRMACQUIREERROR, /* XfrmAcquireError */
340340
LINUX_MIB_XFRMOUTSTATEDIRERROR, /* XfrmOutStateDirError */
341+
LINUX_MIB_XFRMINSTATEDIRERROR, /* XfrmInStateDirError */
341342
__LINUX_MIB_XFRMMAX
342343
};
343344

net/ipv6/xfrm6_input.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,13 @@ int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr,
266266
if (!x)
267267
continue;
268268

269+
if (unlikely(x->dir && x->dir != XFRM_SA_DIR_IN)) {
270+
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEDIRERROR);
271+
xfrm_state_put(x);
272+
x = NULL;
273+
continue;
274+
}
275+
269276
spin_lock(&x->lock);
270277

271278
if ((!i || (x->props.flags & XFRM_STATE_WILDRECV)) &&

net/xfrm/xfrm_input.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,11 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
466466
if (encap_type < 0 || (xo && xo->flags & XFRM_GRO)) {
467467
x = xfrm_input_state(skb);
468468

469+
if (unlikely(x->dir && x->dir != XFRM_SA_DIR_IN)) {
470+
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEDIRERROR);
471+
goto drop;
472+
}
473+
469474
if (unlikely(x->km.state != XFRM_STATE_VALID)) {
470475
if (x->km.state == XFRM_STATE_ACQ)
471476
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)
571576
goto drop;
572577
}
573578

579+
if (unlikely(x->dir && x->dir != XFRM_SA_DIR_IN)) {
580+
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEDIRERROR);
581+
xfrm_state_put(x);
582+
goto drop;
583+
}
584+
574585
skb->mark = xfrm_smark_get(skb->mark, x);
575586

576587
sp->xvec[sp->len++] = x;

net/xfrm/xfrm_proc.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ static const struct snmp_mib xfrm_mib_list[] = {
4242
SNMP_MIB_ITEM("XfrmOutStateInvalid", LINUX_MIB_XFRMOUTSTATEINVALID),
4343
SNMP_MIB_ITEM("XfrmAcquireError", LINUX_MIB_XFRMACQUIREERROR),
4444
SNMP_MIB_ITEM("XfrmOutStateDirError", LINUX_MIB_XFRMOUTSTATEDIRERROR),
45+
SNMP_MIB_ITEM("XfrmInStateDirError", LINUX_MIB_XFRMINSTATEDIRERROR),
4546
SNMP_MIB_SENTINEL
4647
};
4748

0 commit comments

Comments
 (0)