[rlc-8/4.18.0-553.162.1.el8_10] mpls: add seqcount to protect the platform_label{,s} pair - #1612
Draft
ciq-kernel-automation[bot] wants to merge 1 commit into
Conversation
|
🤖 Validation Checks In Progress Workflow run: https://github.com/ctrliq/kernel-src-tree/actions/runs/35040099672 |
🔍 Interdiff Analysis
================================================================================
* 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. |
|
✅ Validation checks completed successfully View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/35040099672 |
bmastbergen
marked this pull request as draft
September 16, 2026 14:59
cve CVE-2026-43042 commit-author Sabrina Dubroca <sd@queasysnail.net> commit 629ec78 upstream-diff Upstream adds seqcount_mutex_t to struct netns_mpls, which breaks kABI by changing the struct size. This backport uses a file-scope seqcount_spinlock_t with a static spinlock in af_mpls.c instead, avoiding any struct layout change. This is safe because resize_platform_label_table() is already RTNL-serialized, so only one writer runs at a time. The seqcount_spinlock_t is RT-safe (readers sleep on the lock instead of spinning when the writer is preempted). The seqcount is statically initialized, so no mpls_net_init() change is needed. On this tree mpls_dump_routes() still runs under RTNL, so only mpls_route_input_rcu() (reached from mpls_forward()) is a true lockless reader; the dump change is extra hardening. The read/write seqcount logic is identical to upstream. 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
force-pushed
the
{bmastbergen_nebusec}_rlc-8/4.18.0-553.162.1.el8_10
branch
from
September 16, 2026 15:50
2138aa3 to
de97983
Compare
|
🤖 Validation Checks In Progress Workflow run: https://github.com/ctrliq/kernel-src-tree/actions/runs/35119249333 |
🔍 Interdiff Analysis
================================================================================
* 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. |
|
✅ Validation checks completed successfully View full results: https://github.com/ctrliq/kernel-src-tree/actions/runs/35119249333 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR has been automatically created after successful completion of all CI stages.
Commit Message(s)
Test Results
✅ Build Stage
✅ Boot Verification
✅ Kernel Selftests
✅ LTP Results
🤖 This PR was automatically generated by GitHub Actions
Run ID: 35118071431