Assignment 1 OS
Assignment 1 OS
UNIVERSITY OF TECHNOLOGY
FACULTY OF COMPUTER SCIENCE & ENGINEERING
OPERATING SYSTEM
Report
Assignment 1
Contents
1 Adding new system call (syscall) 2
1.1 Preparation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.2 Configuration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
2 Syscall implementation 5
2.1 Adding syscall’s definition and declaration . . . . . . . . . . . . . . . . . . 5
2.2 Adding the source file into the kernel source directory . . . . . . . . . . . . 6
1.1 Preparation
1. Set up a machine to be added the syscall, the specs of the system using in this report
is:
It is recommend to use the same Ubuntu’s version for the compatibility with the version
of the kernel going to be built.
(c) Get the developer’s libraries for ncurses (to edit configuration file through terminal
interface)
$ sudo apt-get install libncurses5-dev
**1 We need to install kernel-package because this package provides the capability to
create a Debian kernel image package by just running make-kpkg kernel image in a
kernel source directory tree. It can also package the relevant kernel headers into a kernel-
headers package, which ease the kernel building’s processes.
1
From now on I use this ** to answer the questions stated in the assignment’s specification
(a) Create a build directory, which stores all the things related to the kernel building
process and download the kernel’s tarball:
$ mkdir ~/kernel_build
The kernel’s version to be used is 4.4.21. Use wget to obtain kernel 4.4.21’s tarball.
$ cd ~/kernel_build
$ wget https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-4.4.21.tar.xz
** We have to use another kernel source from the server such as http://www.kernel.org
when we encounter some situation where we want to compile a new kernel. The orignal
kernel on the running OS was installed from a pre-compiled binary, we can compile the
original kernel by getting the right kernel’s source, and using a compiler to compile it.
(b) After getting it, unpack the kernel tarball with:
$ tar -xvJf linux -4.4.21.tar.xz
1.2 Configuration
1. Get the original config file and put it in the kernel source’s directory (The OS I’m
using has the original kernel’s version of 4.4.0-142-generic):
$ cp /boot/config-4.4.0-142-generic ~/kernel_build/linux-4.4.21/.config
3. Renaming kernel version in the General Setup by changing the field highlighted as
follows:
2 Syscall implementation
1. Add the syscall’s declaration into the syscall 32.tbl and syscall 64.tbl. Both of
these files are located at [kernel source dir]1 /arch/x86/entry/syscalls
1
[kernel source dir] in my case was ~/kernel build/linux-4.4.21
struct proc_segs;
2.2 Adding the source file into the kernel source directory
The implementation of the syscall is included as a .c file with the report, name as
sys procmem.c.
Copy the sys procmem.c to [kernel source dir]/kernel directory and add the follow-
ing line to the Makefile at the same directory:
obj-y += sys_procmem.o
1
will be used when we test our syscall
This tell kbuild that there is will be sys procmem.o object in the current directory,
sys procmem.o will be built from sys procmem.c.
1. Run the following command first (we can run this in parallel using -j[np] tag where
[np] is the number of processes we want to run the command):
$ make
2. After make, the vmlinuz will be created. Build the loadable kernel modules with this
following command, this command can be run in parallel too.
$ make modules
** The meaning of these two stages (namely make and make modules) are:
• make compiles and links the kernel image. This is a single file named vmlinuz
mentioned above.
• make modules compiles individual files for each question you answered M during the
kernel configuration (We don’t actually do this part, the kernel’s original configu-
ration file’s already done this for us). The object code is linked against the freshly
built kernel.
1. After adding syscall and installing the kernel by following the steps, reboot the VM
by running:
$ sudo reboot
$ uname -r
#include <sys/syscall.h>
#include <stdio.h>
#define SIZE 10
int main() {
long sysvalue;
unsigned long info[SIZE];
sysvalue = syscall(546, 1, info);
// change the first argument to the number of your
// syscall added in the syscalls_32.tbl (32-bit)
// or syscalls_64.tbl (64-bit)
printf("My id: %lu\n", info[0]);
}
I’m using 64-bit kernel so I’m calling the 546 syscall number.
The result is as follows:
** This program can validate if our system works or not since it’s calling the syscall and
getting the correct value of the first field from the struct proc_segs we assigned in our
sys procmem.c file.
This header contains the prototype of the wrapper and declare proc segs struct. The
header’s name is procmem.h and contains these as follows:
#ifndef _PROC_MEM_H_
#define _PROC_MEM_H_
#include <unistd.h>
struct proc_segs {
unsigned long id;
unsigned long start_code;
unsigned long end_code;
unsigned long start_data;
unsigned long end_data;
unsigned long start_heap;
unsigned long end_heap;
unsigned long start_stack;
};
** We have to re-define proc segs struct while we have already defined it inside the
kernel because when we call the syscall, we only get the info struct defined in kernel.
To use and extract information from the struct on user-space, we have to re-define the
struct.
The implementation of the wrapper is included as a .c file with the report, name as
procmem.c.
4.3 Validation
1. To install the wrapper, first copy the header file procmem.h to /usr/include directory
to make it visible to GCC by running:
** The root privilege is required to copy the header file to /usr/include as the / directory
is under root privilege. We are using the system as a common user, not root user, so we
are prevented to access the root’s directory (e.g. copying, moving files). Using the system
as a root user won’t need the sudo to do the task.
2. Compile our source code as a shared object to allow user to integrate our system call
to their applications. To do so, run the following command in the directory contains the
procmem.c and procmem.h files:
** We must put -shared and -fpic option into gcc command to make this gener-
ated binary a shared one (using -shared option). Shared libraries are usually position-
independent. And for position-independent, you have to load globals or jump to functions
using relative addresses (by adding -fpic option). The purpose of this is to make the
generated binary be called and used from anywhere without the actual file being in the
compiling directory.
3. Check all the work by writing a C program and compile it with -lprocmem option:
Compiling (I put the program under main.c:
The program:
#include <procmem.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdint.h>
int main() {
pid_t mypid = getpid();
printf("PID: %d\n", mypid);
struct prog_segs info;
if (procmem(mypid, &info) == 0) {
printf("Code segment: %lx-%lx\n", info.start_code, info.end_code);
printf("Data segment: %lx-%lx\n", info.start_data, info.end_data);
printf("Heap segment: %lx-%lx\n", info.start_heap, info.end_heap);
printf("Start stack: %lx\n", info.start_stack);
} else {
printf("Cannot get information from the process %d\n", mypid);
}
}
The result: