[Lguest] NX bit support
Philip Sanderson
philip.k.sanderson at gmail.com
Mon Nov 8 22:22:20 EST 2010
On Mon, Nov 8, 2010 at 8:27 PM, Rusty Russell <rusty at rustcorp.com.au> wrote:
> On Sat, 6 Nov 2010 10:43:26 pm Philip Sanderson wrote:
> > Hello,
> >
> > short version:
> >
> > - Any plans for NX bit support?
>
> I haven't even looked at it. I NX requires PAE, but that's all I know...
>
>
Hmm. Well, it sets an extra bit in the PTE entry, which I think is being
filtered out somewhere.
> Oh, and it's generally preferred in the kernel world to put patches
> inline for easier quoting BTW.
> > - Patch for Documentation/lguest/lguest.c -- remove prot_exec, adds
> chroot.
>
> Hmm, it's an lguest flaw that we don't enforce this in the module, really.
> But making life easier for PaX/SELinux makes sense.
could you re-send with that fixed?
>
>
As requested. I have updated lguest.txt to reflect that rng-tools is
required.
diff -ur linux-2.6.35.8-orig/Documentation/lguest/lguest.c
linux-2.6.35.8/Documentation/lguest/lguest.c
--- linux-2.6.35.8-orig/Documentation/lguest/lguest.c 2010-10-29
15:52:43.000000000 +1100
+++ linux-2.6.35.8/Documentation/lguest/lguest.c 2010-11-08
21:51:34.244586003 +1100
@@ -39,6 +39,9 @@
#include <limits.h>
#include <stddef.h>
#include <signal.h>
+#include <pwd.h>
+#include <grp.h>
+
#include "linux/lguest_launcher.h"
#include "linux/virtio_config.h"
#include "linux/virtio_net.h"
@@ -298,20 +301,25 @@
/*
* We use a private mapping (ie. if we write to the page, it will be
- * copied).
+ * copied). We allocate an extra two pages PROT_NONE to act as guard
pages
+ * against invalid read/write attempts that exceed allocated space.
*/
- addr = mmap(NULL, getpagesize() * num,
- PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, fd, 0);
+ addr = mmap(NULL, getpagesize() * (num+2),
+ PROT_NONE, MAP_PRIVATE, fd, 0);
+
if (addr == MAP_FAILED)
err(1, "Mmapping %u pages of /dev/zero", num);
+ if(mprotect(addr + getpagesize(), getpagesize() * num,
PROT_READ|PROT_WRITE) == -1)
+ err(1, "mprotect rw %u pages failed", num);
+
/*
* One neat mmap feature is that you can close the fd, and it
* stays mapped.
*/
close(fd);
- return addr;
+ return addr+getpagesize();
}
/* Get some more pages for a device. */
@@ -343,7 +351,7 @@
* done to it. This allows us to share untouched memory between
* Guests.
*/
- if (mmap(addr, len, PROT_READ|PROT_WRITE|PROT_EXEC,
+ if (mmap(addr, len, PROT_READ|PROT_WRITE,
MAP_FIXED|MAP_PRIVATE, fd, offset) != MAP_FAILED)
return;
@@ -573,11 +581,13 @@
unsigned int line)
{
/*
- * We have to separately check addr and addr+size, because size could
- * be huge and addr + size might wrap around.
+ * Check if the requested address and size exceeds the allocated
memory,
+ * or addr + size wraps around.
*/
- if (addr >= guest_limit || addr + size >= guest_limit)
+
+ if ((addr + size) > guest_limit || (addr + size) < addr)
errx(1, "%s:%i: Invalid address %#lx", __FILE__, line, addr);
+
/*
* We return a pointer for the caller's convenience, now we know it's
* safe to use.
@@ -1882,6 +1892,8 @@
{ "block", 1, NULL, 'b' },
{ "rng", 0, NULL, 'r' },
{ "initrd", 1, NULL, 'i' },
+ { "username", 1, NULL, 'u' },
+ { "chroot", 1, NULL, 'c' },
{ NULL },
};
static void usage(void)
@@ -1904,6 +1916,12 @@
/* If they specify an initrd file to load. */
const char *initrd_name = NULL;
+ /* Password structure for initgroups/setres[gu]id */
+ struct passwd *user_details = NULL;
+
+ /* Directory to chroot to */
+ char *chroot_path = NULL;
+
/* Save the args: we "reboot" by execing ourselves again. */
main_args = argv;
@@ -1960,6 +1978,16 @@
case 'i':
initrd_name = optarg;
break;
+ case 'u':
+ user_details = getpwnam(optarg);
+
+ if(! user_details)
+ err(1, "getpwnam failed, incorrect uername?");
+
+ break;
+ case 'c':
+ chroot_path = optarg;
+ break;
default:
warnx("Unknown argument %s", argv[optind]);
usage();
@@ -2031,6 +2059,39 @@
/* If we exit via err(), this kills all the threads, restores tty. */
atexit(cleanup_devices);
+ /* If requested, chroot to a directory */
+
+ if(chroot_path) {
+ if(chroot(chroot_path) != 0)
+ err(1, "chroot(\"%s\") failed", chroot_path);
+
+ if(chdir("/") != 0)
+ err(1, "chdir(\"/\") failed");
+
+ verbose("chroot done");
+ }
+
+ /* If requested, drop privileges */
+ if(user_details) {
+ uid_t u;
+ gid_t g;
+
+ u = user_details->pw_uid;
+ g = user_details->pw_gid;
+
+ if(initgroups(user_details->pw_name, g) != 0)
+ err(1, "initgroups failed");
+
+ if(setresgid(g, g, g) != 0)
+ err(1, "setresgid failed");
+
+ if(setresuid(u, u, u) != 0)
+ err(1, "setresuid failed");
+
+ verbose("Dropping privileges completed");
+ }
+
+
/* Finally, run the Guest. This doesn't return. */
run_guest();
}
diff -ur linux-2.6.35.8-orig/Documentation/lguest/lguest.txt
linux-2.6.35.8/Documentation/lguest/lguest.txt
--- linux-2.6.35.8-orig/Documentation/lguest/lguest.txt 2010-10-29
15:52:43.000000000 +1100
+++ linux-2.6.35.8/Documentation/lguest/lguest.txt 2010-11-08
21:29:19.188586003 +1100
@@ -114,6 +114,11 @@
See http://linux-net.osdl.org/index.php/Bridge for general information
on how to get bridging working.
+- Random number generation. Using the --rng option will provide a
+ /dev/hwrng in the guest that will read from the host's /dev/random.
+ Use this option in conjunction with rng-tools (see ../hw_random.txt)
+ to provide entropy to the guest kernel's /dev/random.
+
There is a helpful mailing list at
http://ozlabs.org/mailman/listinfo/lguest
Good luck!
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).
Ah, it will appear as /dev/hwrng. It's a weirdness of Linux that our actual
> hardware number generators are not wired up to /dev/random...
>
>
Reflected this in the documentation, thanks :-)
> Thanks!
> Rusty.
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.ozlabs.org/pipermail/lguest/attachments/20101108/935ec7c0/attachment-0001.html>
More information about the Lguest
mailing list