Skip to content

Commit e438eda

Browse files
committed
Merge tag 'ipsec-2023-06-20' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
ipsec-2023-06-20
2 parents 440d71e + f015b90 commit e438eda

File tree

8 files changed

+79
-8
lines changed

8 files changed

+79
-8
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/ipv4/esp4_offload.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,9 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features_
340340

341341
secpath_reset(skb);
342342

343+
if (skb_needs_linearize(skb, skb->dev->features) &&
344+
__skb_linearize(skb))
345+
return -ENOMEM;
343346
return 0;
344347
}
345348

net/ipv4/xfrm4_input.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ int xfrm4_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
164164
kfree_skb(skb);
165165
return 0;
166166
}
167+
EXPORT_SYMBOL(xfrm4_udp_encap_rcv);
167168

168169
int xfrm4_rcv(struct sk_buff *skb)
169170
{

net/ipv6/esp6_offload.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,9 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features
374374

375375
secpath_reset(skb);
376376

377+
if (skb_needs_linearize(skb, skb->dev->features) &&
378+
__skb_linearize(skb))
379+
return -ENOMEM;
377380
return 0;
378381
}
379382

net/ipv6/xfrm6_input.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ int xfrm6_udp_encap_rcv(struct sock *sk, struct sk_buff *skb)
8686
__be32 *udpdata32;
8787
__u16 encap_type = up->encap_type;
8888

89+
if (skb->protocol == htons(ETH_P_IP))
90+
return xfrm4_udp_encap_rcv(sk, skb);
91+
8992
/* if this is not encapsulated socket, then just return now */
9093
if (!encap_type)
9194
return 1;

net/xfrm/xfrm_input.c

Lines changed: 4 additions & 4 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
}
@@ -330,11 +331,10 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x,
330331
{
331332
switch (x->props.mode) {
332333
case XFRM_MODE_BEET:
333-
switch (XFRM_MODE_SKB_CB(skb)->protocol) {
334-
case IPPROTO_IPIP:
335-
case IPPROTO_BEETPH:
334+
switch (x->sel.family) {
335+
case AF_INET:
336336
return xfrm4_remove_beet_encap(x, skb);
337-
case IPPROTO_IPV6:
337+
case AF_INET6:
338338
return xfrm6_remove_beet_encap(x, skb);
339339
}
340340
break;

net/xfrm/xfrm_interface_core.c

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,6 +310,52 @@ static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
310310
skb->mark = 0;
311311
}
312312

313+
static int xfrmi_input(struct sk_buff *skb, int nexthdr, __be32 spi,
314+
int encap_type, unsigned short family)
315+
{
316+
struct sec_path *sp;
317+
318+
sp = skb_sec_path(skb);
319+
if (sp && (sp->len || sp->olen) &&
320+
!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family))
321+
goto discard;
322+
323+
XFRM_SPI_SKB_CB(skb)->family = family;
324+
if (family == AF_INET) {
325+
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
326+
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL;
327+
} else {
328+
XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
329+
XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL;
330+
}
331+
332+
return xfrm_input(skb, nexthdr, spi, encap_type);
333+
discard:
334+
kfree_skb(skb);
335+
return 0;
336+
}
337+
338+
static int xfrmi4_rcv(struct sk_buff *skb)
339+
{
340+
return xfrmi_input(skb, ip_hdr(skb)->protocol, 0, 0, AF_INET);
341+
}
342+
343+
static int xfrmi6_rcv(struct sk_buff *skb)
344+
{
345+
return xfrmi_input(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
346+
0, 0, AF_INET6);
347+
}
348+
349+
static int xfrmi4_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
350+
{
351+
return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET);
352+
}
353+
354+
static int xfrmi6_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
355+
{
356+
return xfrmi_input(skb, nexthdr, spi, encap_type, AF_INET6);
357+
}
358+
313359
static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
314360
{
315361
const struct xfrm_mode *inner_mode;
@@ -945,8 +991,8 @@ static struct pernet_operations xfrmi_net_ops = {
945991
};
946992

947993
static struct xfrm6_protocol xfrmi_esp6_protocol __read_mostly = {
948-
.handler = xfrm6_rcv,
949-
.input_handler = xfrm_input,
994+
.handler = xfrmi6_rcv,
995+
.input_handler = xfrmi6_input,
950996
.cb_handler = xfrmi_rcv_cb,
951997
.err_handler = xfrmi6_err,
952998
.priority = 10,
@@ -996,8 +1042,8 @@ static struct xfrm6_tunnel xfrmi_ip6ip_handler __read_mostly = {
9961042
#endif
9971043

9981044
static struct xfrm4_protocol xfrmi_esp4_protocol __read_mostly = {
999-
.handler = xfrm4_rcv,
1000-
.input_handler = xfrm_input,
1045+
.handler = xfrmi4_rcv,
1046+
.input_handler = xfrmi4_input,
10011047
.cb_handler = xfrmi_rcv_cb,
10021048
.err_handler = xfrmi4_err,
10031049
.priority = 10,

net/xfrm/xfrm_policy.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,6 +1831,7 @@ int xfrm_policy_flush(struct net *net, u8 type, bool task_valid)
18311831

18321832
__xfrm_policy_unlink(pol, dir);
18331833
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
1834+
xfrm_dev_policy_delete(pol);
18341835
cnt++;
18351836
xfrm_audit_policy_delete(pol, 1, task_valid);
18361837
xfrm_policy_kill(pol);
@@ -1869,6 +1870,7 @@ int xfrm_dev_policy_flush(struct net *net, struct net_device *dev,
18691870

18701871
__xfrm_policy_unlink(pol, dir);
18711872
spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
1873+
xfrm_dev_policy_delete(pol);
18721874
cnt++;
18731875
xfrm_audit_policy_delete(pol, 1, task_valid);
18741876
xfrm_policy_kill(pol);
@@ -3349,6 +3351,13 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star
33493351
if (xfrm_state_ok(tmpl, sp->xvec[idx], family, if_id))
33503352
return ++idx;
33513353
if (sp->xvec[idx]->props.mode != XFRM_MODE_TRANSPORT) {
3354+
if (idx < sp->verified_cnt) {
3355+
/* Secpath entry previously verified, consider optional and
3356+
* continue searching
3357+
*/
3358+
continue;
3359+
}
3360+
33523361
if (start == -1)
33533362
start = -2-idx;
33543363
break;
@@ -3723,6 +3732,9 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
37233732
* Order is _important_. Later we will implement
37243733
* some barriers, but at the moment barriers
37253734
* are implied between each two transformations.
3735+
* Upon success, marks secpath entries as having been
3736+
* verified to allow them to be skipped in future policy
3737+
* checks (e.g. nested tunnels).
37263738
*/
37273739
for (i = xfrm_nr-1, k = 0; i >= 0; i--) {
37283740
k = xfrm_policy_ok(tpp[i], sp, k, family, if_id);
@@ -3741,6 +3753,8 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
37413753
}
37423754

37433755
xfrm_pols_put(pols, npols);
3756+
sp->verified_cnt = k;
3757+
37443758
return 1;
37453759
}
37463760
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLBLOCK);

0 commit comments

Comments
 (0)