Skip to content

[rlc-8/4.18.0-553.162.1.el8_10] mpls: add seqcount to protect the platform_label{,s} pair - #1612

Open
ciq-kernel-automation[bot] wants to merge 1 commit into
rlc-8/4.18.0-553.162.1.el8_10from
{bmastbergen_nebusec}_rlc-8/4.18.0-553.162.1.el8_10
Open

ciq-kernel-automation[bot] wants to merge 1 commit into
rlc-8/4.18.0-553.162.1.el8_10from
{bmastbergen_nebusec}_rlc-8/4.18.0-553.162.1.el8_10

Conversation

@ciq-kernel-automation

@ciq-kernel-automation ciq-kernel-automation Bot commented Sep 16, 2026

Copy link
Copy Markdown

Summary

This PR has been automatically created after successful completion of all CI stages.

Commit Message(s)

mpls: add seqcount to protect the platform_label{,s} pair

cve CVE-2026-43042
commit-author Sabrina Dubroca <sd@queasysnail.net>
commit 629ec78ef8608d955ce217880cdc3e1873af3a15
upstream-diff Uses a file-scope seqcount_t instead of upstream's
  per-netns seqcount_mutex_t to avoid a kABI-breaking struct
  change. Write side uses local_bh_disable() with a conditional preempt_disable() on PREEMPT_RT
  for RT safety. Uses rcu_dereference_rtnl() instead of
  upstream's plain rcu_dereference() to stay lockdep-clean
  under RTNL. mpls_dump_routes() still runs under RTNL on
  this tree; the seqcount there is extra hardening.

Test Results

✅ Build Stage

Architecture Build Time Total Time
x86_64 19m 25s 20m 33s
aarch64 11m 0s 11m 43s

✅ Boot Verification

✅ Kernel Selftests

Architecture Passed Failed Compared Against Status
x86_64 121 35 rlc-8/4.18.0-553.162.1.el8_10 ⚠️ No baseline available
aarch64 72 32 rlc-8/4.18.0-553.162.1.el8_10 ⚠️ No baseline available

✅ LTP Results

Architecture Passed Failed Compared Against Status
x86_64 1409 83 rlc-8/4.18.0-553.162.1.el8_10 ⚠️ No baseline available
aarch64 1380 84 rlc-8/4.18.0-553.162.1.el8_10 ⚠️ No baseline available

🤖 This PR was automatically generated by GitHub Actions
Run ID: 35244468137

@ciq-kernel-automation ciq-kernel-automation Bot added the created-by-kernelci Tag PRs that were automatically created when a user branch was pushed to the repo (kernelCI) label Sep 16, 2026
@github-actions

Copy link
Copy Markdown

🤖 Validation Checks In Progress Workflow run: https://github.com/ctrliq/kernel-src-tree/actions/runs/35040099672

@github-actions

Copy link
Copy Markdown

🔍 Interdiff Analysis

  • ⚠️ PR commit 2138aa3ee6ac (mpls: add seqcount to protect the platform_label{,s} pair) → upstream 629ec78ef860
    Differences found:
================================================================================
*    DELTA DIFFERENCES - code changes that differ between the patches          *
================================================================================

--- b/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -36,8 +36,6 @@
 
 #define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1)
 
-static seqcount_t mpls_platform_label_seq = SEQCNT_ZERO(mpls_platform_label_seq);
-
 static int label_limit = (1 << 20) - 1;
 static int ttl_max = 255;
 
@@ -75,32 +73,16 @@
 		       struct nlmsghdr *nlh, struct net *net, u32 portid,
 		       unsigned int nlm_flags);
 
-static struct mpls_route __rcu **mpls_platform_label_rcu(struct net *net,
-							size_t *platform_labels)
-{
-	struct mpls_route __rcu **platform_label;
-	unsigned int sequence;
-
-	do {
-		sequence = read_seqcount_begin(&mpls_platform_label_seq);
-		platform_label = rcu_dereference(net->mpls.platform_label);
-		*platform_labels = net->mpls.platform_labels;
-	} while (read_seqcount_retry(&mpls_platform_label_seq, sequence));
-
-	return platform_label;
-}
-
 static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index)
 {
-	struct mpls_route __rcu **platform_label;
-	size_t platform_labels;
-
-	platform_label = mpls_platform_label_rcu(net, &platform_labels);
+	struct mpls_route *rt = NULL;
 
-	if (index < platform_labels)
-		return rcu_dereference(platform_label[index]);
-
-	return NULL;
+	if (index < net->mpls.platform_labels) {
+		struct mpls_route __rcu **platform_label =
+			rcu_dereference(net->mpls.platform_label);
+		rt = rcu_dereference(platform_label[index]);
+	}
+	return rt;
 }
 
 bool mpls_output_possible(const struct net_device *dev)
@@ -2233,7 +2215,8 @@
 	if (index < MPLS_LABEL_FIRST_UNRESERVED)
 		index = MPLS_LABEL_FIRST_UNRESERVED;
 
-	platform_label = mpls_platform_label_rcu(net, &platform_labels);
+	platform_label = rtnl_dereference(net->mpls.platform_label);
+	platform_labels = net->mpls.platform_labels;
 
 	if (filter.filter_set)
 		flags |= NLM_F_DUMP_FILTERED;
@@ -2620,10 +2603,10 @@
 
 	/* Update the global pointers */
 	local_bh_disable();
-	write_seqcount_begin(&mpls_platform_label_seq);
+	write_seqcount_begin(&net->mpls.platform_label_seq);
 	net->mpls.platform_labels = limit;
 	rcu_assign_pointer(net->mpls.platform_label, labels);
-	write_seqcount_end(&mpls_platform_label_seq);
+	write_seqcount_end(&net->mpls.platform_label_seq);
 	local_bh_enable();
 
 	rtnl_unlock();

################################################################################
!    REJECTED PATCH2 HUNKS - could not be compared; manual review needed       !
################################################################################

--- b/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -83,6 +83,20 @@
 	return mpls_dereference(net, platform_label[index]);
 }
 
+static struct mpls_route __rcu **mpls_platform_label_rcu(struct net *net, size_t *platform_labels)
+{
+	struct mpls_route __rcu **platform_label;
+	unsigned int sequence;
+
+	do {
+		sequence = read_seqcount_begin(&net->mpls.platform_label_seq);
+		platform_label = rcu_dereference(net->mpls.platform_label);
+		*platform_labels = net->mpls.platform_labels;
+	} while (read_seqcount_retry(&net->mpls.platform_label_seq, sequence));
+
+	return platform_label;
+}
+
 static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned int index)
 {
 	struct mpls_route __rcu **platform_label;
@@ -86,6 +100,9 @@
 static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned int index)
 {
 	struct mpls_route __rcu **platform_label;
+	size_t platform_labels;
+
+	platform_label = mpls_platform_label_rcu(net, &platform_labels);
 
 	if (index >= net->mpls.platform_labels)
 		return NULL;
@@ -87,7 +104,7 @@
 {
 	struct mpls_route __rcu **platform_label;
 
-	if (index >= net->mpls.platform_labels)
+	if (index >= platform_labels)
 		return NULL;
 
 	platform_label = rcu_dereference(net->mpls.platform_label);
@@ -90,7 +107,6 @@
 	if (index >= net->mpls.platform_labels)
 		return NULL;
 
-	platform_label = rcu_dereference(net->mpls.platform_label);
 	return rcu_dereference(platform_label[index]);
 }
 
@@ -2240,8 +2256,7 @@
 	if (index < MPLS_LABEL_FIRST_UNRESERVED)
 		index = MPLS_LABEL_FIRST_UNRESERVED;
 
-	platform_label = rcu_dereference(net->mpls.platform_label);
-	platform_labels = net->mpls.platform_labels;
+	platform_label = mpls_platform_label_rcu(net, &platform_labels);
 
 	if (filter.filter_set)
 		flags |= NLM_F_DUMP_FILTERED;
@@ -2732,6 +2751,8 @@
 	int i;
 
 	mutex_init(&net->mpls.platform_mutex);
+	seqcount_mutex_init(&net->mpls.platform_label_seq, &net->mpls.platform_mutex);
+
 	net->mpls.platform_labels = 0;
 	net->mpls.platform_label = NULL;
 	net->mpls.ip_ttl_propagate = 1;

================================================================================
*    CONTEXT DIFFERENCES - surrounding code differences between the patches    *
================================================================================

--- b/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -70,13 +66,12 @@
 
-static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index)
+static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned int index)
 {
-	struct mpls_route *rt = NULL;
+	struct mpls_route __rcu **platform_label;
 
-	if (index < net->mpls.platform_labels) {
-		struct mpls_route __rcu **platform_label =
-			rcu_dereference(net->mpls.platform_label);
-		rt = rcu_dereference(platform_label[index]);
-	}
-	return rt;
+	if (index >= net->mpls.platform_labels)
+		return NULL;
+
+	platform_label = rcu_dereference(net->mpls.platform_label);
+	return rcu_dereference(platform_label[index]);
 }
 
@@ -2215,7 +2240,7 @@
 	if (index < MPLS_LABEL_FIRST_UNRESERVED)
 		index = MPLS_LABEL_FIRST_UNRESERVED;
 
-	platform_label = rtnl_dereference(net->mpls.platform_label);
+	platform_label = rcu_dereference(net->mpls.platform_label);
 	platform_labels = net->mpls.platform_labels;
 
 	if (filter.filter_set)
@@ -2599,7 +2624,8 @@
 	}
 
 	/* Update the global pointers */
 	net->mpls.platform_labels = limit;
 	rcu_assign_pointer(net->mpls.platform_label, labels);
 
-	rtnl_unlock();
+	mutex_unlock(&net->mpls.platform_mutex);
+

================================================================================
*    ONLY IN PATCH2 - files not modified by patch1                             *
================================================================================

--- a/include/net/netns/mpls.h
+++ b/include/net/netns/mpls.h
@@ -17,6 +17,7 @@ struct netns_mpls {
 	size_t platform_labels;
 	struct mpls_route __rcu * __rcu *platform_label;
 	struct mutex platform_mutex;
+	seqcount_mutex_t platform_label_seq;
 
 	struct ctl_table_header *ctl;
 };

This is an automated interdiff check for backported commits.

@github-actions

Copy link
Copy Markdown

Validation checks completed successfully View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/35040099672

@bmastbergen
bmastbergen marked this pull request as draft September 16, 2026 14:59
@bmastbergen
bmastbergen force-pushed the {bmastbergen_nebusec}_rlc-8/4.18.0-553.162.1.el8_10 branch from 2138aa3 to de97983 Compare September 16, 2026 15:50
@github-actions

Copy link
Copy Markdown

🤖 Validation Checks In Progress Workflow run: https://github.com/ctrliq/kernel-src-tree/actions/runs/35119249333

@github-actions

Copy link
Copy Markdown

🔍 Interdiff Analysis

  • ⚠️ PR commit de979833e369 (mpls: add seqcount to protect the platform_label{,s} pair) → upstream 629ec78ef860
    Differences found:
================================================================================
*    DELTA DIFFERENCES - code changes that differ between the patches          *
================================================================================

--- b/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -36,10 +36,6 @@
 
 #define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1)
 
-static DEFINE_SPINLOCK(mpls_platform_label_lock);
-static seqcount_spinlock_t mpls_platform_label_seq =
-	SEQCNT_SPINLOCK_ZERO(mpls_platform_label_seq, &mpls_platform_label_lock);
-
 static int label_limit = (1 << 20) - 1;
 static int ttl_max = 255;
 
@@ -77,32 +73,16 @@
 		       struct nlmsghdr *nlh, struct net *net, u32 portid,
 		       unsigned int nlm_flags);
 
-static struct mpls_route __rcu **mpls_platform_label_rcu(struct net *net,
-							size_t *platform_labels)
-{
-	struct mpls_route __rcu **platform_label;
-	unsigned int sequence;
-
-	do {
-		sequence = read_seqcount_begin(&mpls_platform_label_seq);
-		platform_label = rcu_dereference(net->mpls.platform_label);
-		*platform_labels = net->mpls.platform_labels;
-	} while (read_seqcount_retry(&mpls_platform_label_seq, sequence));
-
-	return platform_label;
-}
-
 static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index)
 {
-	struct mpls_route __rcu **platform_label;
-	size_t platform_labels;
-
-	platform_label = mpls_platform_label_rcu(net, &platform_labels);
+	struct mpls_route *rt = NULL;
 
-	if (index < platform_labels)
-		return rcu_dereference(platform_label[index]);
-
-	return NULL;
+	if (index < net->mpls.platform_labels) {
+		struct mpls_route __rcu **platform_label =
+			rcu_dereference(net->mpls.platform_label);
+		rt = rcu_dereference(platform_label[index]);
+	}
+	return rt;
 }
 
 bool mpls_output_possible(const struct net_device *dev)
@@ -2235,7 +2215,8 @@
 	if (index < MPLS_LABEL_FIRST_UNRESERVED)
 		index = MPLS_LABEL_FIRST_UNRESERVED;
 
-	platform_label = mpls_platform_label_rcu(net, &platform_labels);
+	platform_label = rtnl_dereference(net->mpls.platform_label);
+	platform_labels = net->mpls.platform_labels;
 
 	if (filter.filter_set)
 		flags |= NLM_F_DUMP_FILTERED;
@@ -2621,12 +2602,12 @@
 	}
 
 	/* Update the global pointers */
-	spin_lock_bh(&mpls_platform_label_lock);
-	write_seqcount_begin(&mpls_platform_label_seq);
+	local_bh_disable();
+	write_seqcount_begin(&net->mpls.platform_label_seq);
 	net->mpls.platform_labels = limit;
 	rcu_assign_pointer(net->mpls.platform_label, labels);
-	write_seqcount_end(&mpls_platform_label_seq);
-	spin_unlock_bh(&mpls_platform_label_lock);
+	write_seqcount_end(&net->mpls.platform_label_seq);
+	local_bh_enable();
 
 	rtnl_unlock();
 

################################################################################
!    REJECTED PATCH2 HUNKS - could not be compared; manual review needed       !
################################################################################

--- b/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -83,6 +83,20 @@
 	return mpls_dereference(net, platform_label[index]);
 }
 
+static struct mpls_route __rcu **mpls_platform_label_rcu(struct net *net, size_t *platform_labels)
+{
+	struct mpls_route __rcu **platform_label;
+	unsigned int sequence;
+
+	do {
+		sequence = read_seqcount_begin(&net->mpls.platform_label_seq);
+		platform_label = rcu_dereference(net->mpls.platform_label);
+		*platform_labels = net->mpls.platform_labels;
+	} while (read_seqcount_retry(&net->mpls.platform_label_seq, sequence));
+
+	return platform_label;
+}
+
 static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned int index)
 {
 	struct mpls_route __rcu **platform_label;
@@ -86,6 +100,9 @@
 static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned int index)
 {
 	struct mpls_route __rcu **platform_label;
+	size_t platform_labels;
+
+	platform_label = mpls_platform_label_rcu(net, &platform_labels);
 
 	if (index >= net->mpls.platform_labels)
 		return NULL;
@@ -87,7 +104,7 @@
 {
 	struct mpls_route __rcu **platform_label;
 
-	if (index >= net->mpls.platform_labels)
+	if (index >= platform_labels)
 		return NULL;
 
 	platform_label = rcu_dereference(net->mpls.platform_label);
@@ -90,7 +107,6 @@
 	if (index >= net->mpls.platform_labels)
 		return NULL;
 
-	platform_label = rcu_dereference(net->mpls.platform_label);
 	return rcu_dereference(platform_label[index]);
 }
 
@@ -2240,8 +2256,7 @@
 	if (index < MPLS_LABEL_FIRST_UNRESERVED)
 		index = MPLS_LABEL_FIRST_UNRESERVED;
 
-	platform_label = rcu_dereference(net->mpls.platform_label);
-	platform_labels = net->mpls.platform_labels;
+	platform_label = mpls_platform_label_rcu(net, &platform_labels);
 
 	if (filter.filter_set)
 		flags |= NLM_F_DUMP_FILTERED;
@@ -2732,6 +2751,8 @@
 	int i;
 
 	mutex_init(&net->mpls.platform_mutex);
+	seqcount_mutex_init(&net->mpls.platform_label_seq, &net->mpls.platform_mutex);
+
 	net->mpls.platform_labels = 0;
 	net->mpls.platform_label = NULL;
 	net->mpls.ip_ttl_propagate = 1;

================================================================================
*    CONTEXT DIFFERENCES - surrounding code differences between the patches    *
================================================================================

--- b/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -70,13 +66,12 @@
 
-static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index)
+static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned int index)
 {
-	struct mpls_route *rt = NULL;
+	struct mpls_route __rcu **platform_label;
 
-	if (index < net->mpls.platform_labels) {
-		struct mpls_route __rcu **platform_label =
-			rcu_dereference(net->mpls.platform_label);
-		rt = rcu_dereference(platform_label[index]);
-	}
-	return rt;
+	if (index >= net->mpls.platform_labels)
+		return NULL;
+
+	platform_label = rcu_dereference(net->mpls.platform_label);
+	return rcu_dereference(platform_label[index]);
 }
 
@@ -2215,7 +2240,7 @@
 	if (index < MPLS_LABEL_FIRST_UNRESERVED)
 		index = MPLS_LABEL_FIRST_UNRESERVED;
 
-	platform_label = rtnl_dereference(net->mpls.platform_label);
+	platform_label = rcu_dereference(net->mpls.platform_label);
 	platform_labels = net->mpls.platform_labels;
 
 	if (filter.filter_set)
@@ -2599,7 +2624,8 @@
 	}
 
 	/* Update the global pointers */
 	net->mpls.platform_labels = limit;
 	rcu_assign_pointer(net->mpls.platform_label, labels);
 
-	rtnl_unlock();
+	mutex_unlock(&net->mpls.platform_mutex);
+

================================================================================
*    ONLY IN PATCH2 - files not modified by patch1                             *
================================================================================

--- a/include/net/netns/mpls.h
+++ b/include/net/netns/mpls.h
@@ -17,6 +17,7 @@ struct netns_mpls {
 	size_t platform_labels;
 	struct mpls_route __rcu * __rcu *platform_label;
 	struct mutex platform_mutex;
+	seqcount_mutex_t platform_label_seq;
 
 	struct ctl_table_header *ctl;
 };

This is an automated interdiff check for backported commits.

@github-actions

Copy link
Copy Markdown

Validation checks completed successfully View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/35119249333

cve CVE-2026-43042
commit-author Sabrina Dubroca <sd@queasysnail.net>
commit 629ec78
upstream-diff Uses a file-scope seqcount_t instead of upstream's
  per-netns seqcount_mutex_t to avoid a kABI-breaking struct
  change. Write side uses local_bh_disable() with a conditional preempt_disable() on PREEMPT_RT
  for RT safety. Uses rcu_dereference_rtnl() instead of
  upstream's plain rcu_dereference() to stay lockdep-clean
  under RTNL. mpls_dump_routes() still runs under RTNL on
  this tree; the seqcount there is extra hardening.

The RCU-protected codepaths (mpls_forward, mpls_dump_routes) can have
an inconsistent view of platform_labels vs platform_label in case of a
concurrent resize (resize_platform_label_table, under
platform_mutex). This can lead to OOB accesses.

This patch adds a seqcount, so that we get a consistent snapshot.

Note that mpls_label_ok is also susceptible to this, so the check
against RTA_DST in rtm_to_route_config, done outside platform_mutex,
is not sufficient. This value gets passed to mpls_label_ok once more
in both mpls_route_add and mpls_route_del, so there is no issue, but
that additional check must not be removed.

	Reported-by: Yuan Tan <tanyuan98@outlook.com>
	Reported-by: Yifan Wu <yifanwucs@gmail.com>
	Reported-by: Juefei Pu <tomapufckgml@gmail.com>
	Reported-by: Xin Liu <bird@lzu.edu.cn>
Fixes: 7720c01 ("mpls: Add a sysctl to control the size of the mpls label table")
Fixes: dde1b38 ("mpls: Convert mpls_dump_routes() to RCU.")
	Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Link: https://patch.msgid.link/cd8fca15e3eb7e212b094064cd83652e20fd9d31.1774284088.git.sd@queasysnail.net
	Signed-off-by: Jakub Kicinski <kuba@kernel.org>
(cherry picked from commit 629ec78)
	Signed-off-by: Brett Mastbergen <bmastbergen@ciq.com>
@bmastbergen
bmastbergen force-pushed the {bmastbergen_nebusec}_rlc-8/4.18.0-553.162.1.el8_10 branch from de97983 to ab05375 Compare September 17, 2026 16:05
@github-actions

Copy link
Copy Markdown

🤖 Validation Checks In Progress Workflow run: https://github.com/ctrliq/kernel-src-tree/actions/runs/35246028773

@github-actions

Copy link
Copy Markdown

🔍 Interdiff Analysis

  • ⚠️ PR commit ab05375a4385 (mpls: add seqcount to protect the platform_label{,s} pair) → upstream 629ec78ef860
    Differences found:
================================================================================
*    DELTA DIFFERENCES - code changes that differ between the patches          *
================================================================================

--- b/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -36,8 +36,6 @@
 
 #define MPLS_NEIGH_TABLE_UNSPEC (NEIGH_LINK_TABLE + 1)
 
-static seqcount_t mpls_platform_label_seq = SEQCNT_ZERO(mpls_platform_label_seq);
-
 static int label_limit = (1 << 20) - 1;
 static int ttl_max = 255;
 
@@ -75,32 +73,16 @@
 		       struct nlmsghdr *nlh, struct net *net, u32 portid,
 		       unsigned int nlm_flags);
 
-static struct mpls_route __rcu **mpls_platform_label_rcu(struct net *net,
-							size_t *platform_labels)
-{
-	struct mpls_route __rcu **platform_label;
-	unsigned int sequence;
-
-	do {
-		sequence = read_seqcount_begin(&mpls_platform_label_seq);
-		platform_label = rcu_dereference_rtnl(net->mpls.platform_label);
-		*platform_labels = net->mpls.platform_labels;
-	} while (read_seqcount_retry(&mpls_platform_label_seq, sequence));
-
-	return platform_label;
-}
-
 static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index)
 {
-	struct mpls_route __rcu **platform_label;
-	size_t platform_labels;
-
-	platform_label = mpls_platform_label_rcu(net, &platform_labels);
+	struct mpls_route *rt = NULL;
 
-	if (index < platform_labels)
-		return rcu_dereference_rtnl(platform_label[index]);
-
-	return NULL;
+	if (index < net->mpls.platform_labels) {
+		struct mpls_route __rcu **platform_label =
+			rcu_dereference(net->mpls.platform_label);
+		rt = rcu_dereference(platform_label[index]);
+	}
+	return rt;
 }
 
 bool mpls_output_possible(const struct net_device *dev)
