mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Rusty Russell <rusty@rustcorp.com.au>
To: Pavel Machek <pavel@ucw.cz>,
	Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>,
	Arjan van de Ven <arjan@linux.intel.com>,
	Borislav Petkov <bp@alien8.de>,
	kernel list <linux-kernel@vger.kernel.org>,
	Stephen Smalley <sds@tycho.nsa.gov>,
	Brian Gerst <brgerst@gmail.com>,
	Denys Vlasenko <dvlasenk@redhat.com>, Peter Anvin <hpa@zytor.com>,
	Mike Galbraith <efault@gmx.de>,
	Peter Zijlstra <peterz@infradead.org>,
	Thomas Gleixner <tglx@linutronix.de>
Subject: Re: 4.4.-rc5: lguest causes ugly warn on: 5 W+X pages found
Date: Wed, 16 Dec 2015 12:54:53 +1030	[thread overview]
Message-ID: <87y4cvw2oa.fsf@rustcorp.com.au> (raw)
In-Reply-To: <20151215211231.GA6752@amd>

Pavel Machek <pavel@ucw.cz> writes:
> Hi!
>
>> > or similar?
>> > 
>> > The above is entirely untested. Maybe it doesn't compile. Or
>> > boot. Or work.
>> 
>> Well, with two extra spaces at each line, it does not apply :-).
>> 
>> I applied it by hand, and the output is:
>> 
>> [    0.000000] MTRR variable ranges enabled:
> ...> [    0.000000] BRK [0x0566c000, 0x0566cfff] PGTABLE
>> 
>> I'll take a look if I can figure out what it means...
>
> Wait, there's more in the log.
>
> [    1.952146] Bluetooth: HCI UART protocol H4 registered
> [    1.954335] Bluetooth: HCI UART protocol BCSP registered
> [    1.956750] usbcore: registered new interface driver btusb
> [    1.958953] ------------[ cut here ]------------
> [    1.961149] WARNING: CPU: 1 PID: 1 at
> ./arch/x86/include/asm/pgtable.h:357
> vmap_page_range_noflush+0x1f0/0x280()
> [    1.963511] Modules linked in:
> [    1.965849] CPU: 1 PID: 1 Comm: swapper/0 Tainted: G        W
> 4.4.0-rc5+ #137
> [    1.968230] Hardware name: LENOVO 17097HU/17097HU, BIOS 7BETD8WW
> (2.19 ) 03/31/2011
> [    1.970593]  00000001 00000000 f5cffe64 c42baaf8 00000000 f5cffe80
> c404066b 00000165
> [    1.973103]  c40fbe70 00000163 00000000 00000000 f5cffe90 c404070f
> 00000009 00000000
> [    1.975670]  f5cffee0 c40fbe70 c4f88348 00000000 ffe6dfff ffe6e000
> c4f8a018 ffe6dfff
> [    1.978304] Call Trace:
> [    1.980882]  [<c42baaf8>] dump_stack+0x41/0x59
> [    1.983464]  [<c404066b>] warn_slowpath_common+0x6b/0xa0
> [    1.986053]  [<c40fbe70>] ? vmap_page_range_noflush+0x1f0/0x280
> [    1.988625]  [<c404070f>] warn_slowpath_null+0xf/0x20
> [    1.991154]  [<c40fbe70>] vmap_page_range_noflush+0x1f0/0x280
> [    1.993676]  [<c40fbf2b>] map_vm_area+0x2b/0x40
> [    1.996153]  [<c4f2c795>] init+0xf8/0x1a4
> [    1.998591]  [<c4f2c69d>] ? edac_init+0x67/0x67
> [    2.001014]  [<c4000442>] do_one_initcall+0xc2/0x1c0
> [    2.003391]  [<c4f044e3>] ? initcall_blacklist+0x97/0x97
> [    2.005815]  [<c4f044e3>] ? initcall_blacklist+0x97/0x97
> [    2.008161]  [<c4051546>] ?
> __usermodehelper_set_disable_depth+0x36/0x40
> [    2.010518]  [<c407d4a6>] ? up_write+0x16/0x40
> [    2.012817]  [<c4f04ba3>] kernel_init_freeable+0xf0/0x16d
> [    2.015078]  [<c4f04ba3>] ? kernel_init_freeable+0xf0/0x16d
> [    2.017386]  [<c4a4d9c8>] kernel_init+0x8/0xc0
> [    2.019661]  [<c4a54149>] ret_from_kernel_thread+0x21/0x38
> [    2.021932]  [<c4a4d9c0>] ? rest_init+0xa0/0xa0
> [    2.024168] ---[ end trace e117245cd61feaf2 ]---
> [    2.026383] lguest: mapped switcher at ffe69000
> [    2.028958] sdhci: Secure Digital Host Controller Interface driver
>
> ...which I don't understand; did not we say warn on _once_?
> ... Um. But I think we have a winner: "lguest: mapped switcher at
> ffe69000".
>
> Rusty, does the switcher need to be W+X?
>
> And yes, I have lguest enabled, not sure why. 

