Skip to content

[ciqlts8_6] mpls: add seqcount to protect the platform_label{,s} pair - #1613

Open
ciq-kernel-automation[bot] wants to merge 1 commit into
ciqlts8_6from
{bmastbergen_nebusec}_ciqlts8_6
Open

ciq-kernel-automation[bot] wants to merge 1 commit into
ciqlts8_6from
{bmastbergen_nebusec}_ciqlts8_6

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

jira VULN-183754
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 17m 52s 18m 52s
aarch64 9m 59s 10m 38s

✅ Boot Verification

✅ Kernel Selftests

Architecture Passed Failed Compared Against Status
x86_64 107 32 ciqlts8_6 ✅ No regressions
aarch64 66 21 ciqlts8_6 ✅ No regressions

✅ LTP Results

Architecture Passed Failed Compared Against Status
x86_64 1437 13 ciqlts8_6 ✅ No regressions
aarch64 1425 14 ciqlts8_6 ✅ No regressions

x86_64 newly passing:

  • read_all_proc (FAIL -> PASS)

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

@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/35041765251

@github-actions

Copy link
Copy Markdown

🔍 Interdiff Analysis

  • ⚠️ PR commit b7f8cfcf77e5 (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)
@@ -2197,7 +2179,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;
@@ -2584,10 +2567,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]);
 }
 
@@ -2179,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)
@@ -2563,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

JIRA PR Check Results

1 commit(s) with issues found:

Commit b7f8cfcf77e5

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

❌ Errors:

  • VULN-183754: Status is 'To Do', expected 'In Progress'

⚠️ Warnings:

  • VULN-183754: No time logged - please log time manually

Summary: Checked 1 commit(s) total.

@github-actions

Copy link
Copy Markdown

Validation checks completed with issues View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/35041765251

@bmastbergen
bmastbergen marked this pull request as draft September 16, 2026 14:59
@bmastbergen
bmastbergen force-pushed the {bmastbergen_nebusec}_ciqlts8_6 branch from b7f8cfc to 0a86ca1 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/35119021094

@github-actions

Copy link
Copy Markdown

🔍 Interdiff Analysis

  • ⚠️ PR commit 0a86ca17a055 (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)
@@ -2199,7 +2179,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;
@@ -2585,12 +2566,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]);
 }
 
@@ -2179,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)
@@ -2563,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

JIRA PR Check Results

1 commit(s) with issues found:

Commit 0a86ca17a055

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

❌ Errors:

  • VULN-183754: Status is 'To Do', expected 'In Progress'

⚠️ Warnings:

  • VULN-183754: No time logged - please log time manually

Summary: Checked 1 commit(s) total.

@github-actions

Copy link
Copy Markdown

Validation checks completed with issues View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/35119021094

@bmastbergen
bmastbergen force-pushed the {bmastbergen_nebusec}_ciqlts8_6 branch from 0a86ca1 to e39c0b7 Compare September 17, 2026 16:05
jira VULN-183754
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}_ciqlts8_6 branch from e39c0b7 to 47918ab Compare September 17, 2026 16:27
@github-actions

Copy link
Copy Markdown

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

@github-actions

Copy link
Copy Markdown

🔍 Interdiff Analysis

  • ⚠️ PR commit 47918ab768f0 (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)
@@ -2197,7 +2179,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;
@@ -2584,14 +2567,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]);
 }
 
@@ -2179,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)
@@ -2563,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/35248060700

@bmastbergen

Copy link
Copy Markdown
Collaborator

PoC results:

4.18.0-bmastbergen_nebusec_ciqlts8_6-47918ab768f0+
[*] CVE-2026-43042 crash PoC v2
[*] Kernel: 4.18.0-bmastbergen_nebusec_ciqlts8_6-47918ab768f0+
[*] 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.

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

@PlaidCat
PlaidCat requested a review from a team September 17, 2026 22:49
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