diff mbox series

[V4,2/8] mm/highmem: Provide CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP

Message ID 20201118204007.028261233@linutronix.de (mailing list archive)
State New, archived
Headers show
Series mm/highmem: Preemptible variant of kmap_atomic & friends | expand

Commit Message

Thomas Gleixner Nov. 18, 2020, 7:48 p.m. UTC
CONFIG_DEBUG_KMAP_LOCAL, which is selected by CONFIG_DEBUG_HIGHMEM is only
providing guard pages, but does not provide a mechanism to enforce the
usage of the kmap_local() infrastructure.

Provide CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP which forces the temporary
mapping even for lowmem pages. This needs to be a seperate config switch
because this only works on architectures which do not have cache aliasing
problems.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
V4: New patch
---
 lib/Kconfig.debug |   14 ++++++++++++++
 mm/highmem.c      |   12 +++++++++++-
 2 files changed, 25 insertions(+), 1 deletion(-)

Comments

Linus Torvalds Nov. 18, 2020, 9:13 p.m. UTC | #1
On Wed, Nov 18, 2020 at 12:58 PM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> Provide CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP which forces the temporary
> mapping even for lowmem pages. This needs to be a seperate config switch
> because this only works on architectures which do not have cache aliasing
> problems.

Very good. And you made sure to have a comment to not enable it for
production systems.

Hopefully people will even read it ;)

              Linus
Mel Gorman Nov. 19, 2020, 8:46 a.m. UTC | #2
On Wed, Nov 18, 2020 at 01:13:57PM -0800, Linus Torvalds wrote:
> On Wed, Nov 18, 2020 at 12:58 PM Thomas Gleixner <tglx@linutronix.de> wrote:
> >
> > Provide CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP which forces the temporary
> > mapping even for lowmem pages. This needs to be a seperate config switch
> > because this only works on architectures which do not have cache aliasing
> > problems.
> 
> Very good. And you made sure to have a comment to not enable it for
> production systems.
> 
> Hopefully people will even read it ;)
> 

And not start thinking it as a security hardening option.
Linus Torvalds Nov. 19, 2020, 5:19 p.m. UTC | #3
On Thu, Nov 19, 2020 at 12:46 AM Mel Gorman <mgorman@suse.de> wrote:
>
> And not start thinking it as a security hardening option.

It's probably the reverse of a hardening option, since it will cause
mapping of stuff in known and controllable virtual addresses.

Although any kmap'able page is likely to already be something you can
read anyway (ie page cache long after security checks have been done).
So it probably really doesn't matter either way.

The only thing that is certain is that it's going to slow down
important code-paths.

             Linus
diff mbox series

Patch

--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -856,9 +856,23 @@  config DEBUG_KMAP_LOCAL
 	  This option enables additional error checking for the kmap_local
 	  infrastructure.  Disable for production use.
 
+config ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP
+	bool
+
+config DEBUG_KMAP_LOCAL_FORCE_MAP
+	bool "Enforce kmap_local temporary mappings"
+	depends on DEBUG_KERNEL && ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP
+	select KMAP_LOCAL
+	select DEBUG_KMAP_LOCAL
+	help
+	  This option enforces temporary mappings through the kmap_local
+	  mechanism for non-highmem pages and on non-highmem systems.
+	  Disable this for production systems!
+
 config DEBUG_HIGHMEM
 	bool "Highmem debugging"
 	depends on DEBUG_KERNEL && HIGHMEM
+	select DEBUG_KMAP_LOCAL_FORCE_MAP if ARCH_SUPPORTS_KMAP_LOCAL_FORCE_MAP
 	select DEBUG_KMAP_LOCAL
 	help
 	  This option enables additional error checking for high memory
--- a/mm/highmem.c
+++ b/mm/highmem.c
@@ -474,7 +474,12 @@  void *__kmap_local_page_prot(struct page
 {
 	void *kmap;
 
-	if (!PageHighMem(page))
+	/*
+	 * To broaden the usage of the actual kmap_local() machinery always map
+	 * pages when debugging is enabled and the architecture has no problems
+	 * with alias mappings.
+	 */
+	if (!IS_ENABLED(CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP) && !PageHighMem(page))
 		return page_address(page);
 
 	/* Try kmap_high_get() if architecture has it enabled */
@@ -494,6 +499,11 @@  void kunmap_local_indexed(void *vaddr)
 
 	if (addr < __fix_to_virt(FIX_KMAP_END) ||
 	    addr > __fix_to_virt(FIX_KMAP_BEGIN)) {
+		if (IS_ENABLED(CONFIG_DEBUG_KMAP_LOCAL_FORCE_MAP)) {
+			/* This _should_ never happen! See above. */
+			WARN_ON_ONCE(1);
+			return;
+		}
 		/*
 		 * Handle mappings which were obtained by kmap_high_get()
 		 * first as the virtual address of such mappings is below