Kernel Dev Blog 1 -- Setup
4/4/2020
I want to grow, and there comes a point where you turn to yourself to do this. I started in calculator programming in grade school and then to web and graphics in high school. Web was a trajectory I was set on with my first job being a basic web developer contractor. It was forgiving and an excellent entry point into this career.
From there my education as an undergraduate in Software Engineering opened me up and improved me considerably from the hacker-diy coder to a principled engineer with foresight. I learned architectural principles, methodologies and a variety of ancillary fields of mathematics and business that helped make my skillset more valuables to others.
After college I did game development with a friend for years, working on the XBOX platform and PC platform mostly. This stretched me considerably as I had to develop for performance and scalability and put the Big^O principles into play. I learned about physics engines, data structures and algorithms such as pooling, quadtrees and pathfinding and even a considerable amount of packeted networking. Multi threaded development went from sandbox-theory to practice and proper object oriented development and memory management was essential for the code to survive our gaming dreams.
Now, back in the web world I have been stretched more in the dev ops and infrastructure areas over the last few years. CI pipelines, EC2 autoscalers, apache bench testing, DDOS and threat mitigations and scalable architectures of applications have been very important. AWS has become my bread and butter, becoming certified and wielding it like there is no other option.
But I find myself getting to that point of saturation, where the growth is beginning to diminish in my mid-thirties and I want to get better. Time to jump into a new pool of water. I truly respect those guys who now how to code for the machine, who speak its true language and provide incredible open source platforms for the world. Guys like Linus, Ken Thompson and John Carmack have always inspired me, so I figured I would take a stab at some lower level engineering: Linux, Device Drivers and Operating Systems in C.
This is my walk into that.
Using KernalNewbies to try and learn about Linux Kernel development: https://kernelnewbies.org/FirstKernelPatch
1. Start
Installed VirtualBox with Ubuntu18 Server
Installed my ashes setup
Installed set of tools:
kerneldev_install.sh
sudo apt-get install libncurses5-dev gcc make git exuberant-ctags libssl-dev bison flex libelf-dev bc
About the Tools
gcc
is obviously the C compiler
make
is the tool to build projecs and link files properly
git
is obvious
libncurses5-dev
lets us build terminal gui editors for menus etc
exuberant-ctags
code index generator for editors
libssl-dev
TLS and SSL protocols for key generation and signing etc
bison
a "parser generator" for language grammars
flex
lexical analyser generator for text pattern matching (combined with parser generator?)
libelf-dev
Executable and Linkable Format standard file format for executable files, object code, libraries etc
bc
math processing language
2. Download the Code
Cloned the repo on a specific branch
git clone -b staging-testing git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
Next is compiling, but reading first...
Digress:: Device Drivers CH1 Book
https://static.lwn.net/images/pdf/LDD3/ch01.pdf
Driver Overview
Drivers provide an API to hardware without exposing the internals of the hardware
Separate "mechanism" from "policy", the drive should provide what can be done with the hardware now how it should be used
write kernel code to access the hardware, but don’t force particularpolicies on the user, since different users have different needs
Drivers are a software layer between applications and hardware and should take into consideration:
- concurrent usage
- synchronous and asynchronous operation
- being opened more than once
- less software layers to reduce "policy"
- library for easier usage with applications
Kernel Overview
Kernel manages four main things:
- Process Management
- Memory Management
- Filesystems
- Device Control (device drivers embedded into the kernel for ever physical hardware attached)
- Networking
Loadable Modules are a thing, meaning that object code can be loaded into the kernel at runtime to extend functionality
Object code Modules can be linked and unlinked with insmod
and rmmod
Loading modules requires super user access and is a method that security vulnerabilities occur, root kits?a
Kernel can also be compiled without supporting modules and only drivers compiled with it function
Device and Module Classes
Char Devices (Character Devices) can be accessed as a stream of bytes
Block Devices host a filesystem for I/O larger than 512 bytes
Network Interfaces in charge of sending and receiving packets with other hosts
Security
Security code is mostly policy and should be addressed at higher levels of code
You should however be conscious of dangerous operations that could damage systems or other users operations
Also coding against vulnerabilities such as buffer overflows are important
Other rules:
- treat user input suspiciously
- initialize all memory used to avoid random code existing in your runtime
Version Numbering
As far as the kernel is concerned, the even-numbered kernel versions (i.e., 2.6.x) are the stable ones for general distribution The odd versions (such as2.7.x), on the contrary, are development snapshots and are quite ephemeral
3. Copy Boot Configuration
The config for drivers etc is not included in the source (since its machine dependent) so we are gonna copy from Ubuntu
There is a config that lives in /boot
that is thre kernel config file which is titled after the current release
Get current release with
$ uname -r # uname get system info, -r gets release version
Which pointed to a file /boot/config-4.15.0-91-generic
Copied to repo codebase
$ cp /boot/config-4.15.0-91-generic .config
Add a local version to the config file so you don't overwrite your OS release config
E.g. CONFIG_LOCALVERSION="-doomguyv1"
You can restore config values to default with make olddefconfig
You can use a cool ncurses editor with make menuconfig
4. Make and Compile
make
or make -jX
where "X" is the number of cores. (My vm was 2 core)
Ran out of HD space with so upped to 40GB
$ make -j2
...
LD [M] sound/usb/line6/snd-usb-pod.ko
LD [M] sound/usb/line6/snd-usb-podhd.ko
LD [M] sound/usb/line6/snd-usb-toneport.ko
LD [M] sound/usb/line6/snd-usb-variax.ko
LD [M] sound/usb/misc/snd-ua101.ko
LD [M] sound/usb/snd-usb-audio.ko
LD [M] sound/usb/snd-usbmidi-lib.ko
LD [M] sound/usb/usx2y/snd-usb-us122l.ko
LD [M] sound/usb/usx2y/snd-usb-usx2y.ko
LD [M] sound/x86/snd-hdmi-lpe-audio.ko
LD [M] virt/lib/irqbypass.ko
Done!
5. Install Kernel
Seems you can do it yourself and update GRUB config to launch into
Guide said Ubuntu has installkernel
script already on it so we can use make
to install
This script installs the kernel to /boot/, installs modules to /lib/modules/X.Y.Z/ (where X.Y.Z is something like 3.1.5), and updates file /boot/grub/grub.conf
This should put a new install into /boot
$ sudo make modules_install install
...
INSTALL drivers/input/mouse/appletouch.ko
INSTALL drivers/input/mouse/bcm5974.ko
INSTALL drivers/input/mouse/cyapatp.ko
...
DEPMOD 5.6.0-doomguyv1+
sh ./arch/x86/boot/install.sh 5.6.0-doomguyv1+ arch/x86/boot/bzImage \
System.map "/boot"
run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 5.6.0-doomguyv1+ /boot/vmlinuz-5.6.0-doomguyv1+
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 5.6.0-doomguyv1+ /boot/vmlinuz-5.6.0-doomguyv1+
update-initramfs: Generating /boot/initrd.img-5.6.0-doomguyv1+
run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 5.6.0-doomguyv1+ /boot/vmlinuz-5.6.0-doomguyv1+
run-parts: executing /etc/kernel/postinst.d/update-notifier 5.6.0-doomguyv1+ /boot/vmlinuz-5.6.0-doomguyv1+
run-parts: executing /etc/kernel/postinst.d/x-grub-legacy-ec2 5.6.0-doomguyv1+ /boot/vmlinuz-5.6.0-doomguyv1+
Searching for GRUB installation directory ... found: /boot/grub
Searching for default file ... found: /boot/grub/default
Testing for an existing GRUB menu.lst file ... found: /boot/grub/menu.lst
Searching for splash image ... none found, skipping ...
Found kernel: /boot/vmlinuz-4.15.0-91-generic
Replacing config file /run/grub/menu.lst with new version
Found kernel: /boot/vmlinuz-5.6.0-doomguyv1+
Found kernel: /boot/vmlinuz-4.15.0-91-generic
Replacing config file /run/grub/menu.lst with new version
Updating /boot/grub/menu.lst ... done
run-parts: executing /etc/kernel/postinst.d/zz-update-grub 5.6.0-doomguyv1+ /boot/vmlinuz-5.6.0-doomguyv1+
Sourcing file `/etc/default/grub'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.6.0-doomguyv1+
Found initrd image: /boot/initrd.img-5.6.0-doomguyv1+
Found linux image: /boot/vmlinuz-4.15.0-91-generic
Found initrd image: /boot/initrd.img-4.15.0-91-generic
done
6. Boot to Kernel
We need to update the GRUB config file at /etc/default/grub
I changed GRUB_TIMEOUT_STYLE
and GRUB_TIMEOUT
#GRUB_TIMEOUT_STYLE=hidden
GRUB_TIMEOUT_STYLE=menu
#GRUB_TIMEOUT=0
GRUB_TIMEOUT=10
$ sudo update-grub2
Sourcing file `/etc/default/grub'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-5.6.0-doomguyv1+
Found initrd image: /boot/initrd.img-5.6.0-doomguyv1+
Found linux image: /boot/vmlinuz-4.15.0-91-generic
Found initrd image: /boot/initrd.img-4.15.0-91-generic
done
$ sudo reboot
From there the GRUB menu appeared and I chose "Advanced Ubuntu Options" where it showed the kernel version
!!!ERROR
Attempting to boot into my build resulted in a long error string that ended in
[ 5.152144] ----[ end Kernel panic - not syncing: System deadlocked on memory ]---
!!!SUCCESS
A little bit of searching and I upped the memory size from 2GB to 4GB on the VM and it worked
$ uname -a
Linux doomkern 5.6.0-doomguyv1+ #2 SMP Sat Apr 4 22:23:48 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
7. GIT Email Setup
Now that we have the Kernel compiling and launching we need text based email system
We need to submit patches via GIT email which can be done with three functions:
sudo apt-get install esmtp
a mail transport client
sudo apt-get install mutt
a text based mail client that can send plan text patches
sudo apt-get install git-email
to send email patches with git
8. Build CTAGS for Kernel Codebase
CTAGS is basically an indexer to find symbols in code (intellisense)
We already installed it so we can build the ctags with
$ make tags
GEN tags