https://codingkaiser.blog/2021/07/17/create-your-own-system-calls%e2%80%8a-%e2%80%8aprocess-weights/ Coding Kaiser Menu * Homepage * Posts * About me * Contact Search Search for: [ ] [Search] Menu Search Coding Kaiser Close Search for: [ ] [Search] * Homepage * Posts * About me * Contact Computer Science Operating Systems Modifying The Linux Kernel - New Syscalls [b549a86ecd97b] by Eliran July 17, 2021 Comments 0 [0_rs7h2diz6g7pp-4-] In this article, we will learn how to modify the linux kernel, add our own unique system calls and finally build the kernel with our added functionality. --------------------------------------------------------------------- Before we get to modify the linux kernel we will have to download it somehow. I am going to specify the steps I took, so make sure you follow precisely to gurantee the same results. * Download a virtual machine software such as Vimware \ VirtualBox * Download a Ubuntu 18.04 image http://releases.ubuntu.com/18.04/ * Set up your virtual OS from the virtual machine software using the image you downloaded Once Ubuntu has loaded, open the terminal and follow along * Installing prerequisites >> sudo sed -i "s/# deb-src/deb-src/g" /etc/apt/sources.list >> sudo apt update -y >> sudo apt install -y build-essential libncurses-dev bison flex >> sudo apt install -y libssl-dev libelf-dev * Download Linux source code >> cd ~ >> apt source linux * Changing permissions and renaming the folder >> sudo chown -R student:student ~/linux-4.15.0/ >> mv ~/linux-4.15.0 ~/linux-4.15.18-custom * Configuring the kernel building process >> cd ~/linux-4.15.18-custom >> cp -f /boot/config-$(uname -r) .config >> geany .config # search the CONFIG_LOCALVERSION parameter and set it to "-custom" >> yes '' | make localmodconfig >> yes '' | make oldconfig * Compiling the kernel >> make -j $(nproc) * Install kernel modules and image >> sudo make modules_install >> sudo make install * Configuring GRUB >> sudo geany /etc/default/grub Once the file is opened do the following * Set 'GRUB_DEFAULT' to "Ubuntu, with Linux4.15.18-custom" * Set 'GRUB_TIMEOUT_STYLE to menu * Set 'GRUB_TIMEOUT' to 5 * Add the line: "GRUB_DISABLE_SUBMENUE=y" at the end of the To finish off, we will have to generate the GRUB config file and reboot with >> sudo update-grub >> sudo reboot Once the OS booted, make sure that you loaded the custom kernel >> uname -r Should result with "4.15.18-custom" That's it, we have done with the prerequisites, it's time to code. --------------------------------------------------------------------- The functionality we are about to add is called process weights. As the name suggests, we will assign every process a weight that will represent how "heavy" it is. Two behaviors that we want to maintain are: * When a process is forked, the child process will have the same weight as his father * The init process weight will be 0 The system calls we are about to implement will be able to * Set the weight of the current process * Get the total weight of the current process recursively --------------------------------------------------------------------- First, we will need to somehow tell each process "FYI, you have a weight now". In order to do so, open ~/linux-4.15.18-custom/include/linux/sched.h And Inside the struct task_struct add an attribute of int weight struct task_struct { #ifdef CONFIG_THREAD_INFO_IN_TASK /* * For reasons of header soup (see current_thread_info()), this * must be the first element of task_struct. */ struct thread_info thread_info; #endif /* -1 unrunnable, 0 runnable, >0 stopped: */ int weight; #line 569 volatile long state; /* * This begins the randomizable portion of task_struct. Only * scheduling-critical items should be added above here. */ randomized_struct_fields_start Now, we would like to tell every process what's his initial weight, in order to do that, under the same directory as before, open init_task.h -- go to the macro definition of INIT_TASK and add an initialization to the weight attribute you just added. #define INIT_TASK(tsk) \ { \ INIT_TASK_TI(tsk) \ .weight = 0, \ #line 228 .state = 0, \ .stack = init_stack, \ ... --------------------------------------------------------------------- In the last section, we were able to tell each process that it has a new attribute called weight and that this attribute should initialize to 0 whenever a new process is created. In this section, we will focus on setting up the ground for our new system calls. Navigate to ~/linux-4.15.18-custom/arch/x86/entry/syscalls/ and open syscall_64.tbl Scroll to the bottom of the file and reserve your syscalls numbers ... 332 common statx sys_statx 333 common hello sys_hello 334 common set_weight sys_set_weight 335 common get_total_weight sys_get_total_weight ... Now we will create our system call signature. go to syscalls.h under the same directory and scroll to the bottom of the file ... asmlinkage long sys_pkey_free(int pkey); asmlinkage long sys_statx(int dfd, const char __user *path, unsigned flags, unsigned mask, struct statx __user *buffer); asmlinkage long sys_hello(void); asmlinkage long sys_set_weight(int weight); #line 944 asmlinkage long sys_get_total_weight(void); #endif --------------------------------------------------------------------- We have set everything up, the only thing missing is the implementation of these new syscalls. Navigate to ~/linux-4.15.18-custom/kernel and create a new file called syscalls_weight.c . Don't forget to go into Makefile under the same directory and add your new file to the building process # SPDX-License-Identifier: GPL-2.0 # # Makefile for the linux kernel. # obj-y = fork.o exec_domain.o panic.o \ cpu.o exit.o softirq.o resource.o \ sysctl.o sysctl_binary.o capability.o ptrace.o user.o \ signal.o sys.o umh.o workqueue.o pid.o task_work.o \ extable.o params.o \ kthread.o sys_ni.o nsproxy.o \ notifier.o ksysfs.o cred.o reboot.o \ async.o range.o smpboot.o ucount.o hello_syscall.o syscalls_weight.o ... Open the file you just created syscalls_weight.c and let's implement our new system calls. First, include the following libraries #include #include #include #include And let's start with the implementation of sys_set_weight asmlinkage long sys_get_weight(int weight){ if(weight < 0){ return -EINVAL; } current->weight = weight; return 0; } Few things to notice * current is a pointer to the current task running * The convention with syscalls is to return 0 if it was successful and return a negative value if some error occurred and that's exactly what we did (considering that we don't want to allow a negative weight). Moving on to the next syscall implementation, we will first define another function that will help us int traverse_children_sum_weight(struct task_struct *root_task){ struct task_struct *task; struct list_head *list; int sum = root_task->weight; list_for_each(list, &root_task->children){ task = list_entry(list, struct task_struct, sibling); sum += traverse_children_sum_weight(task, true); } return sum; Then, our syscall implementation will be asmlinkage long sys_get_total_weight(void){ return traverse_children_sum_weight(current); } --------------------------------------------------------------------- We did it. all you have to do now is to build your kernel, restart your machine and you are free to use these brand new kernel features that you just created. To build and restart, simply execute the following make -j $(nproc) sudo cp -f arch/x86/boot/bzImage /boot/vmlinuz-4.15.18-custom sudo reboot Can you think of some new interesting features you can add? Maybe it will be your next coding project. Share this: * Tweet * * More * * * * * Telegram * WhatsApp * * Email * Like this: Like Loading... 0 comments on "Modifying The Linux Kernel - New Syscalls" Leave a Reply Cancel reply Enter your comment here... [ ] Fill in your details below or click an icon to log in: * * * * Gravatar Email (required) (Address never made public) [ ] Name (required) [ ] Website [ ] WordPress.com Logo You are commenting using your WordPress.com account. ( Log Out / Change ) Google photo You are commenting using your Google account. ( Log Out / Change ) Twitter picture You are commenting using your Twitter account. ( Log Out / Change ) Facebook photo You are commenting using your Facebook account. ( Log Out / Change ) Cancel Connecting to %s [ ] Notify me of new comments via email. [ ] Notify me of new posts via email. [Post Comment] [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ] Post navigation Previous Post Next Post Related Coding Kaiser Subscribe to Blog via Email Enter your email address to subscribe to this blog and receive notifications of new posts by email. Email Address: [ ] Subscribe Website Powered by WordPress.com. Send to Email Address [ ] Your Name [ ] Your Email Address [ ] [ ] loading [Send Email] Cancel Post was not sent - check your email addresses! Email check failed, please try again Sorry, your blog cannot share posts by email. %d bloggers like this: [b]