Hi,
a my Project Owncloud on a Raspberry Pi I want to use AppArmor to protect the lighttpd webserver. Unfortunately the default kernel is complied without apparmor support.
So I decided to build my own kernel:-)
Here are the steps to (cross) compile the new kernel on a x64 Intel based computer.
First of all update the Rasperries Firmware and therefore the kernel to the latest revision.
pi@raspi ~$ sudo rpi-update pi@raspi ~$ sudo reboot
Check Version
pi@raspi ~$ uname -a Linux raspi.yourdomain 4.1.13+ #1 PREEMPT Tue Oct 24 13:10:50 CET 2015 armv6l GNU/Linux
Get the kernel config file (.config). The kernel provides this in /proc/config.gz. The raspbian kernel does provide it by default. You must load the configs.ko kernel module
pi@raspi ~$ sudo modprobe configs pi@raspi ~$ zcat /proc/config.gz > ~/.config
Or after installing kernel sources you can also use the script “extract-ikconfig” in the scripts folder to extract the config from the kernel image file.
Go to the x86 PC. Make sure you have free at least 5GB of disk space. Define the build directory
michael@devdeb ~ $ mkdir $HOME/raspbian-kernel michael@devdeb ~ $ cd $HOME/raspbian-kernel
Get the kernel config file from Raspberry to your home
michael@devdeb ~ $ scp pi@IPAddressRaspPI:/home/pi/.config ~/.config.raspberry
Get ARM Compiler
michael@devdeb:/home/michael/raspbian-kernel $ git clone https://github.com/raspberrypi/tools
The next step is to determine the git path of the current kernel. These steps are not necessary if you want to compile a version 4.1.x
# Determine git pathof current Kernel. Not necessary if you know it, in this example 4.1.x # git clone --depth 1 https://github.com/raspberrypi/linux.git # cd linux # git show-ref # 06d4ed20f68e37bc556062990aa41a8fc11438d1 refs/heads/rpi-4.1.y # 06d4ed20f68e37bc556062990aa41a8fc11438d1 refs/remotes/origin/HEAD # 06d4ed20f68e37bc556062990aa41a8fc11438d1 refs/remotes/origin/rpi-4.1.y
Some Environmentvariables with a decision first for which Raspberry you want to compile the kernel
# New Kernelfilename export KERNEL=kernel-custom # Kernel sources directory michael@devdeb ~ $ export KERNEL_SRC=$HOME/raspbian-kernel/rpi-4.1.y # gcc Compiler Prefix # michael@devdeb ~ $ export CCPREFIX=$HOME/raspbian-kernel/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi- michael@devdeb ~ $ export CCPREFIX=$HOME/raspbian-kernel/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- # Root for tar Archive for the transfer to Pi michael@devdeb ~ $ export RASP_FILE_ROOT=$HOME/raspbian-kernel/root # Folder latest firmware michael@devdeb ~ $ export FIRMWARE=$HOME/raspbian-kernel/firmware # Target directory for the new kernel modules michael@devdeb ~ $ export MODULES_TEMP=$HOME/raspbian-kernel/lib/modules # Create folders michael@devdeb ~ $ mkdir -p $KERNEL_SRC michael@devdeb ~ $ mkdir -p $MODULES_TEMP michael@devdeb ~ $ mkdir -p $RASP_FILE_ROOT
While it is important in which directory a command is executed and the command lines and prompt are partitialy rather long and therefore uses a lot of space. I insert before each command block a pwd to show the working directory and “hide” the prompt in front of the commands.
Get the latest sources
michael@devdeb ~ $ cd $KERNEL_SRC pwd # /home/michael/raspbian-kernel/rpi-4.1.y git init git fetch https://github.com/raspberrypi/linux.git rpi-4.1.y:refs/remotes/origin/rpi-4.1.y git checkout refs/remotes/origin/rpi-4.1.y
Clean up
pwd # /home/michael/raspbian-kernel/rpi-4.1.y make mrproper
Copy the .config file to the kernel build folder
pwd # /home/michael/raspbian-kernel/rpi-4.1.y cp ~/.config.raspberry .config
It’s time to customize the kernel. I want to enable apparmor. CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 enables AppArmor by default.
pwd # /home/michael/raspbian-kernel/rpi-4.1.y # CONFIG_AUDIT=y sed -r 's/^((CONFIG\_AUDIT=.*$)|(^# CONFIG\_AUDIT\s.*$))/CONFIG\_AUDIT=y/m' .config -i # CONFIG_CRYPTO_SHA1=y sed -r 's/^((CONFIG\_CRYPTO\_SHA1=.*$)|(^# CONFIG\_CRYPTO\_SHA1\s.*$))/CONFIG\_CRYPTO\_SHA1=y/m' .config -i # CONFIG_SECURITY=y sed -r 's/^((CONFIG\_SECURITY=.*$)|(^# CONFIG\_SECURITY\s.*$))/CONFIG\_SECURITY=y/m' .config -i # CONFIG_SECURITYFS=Y sed -r 's/^((CONFIG\_SECURITYFS=.*$)|(^# CONFIG\_SECURITYFS\s.*$))/CONFIG\_SECURITYFS=y/m' .config -i # CONFIG_SECURITY_NETWORK=y # CONFIG_SECURITY_PATH=y # CONFIG_SECURITY_APPARMOR=y # CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1 # CONFIG_SECURITY_APPARMOR_HASH=y # CONFIG_INTEGRITY=y # CONFIG_INTEGRITY_AUDIT=y sed '/CONFIG_SECURITYFS=y/a CONFIG_SECURITY_NETWORK=y\nCONFIG_SECURITY_PATH=y\nCONFIG_SECURITY_APPARMOR=y\nCONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1\nCONFIG_SECURITY_APPARMOR_HASH=y\nCONFIG_INTEGRITY=y\nCONFIG_INTEGRITY_AUDIT=y' .config -i # Version -apparmor sed -r 's/^CONFIG_LOCALVERSION=.*$/CONFIG_LOCALVERSION="-apparmor"/m' .config -i
You can make your own changes by opening the kernels config menu. Prior to this you have to install the ncurses-dev paket.
pwd # /home/michael/raspbian-kernel/rpi-4.1.y apt-get install libncurses5-dev ARCH=arm CROSS_COMPILE=${CCPREFIX} make menuconfig
Start compiling and get a coup of coffee or two. This takes a while.
pwd # /home/michael/raspbian-kernel/rpi-4.1.y ARCH=arm CROSS_COMPILE=${CCPREFIX} make olddefconfig ARCH=arm CROSS_COMPILE=${CCPREFIX} make zImage modules dtbs ARCH=arm CROSS_COMPILE=${CCPREFIX} INSTALL_MOD_PATH=${MODULES_TEMP} make modules_install
Move the lib folder which contains the new kernel modules to the root of the to created tar archive
cd ${MODULES_TEMP} pwd # /home/michael/raspbian-kernel/lib/modules mv lib $RASP_FILE_ROOT
Copy the new kernel, the device tree binaries and the overlays to tar archive
pwd # /home/michael/raspbian-kernel/rpi-4.1.y mkdir -p $RASP_FILE_ROOT/boot/overlays ./scripts/mkknlimg ${KERNEL_SRC}/arch/arm/boot/zImage $RASP_FILE_ROOT/boot/${KERNEL}.img cp ${KERNEL_SRC}/arch/arm/boot/dts/*.dtb $RASP_FILE_ROOT/boot/ cp ${KERNEL_SRC}/arch/arm/boot/dts/overlays/*.dtb* $RASP_FILE_ROOT/boot/overlays cp ${KERNEL_SRC}/arch/arm/boot/dts/overlays/README $RASP_FILE_ROOT/boot/overlays
Get the latest firmware.Use showref to get the path for git checkout
cd $HOME/raspbian-kernel pwd # /home/michael/raspbian-kernel git clone --depth=1 https://github.com/raspberrypi/firmware.git cd firmware # git show-ref git checkout refs/remotes/origin/master
And also copy the firmware to the tar root
cp $HOME/raspbian-kernel/firmware/boot/bootcode.bin $RASP_FILE_ROOT/boot cp $HOME/raspbian-kernel/firmware/boot/fixup*.dat $RASP_FILE_ROOT/boot cp $HOME/raspbian-kernel/firmware/boot/start*.elf $RASP_FILE_ROOT/boot mkdir -p $RASP_FILE_ROOT/opt cd $HOME/raspbian-kernel/firmware/hardfp/opt cp -r . $RASP_FILE_ROOT/opt
Create the tar archive to transfer the new kernel to the Raspberry
cd $RASP_FILE_ROOT pwd # /home/michael/raspbian-kernel/root tar -cvf $HOME/raspbian-kernel/kernel.tar . gzip $HOME/raspbian-kernel/kernel.tar
Copy the complete kernel archive to the Raspberry
scp /home/michael/raspbian-kernel/kernel.tar.gz pi@IPAddressRaspPI:/home/pi
And install the new kernel. Note: This overwrites the already installed kernel.img.
pi@raspi ~$ sudo su - root@raspi:/home/pi # tar --no-same-owner -xvzf kernel.tar.gz -C / # Edit config.txt root@raspi:/home/pi # cp /boot/config.txt /boot/config.txt-`date +%Y%m%k-%I%M%S` root@raspi:/home/pi # grep -q '^kernel=.*' /boot/config.txt && sed -i 's/^kernel=.*/kernel=kernel-custom.img/m' /boot/config.txt || echo 'kernel=kernel-custom.img' >> /boot/config.txt
Reboot the raspberry an check the new kernel version
pi@raspi ~$ uname -a Linux raspi.yourdomain 4.1.13-apparmor+ #1 PREEMPT Tue Oct 25 23:10:50 CET 2015 armv6l GNU/Linux
The script (currently works only an Raspberry Models 1 and it requieres sshpass to run) attached does all things to create the tar archive at once, adjust the IP_RASPBERRY= with the IP Address of your Pi, the SSHPASS= variable with the password of user “pi”, you can also give the password as parameter to the script and then start the script with
apt-get install sshpass bash BuildKernelRaspberryPi.sh PiPassword
and wait…… 🙂
Michael
References: eLinux.org
Raspberry.org
thank you for your insperation. I built up a “little” ansible-playbook based on your tutorial. You can read it here: