aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation
diff options
context:
space:
mode:
authorPhilip Sanderson <philip.k.sanderson@gmail.com>2011-01-20 22:37:28 -0500
committerRusty Russell <rusty@rustcorp.com.au>2011-01-20 06:07:29 -0500
commit5230ff0cccb0611830bb02b097535868df02752a (patch)
tree7d1345e1ede12e2fd85918c9944fe929017cde6b /Documentation
parent8aeb36e8f6d7eaa9cafc970b700414205743b258 (diff)
lguest: example launcher to use guard pages, drop PROT_EXEC, fix limit logic
PROT_EXEC seems to be completely unnecessary (as the lguest binary never executes there), and will allow it to work with SELinux (and more importantly, PaX :-) as they can/do forbid writable and executable mappings. Also, map PROT_NONE guard pages at start and end of guest memory for extra paranoia. I changed the length check to addr + size > guest_limit because >= is wrong (addr of 0, size of getpagesize() with a guest_limit of getpagesize() would false positive). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'Documentation')
-rw-r--r--Documentation/lguest/lguest.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index f64b85bcd6d4..d9da7e148538 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -301,20 +301,27 @@ static void *map_zeroed_pages(unsigned int num)
301 301
302 /* 302 /*
303 * We use a private mapping (ie. if we write to the page, it will be 303 * We use a private mapping (ie. if we write to the page, it will be
304 * copied). 304 * copied). We allocate an extra two pages PROT_NONE to act as guard
305 * pages against read/write attempts that exceed allocated space.
305 */ 306 */
306 addr = mmap(NULL, getpagesize() * num, 307 addr = mmap(NULL, getpagesize() * (num+2),
307 PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0); 308 PROT_NONE, MAP_PRIVATE, fd, 0);
309
308 if (addr == MAP_FAILED) 310 if (addr == MAP_FAILED)
309 err(1, "Mmapping %u pages of /dev/zero", num); 311 err(1, "Mmapping %u pages of /dev/zero", num);
310 312
313 if (mprotect(addr + getpagesize(), getpagesize() * num,
314 PROT_READ|PROT_WRITE) == -1)
315 err(1, "mprotect rw %u pages failed", num);
316
311 /* 317 /*
312 * One neat mmap feature is that you can close the fd, and it 318 * One neat mmap feature is that you can close the fd, and it
313 * stays mapped. 319 * stays mapped.
314 */ 320 */
315 close(fd); 321 close(fd);
316 322
317 return addr; 323 /* Return address after PROT_NONE page */
324 return addr + getpagesize();
318} 325}
319 326
320/* Get some more pages for a device. */ 327/* Get some more pages for a device. */
@@ -346,7 +353,7 @@ static void map_at(int fd, void *addr, unsigned long offset, unsigned long len)
346 * done to it. This allows us to share untouched memory between 353 * done to it. This allows us to share untouched memory between
347 * Guests. 354 * Guests.
348 */ 355 */
349 if (mmap(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC, 356 if (mmap(addr, len, PROT_READ|PROT_WRITE,
350 MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED) 357 MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED)
351 return; 358 return;
352 359
@@ -576,10 +583,10 @@ static void *_check_pointer(unsigned long addr, unsigned int size,
576 unsigned int line) 583 unsigned int line)
577{ 584{
578 /* 585 /*
579 * We have to separately check addr and addr+size, because size could 586 * Check if the requested address and size exceeds the allocated memory,
580 * be huge and addr + size might wrap around. 587 * or addr + size wraps around.
581 */ 588 */
582 if (addr >= guest_limit || addr + size >= guest_limit) 589 if ((addr + size) > guest_limit || (addr + size) < addr)
583 errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr); 590 errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr);
584 /* 591 /*
585 * We return a pointer for the caller's convenience, now we know it's 592 * We return a pointer for the caller's convenience, now we know it's