# OS Homework1
##### 310551126 蔡鎔駿
https://hackmd.io/@roger90810/OS-HW1
## Prepare Environment
```shell
sudo apt install libncurses5 libncurses5-dev libncurses-dev qtbase5-dev-tools flex \
bison openssl libssl-dev dkms libelf-dev libudev-dev libpci-dev libiberty-dev autoconf
```
## 1. Modify Version number suffix
```shell
cd linux
make defconfig
make -j4 LOCALVERSION=-os-310551126
sudo make modules_install install
sudo update-grub2
```

## 2. Add System Call
### sys_hello
in linux-5.19.12, create a folder `hello`
```shell
cd linux-5.19.12
mkdir hello
```
create a file `hello.c`, implement our system call
SYSCALL_DEFINEn means there are n arguments in this system call.
```c
#include <linux/kernel.h>
#include <linux/syscalls.h>
SYSCALL_DEFINE0(hello)
{
printk("Hello world\n");
printk("310551126\n");
return 0;
}
```
create a Makefile for our system call
```make
obj-y := hello.o
```
Modify system call entry table `arch/x86/entry/syscalls/syscall_64.tbl`
```
...
547 x32 pwritev2 compat_sys_pwritev64v2
# This is the end of the legacy x32 range. Numbers 548 and above are
# not special and are not to be used for x32-specific syscalls.
548 common hello sys_hello # add this line
```
add our system call to kernel header file `include/linux/syscalls.h`
```h
...
int __sys_setsockopt(int fd, int level, int optname, char __user *optval,
int optlen);
asmlinkage long sys_hello(void); // add this line
#endif
```
Modify kernel's Makefile, add our system call module in it.
```make
...
ifeq ($(KBUILD_EXTMOD),)
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ hello/
core-$(CONFIG_BLOCK) += block/
core-$(CONFIG_IO_URING) += io_uring/
...
```
Result:

### sys_revstr
in linux-5.19.12, create a folder `revstr`
```shell
cd linux-5.19.12
mkdir revstr
```
create a file `revstr.c`, implement our system call
* Here we need two arguments, *length* and *string*, so we use `SYSCALL_DEFINE2` here.
* The modifiers `__user` means this is from user address space.
* We can not access the data from userspace address directly, we need to use `copy_from_user` to copy the data from userspace to kernel space.
* Before we copy the data, we need to allocate a space for the data copy, using `kmalloc` to allocate a space in kernel space.
* After reverse the string, we need to save it to userspace, using `copy_to_user` to copy back to the userspcae.
* Here I encounter a problem, the return value of `copy_to_user` is the number of bytes that could not be copied. On success, this will be zero. My return value is the length I want to copy, but the copy is success (I check the string at user program, it is reversed).
```c
#include <linux/kernel.h>
#include <linux/syscalls.h>
SYSCALL_DEFINE2(revstr, int, len, char __user *, str)
{
int i = 0;
int j = len - 1;
char *kstr;
unsigned long ret;
kstr = (char *)kmalloc(len + 1, GFP_KERNEL);
if (!kstr)
return -ENOMEM;
if (copy_from_user(kstr, str, len))
return -EFAULT;
kstr[len] = '\0';
printk("The origin string: %s\n", kstr);
while (i < j) {
char tmp = kstr[i];
kstr[i] = kstr[j];
kstr[j] = tmp;
i++;
j--;
}
printk("The reversed string: %s\n", kstr);
ret = copy_to_user(str, kstr, len);
/* if (copy_to_user(str, kstr, len)) */
/* return -EFAULT; */
kfree(kstr);
return 0;
}
```
create a Makefile for our system call
```make
obj-y := revstr.o
```
Modify system call entry table `arch/x86/entry/syscalls/syscall_64.tbl`
```
...
547 x32 pwritev2 compat_sys_pwritev64v2
# This is the end of the legacy x32 range. Numbers 548 and above are
# not special and are not to be used for x32-specific syscalls.
548 common hello sys_hello
549 common revstr sys_revstr # add this line
```
add our system call to kernel header file `include/linux/syscalls.h`
```h
...
int __sys_setsockopt(int fd, int level, int optname, char __user *optval,
int optlen);
asmlinkage long sys_hello(void);
asmlinkage long sys_revstr(int len, char __user *str); // add this line
#endif
```
Modify kernel's Makefile, add our system call module in it.
```make
...
ifeq ($(KBUILD_EXTMOD),)
core-y += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ hello/ revstr/
core-$(CONFIG_BLOCK) += block/
core-$(CONFIG_IO_URING) += io_uring/
...
```
Result:
