MMotor OS
System

Processes and roles

Motor OS has no users, no groups, and no root account. A process's authority is a capability word fixed at creation, and three roles derived from that word decide what it may do with files.

Capabilities

Every process carries an immutable 64-bit capability word, set when the process is created and readable by the process itself without a syscall (it is in a read-only page the kernel maps into every process). The defined bits:

CapabilityMeaning
CAP_SYSSystem authority: root-like, unkillable from userspace, may grant any capability to a child.
CAP_IO_MANAGERMay map device memory and contiguous physical memory; held by sys-io.
CAP_SPAWNMay create processes.
CAP_LOGMay write records to the kernel log and to the logging service.
CAP_SHUTDOWNMay halt the machine.
CAP_SPAWN_DETACHEDMay create detached children that outlive the parent.
CAP_INTERACTIVEActs with the authority of the logged-in user.

The kernel enforces one rule at spawn: a parent without CAP_SYS may only grant a subset of its own capabilities, and never CAP_SYS or CAP_IO_MANAGER. A CAP_SYS parent may grant anything. Because a capability can never be gained after creation, a process cannot escalate.

The three roles

A role is derived from the capability word: CAP_SYS means System; otherwise CAP_INTERACTIVE means Interactive; otherwise the role is None. The roles are ordered, System above Interactive above None, and they are the only identity the filesystem knows about: every file and directory stores one permission byte per role.

RoleMeaningTypical holders
SystemThe OS itself; owns installed content and system logs.sys-io, sys-init, strobe
InteractiveThe logged-in user's authority: may read and run installed programs, and owns /user.sys-tty, russhd, console and SSH shells, the commands they run, user daemons
NoneLeast privilege: public read and execute, writes only to shared scratch directories.dns-resolver, other services, deliberately sandboxed children

A server that wants to know who it is talking to asks the kernel for the capabilities of the process at the other end of a connection; the answer comes from the kernel, not from the client, so it cannot be forged. sys-io does this once per filesystem connection and uses the result for every permission check on that connection. If the query fails, the connection is dropped rather than given a default role.

Spawning

There is no fork and no exec. std::process::Command works, and behind it the runtime in the parent builds the child directly: it creates an address space, loads the ELF executable into it, maps the runtime, writes the arguments and environment, sets up stdio, creates the process object with the chosen capabilities, and wakes the main thread. The program file's execute permission for the parent's role is checked before loading; a script needs both the script and its interpreter to be executable.

The child's capabilities come from an environment key that the parent's runtime consumes at spawn time and the child never sees:

Without MOTOR_OS_CAPS the default depends on the parent's role. An Interactive parent gets an Interactive child (a shell and the commands it runs), without CAP_LOG. A System parent gets a None child by default: a system service must say explicitly when it is creating a user session, so that a logged-in session cannot appear by accident. A None parent gets a None child. In every case the default is intersected with what the parent holds, and CAP_SPAWN is included so that children can have children.

How a session gets its role

The chain is explicit at every step. sys-init starts sys-tty and russhd with a mask that includes CAP_INTERACTIVE; sys-tty starts the console shell with the same role it has itself; russhd gives each authenticated session shell the Interactive bit; and from there the default rule carries Interactive down to every command. The shipped sys-init.cfg gives russhd the mask 124 (CAP_SPAWN | CAP_LOG | CAP_SHUTDOWN | CAP_SPAWN_DETACHED | CAP_INTERACTIVE) and the DNS resolver the mask 8 (CAP_LOG only). A test image variant runs the serial console as System instead, using tty:system: in the configuration.

russhd itself runs as Interactive, including its pre-authentication code and its in-process SFTP implementation. This is an explicit interim choice: a non-System parent cannot pass on a capability it does not hold, and SFTP needs filesystem authority. The authentication boundary protects that authority; a future change may keep the network front end at None and hand each authenticated session to an Interactive worker.

What roles mean day to day

The permission bits themselves, and the policy that assigns them when an image is built, are described under Filesystem. The design documents are docs/process-roles.md and src/sys/lib/motor-fs/PERMISSIONS_DESIGN.md in the repository.

Threads, killing, and exit

Threads are kernel objects created with a syscall; the runtime implements std::thread, thread-local storage, and futex-based synchronization on top. A parent can kill its child (Child::kill) and wait for it; there is no signal to catch, so a killed process simply stops. Ctrl+C from a terminal terminates a process with status 130 unless it registered a handler; see Terminals. Exit codes are reported to the parent as on other systems, and rush treats 130 as an interrupt.