No.  The layout is "<text page> <per-cpu-stack-pages>..." and I lazily
did that as a single
        map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, lg_switcher_pages);

This boots, does it solve the problem?

Thanks!
Rusty.

From: Rusty Russell <rusty@rustcorp.com.au>
Subject: lguest: map switcher text R/O.

Pavel noted that lguest maps the switcher code executable and
read-write.  This is a bad idea for any kernel text, but particularly
for text mapped at a fixed address.

Create two vmas, one for the text (PAGE_KERNEL_RX) and another for the
stacks (PAGE_KERNEL).  Use VM_NO_GUARD to map them adjacent (as
expected by the rest of the code).

Reported-by: Pavel Machek <pavel@ucw.cz>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff --git a/arch/x86/include/asm/lguest.h b/arch/x86/include/asm/lguest.h
index 3bbc07a57a31..73d0c9b92087 100644
--- a/arch/x86/include/asm/lguest.h
+++ b/arch/x86/include/asm/lguest.h
@@ -12,7 +12,9 @@
 #define GUEST_PL 1
 
 /* Page for Switcher text itself, then two pages per cpu */
-#define TOTAL_SWITCHER_PAGES (1 + 2 * nr_cpu_ids)
+#define SWITCHER_TEXT_PAGES (1)
+#define SWITCHER_STACK_PAGES (2 * nr_cpu_ids)
+#define TOTAL_SWITCHER_PAGES (SWITCHER_TEXT_PAGES + SWITCHER_STACK_PAGES)
 
 /* Where we map the Switcher, in both Host and Guest. */
 extern unsigned long switcher_addr;
diff --git a/drivers/lguest/core.c b/drivers/lguest/core.c
index 312ffd3d0017..021915baef35 100644
--- a/drivers/lguest/core.c
+++ b/drivers/lguest/core.c
@@ -22,7 +22,8 @@
 
 unsigned long switcher_addr;
 struct page **lg_switcher_pages;
-static struct vm_struct *switcher_vma;
+static struct vm_struct *switcher_text_vma;
+static struct vm_struct *switcher_stacks_vma;
 
 /* This One Big lock protects all inter-guest data structures. */
 DEFINE_MUTEX(lguest_lock);
@@ -83,54 +84,80 @@ static __init int map_switcher(void)
 	}
 
 	/*
+	 * Copy in the compiled-in Switcher code (from x86/switcher_32.S).
+	 * It goes in the first page, which we map in momentarily.
+	 */
+	memcpy(kmap(lg_switcher_pages[0]), start_switcher_text,
+	       end_switcher_text - start_switcher_text);
+	kunmap(lg_switcher_pages[0]);
+
+	/*
 	 * We place the Switcher underneath the fixmap area, which is the
 	 * highest virtual address we can get.  This is important, since we
 	 * tell the Guest it can't access this memory, so we want its ceiling
 	 * as high as possible.
 	 */
-	switcher_addr = FIXADDR_START - (TOTAL_SWITCHER_PAGES+1)*PAGE_SIZE;
+	switcher_addr = FIXADDR_START - TOTAL_SWITCHER_PAGES*PAGE_SIZE;
 
 	/*
-	 * Now we reserve the "virtual memory area" we want.  We might
-	 * not get it in theory, but in practice it's worked so far.
-	 * The end address needs +1 because __get_vm_area allocates an
-	 * extra guard page, so we need space for that.
+	 * Now we reserve the "virtual memory area"s we want.  We might
+	 * not get them in theory, but in practice it's worked so far.
+	 *
+	 * We want the switcher text to be read-only and executable, and
+	 * the stacks to be read-write and non-executable.
 	 */
-	switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
-				     VM_ALLOC, switcher_addr, switcher_addr
-				     + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
-	if (!switcher_vma) {
+	switcher_text_vma = __get_vm_area(PAGE_SIZE, VM_ALLOC|VM_NO_GUARD,
+					  switcher_addr,
+					  switcher_addr + PAGE_SIZE);
+
+	if (!switcher_text_vma) {
 		err = -ENOMEM;
 		printk("lguest: could not map switcher pages high\n");
 		goto free_pages;
 	}
 
+	switcher_stacks_vma = __get_vm_area(SWITCHER_STACK_PAGES * PAGE_SIZE,
+					    VM_ALLOC|VM_NO_GUARD,
+					    switcher_addr + PAGE_SIZE,
+					    switcher_addr + TOTAL_SWITCHER_PAGES * PAGE_SIZE);
+	if (!switcher_stacks_vma) {
+		err = -ENOMEM;
+		printk("lguest: could not map switcher pages high\n");
+		goto free_text_vma;
+	}
+
 	/*
 	 * This code actually sets up the pages we've allocated to appear at
 	 * switcher_addr.  map_vm_area() takes the vma we allocated above, the
-	 * kind of pages we're mapping (kernel pages), and a pointer to our
-	 * array of struct pages.
+	 * kind of pages we're mapping (kernel text pages and kernel writable
+	 * pages respectively), and a pointer to our array of struct pages.
 	 */
-	err = map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, lg_switcher_pages);
+	err = map_vm_area(switcher_text_vma, PAGE_KERNEL_RX, lg_switcher_pages);
+	if (err) {
+		printk("lguest: text map_vm_area failed: %i\n", err);
+		goto free_vmas;
+	}
+
+	err = map_vm_area(switcher_stacks_vma, PAGE_KERNEL,
+			  lg_switcher_pages + SWITCHER_TEXT_PAGES);
 	if (err) {
-		printk("lguest: map_vm_area failed: %i\n", err);
-		goto free_vma;
+		printk("lguest: stacks map_vm_area failed: %i\n", err);
+		goto free_vmas;
 	}
 
 	/*
 	 * Now the Switcher is mapped at the right address, we can't fail!
-	 * Copy in the compiled-in Switcher code (from x86/switcher_32.S).
 	 */
-	memcpy(switcher_vma->addr, start_switcher_text,
-	       end_switcher_text - start_switcher_text);
-
 	printk(KERN_INFO "lguest: mapped switcher at %p\n",
-	       switcher_vma->addr);
+	       switcher_text_vma->addr);
 	/* And we succeeded... */
 	return 0;
 
-free_vma:
-	vunmap(switcher_vma->addr);
+free_vmas:
+	/* Undoes map_vm_area and __get_vm_area */ 
+	vunmap(switcher_stacks_vma->addr);
+free_text_vma:
+	vunmap(switcher_text_vma->addr);
 free_pages:
 	i = TOTAL_SWITCHER_PAGES;
 free_some_pages:
@@ -148,7 +175,8 @@ static void unmap_switcher(void)
 	unsigned int i;
 
 	/* vunmap() undoes *both* map_vm_area() and __get_vm_area(). */
-	vunmap(switcher_vma->addr);
+	vunmap(switcher_text_vma->addr);
+	vunmap(switcher_stacks_vma->addr);
 	/* Now we just need to free the pages we copied the switcher into */
 	for (i = 0; i < TOTAL_SWITCHER_PAGES; i++)
 		__free_pages(lg_switcher_pages[i], 0);

  reply	other threads:[~2015-12-16  2:25 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-11-15  7:00 4.4-rc0: " Pavel Machek
2015-11-23 14:37 ` Mihai Donțu
2015-12-08 21:19   ` Kees Cook
2015-12-09  0:10     ` Dave Jones
2015-12-09 19:33     ` Mihai Donțu
2015-12-14  8:04 ` 4.4-rc5: ugly warn on: " Pavel Machek
2015-12-14  8:58   ` Borislav Petkov
2015-12-14  9:07     ` Pavel Machek
2015-12-14  9:15       ` Borislav Petkov
2015-12-14 19:18       ` Linus Torvalds
2015-12-14 20:26         ` Pavel Machek
2015-12-14 21:02           ` Andy Lutomirski
2015-12-14 21:24             ` Arjan van de Ven
2015-12-14 22:25               ` Andy Lutomirski
2015-12-15  9:40                 ` Pavel Machek
2015-12-15 17:45                   ` Linus Torvalds
2015-12-15 18:30                     ` Borislav Petkov
2015-12-15 19:06                       ` Linus Torvalds
2015-12-15 19:15                         ` Borislav Petkov
2015-12-15 18:40                     ` Andy Lutomirski
2015-12-15 19:08                       ` Linus Torvalds
2015-12-15 20:58                     ` Pavel Machek
2015-12-15 21:12                       ` 4.4.-rc5: lguest causes " Pavel Machek
2015-12-16  2:24                         ` Rusty Russell [this message]
2015-12-16  8:10                           ` Pavel Machek
2015-12-15 21:33                       ` 4.4-rc5: " Borislav Petkov
2015-12-15 22:07                         ` Pavel Machek
2015-12-15 22:15                           ` Borislav Petkov
2015-12-15  7:56               ` Pavel Machek
2015-12-15  8:09                 ` [PATCH 0/2] x86/mm: A _PAGE_NX fixlet and a kmap cleanup Andy Lutomirski
2015-12-15  8:09                   ` [PATCH 1/2] x86_32/mm: Set NX in __supported_pte_mask before enabling paging Andy Lutomirski
2015-12-15  8:09                   ` [PATCH 2/2] x86/mm: Make kmap_prot into a #define Andy Lutomirski
2016-01-19  9:26                   ` [PATCH 0/2] x86/mm: A _PAGE_NX fixlet and a kmap cleanup Ingo Molnar
2016-01-19 19:44                     ` Andy Lutomirski
2015-12-15 13:26                 ` 4.4-rc5: ugly warn on: 5 W+X pages found Arjan van de Ven
2015-12-15 14:08                   ` Pavel Machek
2015-12-15 16:28                     ` H. Peter Anvin
2015-12-15 17:45                       ` Pavel Machek
2015-12-14 12:29   ` Pavel Machek

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=87y4cvw2oa.fsf@rustcorp.com.au \
    --to=rusty@rustcorp.com.au \
    --cc=arjan@linux.intel.com \
    --cc=bp@alien8.de \
    --cc=brgerst@gmail.com \
    --cc=dvlasenk@redhat.com \
    --cc=efault@gmx.de \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@amacapital.net \
    --cc=pavel@ucw.cz \
    --cc=peterz@infradead.org \
    --cc=sds@tycho.nsa.gov \
    --cc=tglx@linutronix.de \
    --cc=torvalds@linux-foundation.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

Powered by JetHome