summaryrefslogtreecommitdiff
path: root/libre/linux-libre-hardened/0001-Revert-mm-sparsemem-fix-race-in-accessing-memory_sec.patch
diff options
context:
space:
mode:
Diffstat (limited to 'libre/linux-libre-hardened/0001-Revert-mm-sparsemem-fix-race-in-accessing-memory_sec.patch')
-rw-r--r--libre/linux-libre-hardened/0001-Revert-mm-sparsemem-fix-race-in-accessing-memory_sec.patch103
1 files changed, 103 insertions, 0 deletions
diff --git a/libre/linux-libre-hardened/0001-Revert-mm-sparsemem-fix-race-in-accessing-memory_sec.patch b/libre/linux-libre-hardened/0001-Revert-mm-sparsemem-fix-race-in-accessing-memory_sec.patch
new file mode 100644
index 000000000..43e1b5d41
--- /dev/null
+++ b/libre/linux-libre-hardened/0001-Revert-mm-sparsemem-fix-race-in-accessing-memory_sec.patch
@@ -0,0 +1,103 @@
+From 95fa13c9fe928ae6e21c1554360b5cada74cc857 Mon Sep 17 00:00:00 2001
+From: Levente Polyak <levente@leventepolyak.net>
+Date: Fri, 2 Feb 2024 02:03:34 +0100
+Subject: [PATCH] Revert "mm/sparsemem: fix race in accessing
+ memory_section->usage"
+
+This reverts commit 3a01daace71b521563c38bbbf874e14c3e58adb7.
+---
+ include/linux/mmzone.h | 14 +++-----------
+ mm/sparse.c | 17 ++++++++---------
+ 2 files changed, 11 insertions(+), 20 deletions(-)
+
+diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
+index a7c32324c263..9db36e197712 100644
+--- a/include/linux/mmzone.h
++++ b/include/linux/mmzone.h
+@@ -1793,7 +1793,6 @@ static inline unsigned long section_nr_to_pfn(unsigned long sec)
+ #define SUBSECTION_ALIGN_DOWN(pfn) ((pfn) & PAGE_SUBSECTION_MASK)
+
+ struct mem_section_usage {
+- struct rcu_head rcu;
+ #ifdef CONFIG_SPARSEMEM_VMEMMAP
+ DECLARE_BITMAP(subsection_map, SUBSECTIONS_PER_SECTION);
+ #endif
+@@ -1987,7 +1986,7 @@ static inline int pfn_section_valid(struct mem_section *ms, unsigned long pfn)
+ {
+ int idx = subsection_map_index(pfn);
+
+- return test_bit(idx, READ_ONCE(ms->usage)->subsection_map);
++ return test_bit(idx, ms->usage->subsection_map);
+ }
+ #else
+ static inline int pfn_section_valid(struct mem_section *ms, unsigned long pfn)
+@@ -2011,7 +2010,6 @@ static inline int pfn_section_valid(struct mem_section *ms, unsigned long pfn)
+ static inline int pfn_valid(unsigned long pfn)
+ {
+ struct mem_section *ms;
+- int ret;
+
+ /*
+ * Ensure the upper PAGE_SHIFT bits are clear in the
+@@ -2025,19 +2023,13 @@ static inline int pfn_valid(unsigned long pfn)
+ if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+ return 0;
+ ms = __pfn_to_section(pfn);
+- rcu_read_lock();
+- if (!valid_section(ms)) {
+- rcu_read_unlock();
++ if (!valid_section(ms))
+ return 0;
+- }
+ /*
+ * Traditionally early sections always returned pfn_valid() for
+ * the entire section-sized span.
+ */
+- ret = early_section(ms) || pfn_section_valid(ms, pfn);
+- rcu_read_unlock();
+-
+- return ret;
++ return early_section(ms) || pfn_section_valid(ms, pfn);
+ }
+ #endif
+
+diff --git a/mm/sparse.c b/mm/sparse.c
+index 338cf946dee8..77d91e565045 100644
+--- a/mm/sparse.c
++++ b/mm/sparse.c
+@@ -791,13 +791,6 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages,
+ if (empty) {
+ unsigned long section_nr = pfn_to_section_nr(pfn);
+
+- /*
+- * Mark the section invalid so that valid_section()
+- * return false. This prevents code from dereferencing
+- * ms->usage array.
+- */
+- ms->section_mem_map &= ~SECTION_HAS_MEM_MAP;
+-
+ /*
+ * When removing an early section, the usage map is kept (as the
+ * usage maps of other sections fall into the same page). It
+@@ -806,10 +799,16 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages,
+ * was allocated during boot.
+ */
+ if (!PageReserved(virt_to_page(ms->usage))) {
+- kfree_rcu(ms->usage, rcu);
+- WRITE_ONCE(ms->usage, NULL);
++ kfree(ms->usage);
++ ms->usage = NULL;
+ }
+ memmap = sparse_decode_mem_map(ms->section_mem_map, section_nr);
++ /*
++ * Mark the section invalid so that valid_section()
++ * return false. This prevents code from dereferencing
++ * ms->usage array.
++ */
++ ms->section_mem_map &= ~SECTION_HAS_MEM_MAP;
+ }
+
+ /*
+--
+2.43.0
+