Skip to content

Kernelbox Setup

Directory Structure

.
├── dev
│   └──
├── fs
│   ├── etc
│   │   └── passwd
│   └── init
├── snippet
└── src
    └── Makefile

Files

passwd

root:x:0:0:root:/root:/bin/sh
curious:x:1000:1000:curious:/home/curious:/bin/sh

init

#!/bin/sh

mount -t proc none /proc
mount -t sysfs none /sys
mount -t 9p -o trans=virtio,version=9p2000.L,nosuid hostshare /home/curious
sysctl -w kernel.perf_event_paranoid=1

cd /home/curious
/bin/sh

poweroff -f

snippet

#!/bin/bash -e


export KERNEL_VERSION=6.8
export BUSYBOX_VERSION=1.36.1
export WORKDIR="$(dirname "$0")"


extend_swap() {
    echo "[+] Extending swap partition..."
    sudo swapoff -a
    sudo fallocate -l 16G /swapfile
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
}


install_dependencies() {
    echo "[+] Checking / Installing dependencies..."
    sudo apt update
    sudo apt install -qy bc make gcc flex bison libncurses-dev libelf-dev libssl-dev cpio build-essential qemu-system-x86
}


build_linux_kernel() {
    echo "[+] Downloading kernel..."
    wget -qc https://mirrors.edge.kernel.org/pub/linux/kernel/v6.x/linux-$KERNEL_VERSION.tar.gz
    tar xzf linux-$KERNEL_VERSION.tar.gz

    echo "[+] Building kernel..."
    pushd linux-$KERNEL_VERSION
    make defconfig
    echo "CONFIG_NET_9P=y" >> .config
    echo "CONFIG_NET_9P_DEBUG=n" >> .config
    echo "CONFIG_9P_FS=y" >> .config
    echo "CONFIG_9P_FS_POSIX_ACL=y" >> .config
    echo "CONFIG_9P_FS_SECURITY=y" >> .config
    echo "CONFIG_NET_9P_VIRTIO=y" >> .config
    echo "CONFIG_VIRTIO_PCI=y" >> .config
    echo "CONFIG_VIRTIO_BLK=y" >> .config
    echo "CONFIG_VIRTIO_BLK_SCSI=y" >> .config
    echo "CONFIG_VIRTIO_NET=y" >> .config
    echo "CONFIG_VIRTIO_CONSOLE=y" >> .config
    echo "CONFIG_HW_RANDOM_VIRTIO=y" >> .config
    echo "CONFIG_DRM_VIRTIO_GPU=y" >> .config
    echo "CONFIG_VIRTIO_PCI_LEGACY=y" >> .config
    echo "CONFIG_VIRTIO_BALLOON=y" >> .config
    echo "CONFIG_VIRTIO_INPUT=y" >> .config
    echo "CONFIG_CRYPTO_DEV_VIRTIO=y" >> .config
    echo "CONFIG_BALLOON_COMPACTION=y" >> .config
    echo "CONFIG_PCI=y" >> .config
    echo "CONFIG_PCI_HOST_GENERIC=y" >> .config
    echo "CONFIG_GDB_SCRIPTS=y" >> .config
    echo "CONFIG_DEBUG_INFO=y" >> .config
    echo "CONFIG_DEBUG_INFO_REDUCED=n" >> .config
    echo "CONFIG_DEBUG_INFO_SPLIT=n" >> .config
    echo "CONFIG_DEBUG_FS=y" >> .config
    echo "CONFIG_DEBUG_INFO_DWARF4=y" >> .config
    echo "CONFIG_DEBUG_INFO_BTF=y" >> .config
    echo "CONFIG_FRAME_POINTER=y" >> .config
    echo "CONFIG_DEBUG_INFO_COMPRESSED_NONE=y" >> .config
    echo "CONFIG_DEBUG_INFO_COMPRESSED_ZLIB=n" >> .config

    sed -i 'N;s/WARN("missing symbol table");\n\t\treturn -1;/\n\t\treturn 0;\n\t\t\/\/ A missing symbol table is actually possible if its an empty .o file.  This can happen for thunk_64.o./g' tools/objtool/elf.c

    sed -i 's/unsigned long __force_order/\/\/ unsigned long __force_order/g' arch/x86/boot/compressed/pgtable_64.c

    make -j`nproc` bzImage
    make -j`nproc` modules
    popd
}


build_busybox () {
    echo "[+] Downloading BusyBox..."
    wget -qc https://busybox.net/downloads/busybox-$BUSYBOX_VERSION.tar.bz2
    tar xjf busybox-$BUSYBOX_VERSION.tar.bz2

    echo "[+] Building BusyBox..."
    pushd busybox-$BUSYBOX_VERSION
    make defconfig
    sed -i 's/# CONFIG_STATIC is not set/CONFIG_STATIC=y/g' .config
    make -j`nproc`
    make install
    popd
}


build_filesystem() {
    echo "[+] Building filesystem..."
    pushd fs
    mkdir -p bin sbin etc proc sys usr/bin usr/sbin root home/curious
    chmod +x init
    popd
    cp -a busybox-$BUSYBOX_VERSION/_install/* fs
}


build_rootfs() {
    pushd fs
    find . -print0 | cpio --null -ov --format=newc | gzip -9 > ../initramfs.cpio.gz
    popd
}


menu() {
    echo "========= KERNELBOX : $KERNEL_VERSION =========";
    echo "Usage : ";
    echo "Extend swap partition : ./snippet extend";
    echo "Build kernelbox :       ./snippet build";
    echo "Start kernelbox :       ./snippet start";
    echo "Build Linux kernel :    ./snippet linux";
    echo "Build BusyBox :         ./snippet busybox";
    echo "Build filesystem :      ./snippet filesystem";
    echo "Build rootfs :          ./snippet rootfs";
}



if [[ $# == 0 ]]; then
    menu
    exit 0
fi


if [[ $1 == "extend" ]]; then
    extend_swap
elif [[ $1 == "build" ]]; then
    install_dependencies
    pushd $WORKDIR
    if ! [ -e linux-$KERNEL_VERSION ]; then
        build_linux_kernel
    fi
    if ! [ -e busybox-$BUSYBOX_VERSION ]; then
        build_busybox
    fi
    build_filesystem
    popd
elif [[ $1 == "start" ]]; then
    cd $WORKDIR
    build_rootfs
    echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
    exec /usr/bin/qemu-system-x86_64 \
        -kernel linux-$KERNEL_VERSION/arch/x86/boot/bzImage \
        -initrd initramfs.cpio.gz \
        -fsdev local,security_model=passthrough,id=fsdev0,path=. \
        -device virtio-9p-pci,id=fs0,fsdev=fsdev0,mount_tag=hostshare \
        -nographic \
        -monitor none \
        -s \
        -append "console=ttyS0 nokaslr"
elif [[ $1 == "linux" ]]; then
    pushd $WORKDIR
    build_linux_kernel
    popd
elif [[ $1 == "busybox" ]]; then
    pushd $WORKDIR
    build_busybox
    popd
elif [[ $1 == "filesystem" ]]; then
    pushd $WORKDIR
    build_filesystem
    popd
elif [[ $1 == "rootfs" ]]; then
    pushd $WORKDIR
    build_rootfs
    popd
fi

Makefile

obj-m = test.o
KERNEL_VERSION=6.8

all: 
    make -C ../linux-$(KERNEL_VERSION) M=$(PWD) modules

clean: 
    make -C ../linux-$(KERNEL_VERSION) M=$(PWD) clean

Reference