LeonOS Documentation

Kernel / user-space boundaries

This page records who owns each boot-time and file-metadata responsibility after the middle layer (middlelayer/osmlayer, middlelayer.sys) was removed, and what happens to data and binaries produced by the old layout. It is the authority for the question "where does this call go now?"; the boot sequence itself is in BOOT_AND_INTEGRITY.md and the published user ABI is in ABI.md.

Before this change the kernel reached a separately loaded Ring-0 module through one callback table (struct leonos_middlelayer_api) and one RPC opcode per service (LEONOS_AUTH_OP_, LEONOS_UNICODE_OP_, LEONOS_VFS_OP_, LEONOS_MOUNT_KIND_). Every entry was an indirection over a call that could have been direct, and several entries had no production caller at all. The indirection and the dead entries are gone; the live ones moved to the single owner that already held the data.

Owners after the migration

ConcernOwnerInterface
UTF-8 / UTF-16LE transcoding for on-disk nameskernel/ntclks/lib/text_utf16.ctext_utf8_to_utf16le(), text_utf16le_to_utf8()
POSIX permission and ACL metadata on FAT32/exFAT (LEONACL.SYS)drivers/bootstrap/storage/storage_sidecar.cstorage_sidecar_permissions(), storage_sidecar_note_deleted(), storage_sidecar_note_renamed()
Kernel DAC decision (task credentials against a permission value)kernel/ntclks/permissions.cfs_permissions_check(), fs_permissions_parent(), fs_permissions_get()
Path and symlink resolution with search permissionkernel/ntclks/permissions.cfs_permissions_resolve(), fs_permissions_resolve_flags()
Root and installer-root mount choice at bootdrivers/bootstrap/storage/storage_mount.cstorage_mount_boot_root()
Device inventory shown to userlanduserland/apps/device-agent over the devmand IPCleonos_device_list() in userland/libc/src/devmand_client.c
Accounts, passwords, sessionspasswd/shadow/group/gshadow plus Linux-PAMdocs/SUDOERS_PAM_STATUS.md, docs/POSIX_PERMISSIONS_2026-09-08.md

Migration table

