Skip to content

PRAZPC/custom-linux-repo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 

Repository files navigation

🐧 Custom Linux Kernel with a New System Call

This project demonstrates the process of customizing the Linux kernel by:

  1. Printing a custom boot message.
  2. Adding and implementing a new system call.
  3. Building a minimal initramfs with BusyBox.
  4. Running the kernel in QEMU.
  5. Testing the syscall using a custom user-space program.

It is intended as a learning project for understanding Linux internals.


🔹 1. Cloning the Linux Kernel

We start by cloning the Linux kernel source from the official repository:

git clone --depth=1 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
cd linux

Why use --depth=1?

  • The full Linux kernel repository is massive (tens of gigabytes).
  • A shallow clone with --depth=1 downloads only the latest snapshot instead of the complete history.
  • This makes the clone much faster and saves disk space.
  • Perfect for learning and experimentation when you don’t need historical commits.

🔹 2. Custom Boot Message

To confirm that we are running our own kernel, we modify the kernel entry point to print a message.

  • Edit init/main.c:
asmlinkage __visible void __init start_kernel(void)
{
     printk(KERN_INFO "CUSTOM KERNEL BOOT BY PRAZWAL NIBHRIT AAYUSH ASHUTOSH\n ");
    ...
}

When the kernel boots in QEMU, this message will appear in the logs (dmesg).

EXPECTED RESULT
[    0.000000] CUSTOM KERNEL BOOT BY PRAZWAL NIBHRIT AAYUSH ASHUTOSH

🔹 3. Adding a Custom System Call

(a) Register the syscall in the syscall table

Edit arch/x86/entry/syscalls/syscall_64.tbl and add:

548    common   my_syscall    sys_my_syscall
  • 548 → syscall number (unused slot).
  • my_syscall → user-visible name.
  • sys_my_syscall → kernel implementation function.

(b) Implement the syscall

Create kernel/my_syscall.c:

#include <linux/kernel.h>
#include <linux/syscalls.h>

SYSCALL_DEFINE0(my_syscall)
{
    printk(KERN_INFO "my_syscall(): called by userspace (Prazwal nibhrit Aayush Ashutosh)\n");
	        
    return 1234; // return something 
}
  • SYSCALL_DEFINE0 → means syscall takes 0 arguments.
  • printk → logs a message in the kernel log.
  • Returns 1234 to user space for verification.

(c) Add to the kernel build system

Edit kernel/Makefile and append:

obj-y += my_syscall.o

This ensures our syscall implementation is compiled.


🔹 4. Building the Kernel

Compile the kernel:

make defconfig
make menuconfig   # (optional, for custom configs) DESELCET NETOWORK , USB DRIVERS AND OTHER DRIVERS FOR FASTER COMPILATION 
make -j$(nproc) bzImage

The compiled kernel image will be created at:

arch/x86/boot/bzImage

🔹 5. Creating a Minimal Initramfs

We need an initramfs so the kernel has something to run after boot.

(a) Create folder structure

mkdir -p ~/initramfs/{bin,sbin,etc,proc,sys,dev,usr}

(b) Add BusyBox

BusyBox provides basic utilities like sh.

cp /bin/busybox initramfs/bin/
chmod +x initramfs/bin/busybox
ln -s /bin/busybox initramfs/bin/sh

(c) Create init script

File: initramfs/init

#!/bin/sh
echo "Prazwal Nibhrit Aayush Ashutosh  Custom Linux Kernel is now booting!"
exec /bin/busybox sh

Make it executable:

chmod +x initramfs/init

🔹 6. User Program to Test the Syscall

Inside initramfs, we place a small program to invoke our new syscall.

File: initramfs/bin/test.c

#include <unistd.h>
#include <sys/syscall.h>
#include <stdio.h>

#define __NR_my_syscall 548  // Must match syscall_64.tbl

int main() {
    long result;

    printf("Calling custom system call...\n");
    result = syscall(__NR_my_syscall);
    printf("Syscall returned: %ld\n", result);

    return 0;
}

Compile statically so it runs inside initramfs without shared libraries:

gcc -static initramfs/bin/test.c -o initramfs/bin/test

🔹 7. Building the Initramfs Image

cd ~/initramfs
find . -print0 | cpio --null -ov --format=newc | gzip -9 > ~/initramfs.cpio.gz

This generates initramfs.cpio.gz, which will be loaded by QEMU.


🔹 8. Running the Kernel in QEMU

Boot your custom kernel with initramfs:

qemu-system-x86_64   -kernel ~/linux/arch/x86/boot/bzImage   -initrd ~/initramfs.cpio.gz   -append "console=ttyS0 init=/init loglevel=7"   -nographic
  • console=ttyS0 → routes kernel logs to QEMU terminal.
  • init=/init → tells kernel which init script to execute.
  • loglevel=7 → maximum log details.
  • -nographic → disables GUI, runs in terminal.

🔹 9. Testing the Custom Syscall

Inside QEMU:

/bin # ./test

Expected output in user-space:

Calling custom system call...
Syscall returned: 1234

Check kernel logs:

dmesg | tail

Output should include:

called by userspace (Prazwal nibhrit Aayush Ashutosh)

🔹 Common Errors & Fixes

Error: Kernel panic - not syncing: No init found
✔️ Fix: Ensure initramfs/init exists and is executable (chmod +x initramfs/init).

Error: ./test: not found inside QEMU
✔️ Fix: Compile with gcc -static so the binary doesn’t need shared libraries.

Error: Wrong syscall return / Invalid argument
✔️ Fix: Ensure syscall number in test.c matches entry in syscall_64.tbl.

Error: BusyBox not working
✔️ Fix: Ensure BusyBox binary is copied into initramfs/bin and symlinked to /bin/sh.


✅ Summary

  • Modified start_kernel() → printed a custom boot message.
  • Added a new syscall (my_syscall) → returns 1234 and logs a message.
  • Built a minimal initramfs with BusyBox + test program.
  • Booted the kernel in QEMU and successfully invoked the syscall.

✨ With this setup, you now have a custom Linux kernel and a working system call running inside QEMU.
Project created by Prazwal ,Nibhrit and Aayush

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published