`What does it mean by speak, friend, and enter?' asked Merry.
'That is plain enough,' said Gimli. `If you are a friend, speak the password, and the doors will open, and you can enter.'
—The Fellowship of the Ring, Book 2, Chapter 4
System calls are the fundamental, most stable interface that is provided by the operating system. They are how user programs request the vast majority of kernel actions: creating, reading, and destroying files; allocating and freeing dynamic memory; executing new programs, etc.
In this studio, you will:
Please complete the required exercises below, as well as any optional enrichment exercises that you wish to complete.
As you work through these exercises, please record your answers, and when finished email your results to email@example.com with the phrase System Calls Studio in the subject line.
Make sure that the name of each person who worked on these exercises is listed in the first answer, and make sure you number each of your responses so it is easy to match your responses with each exercise.
Navigate outside of the linux source code directory
and make a new directory for your userspace programs, and a new file called
lib_call.c. In Linux, all users have an associated user ID number.
Write a short program that reads your user ID, then attempts to set it to
zero (the root uid),
and then reads it again with the functions
setuid. Use the man pages at
man getuid and
man setuid to understand what header
files you need to include and how to call these functions.
Since the call to
setuid may fail, we need to do proper unix
style error checking. Store the return value from setuid into a variable,
and follow it up with something like:
if( return_val != 0 ) printf("Error to setuid failed! Reason: %s\n", strerror(errno));
Again, you can use the man pages to determine which header files to include
with the commands
man strerror, and
At the end of your program, write out the before and after values of the user ID. As the answer to this question, copy and paste your program output.
man syscall(this is a different page than we accessed before, which was
man syscalls). Copy your program to a new file called
native_call.cand replace the calls to
setuidwith calls to
syscall. To do so, you will have to determine their ARM architecture specific system call numbers by looking at the linux source files
As the answer to this exercise, copy and paste your program output.
setuidand give any process the root user ID (this is a bad thing in general, but it is illustrative). You will write the second system call, which will print a message into the kernel log.
Note:When making changes to the linux source code, add the comment //AOS before each section. This, along with generating file diffs is how we will keep track of the changes made to the kernel.
There are five discrete tasks we need to accomplish to do so:
First, we declare two new function prototypes that take no arguments at the
include/linux/syscalls.h. Before doing so, make a backup
with the command
cp syscalls.h syscalls.h.orig
You can use the prototype for
sys_getuid as a template for this. Make sure that you use
void in the argument list to indicate no arguments, since in
C programming a function declared
f(void) is not the same as
a function declared
f() (which inidicates that the function may
take any number of parameters of unknown type). Our new system call is going
to do something relatively bad (in operating system terms), so call it
sys_badcall. Make a second prototype that accepts one integer
parameter and call it what you would like.
As the answer to this exercise, give the two function prototypes you've made.
arch/arm/kernel/. The naming convention for a file that only implements a system call is to call the file by the syscall name, so since our prototype is called
sys_badcall, you would create the file
sys_badcall.c. (Additionally, there are other places we could have put this file, but since we're only adding this call for the ARM architecture, this is the most appropriate place.) Make a second file for your second system call in the same place and with the same naming convention.
For the implementation of
sys_badcall, copy and paste the
contents of the file found here. Take a moment
to look through this file. Notice that the function declaration isn't a normal
declaration, but actually made through the macro
(the zero comes from that this syscall takes zero arguments, and is defined
For the implementation of your second syscall, use sys_badcall.c as a
template. You'll need to change the
SYSCALL_DEFINE0 macro to
reference the name you came up with, as well as the fact that this function
accepts an integer parameter. You do this by passing the type and the name of
the parameter to the macro as such:
SYSCALL_DEFINE1( your_name, int, param_name )
In the body of this syscall, use the kernel function
to print a message along with the value of the parameter. You can use
printk as you would use
printf. Be sure to return
a proper return value from this function.
Leave the answer to this exercise blank.
arch/arm/kernel/) and add our two new files to the end of the object file list, which starts on the line with
obj-y(make sure you do not add your files after a
\character, as this specifies the start of a new line.
Leave the answer to this exercise blank.
Before modifying this file, make a copy into
Then, open the file and write system call numbers 388 and 389 for
sys_badcall and your own system call near the bottom of the file. Use the
other system calls as a template for how to do so.
Next we will modify
arch/arm/kernel/calls.S. This is actually
an ARM assembly language file that defines the system call table. Similar to
before, first make a backup of
calls.S and then
add two new invocations of the
CALL macro near the end
of the file for
sys_badcall and your function.
Finally, we need to update the symbol that tells the kernel how many system
calls that it has. Go to
arch/arm/include/asm/unistd.h, make a
backup copy, and update the value of
__NR_syscalls to 392. This
seems strange, but on the ARM architecture the system call table can only be
certain sizes. See the enrichment exercises for more info.
Leave this exercise blank.
drivers, etc.) you should issue the command
make cleanto remove previous build products.
Then, to differentiate your
next kernel from your current, we'll modify the kernel LOCALVERSION. Rather
than using the
menuconfig like last time, it's faster and easier
to modify the configuration directly. In the base directory, open the file
.config (the leading period means that this is a hidden
file that is not normally displayed) and modify the
CONFIG_LOCALVERSION string to reflect the fact that this new
kernel implements studio 2.
You can now build your new kernel following the procedure outlined in studio 1.
uname -a), you're now ready invoke your new system calls. First, make a copy of
lib_call.cand call it
badcall_call.c. Then, replace the call to
setuidwith a native system call to
As the answer to this exercise, copy and paste the output from
As the answer to this exercise, copy and paste the last few lines of the system message log.
To submit this studio, include the answers to exercises given above, attach the userspace programs you wrote, as well as diffs of the kernel source code files you modified. To create a diff, use the diff program with the backup versions of the source code you modified.
diff -up unistd.h unistd.h.orig > unistd.h.diff
For this studio, you will submit:
If you don't have an original copy for any of these files, you can find them in the original source code package.
The kernel code that contains the entry point for system calls is found