Thursday, February 25, 2010

How to find all processes in Linux manually

How to find all processes in Linux manually

Linux kernel already provides a MACRO called for_each_process to go through each process. However, you may need to find all the processes manually sometimes. Following is the method:

Environment:

QEMU 0.10.2
QEMU VM: Cent OS 5.3 (Linux 2.6.18)
ARCH :X86-32

Basic idea:

We know that every process has a task_struct in Linux. The task_struct has a member called “tasks”. It is a list_head and all the processes are linked together by task_struct.tasks.

Therefore, to find out all the processes, we could find one task_struct and then follow the tasks member. Other useful members in task_struct are: pid (it is similar to thread id on Windows), tgid ( it is similar to process id on Windows), comm (command line, can be used as process name ).

Next, we are going to use QEMU to find all the processes manually from QEMU monitor. In GDB, we could use “p task->tgid” command to print out the tgid. But QEMU does not support that. So we have to know the exact offset for each interesting member of task_struct.

To find out the offset for members such as tasks, pid, I use a kernel module to print out them. Following is the result: (pid =0xbc means the offset of pid in tasks_struct is at 0xbc)

pid = 0Xbc
tgid = 0Xc0
comm = 0X1AC
tasks = 0X80

The next thing we need to know is how to find the first task_struct. You can read ULK3 or LKD2 to find the answer. In sum, find esp first, in QEMU, esp can be obtained by using “p $esp”, let’s say it is 0xc100,4566. Set the low 13bit of the esp to 0, we get 0xc100,4000. This is the value of “current”, and it’s first member is the *task_struct.

OK, let’s do a real experiment :
1) Setup a QEMU VM with CentOS 5.3 installed as the guest OS. And run it.
2) Press alt+ctrl+2 to switch to QEMU monitor. Then type “stop” in the QEMU monitor. This stops the QEMU emulation so that we don’t need to worry about the memory changes due to a process exit.
3) Type p$esp to find esp. It is 0xc3a94f78 in my experiment.
4) Find THEAD_INFO . That is to set the low 13bit of esp to 0. We got 0xc3a94000
5) x /20w 0xc3a94000 . This will show the content of THREAD_INFO. The first member is the *task. The result is 0xc3aaa370. (Note that, sometimes the value here might be 0, just press “c” to let QEMU continue and “stop” to try more times.)
6) Now we know the address for task_struct, then it is easy to find tgid, tasks and comm. For example, pid is at 0xc3aaa42c (task_struct+0XBC). Note that when checking the content of “comm”, use following command in QEMU : x /20b 0xc3aaa51c. Otherwise, the byte order is reversed by QEMU.
7) Now we know the info about the current process. To find out the next one, just follow task_struct->tasks. Note that the address of task_struct->tasks->next is not the base address of task_struct. The base address of next task_strcut is 0x80 smaller. Then you can repeat the above steps to find out all the processes.

No comments: