Skip to content

Latest commit

 

History

History
144 lines (113 loc) · 6.5 KB

architecture.md

File metadata and controls

144 lines (113 loc) · 6.5 KB

DawnShell architecture

한국어 · Documentation · Glossary

DawnShell is a standalone Android app with its own UID. Android's isolation model is documented in the AOSP app sandbox guide.

Boot flow

LOCKED_BOOT_COMPLETED
  -> BootReceiver
  -> BfuBootstrapService foreground service
  -> verify DE storage and pre-authorized root
  -> validate Debian rootfs
  -> prepare namespaces and cgroups
  -> full mode: start systemd as Debian PID 1 -> ssh.service
  -> optional unsupported-kernel fallback: direct sshd, no systemd

USER_UNLOCKED
  -> record the event
  -> keep the existing Debian instance running

The receiver and service are Direct-Boot-aware as required by Google's Direct Boot guide.

Storage boundaries

App Device Encrypted (DE) storage contains only boot settings, public keys, runtime files, markers, and logs. It is located through createDeviceProtectedStorageContext(); see the Context API.

App Credential Encrypted (CE) storage contains the SSH client private key and is used only after first unlock. The boot gate verifies that app CE remains inaccessible during BFU. Debian's complete rootfs is held separately at the fixed root-only path /data/local/debian.

See the AOSP FBE guide for the platform storage model.

Bootstrap runtime

The APK contains source-built BusyBox, pkgdetails, statically linked gpgv, Debian archive keys, and a namespace launcher for armeabi-v7a, arm64-v8a, and x86_64. The installer verifies Debian Release signatures, indexes, and package hashes before publishing a rootfs.

Root boundary

Magisk approval is obtained while Android is unlocked and must be permanent. Root helpers accept fixed operation IDs and fixed paths, avoid secrets in command lines and logs, never remount Android's host /data, and revalidate every target before stop or deletion.

systemd environment

Private mount, PID, UTS, and cgroup namespaces isolate Debian's filesystem, process IDs, hostname, and delegated resource view. The network namespace remains shared with Android so existing Wi-Fi, mobile, VPN, and USB Ethernet interfaces are available without emulation.

Full mode is the default and fails closed when its required PID/cgroup namespaces cannot be created. The separate host-PID compatibility option permits a narrower fallback: mount and UTS remain private, while PID, IPC, cgroup, and network views are shared and the supervisor starts OpenSSH directly. State files record launch_mode=compat; status and health validate the tracked sshd executable, process start time, private mount/UTS identities, and TCP 22. No systemd, D-Bus, delegated cgroups, Docker, or enabled systemd units run in this mode.

The cgroup policy probes a delegated v2 subtree and device BPF first. If load or attach fails, it cleans every probe resource and falls back to isolated cgroup v1 devices and name=systemd views. Android's global hierarchy is never exposed for Debian to modify.

Kernels that carry neither device policy backend fall back once more to a name=systemd-only view, reported as cgroup_mode=v1-nodev. Linux added BPF_PROG_TYPE_CGROUP_DEVICE in 4.15, and a kernel built without CONFIG_CGROUP_DEVICE has no v1 devices controller, so both device gates can be missing at once. That tier starts only while USB passthrough is off, because no device policy can be enforced there; /dev/bus/usb keeps its empty read-only overmount and the launcher logs cgroup_major_189_denied=false.

USB passthrough is a DE-backed, default-off launch policy. Off mode overmounts Debian's /dev/bus/usb with an empty read-only filesystem and denies character major 189 using cgroup-device BPF on v2 or devices.deny on v1. Direct mode retains the shared /dev USB view and Android driver bindings. Exclusive mode uses the same raw view, scans sysfs every two seconds, and unbinds only interfaces matching the saved VID:PID allowlist. The supervisor records each detached interface and rebinds it in reverse order after Debian PID 1 exits. Hot-plug is handled without restarting Debian. Cgroup policy remains limited to DawnShell's delegated subtree; exclusive driver unbinding is necessarily host-wide and is therefore a separately warned, explicit option.

Hardware video codec bridge

Hardware video acceleration does not pass GPU device nodes into Debian. The app-local :codec process is retained only for capability and file diagnostics. Debian commands use an on-demand bionic NDK worker instead:

static dawnshell-codec parent
  → inherited memfd request/response slots + two eventfds
  → private dawnshell-codec-worker child
  → AMediaCodec / AImageReader / ANativeWindow

There is no listening socket, descriptor transfer, registered service, or persistent Debian codec daemon. One command owns one worker; parent death terminates the child and releases its sessions. The private Debian mount namespace exposes only read-only /system, /apex, and optional /linkerconfig so the bionic worker can resolve Android runtime libraries. App-private and normal app CE storage are not exposed.

The APK ships static clients and dynamic NDK workers for armv7, arm64, and x86_64. The worker implements AVC/HEVC byte-buffer decode and encode plus decoder-Surface-to-encoder-Surface transcoding. Hardware candidates are selected from modern platform metadata or conservative Exynos and Qualcomm component names. Software codecs are never silently selected. Session statistics verify keyframes, timestamps, EOS, inherited shared-memory transport, and zero CPU YUV frames on the Surface path. USER_UNLOCKED does not stop Debian; a worker is created only when a codec command runs in either BFU or AFU.

SSH keys

The app generates an Ed25519 key pair after unlock. The private half stays in app CE; only the public half is copied to DE and Debian. Private-key export occurs only after explicit user action.

Duplicate prevention

Boot ID, supervisor PID, process identity, and namespace checks prevent duplicate Debian instances. Stale state is removed only after the corresponding process has been proven absent or unrelated.

Related documents