Linux kernel Crash analysis (1)

Source: Internet
Author: User

Linux kernel Crash analysis (1)

During work, we often encounter some kernel crash situations. This article analyzes the crash output information based on the kernel. The kernel version used is Linux2.6.32.

The lifecycle of a process ranges from several milliseconds to several months. Generally, it interacts with the kernel. For example, a user space program uses system calls to enter the kernel space. In this case, the stack space of the user space is no longer used, and the corresponding Kernel stack space is used. For each process, the Linux kernel stores two different data structures in a separate storage space allocated to the process: one is the kernel-state process stack, the other is the data structure thread_info next to the process descriptor, which is called the thread descriptor. The size of the core stack is generally 8 KB, that is, 8192 bytes, occupying two pages. The thread_info.h file in the Linux-2.6.32 kernel has a definition of the kernel stack:

#define THREAD_SIZE               8192

In the linux kernel, use the following consortium struct to represent the thread Descriptor and kernel stack of a process. The File include/linux/sched. h is in the kernel.

union thread_union {  struct thread_info thread_info;  unsigned long stack[THREAD_SIZE/sizeof(long)];};

This structure is a consortium. We have seen an explanation of union in the C Language. In C Programming Language, the consortium is described as follows:

1) A consortium is a structure;

2) The offset of all its members to the base address is 0;

3) The structure space should be large enough to accommodate the "widest" member;

4) The alignment method should be suitable for all the members;

The preceding description shows that the size of the thread_union struct is 8192 bytes. That is, the size of the stack array. The type is unsigned long. Because all member variables in a consortium occupy the same memory area, there is always a concept when writing code. Only one member variable can be used for an instance of a consortium, otherwise, the original variable will be overwritten. If this statement is correct, there must be a premise that the number of bytes occupied by the members is the same. When the number of bytes occupied by the members is different, only the corresponding bytes are overwritten. For the thread_union consortium, we can access the two members at the same time, as long as the addresses of the two member variables can be obtained correctly.

When a process in the kernel uses too much stack space, the kernel stack will overflow to the thread_info part, which will cause serious problems and the system will restart), for example, the hierarchy of recursive calls is too deep; the data structure defined in the function is too large.

Figure: Relationship between thread_infotask_struct and kernel stack in a process

Let's take a look at the structure of thread_info:

