mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Daniel Palmer <daniel@thingy.jp>
To: geert@linux-m68k.org, linux-m68k@lists.linux-m68k.org
Cc: linux-kernel@vger.kernel.org, Daniel Palmer <daniel@thingy.jp>
Subject: [PATCH] m68k: Implement kernel memory protection
Date: Mon, 17 Nov 2025 07:05:08 +0900	[thread overview]
Message-ID: <20251116220508.1513445-1-daniel@thingy.jp> (raw)

Every time I boot linux on my various m68k machines I see
"This architecture does not have kernel memory protection."

I wondered why this was as some of my machines even have one of
those fancy MMU doodads. I worked out it was because we don't have
CONFIG_ARCH_HAS_STRICT_KERNEL_RWX, found kernel_set_cachemode()
seemed like it had the code for setting some extra flags for
kernel pages and turned that into something that sets write
protect for kernel pages.

So now we can make CONFIG_ARCH_HAS_STRICT_KERNEL_RWX=y and
provide mark_rodata_ro() to mark the kernel text and rodata
as write protected.

The test enabled by CONFIG_DEBUG_RODATA_TEST=y says this is
working, but I've only tested on the virt machine.

Signed-off-by: Daniel Palmer <daniel@thingy.jp>
---
 arch/m68k/Kconfig   |  1 +
 arch/m68k/mm/init.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

diff --git a/arch/m68k/Kconfig b/arch/m68k/Kconfig
index 11835eb59d94..2137fd19ffbd 100644
--- a/arch/m68k/Kconfig
+++ b/arch/m68k/Kconfig
@@ -8,6 +8,7 @@ config M68K
 	select ARCH_HAS_CPU_FINALIZE_INIT if MMU
 	select ARCH_HAS_CURRENT_STACK_POINTER
 	select ARCH_HAS_DMA_PREP_COHERENT if M68K_NONCOHERENT_DMA && !COLDFIRE
+	select ARCH_HAS_STRICT_KERNEL_RWX if MMU
 	select ARCH_HAS_SYNC_DMA_FOR_DEVICE if M68K_NONCOHERENT_DMA
 	select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
 	select ARCH_MIGHT_HAVE_PC_PARPORT if ISA
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index 488411af1b3f..bc1147f25624 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -123,3 +123,72 @@ void __init mem_init(void)
 {
 	init_pointer_tables();
 }
+
+#ifdef CONFIG_MMU
+/*
+ * Based on (basically copy/pasted) kernel_set_cachemode() because
+ * presumably that is correct and covers the required differences.
+ */
+static void __mark_ro_data(unsigned long virtaddr, ssize_t size)
+{
+	pgd_t *pgd_dir;
+	p4d_t *p4d_dir;
+	pud_t *pud_dir;
+	pmd_t *pmd_dir;
+	pte_t *pte_dir;
+
+	while (size > 0) {
+		pgd_dir = pgd_offset_k(virtaddr);
+		p4d_dir = p4d_offset(pgd_dir, virtaddr);
+		pud_dir = pud_offset(p4d_dir, virtaddr);
+		if (pud_bad(*pud_dir)) {
+			pud_clear(pud_dir);
+			return;
+		}
+		pmd_dir = pmd_offset(pud_dir, virtaddr);
+
+#if CONFIG_PGTABLE_LEVELS == 3
+		if (CPU_IS_020_OR_030) {
+			unsigned long pmd = pmd_val(*pmd_dir);
+
+			if ((pmd & _DESCTYPE_MASK) == _PAGE_PRESENT) {
+				*pmd_dir = __pmd(pmd | _PAGE_RONLY);
+				virtaddr += PMD_SIZE;
+				size -= PMD_SIZE;
+				continue;
+			}
+		}
+#endif
+
+		if (pmd_bad(*pmd_dir)) {
+			pmd_clear(pmd_dir);
+			return;
+		}
+		pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
+
+		set_pte(pte_dir, pte_wrprotect(*pte_dir));
+		virtaddr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+}
+
+void mark_rodata_ro(void)
+{
+	unsigned long start;
+	unsigned long end;
+
+	/* kernel text - kernel_pg_dir lives in the first page, so skip that */
+	start = (unsigned long) _stext + PAGE_SIZE;
+	end = (unsigned long) _etext;
+	pr_info("Write protecting kernel text: 0x%lx - 0x%lx\n", start, end);
+	__mark_ro_data(start, end - start);
+
+	/* ro data */
+	start = (unsigned long) __start_rodata;
+	end = (unsigned long) __end_rodata;
+	pr_info("Write protecting kernel read-only data: 0x%lx - 0x%lx\n", start, end);
+	__mark_ro_data(start, end - start);
+
+	flush_tlb_all();
+}
+#endif
-- 
2.51.0


             reply	other threads:[~2025-11-16 22:06 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-16 22:05 Daniel Palmer [this message]
2025-11-17  3:04 ` Greg Ungerer
2025-11-17  9:42   ` Daniel Palmer
2025-11-17 17:41     ` Michael Schmitz
2025-11-17 22:01       ` Daniel Palmer
2025-11-17 23:14         ` Michael Schmitz
2025-11-18 10:55           ` Daniel Palmer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251116220508.1513445-1-daniel@thingy.jp \
    --to=daniel@thingy.jp \
    --cc=geert@linux-m68k.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-m68k@lists.linux-m68k.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®