hc
2024-10-22 8ac6c7a54ed1b98d142dce24b11c6de6a1e239a5
kernel/net/xfrm/xfrm_policy.c
....@@ -3240,7 +3240,7 @@
32403240
32413241 static inline int
32423242 xfrm_state_ok(const struct xfrm_tmpl *tmpl, const struct xfrm_state *x,
3243
- unsigned short family)
3243
+ unsigned short family, u32 if_id)
32443244 {
32453245 if (xfrm_state_kern(x))
32463246 return tmpl->optional && !xfrm_state_addr_cmp(tmpl, x, tmpl->encap_family);
....@@ -3251,7 +3251,8 @@
32513251 (tmpl->allalgs || (tmpl->aalgos & (1<<x->props.aalgo)) ||
32523252 !(xfrm_id_proto_match(tmpl->id.proto, IPSEC_PROTO_ANY))) &&
32533253 !(x->props.mode != XFRM_MODE_TRANSPORT &&
3254
- xfrm_state_addr_cmp(tmpl, x, family));
3254
+ xfrm_state_addr_cmp(tmpl, x, family)) &&
3255
+ (if_id == 0 || if_id == x->if_id);
32553256 }
32563257
32573258 /*
....@@ -3263,7 +3264,7 @@
32633264 */
32643265 static inline int
32653266 xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int start,
3266
- unsigned short family)
3267
+ unsigned short family, u32 if_id)
32673268 {
32683269 int idx = start;
32693270
....@@ -3273,9 +3274,16 @@
32733274 } else
32743275 start = -1;
32753276 for (; idx < sp->len; idx++) {
3276
- if (xfrm_state_ok(tmpl, sp->xvec[idx], family))
3277
+ if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
32773278 return ++idx;
32783279 if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
3280
+ if (idx < sp->verified_cnt) {
3281
+ /* Secpath entry previously verified, consider optional and
3282
+ * continue searching
3283
+ */
3284
+ continue;
3285
+ }
3286
+
32793287 if (start == -1)
32803288 start = -2-idx;
32813289 break;
....@@ -3671,6 +3679,7 @@
36713679 tpp[ti++] = &pols[pi]->xfrm_vec[i];
36723680 }
36733681 xfrm_nr = ti;
3682
+
36743683 if (npols > 1) {
36753684 xfrm_tmpl_sort(stp, tpp, xfrm_nr, family);
36763685 tpp = stp;
....@@ -3681,9 +3690,12 @@
36813690 * Order is _important_. Later we will implement
36823691 * some barriers, but at the moment barriers
36833692 * are implied between each two transformations.
3693
+ * Upon success, marks secpath entries as having been
3694
+ * verified to allow them to be skipped in future policy
3695
+ * checks (e.g. nested tunnels).
36843696 */
36853697 for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
3686
- k = xfrm_policy_ok(tpp[i], sp, k, family);
3698
+ k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
36873699 if (k < 0) {
36883700 if (k < -1)
36893701 /* "-2 - errored_index" returned */
....@@ -3699,6 +3711,8 @@
36993711 }
37003712
37013713 xfrm_pols_put(pols, npols);
3714
+ sp->verified_cnt = k;
3715
+
37023716 return 1;
37033717 }
37043718 XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK);