Monday, September 22, 2008

/proc/kcore part II

It will take me a few posts to go through the kcore file... The last kcore post dealt only with ELF headers of the kcore file. After the ELF header ends, there are 3 program headers:

From elf.h we see that the structure of a program header is:

typedef struct
{
Elf32_Word p_type; /* Segment type */
Elf32_Off p_offset; /* Segment file offset */
Elf32_Addr p_vaddr; /* Segment virtual address */
Elf32_Addr p_paddr; /* Segment physical address */
Elf32_Word p_filesz; /* Segment size in file */
Elf32_Word p_memsz; /* Segment size in memory */
Elf32_Word p_flags; /* Segment flags */
Elf32_Word p_align; /* Segment alignment */
} Elf32_Phdr;



A look at the first program header below:

0000030: 0000 0000 0400 0000 9400 0000 0000 0000 ................
0000040: 0000 0000 d807 0000 0000 0000 0000 0000 ................
0000050: 0000 0000



The first program header is of type PT_NOTE (Auxiliary info) which has a value of 0x4
We can see that the offset is 0x94
The filesize has a value of 0x7d8

All other parts of the struct are set to 0x0

A look at the second program header below:

0000050: 0000 0000 0100 0000 0010 8038 0000 80f8 ...........8....
0000060: 0000 0000 00e0 ff06 00e0 ff06 0700 0000 ................
0000070: 0010 0000



The type is of type PT_LOAD 0x1 (loadable program segment)
The offset is 0x38801000
vaddr is 0xf8800000 (vmalloc)
filesz and memsz are both 0x6ffe000
flags are 0x7 (PF_R | PF_W | PF_X)
page alignment is 0x1000 (size of a page - 4096)

The other remaining part of the structure (p_paddr) is 0x0

The third program header looks like:

0000070: 0010 0000 0100 0000 0010 0000 0000 00c0 ................
0000080: 0000 0000 0000 0038 0000 0038 0700 0000 .......8...8....
0000090: 0010 0000



The type is of type PT_LOAD 0x1 (loadable program segment)
The offset is 0x1000 (size of a page - 4096)
vaddr is 0xc0000000 (start of lowmem)
filesz and memsz are both 0x38000000 (size of (kcore-4096))
flags are 0x7 (PF_R | PF_W | PF_X)
page alignment is 0x1000 (size of a page - 4096)

The other remaining part of the structure (p_paddr) is 0x0

From my messages file to compare:

Sep 15 12:28:57 kanga kernel:
Memory: 2060724k/2087616k available
(2252k kernel code, 25548k reserved, 1182k data, 284k init, 1170112k highmem)
Sep 15 12:28:57 kanga kernel: virtual kernel memory layout:
Sep 15 12:28:57 kanga kernel: fixmap : 0xffc53000 - 0xfffff000 (3760 kB)
Sep 15 12:28:57 kanga kernel: pkmap : 0xff400000 - 0xff800000 (4096 kB)
Sep 15 12:28:57 kanga kernel: vmalloc : 0xf8800000 - 0xff3fe000 ( 107 MB)
Sep 15 12:28:57 kanga kernel: lowmem : 0xc0000000 - 0xf8000000 ( 896 MB)
Sep 15 12:28:57 kanga kernel: .init : 0xc0761000 - 0xc07a8000 ( 284 kB)
Sep 15 12:28:57 kanga kernel: .data : 0xc063337f - 0xc075ab88 (1182 kB)
Sep 15 12:28:57 kanga kernel: .text : 0xc0400000 - 0xc063337f (2252 kB)



Notes

The next three sections will use this structure:

struct memelfnote
{
const char *name;
int type;
unsigned int datasz;
void *data;
};



Looking at the first note (only the interesting part, the rest is zeroed out):

0000090: 0010 0000 0500 0000 9000 0000 0100 0000 ................
00000a0: 434f 5245



In this case the items shown are not in the same order of the struct. This is because they have been placed in a slightly different order.

First we have the size of the name: 0x5 (strlen(CORE)+1)
Then the data size: 0x90 (size of elf_prstatus struct)
Then the type: 0x1 (NT_PRSTATUS)
Then the name itself: CORE
And finally the data, which has been zeroed out (not shown).

The next note looks like the following:


0500 0000 7c00 0000 ............|...
0000140: 0300 0000 434f 5245 0000 0000 0052 0000 ....CORE.....R..
0000150: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000160: 0000 0000 0000 0000 766d 6c69 6e75 7800 ........vmlinux.
0000170: 0000 0000 0000 0000 726f 2072 6f6f 743d ........ro root=
0000180: 2f64 6576 2f56 6f6c 4772 6f75 7030 302f /dev/VolGroup00/
0000190: 4c6f 6756 6f6c 3030 2072 6867 6220 7175 LogVol00 rhgb qu
00001a0: 6965 7400 0000 0000 0000 0000 0000 0000 iet.............
00001b0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
00001c0: 0000 0000 0000 0000



First we have the size of the name: 0x5 (strlen(CORE)+1)
Then the data size: 0x7c (sizeof(struct elf_prpsinfo))
Then the type: 0x3 (NT_PRPSINFO )
Then the name itself: CORE
And finally the data, which uses the elf_prpsinfo structure:

struct elf_prpsinfo
{
char pr_state; /* numeric process state */
char pr_sname; /* char for pr_state */
char pr_zomb; /* zombie */
char pr_nice; /* nice val */
unsigned long pr_flag; /* flags */
__kernel_uid_t pr_uid;
__kernel_gid_t pr_gid;
pid_t pr_pid, pr_ppid, pr_pgrp, pr_sid;
/* Lots missing */
char pr_fname[16]; /* filename of executable */
char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */
};



The data consists of:
pr_state 0x0
pr_sname 0x52 (R)
pr_zomb 0x0
Executable file name (pr_fname) "vmlinux"
Saved command line (pr_psargs) up to 80 characters
ro root=/dev/VolGroup00/LogVol00 rhgb quiet

The rest is zeroed out from a memset command

The third note denotes information about the current task. Here is part of it:


0500 0000 9006 0000 ................
00001d0: 0400 0000 434f 5245 0000 0000 0000 0000 ....CORE........
00001e0: 0020 b2f0 0200 0000 0021 4000 ffff ffff . .......!@.....
00001f0: 7800 0000 7800 0000 7800 0000 b086 8af0 x...x...x.......
0000200: b086 8af0 4072 63c0 0004 0000 0000 4000 ....@rc.......@.
0000210: 0100 0000 0000 0000 0000 0000 0100 0000 ................
0000220: 494c 6a33 c10a 0000 2fd2 1d00 0000 0000 ILj3..../.......
0000230: 85b4 abc6 0c01 0000 6134 0c00 0000 0000 ........a4......
0000240: 0000 0000 0000 0000 5669 0d00 0000 0000



First we have the size of the name: 0x5 (strlen(CORE)+1)
Then the data size: 0x690 (sizeof(struct task_struct) found in linux/sched.h)
Then the type: 0x4 (NT_TASKSTRUCT )
Then the name itself: CORE
And finally the data, which consists of `current' which is the current thread (not shown above).

Now we must dissect task_struct info, which we'll do a bit later...

2 comments:

Brendan Dolan-Gavitt said...

Cool stuff! I've been meaning to get more into Linux memory analysis, so I'm really looking forward to reading about task_struct and so on :)

Keep up the great posts!

Jamie Levy said...

Thanks, moyix :-)

I didn't know anyone read my blog...

It will take a little while, but we'll get through it ;-)