GFDL:Implement a system call on Linux 2.6 for i386

Implementing a System Call on Linux 2.6 for i386Amit Choudharyhttp://amit-choudhary.blogspot.comamit2030 AT gmail DOT comVersion 1.0, 27 October 2006This HOWTO describes information about implementing system calls in Linux operating system for i386 architecture with 2.6 kernels. General information about the used and modified files is available as well as description of the source and makefiles and test user space C program too.</P><H1 CLASS="western">Table of contents</H1><UL>Introduction</P>System call</P>List of files to be 	modified/created</P>Kernel files to be modified</P></UL><UL><UL><LI VALUE=1>syscall_table.S</P>unistd.h</P>syscalls.h</P>Makefile</P></UL>New kernel files/directories to be 	created</P></UL><UL><UL><LI VALUE=1>mycall</P>mycall.c</P>Makefile</P></UL>New user space files, to be 	created, to test our system call</P></UL><UL><UL><LI VALUE=1>testmycall.h</P>testmycall.c</P></UL><P STYLE="margin-bottom: 0in">_syscallN macro</P><P STYLE="margin-bottom: 0in">Testing our new system call</P><P STYLE="margin-bottom: 0in">Questions And Suggestions</P><P STYLE="margin-bottom: 0in">Copyright</P><P STYLE="margin-bottom: 0in">License</P></UL><H1 CLASS="western">1. Introduction</H1><P STYLE="margin-bottom: 0in">This document explains how to implement a new system call on linux 2.6. A system call is used by application (user) programs to request service from the operating system.</P><H1 CLASS="western">2. System call</H1><P STYLE="margin-bottom: 0in">A system call is used by application (user) programs to request service from the operating system. The following statements illustrate why system calls are needed. An operating system can access a system's hardware directly, but a user program is not given direct access to the hardware. This is done so that the kernel can keep the system safe and secure from malicious user programs. But often, a user program requires some information from the hardware (e.g., from a web camera to show you the picture), but it cannot get the information directly. So, it requests the operating system to supply it the information. This request is made by using an appropriate system call.</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">A system call executes in the kernel mode. Every system call has a number associated with it. This number is passed to the kernel and that's how the kernel knows which system call was made. When a user program issues a system call, it is actually calling a library routine. The library routine issues a trap to the Linux operating system by executing INT 0x80 assembly instruction. It also passes the system call number to the kernel using the EAX register. The arguments of the system call are also passed to the kernel using other registers (EBX, ECX, etc.). The kernel executes the system call and returns the result to the user program using a register. If the system call needs to supply the user program with large amounts of data, it will use another mechanism (e.g., copy_to_user call).</P><H1 CLASS="western">3. List of files to be modified/created</H1><P STYLE="margin-bottom: 0in">Assume that your linux source base directory is /usr/src/linux.</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">Kernel files to be modified are listed below:</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">1. /usr/src/linux/arch/i386/kernel/syscall_table.S</P><P STYLE="margin-bottom: 0in">2. /usr/src/linux/include/asm-i386/unistd.h</P><P STYLE="margin-bottom: 0in">3. /usr/src/linux/include/linux/syscalls.h</P><P STYLE="margin-bottom: 0in">4. /usr/src/linux/Makefile</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">New kernel files/directories to be created are listed below:</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">1. /usr/src/linux/mycall - Directory that will contain the source file, header file and the Makefile for our system call (You can also implement your system call in an existing file).</P><P STYLE="margin-bottom: 0in">2. /usr/src/linux/mycall/mycall.c - Source file containing our system call code.</P><P STYLE="margin-bottom: 0in">3. /usr/src/linux/mycall/Makefile - Makefile</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">New user space files, to be created, to test our system call are listed below:</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">1. testmycall.c – Source file that will call our system call.</P><P STYLE="margin-bottom: 0in">2. testmycall.h - Header file.</P><H1 CLASS="western">4. Kernel files to be modified</H1><H1 CLASS="western">4.1 syscall_table.S</H1><P STYLE="margin-bottom: 0in">Full path of the file - /usr/src/linux/arch/i386/kernel/syscall_table.S</P><P STYLE="margin-bottom: 0in">This file contains system call names.</P><UL><P STYLE="margin-bottom: 0in">Add a line to the end of this file 	(Let's assume that the name of our system call is mycall).</P><P STYLE="margin-bottom: 0in">Add &quot;.long sys_mycall&quot; 	at the end of the list.</P></UL><H1 CLASS="western">4.2 unistd.h</H1><P STYLE="margin-bottom: 0in">Full path of the file - /usr/src/linux/include/asm-i386/unistd.h</P><P STYLE="margin-bottom: 0in">This file contains the system call number that is passed to the kernel through the register (EAX) when a system call is invoked. </P><UL><P STYLE="margin-bottom: 0in">Add &quot;#define __NR_mycall 	&lt;Last_System_Call_Num + 1&gt;&quot; at the end of the list.</P></UL><P STYLE="margin-bottom: 0in">If the last system call defined here is:</P><P STYLE="margin-bottom: 0in">&quot;#define __NR_vmsplice316&quot;, then add:</P><P STYLE="margin-bottom: 0in">&quot;#define __NR_mycall317&quot; at the end of the list.</P><UL><P STYLE="margin-bottom: 0in">Increment the &quot;NR_syscalls&quot; 	by 1. So, if NR_syscalls is defined as:</P></UL><P STYLE="margin-bottom: 0in">&quot;#define NR_syscalls 317&quot;, then change it to:</P><P STYLE="margin-bottom: 0in">&quot;#define NR_syscalls 318&quot;</P><H1 CLASS="western">4.3 syscalls.h</H1><P STYLE="margin-bottom: 0in">Full path of the file - /usr/src/linux/include/linux/syscalls.h</P><P STYLE="margin-bottom: 0in">This file contain the declarations for system calls.</P><UL><P STYLE="margin-bottom: 0in">Add the following line at the end 	of the file:</P></UL><P STYLE="margin-bottom: 0in">&quot;asmlinkage long sys_mycall(int i);&quot;</P><H1 CLASS="western">4.4 Makefile</H1><P STYLE="margin-bottom: 0in">Full path of the file - /usr/src/linux/Makefile</P><P STYLE="margin-bottom: 0in"><BR></P><UL><P STYLE="margin-bottom: 0in">Add mycall/ to core-y (Search for 	regex: core-y.*+=). You will be creating this directory. This 	directory will contain the source file, header file and the Makefile 	for our system call.</P></UL><H1 CLASS="western">5. New kernel files/directories to be created</H1><H1 CLASS="western">5.1 mycall</H1><P STYLE="margin-bottom: 0in">Full path of the file - /usr/src/linux/mycall</P><P STYLE="margin-bottom: 0in"><BR></P><UL><P STYLE="margin-bottom: 0in">Create a new directory in 	/usr/src/linux and name it &quot;mycall&quot;.</P></UL><H1 CLASS="western">5.2 mycall.c</H1><P STYLE="margin-bottom: 0in">Full path of the file - /usr/src/linux/mycall/mycall.c</P><P STYLE="margin-bottom: 0in"><BR></P><UL><P STYLE="margin-bottom: 0in">Create a source file named 	&quot;mycall.c&quot; in dir &quot;mycall&quot;. mycall.c will have 	the code for our system call. The definition of the system call in 	the source file would be asmlinkage long sys_mycall(...){...}. It 	should include the file linux/linkage.h So, the file &quot;mycall.c&quot; 	will look like:</P></UL><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">/*---Start of mycall.c*/</P><P STYLE="margin-bottom: 0in">#include&lt;linux/linkage.h&gt;</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">asmlinkage long sys_mycall(int i)</P><P STYLE="margin-bottom: 0in">{</P><P STYLE="margin-bottom: 0in">return i+10;</P><P STYLE="margin-bottom: 0in">}</P><P STYLE="margin-bottom: 0in">/*---End of mycall.c--*/</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">What is asmlinkage?</P><P STYLE="margin-bottom: 0in">Asmlinkage is used to look for the arguments on the kernel stack.</P><H1 CLASS="western">5.3 Makefile</H1><P STYLE="margin-bottom: 0in">Full path of the file - /usr/src/linux/mycall/Makefile</P><P STYLE="margin-bottom: 0in">The Makefile in dir &quot;mycall&quot; will have only one line:</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">#####Makefile Start#####</P><P STYLE="margin-bottom: 0in">obj-y := mycall.o</P><P STYLE="margin-bottom: 0in">#####Makefile End#######</P><H1 CLASS="western">6. New user space files, to be created, to test our system call</H1><H1 CLASS="western">6.1 testmycall.h (new user space header file to be created)</H1><P STYLE="margin-bottom: 0in">testmycall.h</P><P STYLE="margin-bottom: 0in"><BR></P><UL><P STYLE="margin-bottom: 0in">Create a header file called 	testmycall.h. This header file should be included by any program 	calling our system call.</P><P STYLE="margin-bottom: 0in">Add three lines to it</P></UL><UL><P STYLE="margin-bottom: 0in">Line 1: This is needed because we 	need the definition of _syscall1.</P></UL><P STYLE="margin-bottom: 0in">#include&lt;linux/unistd.h&gt;</P><UL><P STYLE="margin-bottom: 0in">Line 2: This is needed because we 	need the number of our system call.</P></UL><P STYLE="margin-bottom: 0in">#define __NR_mycall 317</P><UL><P STYLE="margin-bottom: 0in">Line 3: This is needed for system 	calls with 1 argument. It is explained in detail below.</P></UL><P STYLE="margin-bottom: 0in">_syscall1(long, mycall, int, i)</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">So, our user header file looks like:</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">/*---Start of header file--*/</P><P STYLE="margin-bottom: 0in">#include&lt;linux/unistd.h&gt;</P><P STYLE="margin-bottom: 0in">#define __NR_mycall 317</P><P STYLE="margin-bottom: 0in">_syscall1(long, mycall, int, i)</P><P STYLE="margin-bottom: 0in">/*---End of header file*/</P><H1 CLASS="western">6.2 testmycall.c (new user space source file to be created)</H1><P STYLE="margin-bottom: 0in">testmycall.c</P><P STYLE="margin-bottom: 0in"><BR></P><UL><P STYLE="margin-bottom: 0in">Create a C file called 	testmycall.c in the same directory as testmycall.h. The C file will 	look like:</P></UL><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">/*---Start of C file--*/</P><P STYLE="margin-bottom: 0in">#include&lt;stdio.h&gt;</P><P STYLE="margin-bottom: 0in">#include &quot;testmycall.h&quot;</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">int main(void)</P><P STYLE="margin-bottom: 0in">{</P><P STYLE="margin-bottom: 0in">printf(&quot;%d\n&quot;, mycall(15));</P><P STYLE="margin-bottom: 0in">}</P><P STYLE="margin-bottom: 0in">/*---End of C file--*/</P><H1 CLASS="western">7. _syscallN macro</H1><UL><P STYLE="margin-bottom: 0in">_syscall0(int,mycall) indicates 	that:</P><P STYLE="margin-bottom: 0in">The name of the system call is 	mycall.</P><P STYLE="margin-bottom: 0in">It takes zero arguments.</P><P STYLE="margin-bottom: 0in">It returns an int.</P></UL><P STYLE="margin-bottom: 0in"><BR></P><UL><P STYLE="margin-bottom: 0in">_syscall1(int,mycall,int,number) 	indicates that:</P><P STYLE="margin-bottom: 0in">The name of the system call is 	mycall.</P><P STYLE="margin-bottom: 0in">It takes one argument.</P><P STYLE="margin-bottom: 0in">The argument is an int named 	number.</P><P STYLE="margin-bottom: 0in">It returns an int.</P></UL><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">When you expand _syscall1(long,mycall,int,i), you get the following code:</P><P STYLE="margin-bottom: 0in">long mycall(int i)</P><P STYLE="margin-bottom: 0in">{</P><P STYLE="margin-bottom: 0in">return syscall(__NR_mycall, i);</P><P STYLE="margin-bottom: 0in">}</P><P STYLE="margin-bottom: 0in"><BR></P><P STYLE="margin-bottom: 0in">But the definition of _syscallN macros are different in the kernel. You can look at /usr/src/linux/include/asm-i386/unistd.h for the definition.</P><H1 CLASS="western">8. Testing our new system call</H1><UL><P STYLE="margin-bottom: 0in">Step 1: Recompile and install the 	new kernel so that our system call becomes available to the 	operating system.</P><P STYLE="margin-bottom: 0in">Step 2: Compile and execute the 	user space C file (testmycall.c) that we created above.</P><P STYLE="margin-bottom: 0in">RESULT: You should see the output 	as 25. This has been tested on kernel 2.6.17.13.</P></UL><H1 CLASS="western">9. Questions And Suggestions</H1><UL><P STYLE="margin-bottom: 0in">Please send a mail to Amit 	Choudhary (amit2030 AT gmail DOT com).</P></UL><P STYLE="margin-bottom: 0in"><BR></P><H1 CLASS="western">10. Copyright.</H1><P STYLE="margin-bottom: 0in">Copyright (c) 2006 by Amit Choudhary.</P><P STYLE="margin-bottom: 0in">Permission is granted to copy, distribute and/or modify this document</P><P STYLE="margin-bottom: 0in">under the terms of the GNU Free Documentation License, Version 1.2</P><P STYLE="margin-bottom: 0in">or any later version published by the Free Software Foundation;</P><P STYLE="margin-bottom: 0in">with no Invariant Sections, no Front-Cover Texts, and no Back-Cover</P><P STYLE="margin-bottom: 0in">Texts. A copy of the license is included in the section entitled &quot;GNU</P><P STYLE="margin-bottom: 0in">Free Documentation License&quot;.</P><H1 CLASS="western">