Files
RedBear-OS/config/redbear-mini.toml
T
Red Bear OS Builder bdc56ddd58 polkit: implement real authorization (v0.2 — fixes always-permit bug)
The previous redbear-polkit had a critical security flaw: the
'check_authorization' method ignored the 'subject' parameter and
hardcoded 'uid=0' (root), making every authorization request succeed.
Any caller could perform any action as 'root'. This was flagged as
5/5 security fragility in the DBUS assessment.

This commit implements real authorization in the polkit daemon:

* Subject UID extraction. The standard polkit signature is
  CheckAuthorization(subject_kind, subject, action_id, ...). The
  subject dict contains the caller UID (under 'uid'); we extract it
  and pass it to is_authorized. No more hardcoded root.

* Comprehensive policy syntax. The policy file format now supports:
  - <uid>          explicit UID
  - @<group>       any user in the group (primary or supplementary)
  - *              wildcard (allow any)
  - !<uid>         explicit deny
  - !@<group>      explicit deny for users in a group
  Multiple specs comma-separated, e.g. '@wheel, 1000, !@restricted'.

* Default-deny for unknown actions. Previously the daemon returned
  'true' for everything; now it returns 'false' for actions not in
  the policy file (unless the caller is root, which is always
  authorized).

* match_user_spec returns None for non-match. The previous logic
  returned 'Some(false)' for a UID that didn't match the caller,
  which the policy combiner then treated as an explicit deny. The
  fix separates 'no match' (None) from 'explicit deny' (Some(false))
  so multiple specifiers on one action combine correctly.

* Env-var override for tests. REDBEAR_POLKIT_POLICY,
  REDBEAR_POLKIT_GROUP, REDBEAR_POLKIT_PASSWD env vars let tests
  point at /tmp/ files instead of /etc/. 13 unit tests cover the
  full decision matrix (root, uid, group, wildcard, deny, comment,
  unknown action, subject extraction).

* Policy file staged in redbear-full.toml and redbear-mini.toml.
  The default /etc/polkit-1/policy.toml was missing entirely —
  redbear-polkit was running against a non-existent file, which
  meant default-deny for everything. The new policy.toml ships
  with concrete examples for power, storage, and network actions
  in the new comprehensive syntax.

* BackendVersion bumped to 0.2.0 to reflect the contract change.

DBUS-PLAN bumped to v3.2 (2026-07-26). §3.1 status table now lists
redbear-polkit v0.2 as done. §14.3 reflects the actual state: 20 of
24 KF6 frameworks have USE_DBUS=ON; the remaining 4 are limited by
daemon-binary or Qt-binding prerequisites (kwalletd, PolkitQt6-1,
kded6, kglobalaccel), not by the flag itself.

Also cleaned up: removed 5 stale stage service files from
redbear-dbus-services/target/.../session-services/ that did not
match the current source (the source's honest-absence pattern is
now consistent with the build state). The cleanup is a local
filesystem operation; the .gitignore already excludes that path.

Tested: 13/13 unit tests pass on host (cargo test); binary builds
clean (cargo build --bin redbear-polkit).
2026-07-26 18:29:22 +09:00

634 lines
13 KiB
TOML

# Red Bear OS Mini Configuration
# Text-only ISO for console/recovery/install on bare metal.
#
# Build: make live CONFIG_NAME=redbear-mini
#
# Target contract:
# - text-login live/recovery/install surface
# - boot framebuffer for VT text consoles via vesad + fbcond
# - all non-graphics, non-firmware packages from the full profile
# - no linux-firmware payload, no firmware-loader, no GPU/display drivers
include = ["minimal.toml", "redbear-legacy-base.toml", "redbear-netctl.toml", "redbear-device-services.toml", "redbear-boot-stages.toml"]
[general]
filesystem_size = 512
[users.messagebus]
uid = 100
gid = 100
name = "messagebus"
home = "/nonexistent"
shell = "/usr/bin/zsh"
[packages]
# Red Bear OS branding and host utilities.
redbear-release = {}
redbear-hwutils = {}
redbear-quirks = {}
# Device driver infrastructure (driver-manager owns the boot-time PCI
# match/claim/spawn path; pcid-spawner is retired and removed)
ehcid = {}
ohcid = {}
uhcid = {}
# Redox-native netctl tooling.
redbear-netctl = {}
redbear-netctl-console = {}
redbear-netstat = {}
redbear-traceroute = {}
redbear-mtr = {}
redbear-nmap = {}
# Wi-Fi control daemon (firmware-loader excluded — no firmware blobs in mini).
redbear-wifictl = {}
# Diagnostics and shell-side utilities.
tlc = {}
#mc = {}
redbear-info = {}
# brush: Rust shell, candidate default login shell (validated in-image before
# switching the [users.*] shell over from zsh).
brush = {}
# Keep package builder utility in live environment.
cub = {}
cpufreqd = {}
thermald = {}
redbear-power = {}
hwrngd = {}
redbear-acmd = {}
redbear-ftdi = {}
redbear-ecmd = {}
redbear-usbaudiod = {}
redbear-usb-hotplugd = {}
driver-params = {}
# ── PCI device database (critical for PCI driver matching) ──
pciids = {}
# ── Filesystem support ──
ext4d = {}
fatd = {}
redoxfs = {}
# ── System installer ──
installer = {}
# ── Input / device management ──
evdevd = {}
udev-shim = {}
# ── D-Bus IPC and session services ──
dbus = {}
redbear-sessiond = {}
redbear-dbus-services = {}
redbear-notifications = {}
redbear-upower = {}
redbear-udisks = {}
redbear-polkit = {}
# ── IOMMU DMA remapping ──
iommu = {}
# ── Standard CLI tools (from server profile) ──
bash = {}
bottom = {}
curl = {}
diffutils = {}
findutils = {}
uutils-tar = {}
bison = {}
flex = {}
meson = {}
ninja-build = {}
m4 = {}
#git = {} # suppressed: cascading rebuild; git not needed for boot/recovery
htop = {}
# ── Build / packaging utilities ──
# patchelf = {} # requires strtold which is missing in relibc
shared-mime-info = {}
# VT/getty/login chain: initfs starts inputd + vesad + fbcond in phase 1,
# then minimal.toml legacy 30_console runs inputd -A 2 + getty 2 + getty debug.
[[files]]
path = "/etc/netctl/active"
data = "wired-dhcp\n"
[[files]]
path = "/etc/init.d/10_smolnetd.service"
data = """
[unit]
description = "Network stack (non-blocking on live-mini)"
requires_weak = [
"00_driver-manager.service",
]
[service]
cmd = "netstack"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/10_dhcpd.service"
data = """
[unit]
description = "DHCP client daemon (non-blocking on live-mini)"
requires_weak = [
"10_smolnetd.service",
]
[service]
cmd = "dhcpd"
args = ["-f"]
type = "oneshot_async"
"""
[[files]]
path = "/etc/issue"
data = """
########## Red Bear OS #########
# Login with the following: #
# `user` #
# `root`:`password` #
################################
"""
# motd is provided by the redbear-release recipe (generated from motd.in
# template with the current git-branch version). Do NOT add a static
# motd [[files]] override here — it creates a collision with recipe
# staging and goes stale when the version bumps.
[[files]]
path = "/etc/init.d/20_audiod.service"
data = """
[unit]
description = "Audio multiplexer (non-blocking on live-mini)"
requires_weak = [
"00_base.target",
]
[service]
cmd = "audiod"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/02_usb_hotplug.service"
data = """
[unit]
description = "USB device hotplug daemon (auto-spawns class drivers)"
requires_weak = [
"00_base.target",
"00_driver-manager.service",
]
[service]
cmd = "redbear-usb-hotplugd"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/02_serial_probe.service"
data = """
[unit]
description = "Serial boot probe marker"
requires_weak = [
"00_base.target",
]
[service]
cmd = "echo"
args = ["RB_SERIAL_PROBE_OK"]
type = "oneshot"
"""
[[files]]
path = "/etc/init.d/00_gpiod.service"
data = """
[unit]
description = "GPIO controller registry"
requires_weak = [
"00_base.target",
]
[service]
cmd = "gpiod"
type = { scheme = "gpio" }
"""
[[files]]
path = "/etc/init.d/00_i2cd.service"
data = """
[unit]
description = "I2C adapter registry"
requires_weak = [
"00_base.target",
]
[service]
cmd = "i2cd"
type = { scheme = "i2c" }
"""
[[files]]
path = "/etc/init.d/00_intel-lpss-i2cd.service"
data = """
[unit]
description = "Intel LPSS I2C controller (PCI + ACPI discovery, DesignWare engine)"
requires_weak = [
"00_i2cd.service",
]
[service]
cmd = "/usr/lib/drivers/intel-lpss-i2cd"
type = { scheme = "i2c-lpss" }
"""
[[files]]
path = "/etc/init.d/00_i2c-dw-acpi.service"
data = """
[unit]
description = "DesignWare ACPI I2C controller"
requires_weak = [
"00_i2cd.service",
]
[service]
cmd = "dw-acpi-i2cd"
type = { scheme = "dw-acpi-i2c" }
"""
[[files]]
path = "/etc/init.d/00_intel-gpiod.service"
data = """
[unit]
description = "Intel ACPI GPIO registrar"
requires_weak = [
"00_gpiod.service",
"00_i2cd.service",
]
[service]
cmd = "intel-gpiod"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/00_i2c-gpio-expanderd.service"
data = """
[unit]
description = "I2C GPIO expander companion bridge"
requires_weak = [
"00_i2cd.service",
"00_gpiod.service",
]
[service]
cmd = "i2c-gpio-expanderd"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/00_i2c-hidd.service"
data = """
[unit]
description = "ACPI I2C HID bring-up daemon"
requires_weak = [
"00_i2cd.service",
"00_intel-lpss-i2cd.service",
"00_i2c-dw-acpi.service",
"00_intel-gpiod.service",
"00_i2c-gpio-expanderd.service",
]
[service]
cmd = "i2c-hidd"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/00_ucsid.service"
data = """
[unit]
description = "USB-C UCSI topology detector"
requires_weak = [
"00_base.target",
"00_i2cd.service",
]
[service]
cmd = "ucsid"
type = { scheme = "ucsi" }
"""
[[files]]
path = "/etc/init.d/12_boot-late.target"
data = """
[unit]
description = "Late boot services target"
requires_weak = [
"00_base.target",
]
"""
[[files]]
path = "/etc/init.d/11_udev.service"
data = """
[unit]
description = "udev compatibility shim"
requires_weak = [
"12_boot-late.target",
"00_driver-manager.service",
]
[service]
cmd = "udev-shim"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/10_evdevd.service"
data = """
[unit]
description = "Evdev input daemon"
requires_weak = [
"12_boot-late.target",
"00_driver-manager.service",
]
[service]
cmd = "evdevd"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/11_wifictl.service"
data = """
[unit]
description = "Wi-Fi control daemon"
requires_weak = [
"12_boot-late.target",
"00_driver-manager.service",
]
[service]
cmd = "redbear-wifictl"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/12_dbus.service"
data = """
[unit]
description = "D-Bus system bus"
requires_weak = [
"12_boot-late.target",
]
[service]
cmd = "dbus-daemon"
args = ["--system", "--nopidfile", "--address=unix:path=/run/dbus/system_bus_socket"]
envs = { DBUS_SYSTEM_BUS_ADDRESS = "unix:path=/run/dbus/system_bus_socket" }
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/13_seatd.service"
data = """
[unit]
description = "seatd seat management (no-op on live-mini)"
[service]
cmd = "echo"
args = ["seatd: skipped on live-mini"]
type = "oneshot"
"""
[[files]]
path = "/etc/init.d/13_redbear-sessiond.service"
data = """
[unit]
description = "Red Bear session broker (org.freedesktop.login1)"
requires_weak = [
"12_dbus.service",
]
[service]
cmd = "redbear-sessiond"
envs = { DBUS_SYSTEM_BUS_ADDRESS = "unix:path=/run/dbus/system_bus_socket" }
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/13_iommu.service"
data = """
[unit]
description = "IOMMU DMA remapping daemon"
requires_weak = [
"12_boot-late.target",
"00_driver-manager.service",
]
[service]
cmd = "/usr/bin/iommu"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/14_redbear-upower.service"
data = """
[unit]
description = "UPower D-Bus service (org.freedesktop.UPower)"
requires_weak = [
"12_dbus.service",
]
[service]
cmd = "redbear-upower"
envs = { DBUS_SYSTEM_BUS_ADDRESS = "unix:path=/run/dbus/system_bus_socket" }
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/14_redbear-udisks.service"
data = """
[unit]
description = "UDisks2 D-Bus service (org.freedesktop.UDisks2)"
requires_weak = [
"12_dbus.service",
]
[service]
cmd = "redbear-udisks"
envs = { DBUS_SYSTEM_BUS_ADDRESS = "unix:path=/run/dbus/system_bus_socket" }
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/14_redbear-polkit.service"
data = """
[unit]
description = "PolicyKit1 D-Bus service (org.freedesktop.PolicyKit1)"
requires_weak = [
"12_dbus.service",
]
[service]
cmd = "redbear-polkit"
envs = { DBUS_SYSTEM_BUS_ADDRESS = "unix:path=/run/dbus/system_bus_socket" }
type = "oneshot_async"
"""
[[files]]
path = "/etc/polkit-1/policy.toml"
data = """
# Red Bear OS polkit policy (v0.2 — comprehensive syntax)
#
# Format: action_id = uid, @group, *, !uid, !@group
#
# Specifiers:
# 1000 - explicit UID
# @wheel - any user in the named group (primary or supplementary)
# * - wildcard (allow any user)
# !1000 - explicit deny (overrides allows)
# !@restricted - explicit deny for users in 'restricted'
#
# UID 0 (root) is implicitly authorized for every action.
# -------- Power management (login1) --------
org.freedesktop.login1.power-off = *
org.freedesktop.login1.reboot = *
org.freedesktop.login1.suspend = *
org.freedesktop.login1.set-user-linger = 0
# -------- Storage (UDisks2) --------
org.freedesktop.udisks2.filesystem-mount = @wheel, 1000
org.freedesktop.udisks2.filesystem-mount-system = 0
# -------- NetworkManager --------
org.freedesktop.NetworkManager.settings.modify.system = 0
org.freedesktop.NetworkManager.enable-disable-wifi = @wheel, 1000
org.freedesktop.NetworkManager.enable-disable-wifi = !@restricted
"""
[[files]]
path = "/var/lib/dbus"
data = ""
directory = true
mode = 0o755
[[files]]
path = "/run/dbus"
data = ""
directory = true
mode = 0o755
[[files]]
path = "/etc/init.d/29_activate_console.service"
data = """
[unit]
description = "Activate console VT"
requires_weak = ["00_base.target"]
[service]
cmd = "inputd"
args = ["-A", "2", "-K", "us"]
type = "oneshot_async"
"""
# NOTE: cpufreqd is already started earlier by 15_cpufreqd.service (from
# redbear-device-services.toml). A second 30_cpufreqd instance used to live here
# and (a) ran cpufreqd twice — double MSR probing + a duplicate 16-line P-state
# dump — and (b) fired at getty time, burying the login banner/prompt under its
# output. Removed; the 15_ instance covers it with settle time before the prompt.
[[files]]
path = "/etc/init.d/30_console.service"
data = """
[unit]
description = "Console terminals"
requires_weak = [
"29_activate_console.service",
"00_ptyd.service",
]
[service]
cmd = "getty"
args = ["2"]
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/31_debug_console.service"
# Serial/debug console handled by fbcond's serial mirror (see minimal.toml).
data = """
[unit]
description = "Debug console (handled by fbcond serial mirror)"
[service]
cmd = "true"
type = "oneshot"
"""
[[files]]
path = "/etc/init.d/00_driver-manager.service"
data = """
[unit]
description = "Driver manager (non-blocking on live-mini)"
[service]
cmd = "driver-manager"
args = ["--hotplug"]
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/00_ipcd.service"
data = """
[unit]
description = "Inter-process communication daemon (non-blocking on live-mini)"
[service]
cmd = "ipcd"
type = "oneshot_async"
"""
[[files]]
path = "/etc/init.d/13_ftdi-probe.service"
data = """
[unit]
description = "FTDI USB serial probe (non-blocking on redbear-mini)"
requires_weak = [
"00_base.target",
]
[service]
cmd = "echo"
args = ["RB_FTDI_PROBE_OK"]
type = "oneshot"
"""
[[files]]
path = "/etc/init.d/00_ptyd.service"
data = """
[unit]
description = "Pseudo-terminal daemon"
[service]
cmd = "ptyd"
# ptyd registers the "pty" scheme and signals readiness by sending its scheme
# cap fd back to init (redox_scheme ready_sync_scheme / ready_with_fd). init's
# scheme-service startup does a call_ro(FD) to receive that fd and register the
# scheme. It MUST therefore be type={scheme="pty"} — NOT "notify". With "notify"
# init does a plain readiness-byte read_exact that ptyd never sends, so init
# blocks forever here (the observed post-switchroot boot hang before the console
# stack). See ptyd/src/main.rs: it is on the SchemeDaemon/ready_with_fd path.
type = { scheme = "pty" }
"""