1) Example code: old libc headers don't have SIOCBRADDIF, and old zlibs don't have gzdirect() -- it's a sanity check anyway. 2) Some people don't build in their source directories, so .config isn't there (thanks to Tony Breeds <tony@bakeyournoodle.com>). 3) Point out that guest and host kernel are usually the same. 4) Set the "no checksum" option on the tun device as a minor optimization. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> --- Documentation/lguest/Makefile | 9 ++++++++- Documentation/lguest/lguest.c | 6 ++++-- Documentation/lguest/lguest.txt | 8 ++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) ==================================================================--- a/Documentation/lguest/Makefile +++ b/Documentation/lguest/Makefile @@ -1,7 +1,14 @@ # This creates the demonstration utility "lguest" which runs a Linux guest. +# For those people that have a separate object dir, look there for .config +KBUILD_OUTPUT := ../.. +ifdef O + ifeq ("$(origin O)", "command line") + KBUILD_OUTPUT := $(O) + endif +endif # We rely on CONFIG_PAGE_OFFSET to know where to put lguest binary. -include ../../.config +include $(KBUILD_OUTPUT)/.config LGUEST_GUEST_TOP := ($(CONFIG_PAGE_OFFSET) - 0x08000000) CFLAGS:=-Wall -Wmissing-declarations -Wmissing-prototypes -O3 \ ==================================================================--- a/Documentation/lguest/lguest.c +++ b/Documentation/lguest/lguest.c @@ -40,6 +40,9 @@ typedef uint8_t u8; #define PAGE_PRESENT 0x7 /* Present, RW, Execute */ #define NET_PEERNUM 1 #define BRIDGE_PFX "bridge:" +#ifndef SIOCBRADDIF +#define SIOCBRADDIF 0x89a2 /* add interface to bridge */ +#endif static bool verbose; #define verbose(args...) \ @@ -166,8 +169,6 @@ static unsigned long unpack_bzimage(int void *img = (void *)0x100000; f = gzdopen(fd, "rb"); - if (gzdirect(f)) - errx(1, "did not find correct gzip header"); while ((ret = gzread(f, img + len, 65536)) > 0) len += ret; if (ret < 0) @@ -820,6 +821,7 @@ static void setup_tun_net(const char *ar strcpy(ifr.ifr_name, "tap%d"); if (ioctl(netfd, TUNSETIFF, &ifr) != 0) err(1, "configuring /dev/net/tun"); + ioctl(netfd, TUNSETNOCSUM, 1); /* You will be peer 1: we should create enough jitter to randomize */ dev = new_device(devices, LGUEST_DEVICE_T_NET, 1, ==================================================================--- a/Documentation/lguest/lguest.txt +++ b/Documentation/lguest/lguest.txt @@ -23,7 +23,10 @@ Developer features: Running Lguest: -- You will need to configure your kernel with the following options: +- Lguest runs the same kernel as guest and host. You can configure + them differently, but usually it's easiest not to. + + You will need to configure your kernel with the following options: CONFIG_HIGHMEM64G=n ("High Memory Support" "64GB")[1] CONFIG_TUN=y/m ("Universal TUN/TAP device driver support") @@ -35,7 +38,8 @@ Running Lguest: CONFIG_HZ=100 ("Timer frequency")[2] - A tool called "lguest" is available in this directory: type "make" - to build it. + to build it. If you didn't build your kernel in-tree, use "make + O=<builddir>". - Create or find a root disk image. There are several useful ones around, such as the xm-test tiny root image at
Rusty Russell
2007-May-04 08:00 UTC
[PATCH 2/3] lguest: remove put_user etc warnings, add bloat
I've long disliked Linux's user access functions. Nonetheless, let's stop the warnings. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> --- drivers/lguest/core.c | 8 +++++--- drivers/lguest/hypercalls.c | 33 ++++++++++++++++++++++----------- drivers/lguest/interrupts_and_traps.c | 17 ++++++++++++----- 3 files changed, 39 insertions(+), 19 deletions(-) ==================================================================--- a/drivers/lguest/core.c +++ b/drivers/lguest/core.c @@ -303,8 +303,9 @@ int run_guest(struct lguest *lg, char *_ /* Hypercalls first: we might have been out to userspace */ do_hypercalls(lg); if (lg->dma_is_pending) { - put_user(lg->pending_dma, (unsigned long *)user); - put_user(lg->pending_key, (unsigned long *)user+1); + if (put_user(lg->pending_dma, (unsigned long *)user) || + put_user(lg->pending_key, (unsigned long *)user+1)) + return -EFAULT; return sizeof(unsigned long)*2; } @@ -350,7 +351,8 @@ int run_guest(struct lguest *lg, char *_ continue; /* If lguest_data is NULL, this won't hurt. */ - put_user(cr2, &lg->lguest_data->cr2); + if (put_user(cr2, &lg->lguest_data->cr2)) + kill_guest(lg, "Writing cr2"); break; case 7: /* We've intercepted a Device Not Available fault. */ /* If they don't want to know, just absorb it. */ ==================================================================--- a/drivers/lguest/hypercalls.c +++ b/drivers/lguest/hypercalls.c @@ -102,7 +102,9 @@ static void do_async_hcalls(struct lgues unsigned int i; u8 st[LHCALL_RING_SIZE]; - copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st)); + if (copy_from_user(&st, &lg->lguest_data->hcall_status, sizeof(st))) + return; + for (i = 0; i < ARRAY_SIZE(st); i++) { struct lguest_regs regs; unsigned int n = lg->next_hcall; @@ -113,12 +115,20 @@ static void do_async_hcalls(struct lgues if (++lg->next_hcall == LHCALL_RING_SIZE) lg->next_hcall = 0; - get_user(regs.eax, &lg->lguest_data->hcalls[n].eax); - get_user(regs.edx, &lg->lguest_data->hcalls[n].edx); - get_user(regs.ecx, &lg->lguest_data->hcalls[n].ecx); - get_user(regs.ebx, &lg->lguest_data->hcalls[n].ebx); + if (get_user(regs.eax, &lg->lguest_data->hcalls[n].eax) + || get_user(regs.edx, &lg->lguest_data->hcalls[n].edx) + || get_user(regs.ecx, &lg->lguest_data->hcalls[n].ecx) + || get_user(regs.ebx, &lg->lguest_data->hcalls[n].ebx)) { + kill_guest(lg, "Fetching async hypercalls"); + break; + } + do_hcall(lg, ®s); - put_user(0xFF, &lg->lguest_data->hcall_status[n]); + if (put_user(0xFF, &lg->lguest_data->hcall_status[n])) { + kill_guest(lg, "Writing result for async hypercall"); + break; + } + if (lg->dma_is_pending) break; } @@ -139,11 +149,12 @@ static void initialize(struct lguest *lg kill_guest(lg, "bad guest page %p", lg->lguest_data); return; } - get_user(lg->noirq_start, &lg->lguest_data->noirq_start); - get_user(lg->noirq_end, &lg->lguest_data->noirq_end); - /* We reserve the top pgd entry. */ - put_user(4U*1024*1024, &lg->lguest_data->reserve_mem); - put_user(lg->guestid, &lg->lguest_data->guestid); + if (get_user(lg->noirq_start, &lg->lguest_data->noirq_start) + || get_user(lg->noirq_end, &lg->lguest_data->noirq_end) + /* We reserve the top pgd entry. */ + || put_user(4U*1024*1024, &lg->lguest_data->reserve_mem) + || put_user(lg->guestid, &lg->lguest_data->guestid)) + kill_guest(lg, "bad guest page %p", lg->lguest_data); /* This is the one case where the above accesses might have * been the first write to a Guest page. This may have caused ==================================================================--- a/drivers/lguest/interrupts_and_traps.c +++ b/drivers/lguest/interrupts_and_traps.c @@ -40,7 +40,8 @@ static void set_guest_interrupt(struct l /* We use IF bit in eflags to indicate whether irqs were disabled (it's always 0, since irqs are enabled when guest is running). */ eflags = lg->regs->eflags; - get_user(irq_enable, &lg->lguest_data->irq_enabled); + if (get_user(irq_enable, &lg->lguest_data->irq_enabled)) + irq_enable = 0; eflags |= (irq_enable & X86_EFLAGS_IF); push_guest_stack(lg, &gstack, eflags); @@ -58,7 +59,8 @@ static void set_guest_interrupt(struct l /* Disable interrupts for an interrupt gate. */ if (idt_type(lo, hi) == 0xE) - put_user(0, &lg->lguest_data->irq_enabled); + if (put_user(0, &lg->lguest_data->irq_enabled)) + kill_guest(lg, "Disabling interrupts"); } void maybe_do_interrupt(struct lguest *lg) @@ -75,7 +77,10 @@ void maybe_do_interrupt(struct lguest *l set_bit(0, lg->irqs_pending); /* Mask out any interrupts they have blocked. */ - copy_from_user(&blk, lg->lguest_data->blocked_interrupts, sizeof(blk)); + if (copy_from_user(&blk, lg->lguest_data->blocked_interrupts, + sizeof(blk))) + return; + bitmap_andnot(blk, lg->irqs_pending, blk, LGUEST_IRQS); irq = find_first_bit(blk, LGUEST_IRQS); @@ -88,12 +93,14 @@ void maybe_do_interrupt(struct lguest *l /* If they're halted, we re-enable interrupts. */ if (lg->halted) { /* Re-enable interrupts. */ - put_user(X86_EFLAGS_IF, &lg->lguest_data->irq_enabled); + if (put_user(X86_EFLAGS_IF, &lg->lguest_data->irq_enabled)) + kill_guest(lg, "Re-enabling interrupts"); lg->halted = 0; } else { /* Maybe they have interrupts disabled? */ u32 irq_enabled; - get_user(irq_enabled, &lg->lguest_data->irq_enabled); + if (get_user(irq_enabled, &lg->lguest_data->irq_enabled)) + irq_enabled = 0; if (!irq_enabled) return; }
Possibly Parallel Threads
- [PATCH 1/3] Documentation and example updates
- [PATCH 0/7] Modify lguest32 to make room for lguest64
- [PATCH 0/7] Modify lguest32 to make room for lguest64
- [PATCH 0/5 -v2] Modify lguest32 to make room for lguest64 (version 2)
- [PATCH 0/5 -v2] Modify lguest32 to make room for lguest64 (version 2)