Add a new system call 🤫

Add a new system call to the kernel

Outcomes:

What to submit:

Procedure:

  1. Start by backing up your compiled kernel from setup

    1. Enter the linux repository

    2. copy arch/riscv/boot/Image to ~/kernel-v6.13

  2. Add a new system call to the Linux kernel

    1. Create a new .c file in the kernel directory within the linux repo named kdlp.c

    2. Using the appropriately numbered SYSCALL_DEFINE macro, define a system call entry function for a new kdlp system call in the kdlp.c file that behaves as follows:

      • Takes two arguments, an argument of type char __user * to specify the buffer and an argument of type size_t to specify the size of the buffer

      • Formats a message into a local buffer that includes at least the student's name and the name of the current task that is running on the CPU, obtained via the get_task_comm macro

      • Determines the amount of data to send: equal to the lesser of the size of the kernel message and how much space the user provided (see min macro)

      • Copies that many bytes from the local message buffer into the user pointer (see the copy_to_user function)

      • Returns a negative error code of -EFAULT (errno 14, bad address) if the copy is not successful

      • Otherwise, returns the amount of data that was copied

    3. The system call implementation should take care to prevent any possibility of a buffer overflow

    4. Modify the makefile for the kernel subdirectory in kernel/Makefile to add kdlp.o to the list of objects that are always compiled (add it to the end of the obj-y variable)

    5. Add an asmlinkage declaration of sys_kdlp to include/linux/syscalls.h (take inspiration from the numerous examples of other system calls in that file)

    6. Add an entry to the system call numbering header

      • On RISC-V the list comes from the modern shared file include/uapi/asm-generic/unistd.h

        • Find where __NR_syscalls is defined and increment the value

        • Just above that line, add a #define for __NR_kdlp with the next system call number that is free

        • Add an invocation of the __SYSCALL macro with the __NR_kdlp number and and the sys_kdlp entry point

        • Take inspiration from the other nearby system calls

    7. Add a table entry to the bottom of the system call table at scripts/syscall.tbl

      • Take inspiration from the other nearby system calls
    8. Before compiling the entire kernel, you will find it helpful to compile your new kdlp.c file in isolation using ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- make kernel/kdlp.o

      • If there are any errors, fix them and re-run the above command until the compilation succeeds
    9. Run ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- make clean in your cloned linux repo

      • This will remove any artifacts from previous compilations

      • You must do this before modifying the localversion

    10. Update the localversion file to create a distinct release string so you can tell this kernel that has your system call apart from any other kernels you have compiled

    11. Compile your new kernel with ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- make -j $(nproc)

    12. If the command finishes, make sure it was successful: echo $? should output 0

      • If it does not, re-run ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- make without -j $(nproc) to get a better error message

      • Fix whatever issue you see, and re-run ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- make -j $(nproc)

      • Repeat this process of checking the result and fixing any errors until it compiles successfully

    13. Boot your new kernel with your the old init program from setup

      • Use the same qemu command from setup

      • If all is well it should boot successfully

      • Congrats, you just wrote your first kernel code!

  3. Make a patch out of your kernel code

  4. Write an assembly language program named syscall.s that invokes your new system call

  5. Answer the following questions in a new text file at ~/submissions/$USER/new_syscall/questions.txt

  6. Run qemu with your original kernel and your new init program again, redirecting the output to ~/submissions/$USER/new_syscall/vanilla_output.txt

This page could be useful: This page should be useful: https://elixir.bootlin.com/linux/latest/ident/get_task_comm

Refer to the Linux kernel documentation about adding system calls for further guidance.

Frequently Asked Questions


msg = (silence)
whoami = None
singularity v0.6-56-g8e52bc8 https://github.com/underground-software/singularity