Skip to content

Commit 5702d72

Browse files
rustyrussell0day robot
authored andcommitted
4.4.-rc5: lguest causes ugly warn on: 5 W+X pages found
Pavel Machek <[email protected]> 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+ torvalds#137 > [ 1.968230] Hardware name: LENOVO 17097HU/17097HU, BIOS 7BETD8WW > (2.19 ) 03/31/2011 > [ 1.970593] 00000001 00000000 f5cffe6 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 <[email protected]> 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 <[email protected]> Signed-off-by: Rusty Russell <[email protected]>
1 parent c8b5db7 commit 5702d72

File tree

2 files changed

+54
-24
lines changed

2 files changed

+54
-24
lines changed

arch/x86/include/asm/lguest.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
#define GUEST_PL 1
1313

1414
/* Page for Switcher text itself, then two pages per cpu */
15-
#define TOTAL_SWITCHER_PAGES (1 + 2 * nr_cpu_ids)
15+
#define SWITCHER_TEXT_PAGES (1)
16+
#define SWITCHER_STACK_PAGES (2 * nr_cpu_ids)
17+
#define TOTAL_SWITCHER_PAGES (SWITCHER_TEXT_PAGES + SWITCHER_STACK_PAGES)
1618

1719
/* Where we map the Switcher, in both Host and Guest. */
1820
extern unsigned long switcher_addr;

drivers/lguest/core.c

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222

2323
unsigned long switcher_addr;
2424
struct page **lg_switcher_pages;
25-
static struct vm_struct *switcher_vma;
25+
static struct vm_struct *switcher_text_vma;
26+
static struct vm_struct *switcher_stacks_vma;
2627

2728
/* This One Big lock protects all inter-guest data structures. */
2829
DEFINE_MUTEX(lguest_lock);
@@ -82,55 +83,81 @@ static __init int map_switcher(void)
8283
}
8384
}
8485

86+
/*
87+
* Copy in the compiled-in Switcher code (from x86/switcher_32.S).
88+
* It goes in the first page, which we map in momentarily.
89+
*/
90+
memcpy(kmap(lg_switcher_pages[0]), start_switcher_text,
91+
end_switcher_text - start_switcher_text);
92+
kunmap(lg_switcher_pages[0]);
93+
8594
/*
8695
* We place the Switcher underneath the fixmap area, which is the
8796
* highest virtual address we can get. This is important, since we
8897
* tell the Guest it can't access this memory, so we want its ceiling
8998
* as high as possible.
9099
*/
91-
switcher_addr = FIXADDR_START - (TOTAL_SWITCHER_PAGES+1)*PAGE_SIZE;
100+
switcher_addr = FIXADDR_START - TOTAL_SWITCHER_PAGES*PAGE_SIZE;
92101

93102
/*
94-
* Now we reserve the "virtual memory area" we want. We might
95-
* not get it in theory, but in practice it's worked so far.
96-
* The end address needs +1 because __get_vm_area allocates an
97-
* extra guard page, so we need space for that.
103+
* Now we reserve the "virtual memory area"s we want. We might
104+
* not get them in theory, but in practice it's worked so far.
105+
*
106+
* We want the switcher text to be read-only and executable, and
107+
* the stacks to be read-write and non-executable.
98108
*/
99-
switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE,
100-
VM_ALLOC, switcher_addr, switcher_addr
101-
+ (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE);
102-
if (!switcher_vma) {
109+
switcher_text_vma = __get_vm_area(PAGE_SIZE, VM_ALLOC|VM_NO_GUARD,
110+
switcher_addr,
111+
switcher_addr + PAGE_SIZE);
112+
113+
if (!switcher_text_vma) {
103114
err = -ENOMEM;
104115
printk("lguest: could not map switcher pages high\n");
105116
goto free_pages;
106117
}
107118

119+
switcher_stacks_vma = __get_vm_area(SWITCHER_STACK_PAGES * PAGE_SIZE,
120+
VM_ALLOC|VM_NO_GUARD,
121+
switcher_addr + PAGE_SIZE,
122+
switcher_addr + TOTAL_SWITCHER_PAGES * PAGE_SIZE);
123+
if (!switcher_stacks_vma) {
124+
err = -ENOMEM;
125+
printk("lguest: could not map switcher pages high\n");
126+
goto free_text_vma;
127+
}
128+
108129
/*
109130
* This code actually sets up the pages we've allocated to appear at
110131
* switcher_addr. map_vm_area() takes the vma we allocated above, the
111-
* kind of pages we're mapping (kernel pages), and a pointer to our
112-
* array of struct pages.
132+
* kind of pages we're mapping (kernel text pages and kernel writable
133+
* pages respectively), and a pointer to our array of struct pages.
113134
*/
114-
err = map_vm_area(switcher_vma, PAGE_KERNEL_EXEC, lg_switcher_pages);
135+
err = map_vm_area(switcher_text_vma, PAGE_KERNEL_RX, lg_switcher_pages);
136+
if (err) {
137+
printk("lguest: text map_vm_area failed: %i\n", err);
138+
goto free_vmas;
139+
}
140+
141+
err = map_vm_area(switcher_stacks_vma, PAGE_KERNEL,
142+
lg_switcher_pages + SWITCHER_TEXT_PAGES);
115143
if (err) {
116-
printk("lguest: map_vm_area failed: %i\n", err);
117-
goto free_vma;
144+
printk("lguest: stacks map_vm_area failed: %i\n", err);
145+
goto free_vmas;
118146
}
119147

120148
/*
121149
* Now the Switcher is mapped at the right address, we can't fail!
122-
* Copy in the compiled-in Switcher code (from x86/switcher_32.S).
123150
*/
124-
memcpy(switcher_vma->addr, start_switcher_text,
125-
end_switcher_text - start_switcher_text);
126-
127151
printk(KERN_INFO "lguest: mapped switcher at %p\n",
128-
switcher_vma->addr);
152+
switcher_text_vma->addr);
129153
/* And we succeeded... */
130154
return 0;
131155

132-
free_vma:
133-
vunmap(switcher_vma->addr);
156+
free_vmas:
157+
/* Undoes map_vm_area and __get_vm_area */
158+
vunmap(switcher_stacks_vma->addr);
159+
free_text_vma:
160+
vunmap(switcher_text_vma->addr);
134161
free_pages:
135162
i = TOTAL_SWITCHER_PAGES;
136163
free_some_pages:
@@ -148,7 +175,8 @@ static void unmap_switcher(void)
148175
unsigned int i;
149176

150177
/* vunmap() undoes *both* map_vm_area() and __get_vm_area(). */
151-
vunmap(switcher_vma->addr);
178+
vunmap(switcher_text_vma->addr);
179+
vunmap(switcher_stacks_vma->addr);
152180
/* Now we just need to free the pages we copied the switcher into */
153181
for (i = 0; i < TOTAL_SWITCHER_PAGES; i++)
154182
__free_pages(lg_switcher_pages[i], 0);

0 commit comments

Comments
 (0)