Skip to content

Commit 5f24f41

Browse files
herbertxklassert
authored andcommitted
xfrm: Remove inner/outer modes from input path
The inner/outer modes were added to abstract out common code that were once duplicated between IPv4 and IPv6. As time went on the abstractions have been removed and we are now left with empty shells that only contain duplicate information. These can be removed one-by-one as the same information is already present elsewhere in the xfrm_state object. Removing them from the input path actually allows certain valid combinations that are currently disallowed. In particular, when a transport mode SA sits beneath a tunnel mode SA that changes address families, at present the transport mode SA cannot have AF_UNSPEC as its selector because it will be erroneously be treated as inter-family itself even though it simply sits beneath one. This is a serious problem because you can't set the selector to non-AF_UNSPEC either as that will cause the selector match to fail as we always match selectors to the inner-most traffic. Signed-off-by: Herbert Xu <[email protected]> Signed-off-by: Steffen Klassert <[email protected]>
1 parent 95b7445 commit 5f24f41

File tree

1 file changed

+23
-43
lines changed

1 file changed

+23
-43
lines changed

net/xfrm/xfrm_input.c

Lines changed: 23 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,6 @@ static int xfrm4_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
231231
{
232232
int err = -EINVAL;
233233

234-
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
235-
goto out;
236-
237234
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
238235
goto out;
239236

@@ -269,8 +266,6 @@ static int xfrm6_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
269266
{
270267
int err = -EINVAL;
271268

272-
if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
273-
goto out;
274269
if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
275270
goto out;
276271

@@ -331,22 +326,26 @@ static int xfrm6_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
331326
*/
332327
static int
333328
xfrm_inner_mode_encap_remove(struct xfrm_state *x,
334-
const struct xfrm_mode *inner_mode,
335329
struct sk_buff *skb)
336330
{
337-
switch (inner_mode->encap) {
331+
switch (x->props.mode) {
338332
case XFRM_MODE_BEET:
339-
if (inner_mode->family == AF_INET)
333+
switch (XFRM_MODE_SKB_CB(skb)->protocol) {
334+
case IPPROTO_IPIP:
335+
case IPPROTO_BEETPH:
340336
return xfrm4_remove_beet_encap(x, skb);
341-
if (inner_mode->family == AF_INET6)
337+
case IPPROTO_IPV6:
342338
return xfrm6_remove_beet_encap(x, skb);
339+
}
343340
break;
344341
case XFRM_MODE_TUNNEL:
345-
if (inner_mode->family == AF_INET)
342+
switch (XFRM_MODE_SKB_CB(skb)->protocol) {
343+
case IPPROTO_IPIP:
346344
return xfrm4_remove_tunnel_encap(x, skb);
347-
if (inner_mode->family == AF_INET6)
345+
case IPPROTO_IPV6:
348346
return xfrm6_remove_tunnel_encap(x, skb);
349347
break;
348+
}
350349
}
351350

352351
WARN_ON_ONCE(1);
@@ -355,9 +354,7 @@ xfrm_inner_mode_encap_remove(struct xfrm_state *x,
355354

356355
static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
357356
{
358-
const struct xfrm_mode *inner_mode = &x->inner_mode;
359-
360-
switch (x->outer_mode.family) {
357+
switch (x->props.family) {
361358
case AF_INET:
362359
xfrm4_extract_header(skb);
363360
break;
@@ -369,25 +366,20 @@ static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
369366
return -EAFNOSUPPORT;
370367
}
371368

372-
if (x->sel.family == AF_UNSPEC) {
373-
inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
374-
if (!inner_mode)
375-
return -EAFNOSUPPORT;
376-
}
377-
378-
switch (inner_mode->family) {
379-
case AF_INET:
369+
switch (XFRM_MODE_SKB_CB(skb)->protocol) {
370+
case IPPROTO_IPIP:
371+
case IPPROTO_BEETPH:
380372
skb->protocol = htons(ETH_P_IP);
381373
break;
382-
case AF_INET6:
374+
case IPPROTO_IPV6:
383375
skb->protocol = htons(ETH_P_IPV6);
384376
break;
385377
default:
386378
WARN_ON_ONCE(1);
387379
break;
388380
}
389381

390-
return xfrm_inner_mode_encap_remove(x, inner_mode, skb);
382+
return xfrm_inner_mode_encap_remove(x, skb);
391383
}
392384

393385
/* Remove encapsulation header.
@@ -433,17 +425,16 @@ static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
433425
}
434426

435427
static int xfrm_inner_mode_input(struct xfrm_state *x,
436-
const struct xfrm_mode *inner_mode,
437428
struct sk_buff *skb)
438429
{
439-
switch (inner_mode->encap) {
430+
switch (x->props.mode) {
440431
case XFRM_MODE_BEET:
441432
case XFRM_MODE_TUNNEL:
442433
return xfrm_prepare_input(x, skb);
443434
case XFRM_MODE_TRANSPORT:
444-
if (inner_mode->family == AF_INET)
435+
if (x->props.family == AF_INET)
445436
return xfrm4_transport_input(x, skb);
446-
if (inner_mode->family == AF_INET6)
437+
if (x->props.family == AF_INET6)
447438
return xfrm6_transport_input(x, skb);
448439
break;
449440
case XFRM_MODE_ROUTEOPTIMIZATION:
@@ -461,7 +452,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
461452
{
462453
const struct xfrm_state_afinfo *afinfo;
463454
struct net *net = dev_net(skb->dev);
464-
const struct xfrm_mode *inner_mode;
465455
int err;
466456
__be32 seq;
467457
__be32 seq_hi;
@@ -491,7 +481,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
491481
goto drop;
492482
}
493483

494-
family = x->outer_mode.family;
484+
family = x->props.family;
495485

496486
/* An encap_type of -1 indicates async resumption. */
497487
if (encap_type == -1) {
@@ -676,17 +666,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
676666

677667
XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
678668

679-
inner_mode = &x->inner_mode;
680-
681-
if (x->sel.family == AF_UNSPEC) {
682-
inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
683-
if (inner_mode == NULL) {
684-
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR);
685-
goto drop;
686-
}
687-
}
688-
689-
if (xfrm_inner_mode_input(x, inner_mode, skb)) {
669+
if (xfrm_inner_mode_input(x, skb)) {
690670
XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR);
691671
goto drop;
692672
}
@@ -701,7 +681,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
701681
* transport mode so the outer address is identical.
702682
*/
703683
daddr = &x->id.daddr;
704-
family = x->outer_mode.family;
684+
family = x->props.family;
705685

706686
err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
707687
if (err < 0) {
@@ -732,7 +712,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
732712

733713
err = -EAFNOSUPPORT;
734714
rcu_read_lock();
735-
afinfo = xfrm_state_afinfo_get_rcu(x->inner_mode.family);
715+
afinfo = xfrm_state_afinfo_get_rcu(x->props.family);
736716
if (likely(afinfo))
737717
err = afinfo->transport_finish(skb, xfrm_gro || async);
738718
rcu_read_unlock();

0 commit comments

Comments
 (0)