This is taken from the work I did on lguest64.
When killing a guest, we read the guest stack to do a nice back trace of
the guest and send it via printk to the host.
So instead of just getting an error message from the lguest launcher of:
lguest: bad read address 537012178 len 1
I also get in my dmesg:
called from [c0405f30] show_trace_log_lvl+0x1a/0x2f
[c04069aa] show_trace+0x12/0x14
[c0406a03] dump_stack+0x16/0x18
[f8c746de] lguest_dump_lg_regs+0x22/0x13c [lg]
[f8c7131b] lgread+0x59/0x90 [lg]
[f8c715bd] run_guest+0x26b/0x406 [lg]
[f8c739be] read+0x73/0x7d [lg]
[c04825e9] vfs_read+0xad/0x161
[c0482a75] sys_read+0x3d/0x61
[c0404f34] syscall_call+0x7/0xb
===
[f8c7131b] lgread+0x59/0x90 [lg]
Printing LG 0 regs cr3: 021eb000
EIP: 0061: [e00227d2]
ESP: 0069:c236fe3c EFLAGS: 00010202
EAX: 0004 EBX: e001fb20 ECX: 0008 EDX: 03f2
ESI: e001ee00 EDI: e001fb60 EBP: c236fea0
CR2: 1278000 lguest_data-cr2: 80011380
errcode: 0 trapnum: d
Stack Dump:
[c1042b7a] trace_hardirqs_on+0x125/0x149
[c123b0ea] wait_for_completion+0x90/0x98
[c123bddc] __mutex_unlock_slowpath+0x129/0x13e
[c1048769] unlock_cpu_hotplug+0x62/0x64
[c104b5b6] sys_init_module+0x14e3/0x162c
[c1081d44] do_sync_read+0xc2/0xff
[c1004f85] restore_nocheck+0x12/0x15
[c1004f34] syscall_call+0x7/0xb
TODO:
- Clean up a little (still has stuff from lguest64 in it).
- Perhaps make a config option or runtime switch to turn it off.
- Send to the launcher the dump instead of printk.
- make modules work too.
Also I need to change the %u of the bad read print to a %x, because
seeing 0x200227d2 is better than seeing 537012178 for addresses.
Signed-off-by: Steven Rostedt [EMAIL PROTECTED]
Index: linux-2.6.21-rc5-mm2/drivers/lguest/Makefile
===
--- linux-2.6.21-rc5-mm2.orig/drivers/lguest/Makefile
+++ linux-2.6.21-rc5-mm2/drivers/lguest/Makefile
@@ -4,4 +4,4 @@ obj-$(CONFIG_LGUEST_GUEST) += lguest.o l
# Host requires the other files, which can be a module.
obj-$(CONFIG_LGUEST) += lg.o
lg-objs := core.o hypercalls.o page_tables.o interrupts_and_traps.o \
- segments.o io.o lguest_user.o hypervisor.o
+ segments.o io.o lguest_user.o hypervisor.o lguest_debug.o
Index: linux-2.6.21-rc5-mm2/drivers/lguest/core.c
===
--- linux-2.6.21-rc5-mm2.orig/drivers/lguest/core.c
+++ linux-2.6.21-rc5-mm2/drivers/lguest/core.c
@@ -210,6 +210,28 @@ int lguest_address_ok(const struct lgues
}
/* Just like get_user, but don't let guest access lguest binary. */
+u8 lgread_u8(struct lguest *lg, u32 addr)
+{
+ u8 val = 0;
+
+ /* Don't let them access lguest binary */
+ if (!lguest_address_ok(lg, addr)
+ || get_user(val, (u32 __user *)addr) != 0)
+ kill_guest(lg, bad read address %u, addr);
+ return val;
+}
+
+u16 lgread_u16(struct lguest *lg, u32 addr)
+{
+ u16 val = 0;
+
+ /* Don't let them access lguest binary */
+ if (!lguest_address_ok(lg, addr)
+ || get_user(val, (u32 __user *)addr) != 0)
+ kill_guest(lg, bad read address %u, addr);
+ return val;
+}
+
u32 lgread_u32(struct lguest *lg, u32 addr)
{
u32 val = 0;
Index: linux-2.6.21-rc5-mm2/drivers/lguest/lg.h
===
--- linux-2.6.21-rc5-mm2.orig/drivers/lguest/lg.h
+++ linux-2.6.21-rc5-mm2/drivers/lguest/lg.h
@@ -176,6 +176,8 @@ extern struct mutex lguest_lock;
/* core.c: */
/* Entry points in hypervisor */
const unsigned long *__lguest_default_idt_entries(void);
+u8 lgread_u8(struct lguest *lg, u32 addr);
+u16 lgread_u16(struct lguest *lg, u32 addr);
u32 lgread_u32(struct lguest *lg, u32 addr);
void lgwrite_u32(struct lguest *lg, u32 val, u32 addr);
void lgread(struct lguest *lg, void *buf, u32 addr, unsigned bytes);
@@ -238,6 +240,7 @@ int hypercall(struct lguest *info, struc
#define kill_guest(lg, fmt...) \
do { \
if (!(lg)-dead) { \
+ lguest_dump_lg_regs(lg);\
(lg)-dead = kasprintf(GFP_ATOMIC, fmt);\
if (!(lg)-dead)\
(lg)-dead = (void *)1; \
@@ -248,5 +251,11 @@ static inline unsigned long guest_pa(str
{
return vaddr - lg-page_offset;
}
+
+/* lguest_debug.c */
+void lguest_print_address(struct lguest *lg, unsigned long address);
+void lguest_dump_trace(struct lguest *lg, struct lguest_regs *regs);
+void lguest_dump_lg_regs(struct lguest *lg);
+
#endif /* __ASSEMBLY__ */
#endif /* _LGUEST_H */
Index: linux-2.6.21-rc5-mm2/drivers/lguest/lguest.c