blog.farhan.codes

Farhan's Personal and Professional Blog


Custom Kernel Modules for Chromebook

Note: I wrote this about a year and a half ago, but I refer to it all the time. Hopefully the instructions have not changed too much! Enjoy!

I recently purchased a Chromebook. It’s great, it symbolizes the direction the PC market should head – inexpensive, low-powered ARM processor, defense in depth resistance to malware and simple for non-technical users. And with crouton, it functions quite cleanly as a Debian-based workstation.

With its simplicity and low price, there are certain key features that are lacking in the stripped down Linux kernel that can make it frustrating for a power-user. Unfortunately, Chromium addons have not or cannot satisfy some tasks that require kernel-level functionality. Even in crouton, you may find your ability limited to the user-space. Those looking for casual additions, recompiling the kernel may seem like daunting over-kill. Instead, compiling and inserting a single module may serve as an apt alternative. In this guide, I will explain how to compile a custom kernel module to add additional functionality to your Chromebook and how to circumvent the built-in security mechanisms that prevent you from adding into the kernel-space.. This guide is specifically written for an ARM-based CPU using kernel 3.10.18 for the CIFS (SMB) module, but can be trivially ported to any other architecture, kernel and module.

Compiling the Kernel Module

As mentioned, Chromium OS is a stripped down version of Linux. Therefore, you should be able to compile and dynamically link kernel modules from the stock kernel into Chromium.

Per Google’s documentation, you must compile the kernel and modules on an x86_64 CPU, even if you will be compiling an ARM or 32-bit x86 module. This is possible thanks to GNU C Compiler’s cross-platform capability. The documentation also specifies using Ubuntu, but it worked just fine on my Debian 8 workstation.

If you have not already done so, install git, subversion and perform the basic configurations:

sudo apt-get install git subversion
git config --global user.email “name@domain.tld”
git config --global user.name "Your Name"

Google manages its various git repositories with wrapper depot_tools, a custom git wrapper. You can clone the associated git repository and set your PATH environmental variable to include the wrapper scripts as follows.

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH=`pwd`/depot_tools:"$PATH"

Next, make a directory where your Chromium OS build will reside, download the Chromium source, and synchronize it to the latest updates. This take around 30 minutes to complete.

mkdir chromiumos && cd chromiumos
repo init -u https://chromium.googlesource.com/chromiumos/manifest.git
repo sync

Once completed, you will need to download the cross-platform SDK environment, build the dependencies and enter a chroot(1) environment. This will take another 30 minutes.

cros_sdk

Now that you are inside the chroot(1) environment, you need to specify the hardware configuration for your Chromebook device, either x86-generic, amd64-generic or arm-generic. You can determine your architecture by running uname -m on your Chromebook. For my ARM-based CPU, I did the following:

export BOARD=arm-generic

Now you must prepare the core packages associated with your board.

./setup_board --board=${BOARD}
./build_packages --board=${BOARD}

Change directory to ~/trunk/src/third_party/kernel/ and then to whichever subdirectory is associated with your kernel (ie, v3.10 for 3.10.18). You can determine your kernel version by running uname -r on your Chromebook.

Next, we will need to tell the kernel which hardware platform you are on and start with the base configuration of the kernel. A list the options of base configurations by running find ./chromeos/config. In my case I am using NVIDIA’s Tegra motherboard, which is ./chromeos/config/armel/chromeos-tegra.flavour.config, so I use chromeos-tegra as follows:

./chromeos/scripts/prepareconfig chromeos-tegra

If you are compiling for a non x86_64 CPU, set the architecture and compiler settings as follows:

export ARCH=arm
export CROSS_COMPILE=armv7a-cros-linux-gnueabi-

This next portion is the same as compiling any other kernel module. Configure the kernel by running make menuconfig

Select whichever controls you would like to install and save. Once completed you will have a .config file that corresponds to your hardware. Since we are only compiling the kernel modules, you can either run make modules to compile all kernel modules, or make fs/cifs/cifs.ko to build only a specific module. I prefer the former because your module may require other dependencies in other modules, such as with crypto/md4.ko for cifs. You can verify that the file was built for the right architecture by running file fs/cifs/cifs.ko. Great! On to inserting the module!

ChromiumOS’s Security Mechanisms

ChromeOS is the official signed release of ChromiumOS, which is what you run in developer mode. Even in developer mode, Google implemented multiple defensive mechanisms to slow down a would-be attacker from gaining access the underlying system. To protect the kernel, Google utilized the Linux Security Module (LSM), which validates files from the root partition against a list of cryptographic hash values stored in the kernel, thereby preventing an attacker from loading a malicious kernel modules. In effect, the only way to insert a kernel module is to have it stored on the root partition. But by default, the root partition is set to read-only, so you cannot simply move a file to the root partition and load it.

Therefore, we must disable the root partition verification running the following script.

sudo /usr/share/vboot/bin/make_dev_ssd.sh --remove_rootfs_verification --partitions 4

Now, reboot the machine and from ChromiumOS remount the root partition to be read-writeable, as follows:

sudo mount -o remount,rw /

From here, you should be able to simply insert the kernel module with insmod. Now, you can install Enjoy!