Skip to content

Commit 1f8b6df

Browse files
Benedict Wongklassert
authored andcommitted
xfrm: Treat already-verified secpath entries as optional
This change allows inbound traffic through nested IPsec tunnels to successfully match policies and templates, while retaining the secpath stack trace as necessary for netfilter policies. Specifically, this patch marks secpath entries that have already matched against a relevant policy as having been verified, allowing it to be treated as optional and skipped after a tunnel decapsulation (during which the src/dst/proto/etc may have changed, and the correct policy chain no long be resolvable). This approach is taken as opposed to the iteration in b0355db, where the secpath was cleared, since that breaks subsequent validations that rely on the existence of the secpath entries (netfilter policies, or transport-in-tunnel mode, where policies remain resolvable). Fixes: b0355db ("Fix XFRM-I support for nested ESP tunnels") Test: Tested against Android Kernel Unit Tests Test: Tested against Android CTS Signed-off-by: Benedict Wong <[email protected]> Signed-off-by: Steffen Klassert <[email protected]>
1 parent 67caf26 commit 1f8b6df

File tree

3 files changed

+14
-0
lines changed

3 files changed

+14
-0
lines changed

include/net/xfrm.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,7 @@ struct xfrm_offload {
10541054
struct sec_path {
10551055
int len;
10561056
int olen;
1057+
int verified_cnt;
10571058

10581059
struct xfrm_state *xvec[XFRM_MAX_DEPTH];
10591060
struct xfrm_offload ovec[XFRM_MAX_OFFLOAD_DEPTH];

net/xfrm/xfrm_input.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ struct sec_path *secpath_set(struct sk_buff *skb)
131131
memset(sp->ovec, 0, sizeof(sp->ovec));
132132
sp->olen = 0;
133133
sp->len = 0;
134+
sp->verified_cnt = 0;
134135

135136
return sp;
136137
}

net/xfrm/xfrm_policy.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3349,6 +3349,13 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star
33493349
if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
33503350
return ++idx;
33513351
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
3352+
if (idx < sp->verified_cnt) {
3353+
/* Secpath entry previously verified, consider optional and
3354+
* continue searching
3355+
*/
3356+
continue;
3357+
}
3358+
33523359
if (start == -1)
33533360
start = -2-idx;
33543361
break;
@@ -3723,6 +3730,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
37233730
* Order is _important_. Later we will implement
37243731
* some barriers, but at the moment barriers
37253732
* are implied between each two transformations.
3733+
* Upon success, marks secpath entries as having been
3734+
* verified to allow them to be skipped in future policy
3735+
* checks (e.g. nested tunnels).
37263736
*/
37273737
for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
37283738
k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
@@ -3741,6 +3751,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
37413751
}
37423752

37433753
xfrm_pols_put(pols, npols);
3754+
sp->verified_cnt = k;
3755+
37443756
return 1;
37453757
}
37463758
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK);

0 commit comments

Comments
 (0)