Original entryProduction consumersNew ownerNew interfaceOld-format compatibility
osmlayer_unicode_utf8_to_utf16le() / osmlayer_unicode_utf16le_to_utf8() (LEONOS_UNICODE_OP_UTF8_TO_UTF16LE, LEONOS_UNICODE_OP_UTF16LE_TO_UTF8)FAT32 LFN build/validate/render, exFAT name decode and name matchkernel/ntclks/lib/text_utf16.ctext_utf8_to_utf16le(), text_utf16le_to_utf8()Byte-for-byte: same U+FFFD substitution with one-byte advance, same rejection of overlong forms, surrogates and codepoints >= 0xF5, same "length needed" reporting when the buffer is short. Existing names on media are unchanged.
LEONOS_UNICODE_OP_LAYOUT_UTF8none (no kernel caller; text layout lives in libc)deletedleonos_text_layout_utf8() in include/leonos/text.hNot applicable; the opcode was unreachable.
osmlayer_auth_op(LEONOS_AUTH_OP_FSPERM) via fs_acl_dispatch() / fs_acl_fill_actor()fs_permissions_get(), fs_permissions_store() (kernel/ntclks/permissions.c), which back stat/chmod/chown and every fs_permissions_check()drivers/bootstrap/storage/storage_sidecar.c (metadata) plus kernel/ntclks/permissions.c (decision)storage_sidecar_permissions(path, value, write)LEONACL.SYS on-disk format is untouched: magic LCAL, version 1 and 2, FNV-1a checksum over [16,len), TLV records, 12-byte ACEs, the legacy deny bit, and the 8192-byte / 64-record caps. Version-1 records are still read and are re-encoded to version 2 on the next write, as before. Corrupt metadata still fails closed (-EIO) instead of default-allowing.
osmlayer_auth_op(LEONOS_AUTH_OP_FSPERM) notify actions (fs_acl_notify() for unlink and rename)syscall.c unlink/rmdir/rename pathsdrivers/bootstrap/storage/storage_sidecar.cstorage_sidecar_note_deleted(), storage_sidecar_note_renamed()Same best-effort contract: a failed metadata cleanup does not fail a completed unlink or rename, and only FAT32/exFAT volumes that actually hold a sidecar are touched.
osmlayer_auth_op(LEONOS_AUTH_OP_AUTHORIZE) via authz_check_path() / authz_check_install()execve, truncate, unlink, rmdir, rename argument checkskernel/ntclks/permissions.cfs_permissions_check(), fs_permissions_parent()The role-based checks (LEONOS_AUTH_ROLE_ADMIN, TASK_FLAG_ELEVATED_ADMIN) remain in the kernel task record; behaviour is the same DAC decision the bridge forwarded, minus the round trip. No permission check was removed or relaxed.
LEONOS_VFS_OP_RESOLVE_PATH (osmlayer_vfs_resolve_path)none: syscall.c already resolved paths in the kernelkernel/ntclks/permissions.c (existing)fs_permissions_resolve(), fs_permissions_resolve_flags()Not applicable; the middle-layer copy was a second implementation with no caller.
osmlayer_bridge_mount_policy() and struct leonos_mount_policy (LEONOS_MOUNT_KIND_, LEONOS_MOUNT_FLAG_)Boot-time root mount only (kernel_start)drivers/bootstrap/storage/storage_mount.cstorage_mount_boot_root(boot, ramdisk_root)The installer/live decision now comes from the kernel command line (mode=installer, mode=live) and the leonos-installer-root module tag, both of which already existed. GRUB configurations that passed those arguments boot identically.
device_catalog op plus struct leonos_device_catalog_query / struct leonos_raw_device_infonone: the formatting helpers in syscall.c had no call sitesuserland/apps/device-agent (already the live producer)leonos_device_list()struct leonos_device_info and the devmand wire format are unchanged; only the unused kernel-side formatter disappeared.
osmlayer_bridge_syscall() (LEONOS_SYSCALL hook into gui.rs, ipc.rs, posix.rs)none: no caller existed in kernel/ntclks/syscall.cdeletedLinux ABI syscalls plus the LeonOS syscalls implemented in kernel/ntclks/syscall.cNot applicable. No reachable syscall changed number, argument layout, or return convention.
Account store /var/lib/leonos/accounts.db, salted SHA-256 checks, session policyalready migrated to passwd/shadow + Linux-PAM before this change; the middle-layer copy was unreachabledeleted with the modulePAM, shadow, sudoA populated private accounts.db is still rejected rather than silently converted, as recorded in include/uapi/README.md.
Boot self-test [osmlayer] selftest passed=5/5boot log onlydeleted with the moduleLoader kernel SHA-256 gate (CONFIG_LOADER_VERIFY_SHA256) and the handoff version checkBoot logs no longer contain an [osmlayer] line. tools/analyze_boot_log.py was updated to stop treating its absence as a degradation.
struct leonos_middlelayer_api, struct leonos_kernel_services, leonos_middlelayer_module_init_fnloader, kernel bridgedeleteddirect kernel-internal callsRemoved from include/leonos/boot_handoff.h and from both SDK copies.
struct leonos_boot_handoff.middlelayer, .middlelayer_apiloader wrote, mm.c reserved, kernel.c loggeddeletedloader, kernel, installer_root module rangesLEONOS_BOOT_HANDOFF_VERSION is 7u. A version-6 handoff is rejected in boot_handoff_is_current(), so a mismatched loader/kernel pair stops with an explicit message instead of reading a removed field.
struct leonos_system_info.middlelayer_nameuserland/libc/src/procsys.c, userland/apps/osverkept as an offset-preserving gapreserved_subsystem_name, always emptyBinaries built against the old header still read every other field at the same offset and see an empty string. The "Middle layer" row was dropped from the About window instead of being filled with a placeholder name.
LEONOS_PATH_OSMLAYER_MANIFEST, LEONOS_PATH_BOOT_MIDDLELAYERno production consumerdeleted from include/leonos/layout.h and its three mirror copiesn/a/usr/lib/leonos/osmlayer.manifest is no longer staged into any root filesystem.
include/uapi/leonos/permissions.h (LEONOS_AUTH_OP_POSIX_PERMISSIONS, LEONOS_PERMISSIONS_GET/SET, struct leonos_permissions_request)kernel ACL bridge only; userland uses stat/chmod/chownheader deleted; struct leonos_permissions moved to kernel/ntclks/include/ntclks/storage.hLinux struct stat, chmod, chownThe permission triple is now clearly kernel-internal, so no internal RPC envelope remains in a published header.
LEONOS_AUTH_OP_, LEONOS_AUTHZ_, struct leonos_authz_request (include/leonos/auth.h)bridge and historical tests onlydeletedLEONOS_AUTH_ROLE_ and the leonos_auth_ calls, unchangedRoles are still published; only the RPC opcodes and request struct left the ABI.
RPR kernel release format_version=1 (kernel + middlelayer pair)userland/storage/leonos-kernel-update, tools/build/rpr-pages.shformat_version=2 (kernel + loader pair)release.txt keys format_version, image_version, version, kernel_file, kernel_sha256, loader_file, loader_sha256A format-1 manifest is refused with an explicit message, because it advertises a payload this system does not load. loader.elf now travels with kernel.sys and both are swapped in one commit window: the handoff layout is compiled into both images, so a kernel-only update could leave an installed system with a loader that the new kernel rejects. A stale /boot/leonos/middlelayer.sys is moved aside during a successful commit and is restored if that commit rolls back.

Build and packaging removals

make middlelayer, MIDDLELAYER_SYS, the middlelayer link step, the middlelayer.sys copies in tools/build/efi-stage.sh and tools/build/rpr-pages.sh, LEONOS_LOADER_MIDDLELAYER_SHA256, middlelayer_name in configs/build-version, and the module2 /leonos/middlelayer.sys lines in boot/grub/installer.cfg and boot/grub/live.cfg are all gone. Because Rust was used only by the middle layer, TOOLCHAIN_RUSTC, the make doctor Rust probe, leonos-config --rustcfg, and the CI Install Rust steps were removed with it; rustc is no longer a build prerequisite.

tools/gen_loader_integrity.py was deleted. It duplicated tools/build/loader-integrity.sh, which is what the Make build actually runs, and leaving two generators for one header contradicted single ownership.

Status

Implemented against the current tree but not compiled, not tested, not run in a virtual machine, and not reviewed. See the handoff notes in the change description for the test files that the interface changes require the owning agent to update.