Skip to content

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

Merged
bmastbergen merged 1 commit into
ciqlts9_2from
{bmastbergen_nebusec}_ciqlts9_2
Sep 18, 2026
Merged

bmastbergen merged 1 commit into
ciqlts9_2from
{bmastbergen_nebusec}_ciqlts9_2

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-183756
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 15m 29s 16m 7s
aarch64 12m 48s 13m 23s

✅ Boot Verification

✅ Kernel Selftests

Architecture Passed Failed Compared Against Status
x86_64 174 24 ciqlts9_2 ✅ No regressions
aarch64 138 30 ciqlts9_2 ✅ No regressions

✅ LTP Results

Architecture Passed Failed Compared Against Status
x86_64 1439 81 ciqlts9_2 ✅ No regressions
aarch64 1404 88 ciqlts9_2 ❌ 5 regressions

aarch64 regressions:

  • fcntl14 (PASS -> FAIL)
  • fcntl14_64 (PASS -> FAIL)
  • fork14 (PASS -> FAIL)
  • futex_cmp_requeue01 (PASS -> FAIL)
  • mmap16 (PASS -> FAIL)

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

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

@github-actions

Copy link
Copy Markdown

🔍 Interdiff Analysis

  • ⚠️ PR commit 4603dc46de9 (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
@@ -37,8 +37,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;
 
@@ -76,32 +74,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)
@@ -2228,7 +2210,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;
@@ -2615,10 +2598,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
@@ -71,13 +67,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]);
 }
 
@@ -2210,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)
@@ -2594,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 4603dc46de99

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

❌ Errors:

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

⚠️ Warnings:

  • VULN-183756: 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/35042921493

@bmastbergen
bmastbergen marked this pull request as draft September 16, 2026 14:58
@bmastbergen
bmastbergen force-pushed the {bmastbergen_nebusec}_ciqlts9_2 branch from 4603dc4 to 2f2ac71 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/35119254056

@github-actions

Copy link
Copy Markdown

🔍 Interdiff Analysis

  • ⚠️ PR commit 2f2ac712c3a (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
@@ -37,10 +37,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;
 
@@ -78,32 +74,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)
@@ -2230,7 +2210,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;
@@ -2616,12 +2597,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
@@ -71,13 +67,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]);
 }
 
@@ -2210,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)
@@ -2594,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 2f2ac712c3a0

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

❌ Errors:

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

⚠️ Warnings:

  • VULN-183756: 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/35119254056

jira VULN-183756
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}_ciqlts9_2 branch from 2f2ac71 to 33ce7a8 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/35245370242

@github-actions

Copy link
Copy Markdown

🔍 Interdiff Analysis

  • ⚠️ PR commit 33ce7a806e2 (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
@@ -37,8 +37,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;
 
@@ -76,32 +74,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)
@@ -2228,7 +2210,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;
@@ -2615,14 +2598,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
@@ -71,13 +67,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]);
 }
 
@@ -2210,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)
@@ -2594,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 33ce7a806e2d

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

❌ Errors:

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

⚠️ Warnings:

  • VULN-183756: 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/35245370242

@github-actions

Copy link
Copy Markdown

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

@github-actions

Copy link
Copy Markdown

🔍 Interdiff Analysis

  • ⚠️ PR commit 33ce7a806e2 (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
@@ -37,8 +37,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;
 
@@ -76,32 +74,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)
@@ -2228,7 +2210,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;
@@ -2615,14 +2598,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
@@ -71,13 +67,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]);
 }
 
@@ -2210,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)
@@ -2594,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/35247890674

@bmastbergen

Copy link
Copy Markdown
Collaborator

PoC results:

5.14.0-bmastbergen_nebusec_ciqlts9_2-33ce7a806e2d+
[*] CVE-2026-43042 crash PoC v2
[*] Kernel: 5.14.0-bmastbergen_nebusec_ciqlts9_2-33ce7a806e2d+
[*] 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
@bmastbergen
bmastbergen merged commit b49cd6b into ciqlts9_2 Sep 18, 2026
5 of 6 checks passed
@bmastbergen
bmastbergen deleted the {bmastbergen_nebusec}_ciqlts9_2 branch September 18, 2026 13:18
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