Struct thread_info {unsigned long flags;/* underlying flag, */int preempt_count;/* 0 => can be preemptible, <0 => bug */mm_segment_t addr_limit; /* process address space */struct task_struct * task;/* task_struct pointer of the current process */struct exec_domain * exec_domain;/* execution interval */_ u32 cpu; /* Current cpu */_ u32 cpu_domain;/* cpu domain */struct cpu_context_save cpu_context;/* cpu context */_ u32 syscall; /* syscall number */_ u8 used_cp [16];/* thread used copro */unsigned long tp_value; struct crunch_state crunchstate; union fp_state fpstate _ attribute _ (aligned (8); union vfp_state vfpstate; # ifdef CONFIG_ARM_THUMBEE unsigned long thumbee_state; /* ThumbEE Handler Base register */# endif struct restart_block;/* implement signal mechanism */};

PS: 1) flag is used to save various specific process signs. The most important two are: TIF_SIGPENDING. If the process has to process the signal, TIF_NEED_RESCHED indicates that the process should be replaced by another process by the scheduler.

Based on the above knowledge, we can see that the above information is printed when the kernel prints the stack information. The following print information is a situation encountered during work. The Kernel stack information is printed. The PC pointer is in dev_get_by_flags and the inaccessible kernel virtual address is 45685516, generally, accessible addresses in the kernel start with 0xCXXXXXXX.

Unable to handle kernel paging request at virtual address 45685516pgd = c65a4000[45685516] *pgd=00000000Internal error: Oops: 1 [#1]last sysfs file: /sys/devices/form/tpm/cfg_l3/l3_rule_addModules linked in: splic mmp(P)CPU: 0    Tainted: P            (2.6.32.11 #42)PC is at dev_get_by_flags+0xfc/0x140LR is at dev_get_by_flags+0xe8/0x140pc : [<c06bee24>]    lr : [<c06bee10>]    psr: 20000013sp : c07e9c28  ip : 00000000  fp : c07e9c64r10: c6bcc560  r9 : c646a220  r8 : c66a0000r7 : c6a00000  r6 : c0204e56  r5 : 30687461  r4 : 45685516r3 : 00000000  r2 : 00000010  r1 : c0204e56  r0 : ffffffffFlags: nzCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment kernelControl: 0005397f  Table: 065a4000  DAC: 00000017Process swapper (pid: 0, stack limit = 0xc07e8270)Stack: (0xc07e9c28 to 0xc07ea000)9c20:                   c0204e56 c6a00000 45685516 c69ffff0 c69ffff0 c69ffff09c40: c6a00000 30687461 c66a0000 c6a00000 00000007 c64b210c c07e9d24 c07e9c689c60: c071f764 c06bed38 c66a0000 c66a0000 c6a00000 c6a00000 c66a0000 c6a000009c80: c07e9cfc c07e9c90 c03350d4 c0334b2c 00000034 00000006 00000100 c64b21049ca0: 0000c4fb c0243ece c66a0000 c0beed04 c033436c c646a220 c07e9cf4 000000009cc0: c66a0000 00000003 c0bee8e8 c0beed04 c07e9d24 c07e9ce0 c06e4f5c 00004c689ce0: 00000000 faa9fea9 faa9fea9 00000000 00000000 c6bcc560 c0335138 c646a2209d00: c66a0000 c64b2104 c085ffbc c66a0000 c0bee8e8 00000000 c07e9d54 c07e9d289d20: c071f9a0 c071ebc0 00000000 c071ebb0 80000000 00000007 c67fb460 c646a2209d40: c0bee8c8 00000608 c07e9d94 c07e9d58 c002a100 c071f84c c0029bb8 800000009d60: c07e9d84 c0beee0c c0335138 c66a0000 c646a220 00000000 c4959800 c49598009d80: c67fb460 00000000 c07e9dc4 c07e9d98 c078f0f4 c0029bc8 00000000 c0029bb89da0: 80000000 c07e9dbc c6b8d340 c66a0520 00000000 c646a220 c07e9dec c07e9dc89dc0: c078f450 c078effc 00000000 c67fb460 c6b8d340 00000000 c67fb460 c64b20f29de0: c07e9e24 c07e9df0 c078fb60 c078f130 00000000 c078f120 80000000 c0029a949e00: 00000806 c6b8d340 c0bee818 00000001 00000000 c4959800 c07e9e64 c07e9e289e20: c002a030 c078f804 c64b2070 00000000 c64b2078 ffc45000 c64b20c2 c085c2dc9e40: 00000000 c085c2c0 00000000 c0817398 00086c2e c085c2c4 c07e9e9c c07e9e689e60: c06c2684 c0029bc8 00000001 00000040 00000000 c085c2dc c085c2c0 000000019e80: 0000012c 00000040 c085c2d0 c0bee818 c07e9ed4 c07e9ea0 c00284e0 c06c26089ea0: bf00da5c 00086c30 00000000 00000001 c097e7d4 c07e8000 00000100 c08162d89ec0: 00000002 c097e7a0 c07e9f14 c07e9ed8 c00283d0 c0028478 56251311 00023c889ee0: c07e9f0c 00000003 c08187ac 00000018 00000000 01000000 c07ebc70 00023cbc9f00: 56251311 00023c88 c07e9f24 c07e9f18 c03391e8 c0028348 c07e9f3c c07e9f289f20: c0028070 c03391b0 ffffffff 0000001f c07e9f94 c07e9f40 c002d4d0 c00280109f40: 00000000 00000001 c07e9f88 60000013 c07e8000 c07ebc78 c0868784 c07ebc709f60: 00023cbc 56251311 00023c88 c07e9f94 c07e9f98 c07e9f88 c025c3e4 c025c3f49f80: 60000013 ffffffff c07e9fb4 c07e9f98 c025c578 c025c3cc 00000000 c09812049fa0: c0025ca0 c0d01140 c07e9fc4 c07e9fb8 c0032094 c025c528 c07e9ff4 c07e9fc89fc0: c0008918 c0032048 c0008388 00000000 00000000 c0025ca0 00000000 000539759fe0: c0868834 c00260a4 00000000 c07e9ff8 00008034 c0008708 00000000 00000000Backtrace:[<c06bed28>] (dev_get_by_flags+0x0/0x140) from [<c071f764>] (arp_process+0xbb4/0xc74) r7:c64b210c r6:00000007 r5:c6a00000 r4:c66a0000

1) First, check that the stack information is printed in the file in the kernel, in fault. in the c file, the __do_kernel_fault function is Unable to handle kernel paging request at virtual address 45685516 in the above print. This address is an inaccessible address in the kernel space.

static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr, struct pt_regs *regs){  /*  * Are we prepared to handle this kernel fault?  */  if (fixup_exception(regs))    return;  /*  * No handler, we'll have to terminate things with extreme prejudice.  */  bust_spinlocks(1);  printk(KERN_ALERT    "Unable to handle kernel %s at virtual address %08lx",    (addr <PAGE_SIZE) ? "NULL pointer dereference" :"paging request", addr);  show_pte(mm, addr);  die("Oops", regs, fsr);  bust_spinlocks(0);  do_exit(SIGKILL);}

2) the following two pieces of information are printed in the show_pte function. The following print involves the global directory of the page and the knowledge of the page table, which will not be analyzed for the time being and will be supplemented later.

pgd = c65a4000[45685516] *pgd=00000000void show_pte(struct mm_struct *mm, unsigned long addr){  pgd_t *pgd;  if (!mm)    mm = &init_mm;   printk(KERN_ALERT "pgd = %p", mm->pgd);  pgd = pgd_offset(mm, addr);  printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));……………………}


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.