-
-
Notifications
You must be signed in to change notification settings - Fork 12
General information
InkBox OS has a very strict security policy which ensures software integrity any time the device boots. The OS is developed in such a way that if the device is not 'rooted', it is completely locked down and can't be accessed from the outside.
When InkBox OS boots, the device is first handed in to the bootloader, which sets up the hardware (CPU, RAM, EPDC, etc.) to be ready for userspace. The first 20 megabytes of the (e)MMC consist of unpartitioned space in which lives U-Boot and various components required for device startup. In newer devices, U-Boot then loads a Device Tree and then a zImage to boot the Linux kernel. On older devices (e.g. Mini, Touch, Glo), a legacy uImage is used instead, without a Device Tree.
Once the kernel image has been loaded, it is then started by U-Boot.
Usually, it is loaded at memory address 0x80800000
. A typical InkBox
OS kernel is about 7 MB in size, depending on the device type. It
contains the core components needed for it to boot, as well as the
kernel modules that pair with that specific version of it. Those can
provide services for Wi-Fi, USB mass storage or USB networking. Those
modules are located in a SquashFS archive inside the initrd that gets
mounted on the main root filesystem (rootfs) during the startup process.
The initial ramdisk, often called initrd, is the first thing that the kernel sets up after initializing itself. It can be stored in a separate file, usually a (compressed) cpio archive that the kernel loads in RAM at run-time, or it can as well be 'embedded' in it, that is, being completely independent of any external filesystem resource. This is what InkBox uses.
In InkBox OS, the purpose of the initrd is to ensure the system is securely and sanely brought to a functional state by mounting partitions, disk images and SquashFS archives to get the main framework up and running. Boot flags can also offer some control on baked-in features, such as debugging the init ramdisk via telnet if needed.
In InkBox, the two main kernel/initrd combinations are the following:
- Standard
- Rooted
Those have huge differences between each other, and it is important to understand them before trying to apply any modification to the current running system. They are described below.
- A Standard kernel is what all so-called 'factory' InkBox images
ship with. The userspace is completely isolated (or as much as
possible) from external environment and things such as USB Networking,
arbitrary code execution is impossible, if not very difficult. The
boot process is heavily secured by digital signature verification for
the root filesystem's SquashFS archive, X11/KoBox extensions and
additional packages. Even if you succeed in connecting to the device
and try to get a shell, the default
passwd
file will prevent you from doing that since the default login redirects to/sbin/nologin
. As such, user access to the framework is very restricted and limits itself to what the default Qt5 and KoBox/X11 (without KTerm) GUI interfaces offer. - A rooted kernel, on the other hand, offers a wide range of permissive features for the advanced user. It allows, among other things, USB Networking activation at boot-time, root shell/console (via SSH, telnet or serial port), full system access. However, some restrictions are still there: for example, all the package's digital signatures are still being verified by OpenSSL at boot. The only way to avoid this is then to either recompile the kernel with your own public key embedded in the initrd, or request a developer key from me at kobox.alpine@gmail.com . This will disable (almost) all packages verification at boot and will allow you, for example, to roll your own KoBox/X11 extensions, without you needing to sign them.
InkBox OS is probably not like your standard Linux distribution you have
installed on your PC or at work. Instead of using a standard root
filesystem stored as a whole in a partition, that part of the framework
is in fact a SquashFS file. At boot, it gets mounted by the initrd with
the script [initrd-root]/etc/init.d/overlay-mount
. A special
FUSE-based filesystem layer, overlayfs-fuse
, permits a read-write root
filesystem with the command ifsctl mnt rootfs rw
. Otherwise, it is
always read-only to minimize flash storage writes and extend the MMC's
lifespan as much as possible. When all the initial mount process is
completed, the rootfs can be chroot'ed into to run the main framework.
The main partition layout looks like this:
PART. NUMBER LABEL DESCRIPTION
1 boot Contains boot flags
2 recoveryfs Recovery partition used to restore InkBox OS
3 rootfs Contains the rootfs SquashFS archive + OpenSSL digest
4 user All user data, such as config options, books, InkBox Software Archives (*.isa)
When the root filesystem has finished mounting, if the user has enabled
X11 (see the X11_START
, the KoBox subsystem is started up. The initrd
proceeds on the steps below, ran from [initrd-root]/etc/init.d/startx
:
- First, the
[initrd-root]/etc/init.d/developer-key
script is executed by the main rcS. If a developer key is found and is valid, then signature verification is disabled. - The base system is mounted from a disk image living at
[sd-p4]/X11/base.img
. This contains another disk image as well as the OpenSSL digest file used for verification against the initrd's public key. It is initially mounted at/opt/X11/base/rootfs
. - A VNC client root filesystem is set up at
/opt/X11/vnc-touch
to handle X11 touch input. Since Qt5 apps work very well on Kobos, especially with touch input, when an X11 app is started, anx11vnc
server is launched on the X11 chroot (with the-localhost
) and it then interacts with a Qt/LibVNCServer-based VNC viewer which doesn't print anything on the screen actually, but handles touch input only. Graphics work is leveraged byfbink-xdamage
. This method of dealing with touch input has its downsides, but scrolling is supported. - Extensions, whether part of the "base" subset or the "user" one, are set up in separate mountpoints. Extensions are in fact other SquashFS archives that contain a small part of a root filesystem. For example, the 'ssh' extension, which is part of the base subset, contains some binaries (ssh, scp) and libraries to get them to work, and really nothing else. The script first starts by mounting (as well as verifying) them in separate folders. Then, same thing is done for the user subset, which contains the extensions the user can add/remove via USB mass storage mode (USBMS), for example the 'C64-Emulator' one.
- When all extensions have been mounted and ready, the whole KoBox/X11
is mounted read-write at
/xorg
byfuse-overlayfs
andunionfs-fuse
, which handle merging them altogether. For what it's worth, when an user clicks on "Reset KoBox userdata", only a simplerm -rf /opt/X11/rootfs/write
+ reboot is done. - On InkBox OS, a (yet) unsolvable issue makes X impossible to start
after
udev
initialization. The process is 'frozen' and stopping it is only possible with SIGKILL (9). Therefore, the script starts it when no services (or very few) are running. Interestingly enough, restarting it afterwards works.
Once all necessary services have been loaded, the initrd issues three
chroot
commands on the openrc
binary in the chroot:
busybox chroot /mnt openrc sysinit
busybox chroot /mnt openrc boot
busybox chroot /mnt openrc default
Which starts the necessary services and helpers for the main Qt GUI interface.
InkBox's main graphical user interface runs in a chroot too, inside the
main rootfs chroot. It uses Qt 5.15.2 and prints directly on the
framebuffer, without any X11 server between the screen and it. To
communicate with external chroots (such as the root filesystem), it
makes use of a FIFO (First-In, First-Out) interface on a named pipe
located at /opt/ibxd
. A listener runs on the main rootfs and if a line
sent is recognized, the corresponding action/command is executed. InkBox
GUI is a system service and you can start/stop/restart it by issuing the
following command:
rc-service inkbox_gui <start|stop|restart>
or
start inkbox_gui
stop inkbox_gui
restart inkbox_gui
InkBox's main Qt 5 GUI comes in a *.isa
file, which contains the
necessary libraries and binaries needed for it to run in multiple
SquashFS archives. This permits a lightweight, portable package that can
be upgraded every release seamlessly by the update script.