Add system call to print process pid in tree structure

Posted by binto on Mon, 14 Feb 2022 14:38:00 +0100

Tip: pay attention to give the virtual machine a large enough disk, more than 60G

1, Design ideas

  1. Download linux kernel source code

  2. Add the system call number to the system call table

  3. Write custom system call functions in the system call header file

  4. Modify the kernel source code and add the implementation of custom system call function

  5. Install the dependency tool, recompile the kernel, and use the new kernel

  6. Write test code and test

2, Implementation process

1. Download the linux kernel source code

Download the kernel source code from the official website at: https://mirrors.edge.kernel.org/pub/linux/kernel/

Download address of domestic source code: http://ftp.sjtu.edu.cn/sites/ftp.kernel.org/pub/linux/kernel/

Check the kernel version of your system, and then find a similar linux version for kernel upgrade. Here I choose 5.14.1

Download the source package and unzip it to / usr/src

mv linux-5.14.1.tar.gz /usr/src

tar xvf linux-5.14.1.tar.gz

2. Add the system call number to the system call table

ABI(Application Binary Interface): binary interface. It defines how the application interacts internally, how the application interacts with the kernel, and how to interact with the library to ensure binary compatibility. For the same ABI, the object code can run normally on any system without recompiling. It focuses on function call conventions, byte order, register usage, system calls, links, library behavior, and the format of binary targets. ABI is a function provided by the operating system and architecture. Defining a set of ABI for an architecture is difficult, and binary portability is difficult.

System call table path: / usr/src/linux-5.14.1/arch/x86/entry/syscalls/syscall_64.tbl

<number>     <abi>             <name>             <entry point>
331	        common	          pkey_free	          sys_pkey_free
332	        common	           statx		       sys_statx
333	        common	       io_pgetevents		sys_io_pgetevents
334	        common	           rseq			       sys_rseq
335           64         print_all_process    sys_print_all_process

3. Write custom system call functions in the system call header file

Add a custom system call declaration in the header file. The path of the header file is: / usr / SRC / linux-5.14.1/arch/x86/include/asm/syscalls h

#ifndef _ASM_X86_SYSCALLS_H
#define _ASM_X86_SYSCALLS_H

/* Common in X86_32 and X86_64 */
/* kernel/ioport.c */
long ksys_ioperm(unsigned long from, unsigned long num, int turn_on);

/* added by me */
asmlinkage long __x64_sys_print_all_process(void);

#endif /* _ASM_X86_SYSCALLS_H */

4. Modify the source code of the system call

At / usr / SRC / linux-5.14.1/kernel/sys C can be added. Note that it cannot be written to the macro

// 335 64      print_all_process   sys_print_all_process
static void print_children(struct task_struct* task, int level){
	struct list_head* pos;
	struct task_struct* ptr;

	// Tree structure output
	int i;
	for(i = level; i > 0; i--){
		printk(KERN_CONT "    ");
	}

	// Process name and pid
	printk(KERN_CONT "|--");
	printk(KERN_CONT "%s[%d]\n", task->comm, task->pid);

	// Use parent task_struct's children two-way linked list, traversing its child processes
	list_for_each(pos, &task->children){
		// Return task_struct pointer to find the task corresponding to pos_ Struct, cheap equivalent to sibling
		ptr = list_entry(pos, struct task_struct, sibling);
		if(ptr != NULL){
			level++;
			// Recursive printing sub process tree
			print_children(ptr, level);
			level--;
		}
	}
}

asmlinkage long __x64_sys_print_all_process(void){
	printk("The Process Tree Is As Follows:");
	print_children(&init_task, 0);
	return 0;
}

5. Install the dependency tool, recompile the kernel and use the new kernel

Switch to root user for operation

apt update
apt install libncurses5-dev libssl-dev
apt install build-essential openssl
apt install zlibc minizip
apt install libidn11-dev libidn11
apt install flex bison
apt install libdw-dev
apt install libncurses-dev
apt install dwarves
apt-get install libdw-dev
make mrproper
make clean
make menuconfig

Pop up the configuration menu, save - > OK - > Exit - > exit

The process of compiling the kernel is very long and there will be various bug s. The version I use is 5.14.1, which requires at least 60G disk and at least 4 hours of compilation

cd /usr/src/linux-5.14.1

Compile kernel: make

After the installation of the module is completed, enter the command in the console: sudo make modules_install

After the module is installed, enter the command in the console to install the kernel: sudo make install

After installation: reboot

You can see that the kernel version has been updated to 5.14.1

6. Write test code and test

#include <linux/unistd.h>
#include <sys/syscall.h>

int main(){
    syscall(335);
    return 0;
}

Since the output statement of the added system call is written by printk, which sends the message to the system log, the console does not output. Enter the command to view the log: dmesg

3, Problems encountered in compiling kernel and Solutions

  1. Compilation error New address family defined, please update secclass_map. solve

  2. No libelf h libdw. h

  3. Problems and solutions when compiling Linux kernel

  4. BTF: .tmp_vmlinux.btf: pahole (pahole) is not available

  5. arch/x86/boot/compressed/vmlinux.bin.lzma] Error 1

4, References

Topics: Linux Operation & Maintenance server