Gentoo GSoC Weekly Report 05/14
Things done this week
This week was about creating a repository for an
init program written in C/C++, testing it out, and trying to load the real init inside Gentoo root. The progress of each subproject are listed below.
Writing a "preinit" in C/C++
I've set up a repository called
preinit_angler, which currently implements the test function (print haiku into kernel message so that we can verify them on next boot) described in this article. Implementing the toy init is necessary is because we set up a tiny-platform that we can place other things onto it in this way: maybe password prompts for entering LUKS passphrases, or options to choose different Android snapshots. What's more, this verifies that our toolchain was really generating correctly statically-linked executables that can be directly executed by the kernel. The repository also holds the incomplete code in attempt to implement Android
cryptfs decryption by hand.
Attempt to decrypt Android userdata
I've ran into problems tackling the native encryption of Android: after spending a considerable amount of time on reading the code and splitting functions out from
vold, I ran into the dead end of ARM's Trusted Execution Environment (TEE, learn more about it here on Wikipedia). The detailed process of my attempt is logged in this article: Analysis of Android cryptfs.
Bypassing Android force encryption and restructuring userdata partition
As we can't use an encrypted
userdata for now, and encryption is forced on AOSP for Nexus 6P, we'll need to bypass the policy. The last section in the
cryptfs analysis article ("What next?") describes how to do this. In short, we modify
fstab so that
vold won't encrypt the phone on first boot.
The next part is about "chainloading" the real, full-blown
/sbin/init, which belongs to OpenRC. This is done in several stages:
userdatapartition, which holds Gentoo's real filesystem root
- switching root into the mounted partition, executing OpenRC's init
- launching Android's init in chroot (with jail if Android init checks if it's PID1; uses jchroot)
Note that for
jchroot to work, several namespace-related config options are needed, specifically:
CONFIG_SYSVIPC CONFIG_IPC_NS CONFIG_PID_NS CONFIG_NET_NS CONFIG_UTS_NS
Failing to enable these options will result in
jchroot (or to say, the
clone(2)) failing with
Current boot sequence, filesystem structure and current work status
After some discussion with UnderSampled, OxR463 and heroxbd on IRC, I feel it necessary to explain a few things here.
Boot sequence and where we are now
The boot sequence is of the following stages:
- bootloader loads
boot.img, executing the kernel;
- kernel executes
/init, which is
preinit, in the initramfs that came with
userdataand handles mountpoints correctly, then executes Gentoo's
- OpenRC starts, launching a service that uses
jchrootto launch Android's init.
We're currently at the
preinit stage, trying to launch OpenRC's init.
The final filesystem structure would be like this: Gentoo root sits in
userdata partition. The path
/var/lib/android is special: it holds the Android
init as well as Android mountpoints. When we
/var/lib/android, Android init would mount the partition it needs correctly, except for
/data in the Android root. We'll need to change the
fstab entry for
userdata into a bind mount of
/data (from Android's perspective of view; the real path in
/var/lib/android/data) to itself, thus making
/data a mountpoint, so as to make
Work to be done next week
By the end of next week we shall see: an Android system successfully booting inside a chroot (and namespaces) under OpenRC init, who gets loaded by
preinit. Several expected problems/projects:
userdata/gentootemporarily to see if OpenRC loads fine. Fix it if it's not working.
userdata, deal with the mountpoints correctly, and edit Android
fstabparser may not support bind mounts; we may have to bind-mount it ourselves and remove that line in
- We'll definitely run into problems, thus a serial console through UART (in headphone jack for Nexus'es and Pixels) is necessary; asynchronous
console-ramoopsdoes not fulfill the requirement for interactions.
This requires a headphone-jack UART cable, which was made by @imi415 on Telegram. Kudos for @imi415!