Skip to content

Commit 9d76deb

Browse files
committed
Merge: [RHEL9.5 P1] SRv6: Backport from upstream
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/3953 JIRA: https://issues.redhat.com/browse/RHEL-30814 JIRA: https://issues.redhat.com/browse/RHEL-31732 CVE: CVE-2024-26735 Signed-off-by: Hangbin Liu <haliu@redhat.com> Approved-by: Guillaume Nault <gnault@redhat.com> Approved-by: Felix Maurer <fmaurer@redhat.com> Merged-by: Lucas Zampieri <lzampier@redhat.com>
2 parents 0697620 + f44dc80 commit 9d76deb

File tree

6 files changed

+1314
-34
lines changed

6 files changed

+1314
-34
lines changed

net/ipv6/exthdrs.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -447,8 +447,6 @@ static int ipv6_srh_rcv(struct sk_buff *skb)
447447

448448
ipv6_hdr(skb)->daddr = *addr;
449449

450-
skb_dst_drop(skb);
451-
452450
ip6_route_input(skb);
453451

454452
if (skb_dst(skb)->error) {
@@ -820,7 +818,6 @@ static int ipv6_rthdr_rcv(struct sk_buff *skb)
820818
*addr = ipv6_hdr(skb)->daddr;
821819
ipv6_hdr(skb)->daddr = daddr;
822820

823-
skb_dst_drop(skb);
824821
ip6_route_input(skb);
825822
if (skb_dst(skb)->error) {
826823
skb_push(skb, skb->data - skb_network_header(skb));

net/ipv6/seg6.c

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -512,22 +512,24 @@ int __init seg6_init(void)
512512
{
513513
int err;
514514

515-
err = genl_register_family(&seg6_genl_family);
515+
err = register_pernet_subsys(&ip6_segments_ops);
516516
if (err)
517517
goto out;
518518

519-
err = register_pernet_subsys(&ip6_segments_ops);
519+
err = genl_register_family(&seg6_genl_family);
520520
if (err)
521-
goto out_unregister_genl;
521+
goto out_unregister_pernet;
522522

523523
#ifdef CONFIG_IPV6_SEG6_LWTUNNEL
524524
err = seg6_iptunnel_init();
525525
if (err)
526-
goto out_unregister_pernet;
526+
goto out_unregister_genl;
527527

528528
err = seg6_local_init();
529-
if (err)
530-
goto out_unregister_pernet;
529+
if (err) {
530+
seg6_iptunnel_exit();
531+
goto out_unregister_genl;
532+
}
531533
#endif
532534

533535
#ifdef CONFIG_IPV6_SEG6_HMAC
@@ -548,11 +550,11 @@ int __init seg6_init(void)
548550
#endif
549551
#endif
550552
#ifdef CONFIG_IPV6_SEG6_LWTUNNEL
551-
out_unregister_pernet:
552-
unregister_pernet_subsys(&ip6_segments_ops);
553-
#endif
554553
out_unregister_genl:
555554
genl_unregister_family(&seg6_genl_family);
555+
#endif
556+
out_unregister_pernet:
557+
unregister_pernet_subsys(&ip6_segments_ops);
556558
goto out;
557559
}
558560

net/ipv6/seg6_iptunnel.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,8 +470,6 @@ static int seg6_input_core(struct net *net, struct sock *sk,
470470
dst = dst_cache_get(&slwt->cache);
471471
preempt_enable();
472472

473-
skb_dst_drop(skb);
474-
475473
if (!dst) {
476474
ip6_route_input(skb);
477475
dst = skb_dst(skb);
@@ -482,6 +480,7 @@ static int seg6_input_core(struct net *net, struct sock *sk,
482480
preempt_enable();
483481
}
484482
} else {
483+
skb_dst_drop(skb);
485484
skb_dst_set(skb, dst);
486485
}
487486

net/ipv6/seg6_local.c

Lines changed: 88 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -109,15 +109,19 @@ struct bpf_lwt_prog {
109109
#define next_csid_chk_lcnode_fn_bits(flen) \
110110
next_csid_chk_lcblock_bits(flen)
111111

112+
/* flag indicating that flavors are set up for a given End* behavior */
113+
#define SEG6_F_LOCAL_FLAVORS SEG6_F_ATTR(SEG6_LOCAL_FLAVORS)
114+
112115
#define SEG6_F_LOCAL_FLV_OP(flvname) BIT(SEG6_LOCAL_FLV_OP_##flvname)
116+
#define SEG6_F_LOCAL_FLV_NEXT_CSID SEG6_F_LOCAL_FLV_OP(NEXT_CSID)
113117
#define SEG6_F_LOCAL_FLV_PSP SEG6_F_LOCAL_FLV_OP(PSP)
114118

115119
/* Supported RFC8986 Flavor operations are reported in this bitmask */
116120
#define SEG6_LOCAL_FLV8986_SUPP_OPS SEG6_F_LOCAL_FLV_PSP
117121

118-
/* Supported Flavor operations are reported in this bitmask */
119-
#define SEG6_LOCAL_FLV_SUPP_OPS (SEG6_F_LOCAL_FLV_OP(NEXT_CSID) | \
122+
#define SEG6_LOCAL_END_FLV_SUPP_OPS (SEG6_F_LOCAL_FLV_NEXT_CSID | \
120123
SEG6_LOCAL_FLV8986_SUPP_OPS)
124+
#define SEG6_LOCAL_END_X_FLV_SUPP_OPS SEG6_F_LOCAL_FLV_NEXT_CSID
121125

122126
struct seg6_flavors_info {
123127
/* Flavor operations */
@@ -411,9 +415,72 @@ static int end_next_csid_core(struct sk_buff *skb, struct seg6_local_lwt *slwt)
411415
return input_action_end_finish(skb, slwt);
412416
}
413417

418+
static int input_action_end_x_finish(struct sk_buff *skb,
419+
struct seg6_local_lwt *slwt)
420+
{
421+
seg6_lookup_nexthop(skb, &slwt->nh6, 0);
422+
423+
return dst_input(skb);
424+
}
425+
426+
static int input_action_end_x_core(struct sk_buff *skb,
427+
struct seg6_local_lwt *slwt)
428+
{
429+
struct ipv6_sr_hdr *srh;
430+
431+
srh = get_and_validate_srh(skb);
432+
if (!srh)
433+
goto drop;
434+
435+
advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
436+
437+
return input_action_end_x_finish(skb, slwt);
438+
439+
drop:
440+
kfree_skb(skb);
441+
return -EINVAL;
442+
}
443+
444+
static int end_x_next_csid_core(struct sk_buff *skb,
445+
struct seg6_local_lwt *slwt)
446+
{
447+
const struct seg6_flavors_info *finfo = &slwt->flv_info;
448+
struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
449+
450+
if (seg6_next_csid_is_arg_zero(daddr, finfo))
451+
return input_action_end_x_core(skb, slwt);
452+
453+
/* update DA */
454+
seg6_next_csid_advance_arg(daddr, finfo);
455+
456+
return input_action_end_x_finish(skb, slwt);
457+
}
458+
414459
static bool seg6_next_csid_enabled(__u32 fops)
415460
{
416-
return fops & BIT(SEG6_LOCAL_FLV_OP_NEXT_CSID);
461+
return fops & SEG6_F_LOCAL_FLV_NEXT_CSID;
462+
}
463+
464+
/* Processing of SRv6 End, End.X, and End.T behaviors can be extended through
465+
* the flavors framework. These behaviors must report the subset of (flavor)
466+
* operations they currently implement. In this way, if a user specifies a
467+
* flavor combination that is not supported by a given End* behavior, the
468+
* kernel refuses to instantiate the tunnel reporting the error.
469+
*/
470+
static int seg6_flv_supp_ops_by_action(int action, __u32 *fops)
471+
{
472+
switch (action) {
473+
case SEG6_LOCAL_ACTION_END:
474+
*fops = SEG6_LOCAL_END_FLV_SUPP_OPS;
475+
break;
476+
case SEG6_LOCAL_ACTION_END_X:
477+
*fops = SEG6_LOCAL_END_X_FLV_SUPP_OPS;
478+
break;
479+
default:
480+
return -EOPNOTSUPP;
481+
}
482+
483+
return 0;
417484
}
418485

419486
/* We describe the packet state in relation to the absence/presence of the SRH
@@ -746,21 +813,14 @@ static int input_action_end(struct sk_buff *skb, struct seg6_local_lwt *slwt)
746813
/* regular endpoint, and forward to specified nexthop */
747814
static int input_action_end_x(struct sk_buff *skb, struct seg6_local_lwt *slwt)
748815
{
749-
struct ipv6_sr_hdr *srh;
750-
751-
srh = get_and_validate_srh(skb);
752-
if (!srh)
753-
goto drop;
754-
755-
advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
756-
757-
seg6_lookup_nexthop(skb, &slwt->nh6, 0);
816+
const struct seg6_flavors_info *finfo = &slwt->flv_info;
817+
__u32 fops = finfo->flv_ops;
758818

759-
return dst_input(skb);
819+
/* check for the presence of NEXT-C-SID since it applies first */
820+
if (seg6_next_csid_enabled(fops))
821+
return end_x_next_csid_core(skb, slwt);
760822

761-
drop:
762-
kfree_skb(skb);
763-
return -EINVAL;
823+
return input_action_end_x_core(skb, slwt);
764824
}
765825

766826
static int input_action_end_t(struct sk_buff *skb, struct seg6_local_lwt *slwt)
@@ -1404,13 +1464,14 @@ static struct seg6_action_desc seg6_action_table[] = {
14041464
.action = SEG6_LOCAL_ACTION_END,
14051465
.attrs = 0,
14061466
.optattrs = SEG6_F_LOCAL_COUNTERS |
1407-
SEG6_F_ATTR(SEG6_LOCAL_FLAVORS),
1467+
SEG6_F_LOCAL_FLAVORS,
14081468
.input = input_action_end,
14091469
},
14101470
{
14111471
.action = SEG6_LOCAL_ACTION_END_X,
14121472
.attrs = SEG6_F_ATTR(SEG6_LOCAL_NH6),
1413-
.optattrs = SEG6_F_LOCAL_COUNTERS,
1473+
.optattrs = SEG6_F_LOCAL_COUNTERS |
1474+
SEG6_F_LOCAL_FLAVORS,
14141475
.input = input_action_end_x,
14151476
},
14161477
{
@@ -2070,7 +2131,8 @@ static int parse_nla_flavors(struct nlattr **attrs, struct seg6_local_lwt *slwt,
20702131
{
20712132
struct seg6_flavors_info *finfo = &slwt->flv_info;
20722133
struct nlattr *tb[SEG6_LOCAL_FLV_MAX + 1];
2073-
unsigned long fops;
2134+
int action = slwt->action;
2135+
__u32 fops, supp_fops;
20742136
int rc;
20752137

20762138
rc = nla_parse_nested_deprecated(tb, SEG6_LOCAL_FLV_MAX,
@@ -2086,7 +2148,8 @@ static int parse_nla_flavors(struct nlattr **attrs, struct seg6_local_lwt *slwt,
20862148
return -EINVAL;
20872149

20882150
fops = nla_get_u32(tb[SEG6_LOCAL_FLV_OPERATION]);
2089-
if (fops & ~SEG6_LOCAL_FLV_SUPP_OPS) {
2151+
rc = seg6_flv_supp_ops_by_action(action, &supp_fops);
2152+
if (rc < 0 || (fops & ~supp_fops)) {
20902153
NL_SET_ERR_MSG(extack, "Unsupported Flavor operation(s)");
20912154
return -EOPNOTSUPP;
20922155
}
@@ -2618,6 +2681,11 @@ int __init seg6_local_init(void)
26182681
*/
26192682
BUILD_BUG_ON(SEG6_LOCAL_MAX + 1 > BITS_PER_TYPE(unsigned long));
26202683

2684+
/* Check whether the number of defined flavors exceeds the maximum
2685+
* allowed value.
2686+
*/
2687+
BUILD_BUG_ON(SEG6_LOCAL_FLV_OP_MAX + 1 > BITS_PER_TYPE(__u32));
2688+
26212689
/* If the default NEXT-C-SID Locator-Block/Node Function lengths (in
26222690
* bits) have been changed with invalid values, kernel build stops
26232691
* here.

tools/testing/selftests/net/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ TEST_PROGS += srv6_end_dt6_l3vpn_test.sh
3434
TEST_PROGS += srv6_hencap_red_l3vpn_test.sh
3535
TEST_PROGS += srv6_hl2encap_red_l2vpn_test.sh
3636
TEST_PROGS += srv6_end_next_csid_l3vpn_test.sh
37+
TEST_PROGS += srv6_end_x_next_csid_l3vpn_test.sh
3738
TEST_PROGS += srv6_end_flavors_test.sh
3839
TEST_PROGS += vrf_strict_mode_test.sh
3940
TEST_PROGS += stress_reuseport_listen.sh

0 commit comments

Comments
 (0)