@@ -2233,7 +2215,8 @@
 	if (index < MPLS_LABEL_FIRST_UNRESERVED)
 		index = MPLS_LABEL_FIRST_UNRESERVED;
 
-	platform_label = mpls_platform_label_rcu(net, &platform_labels);
+	platform_label = rtnl_dereference(net->mpls.platform_label);
+	platform_labels = net->mpls.platform_labels;
 
 	if (filter.filter_set)
 		flags |= NLM_F_DUMP_FILTERED;
@@ -2620,14 +2603,10 @@
 
 	/* Update the global pointers */
 	local_bh_disable();
-	if (IS_ENABLED(CONFIG_PREEMPT_RT))
-		preempt_disable();
-	write_seqcount_begin(&mpls_platform_label_seq);
+	write_seqcount_begin(&net->mpls.platform_label_seq);
 	net->mpls.platform_labels = limit;
 	rcu_assign_pointer(net->mpls.platform_label, labels);
-	write_seqcount_end(&mpls_platform_label_seq);
-	if (IS_ENABLED(CONFIG_PREEMPT_RT))
-		preempt_enable();
+	write_seqcount_end(&net->mpls.platform_label_seq);
 	local_bh_enable();
 
 	rtnl_unlock();

################################################################################
!    REJECTED PATCH2 HUNKS - could not be compared; manual review needed       !
################################################################################

--- b/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -83,6 +83,20 @@
 	return mpls_dereference(net, platform_label[index]);
 }
 
+static struct mpls_route __rcu **mpls_platform_label_rcu(struct net *net, size_t *platform_labels)
+{
+	struct mpls_route __rcu **platform_label;
+	unsigned int sequence;
+
+	do {
+		sequence = read_seqcount_begin(&net->mpls.platform_label_seq);
+		platform_label = rcu_dereference(net->mpls.platform_label);
+		*platform_labels = net->mpls.platform_labels;
+	} while (read_seqcount_retry(&net->mpls.platform_label_seq, sequence));
+
+	return platform_label;
+}
+
 static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned int index)
 {
 	struct mpls_route __rcu **platform_label;
@@ -86,6 +100,9 @@
 static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned int index)
 {
 	struct mpls_route __rcu **platform_label;
+	size_t platform_labels;
+
+	platform_label = mpls_platform_label_rcu(net, &platform_labels);
 
 	if (index >= net->mpls.platform_labels)
 		return NULL;
@@ -87,7 +104,7 @@
 {
 	struct mpls_route __rcu **platform_label;
 
-	if (index >= net->mpls.platform_labels)
+	if (index >= platform_labels)
 		return NULL;
 
 	platform_label = rcu_dereference(net->mpls.platform_label);
@@ -90,7 +107,6 @@
 	if (index >= net->mpls.platform_labels)
 		return NULL;
 
-	platform_label = rcu_dereference(net->mpls.platform_label);
 	return rcu_dereference(platform_label[index]);
 }
 
@@ -2240,8 +2256,7 @@
 	if (index < MPLS_LABEL_FIRST_UNRESERVED)
 		index = MPLS_LABEL_FIRST_UNRESERVED;
 
-	platform_label = rcu_dereference(net->mpls.platform_label);
-	platform_labels = net->mpls.platform_labels;
+	platform_label = mpls_platform_label_rcu(net, &platform_labels);
 
 	if (filter.filter_set)
 		flags |= NLM_F_DUMP_FILTERED;
@@ -2732,6 +2751,8 @@
 	int i;
 
 	mutex_init(&net->mpls.platform_mutex);
+	seqcount_mutex_init(&net->mpls.platform_label_seq, &net->mpls.platform_mutex);
+
 	net->mpls.platform_labels = 0;
 	net->mpls.platform_label = NULL;
 	net->mpls.ip_ttl_propagate = 1;

================================================================================
*    CONTEXT DIFFERENCES - surrounding code differences between the patches    *
================================================================================

--- b/net/mpls/af_mpls.c
+++ b/net/mpls/af_mpls.c
@@ -70,13 +66,12 @@
 
-static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned index)
+static struct mpls_route *mpls_route_input_rcu(struct net *net, unsigned int index)
 {
-	struct mpls_route *rt = NULL;
+	struct mpls_route __rcu **platform_label;
 
-	if (index < net->mpls.platform_labels) {
-		struct mpls_route __rcu **platform_label =
-			rcu_dereference(net->mpls.platform_label);
-		rt = rcu_dereference(platform_label[index]);
-	}
-	return rt;
+	if (index >= net->mpls.platform_labels)
+		return NULL;
+
+	platform_label = rcu_dereference(net->mpls.platform_label);
+	return rcu_dereference(platform_label[index]);
 }
 
