Am Freitag, den 03.10.2014, 10:17 +0200 schrieb Richard Weinberger:
> On Fri, Oct 3, 2014 at 1:21 AM, Thomas Meyer <tho...@m3y3r.de> wrote:
> > Hi,
> >
> > When you pass an initrd to UML and the size of the initrd is too big for
> > the current kernel memory, a panic() call is done with the message("Out
> > of memory").
> >
> > But this message never hits the stdout as the following stack trace
> > dumps because there is no current_thread_info() in the UML stack, which
> > is still active at this time:
> 
> Do you see the message if you boot UML with the earlyprintk parameter?
> 
Hi,

this panic happens really early, actually only the boot memory is setup
correctly at this point in time, no console, no early console.

The following patch enables UML to also print stack traces from really
early panics, like when the initrd is too big for the allocated memory.
The patch fixes the current_thread_info() access from non-kernel-stack,
i.e. the UML stack itself.
It also registers an kmsg_dumper that dumps the kernel messge buffer via
printf to stdout.
The panic_exit handler is changed to call the kmsg_dumper, as it would
have been the case if the panic_notifer would have return into the
panic() method.

Result looks like this:
[...]
UML running in SKAS0 mode
Adding 19550208 bytes to physical memory to account for exec-shield gap
<1>[    0.000000] bootmem alloc of 44301012 bytes failed!
<0>[    0.000000] Kernel panic - not syncing: Out of memory
<4>[    0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 3.16.2-dirty #144
<6>[    0.000000] Stack:
<4>[    0.000000]  605f2947 00000002 7fffd9728d68 00000000
<4>[    0.000000]  ffffffff 6002be30 7fffd9729078 60372980
<4>[    0.000000]  7fffd9728d40 604afa9c 60601d98 604ac0cb
<6>[    0.000000] Call Trace:
<6>[    0.000000]  [<6002be30>] ? current_thread_info+0x0/0x40
<6>[    0.000000]  [<60372980>] ? strlen+0x0/0x30
<6>[    0.000000]  [<604afa9c>] dump_stack+0x6b/0x87
<6>[    0.000000]  [<604ac0cb>] ? printk+0x0/0xa0
<6>[    0.000000]  [<60377b90>] ? bust_spinlocks+0x0/0x60
<6>[    0.000000]  [<604ab55b>] panic+0x15d/0x305
<6>[    0.000000]  [<604ab3fe>] ? panic+0x0/0x305
<6>[    0.000000]  [<60046990>] ? memcpy+0x0/0x140
<6>[    0.000000]  [<604ac0cb>] ? printk+0x0/0xa0
<6>[    0.000000]  [<60011862>] ? alloc_bootmem_core+0x0/0x114
<6>[    0.000000]  [<600119a9>] ? ___alloc_bootmem_nopanic+0x33/0x50
<6>[    0.000000]  [<60372980>] ? strlen+0x0/0x30
<6>[    0.000000]  [<60011f88>] __alloc_bootmem+0x4d/0x51
<6>[    0.000000]  [<600060fc>] read_initrd+0x83/0x156
<6>[    0.000000]  [<60005da1>] linux_main+0x466/0x4a9
<6>[    0.000000]  [<6003ff80>] ? change_sig+0x0/0x80
<6>[    0.000000]  [<60006c0b>] main+0x18b/0x390
<6>[    0.000000]  [<600261f0>] ? _start+0x0/0x30
<6>[    0.000000]  [<60006a80>] ? main+0x0/0x390
<6>[    0.000000]  [<600261f0>] ? _start+0x0/0x30
<6>[    0.000000]  [<604aa8c0>] ? __libc_csu_init+0x0/0x70
<6>[    0.000000]  [<600261f0>] ? _start+0x0/0x30
<6>[    0.000000]  [<60026219>] ? _start+0x29/0x30
<6>[    0.000000]  [<600261f0>] ? _start+0x0/0x30
<6>[    0.000000] 
<6>[    0.000000] Stopping all CPUs...done

Feedback/comments are most welcome.

diff --git a/arch/um/include/asm/thread_info.h 
b/arch/um/include/asm/thread_info.h
--- a/arch/um/include/asm/thread_info.h
+++ b/arch/um/include/asm/thread_info.h
@@ -44,17 +44,8 @@ struct thread_info {
 #define init_stack             (init_thread_union.stack)
 
 #define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
-/* how to get the thread information struct from C */
-static inline struct thread_info *current_thread_info(void)
-{
-       struct thread_info *ti;
-       unsigned long mask = THREAD_SIZE - 1;
-       void *p;
 
-       asm volatile ("" : "=r" (p) : "0" (&ti));
-       ti = (struct thread_info *) (((unsigned long)p) & ~mask);
-       return ti;
-}
+extern struct thread_info *current_thread_info(void);
 
 #define THREAD_SIZE_ORDER CONFIG_KERNEL_STACK_ORDER
 
diff --git a/arch/um/include/shared/kern_util.h 
b/arch/um/include/shared/kern_util.h
--- a/arch/um/include/shared/kern_util.h
+++ b/arch/um/include/shared/kern_util.h
@@ -19,6 +19,7 @@ extern int kmalloc_ok;
 #define UML_ROUND_UP(addr) \
        ((((unsigned long) addr) + PAGE_SIZE - 1) & PAGE_MASK)
 
+extern int is_kernel_addr(void* addr);
 extern unsigned long alloc_stack(int order, int atomic);
 extern void free_stack(unsigned long stack, int order);
 
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile
--- a/arch/um/kernel/Makefile
+++ b/arch/um/kernel/Makefile
@@ -13,7 +13,7 @@ clean-files :=
 obj-y = config.o exec.o exitcode.o irq.o ksyms.o mem.o \
        physmem.o process.o ptrace.o reboot.o sigio.o \
        signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o \
-       um_arch.o umid.o maccess.o skas/
+       um_arch.o umid.o maccess.o kmsg_dump.o skas/
 
 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o
 obj-$(CONFIG_GPROF)    += gprof_syms.o
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -11,6 +11,7 @@
 #include <linux/string.h>
 #include <linux/utsname.h>
 #include <linux/sched.h>
+#include <linux/kmsg_dump.h>
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
 @@ -234,6 +235,7 @@ static void __init uml_postsetup(void)
 static int panic_exit(struct notifier_block *self, unsigned long unused1,
                      void *unused2)
 {
+       kmsg_dump(KMSG_DUMP_PANIC);
        bust_spinlocks(1);
        bust_spinlocks(0);
        uml_exitcode = 1;
@@ -407,3 +421,21 @@ void alternatives_smp_module_del(struct module *mod)
 {
 }
 #endif
+
+/* how to get the thread information struct from C */
+inline struct thread_info *current_thread_info(void)
+{
+       struct thread_info *ti;
+       unsigned long mask = THREAD_SIZE - 1;
+       void *p;
+
+       asm volatile ("" : "=r" (p) : "0" (&ti));
+       ti = (struct thread_info *) (((unsigned long)p) & ~mask);
+       if(!is_kernel_addr((void*)ti)) {
+               return &init_thread_info;
+       }
+       return ti;
+}
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -254,7 +255,7 @@ void __wrap_free(void *ptr)
         * there is a possibility for memory leaks.
         */
 
-       if ((addr >= uml_physmem) && (addr < high_physmem)) {
+       if (is_kernel_addr(addr)) {
                if (kmalloc_ok)
                        kfree(ptr);
        }
@@ -264,3 +265,10 @@ void __wrap_free(void *ptr)
        }
        else __real_free(ptr);
 }
+
+int is_kernel_addr(void* addr)
+{
+       if((addr >= uml_physmem) && (addr < high_physmem))
+               return 1;
+       return 0;
+}
\ No newline at end of file
--- /dev/null   2014-10-01 22:51:22.599698712 +0200
+++ arch/um/kernel/kmsg_dump.c  2014-10-04 01:33:45.792999523 +0200
@@ -0,0 +1,25 @@
+#include <linux/kmsg_dump.h>
+#include <shared/init.h>
+#include <shared/kern.h>
+
+static struct kmsg_dumper pf_dumper;
+
+static void pf_kmsg_dump(struct kmsg_dumper *dumper,
+                        enum kmsg_dump_reason reason)
+{
+       static char line[1024];
+       size_t len;
+
+       while (kmsg_dump_get_line(dumper, true, line, sizeof(line), &len)) {
+               line[len-1] = '\0';
+               printf("%s\n", line);
+       }
+}
+
+int kmsg_dump_printf(void)
+{
+       pf_dumper.dump = pf_kmsg_dump;
+       return kmsg_dump_register(&pf_dumper);
+}
+
+__uml_initcall(kmsg_dump_printf);



------------------------------------------------------------------------------
Meet PCI DSS 3.0 Compliance Requirements with EventLog Analyzer
Achieve PCI DSS 3.0 Compliant Status with Out-of-the-box PCI DSS Reports
Are you Audit-Ready for PCI DSS 3.0 Compliance? Download White paper
Comply to PCI DSS 3.0 Requirement 10 and 11.5 with EventLog Analyzer
http://pubads.g.doubleclick.net/gampad/clk?id=154622311&iu=/4140/ostg.clktrk
_______________________________________________
User-mode-linux-devel mailing list
User-mode-linux-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/user-mode-linux-devel

Reply via email to