@@ -2215,7 +2240,7 @@
 	if (index < MPLS_LABEL_FIRST_UNRESERVED)
 		index = MPLS_LABEL_FIRST_UNRESERVED;
 
-	platform_label = rtnl_dereference(net->mpls.platform_label);
+	platform_label = rcu_dereference(net->mpls.platform_label);
 	platform_labels = net->mpls.platform_labels;
 
 	if (filter.filter_set)
@@ -2599,7 +2624,8 @@
 	}
 
 	/* Update the global pointers */
 	net->mpls.platform_labels = limit;
 	rcu_assign_pointer(net->mpls.platform_label, labels);
 
-	rtnl_unlock();
+	mutex_unlock(&net->mpls.platform_mutex);
+

================================================================================
*    ONLY IN PATCH2 - files not modified by patch1                             *
================================================================================

--- a/include/net/netns/mpls.h
+++ b/include/net/netns/mpls.h
@@ -17,6 +17,7 @@ struct netns_mpls {
 	size_t platform_labels;
 	struct mpls_route __rcu * __rcu *platform_label;
 	struct mutex platform_mutex;
+	seqcount_mutex_t platform_label_seq;
 
 	struct ctl_table_header *ctl;
 };

This is an automated interdiff check for backported commits.

@github-actions

Copy link
Copy Markdown

Validation checks completed successfully View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/35246028773

@bmastbergen

Copy link
Copy Markdown
Collaborator

PoC results:

4.18.0-bmastbergen_nebusec_rlc-8_4.18.0-553.162.1.el8_10-ab0+
[*] CVE-2026-43042 crash PoC v2
[*] Kernel: 4.18.0-bmastbergen_nebusec_rlc-8_4.18.0-553.162.1.el8_10-ab0+
[*] CPUs: 16
[*] Writers on CPU 0 (nice 19), senders on CPU 1
[*] Racing platform_labels 16<->2048, labels 17-255
[*] Timer jammer creating preemption points
[*] Running for 60 seconds...
[+] 60 seconds without crash — kernel appears PATCHED

@bmastbergen
bmastbergen marked this pull request as ready for review September 17, 2026 20:18
@bmastbergen
bmastbergen requested a review from a team September 17, 2026 20:42

@PlaidCat PlaidCat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

Comment thread net/mpls/af_mpls.c

/* Update the global pointers */
local_bh_disable();
if (IS_ENABLED(CONFIG_PREEMPT_RT))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI
The RT kernel is not technically supported in this code branch its an independent code branch in Rocky 8.

This is technically a NOOP but its good incase we ever need to cross promote this for anyreason to an RT kernel branch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

created-by-kernelci Tag PRs that were automatically created when a user branch was pushed to the repo (kernelCI)

Development

Successfully merging this pull request may close these issues.

3 participants