diff --git a/docs/HARDENING.md b/docs/HARDENING.md index 17927f3..6427cac 100644 --- a/docs/HARDENING.md +++ b/docs/HARDENING.md @@ -41,6 +41,21 @@ kickstart `%post` or the overlay tree shipped in `/etc`. `sys_admin` and `perfmon` capabilities required by the modules-lock service. Source: `scripts/selinux/veilor-systemd.te`. +### veilor-firstboot SELinux confinement + +The first-boot password service is privileged (it has to write +`/etc/shadow`) but small. Module `veilor-firstboot` carves a tight domain: + +- Allowed: read `/etc/passwd`, exec `passwd(1)`, write + `/var/lib/veilor-firstboot.done`, write `/etc/sddm.conf.d/`, + start `sddm.service`. +- `neverallow` rules block: network sockets (no phone-home), + `home_root_t` / `user_home_t` access, `sys_module`, `sys_ptrace`, + `sys_rawio`. + +Source: `scripts/selinux/veilor-firstboot.te`. Build & load with +`scripts/selinux/build-policy.sh` (loads all modules in one pass). + ## Network surface - **firewalld** default zone = `drop`. @@ -119,6 +134,57 @@ sudo usbguard allow-device `bluetooth`, `ModemManager`, `gssproxy`, `atd`, `pcscd.socket`, `pcscd.service`, `kdeconnectd` (removed at package level). +## AppArmor (v0.5) + +Fedora 43 ships AppArmor alongside SELinux. veilor-os keeps SELinux as the +primary MAC layer (enforcing, targeted) but ships AppArmor profile +skeletons for high-risk userland binaries that benefit from a second, +binary-scoped policy on top of SELinux's role-based one. + +Profiles live in `scripts/apparmor/`: + +| Profile | Target | Default mode | +|---------|--------|--------------| +| `usr.bin.thorium` | Thorium browser | `complain` | +| `usr.local.bin.lm-studio` | LM Studio LLM runner | `complain` | +| `usr.bin.veilor-power` | Power profile switcher | `enforce` | + +Profiles are **not** loaded automatically — they are opt-in until v0.5. +Enable a profile post-install with: + +```bash +sudo dnf install apparmor-utils apparmor-parser +sudo install -m 0644 scripts/apparmor/usr.bin.thorium /etc/apparmor.d/ +sudo apparmor_parser -r /etc/apparmor.d/usr.bin.thorium +sudo aa-complain /etc/apparmor.d/usr.bin.thorium # log only +sudo aa-enforce /etc/apparmor.d/usr.bin.thorium # block +``` + +Refine `complain`-mode profiles with `aa-logprof` after exercising the +app through normal use; it converts logged denials into rule additions +interactively. + +## Audit log shipping (optional) + +Local journald is the default audit sink. For off-device shipping to a +trusted log collector (Loki / Wazuh / Splunk), veilor-os ships a +disabled-by-default plugin template: + +- `/etc/audit/plugins.d/veilor-remote.conf` — auditd plugin shim + (set `active = yes` to enable). +- `/etc/audisp/audisp-remote.conf.disabled` — audisp-remote target + config template (rename to `audisp-remote.conf` and edit + `remote_server` to enable). + +**Warning:** enabling remote audit shipping leaks every privileged syscall, +file-watch hit, and auth event off-device. Treat the collector as a host +with the same trust level as root. Only enable if the collector itself is +hardened and the transport is TLS or kerberized. + +Reference integration paths in the template: Loki via promtail/vector +syslog source, Wazuh via local wazuh-agent (no network shipping needed), +Splunk via HEC bridge. + ## What's *not* enabled by default - **Disk swap** — replaced by zram (RAM-only, no key leak risk). diff --git a/overlay/etc/audisp/audisp-remote.conf.disabled b/overlay/etc/audisp/audisp-remote.conf.disabled new file mode 100644 index 0000000..391f92a --- /dev/null +++ b/overlay/etc/audisp/audisp-remote.conf.disabled @@ -0,0 +1,58 @@ +# veilor-os audisp-remote configuration template (DISABLED by default) +# +# IMPORTANT: enabling remote audit shipping leaks security events off-device. +# Only enable if you have a trusted log collector — the remote endpoint +# will receive every privileged syscall, file-watch hit, auth event, and +# sudoers/SSH config change recorded by auditd. +# +# To activate: +# 1. Set veilor-remote.conf `active = yes` (in /etc/audit/plugins.d/). +# 2. Copy this file to /etc/audisp/audisp-remote.conf (drop `.disabled`). +# 3. Edit `remote_server` + TLS settings below. +# 4. systemctl restart auditd +# +# Loki / Wazuh / Splunk integration paths: +# +# Loki - point remote_server at a syslog-to-Loki shim (promtail or +# vector with `syslog` source, format = "rfc5424"). Use TCP+TLS. +# Wazuh - run wazuh-agent locally; it pulls /var/log/audit/audit.log +# directly. In that case leave remote_server empty and rely on +# wazuh-agent's filebeat-style tailer instead of audisp-remote. +# Splunk - use a Splunk HEC bridge (rsyslog-omhttp or vector http sink). +# audisp-remote speaks plain syslog/TLS; it does not speak HEC +# natively. + +# ---- transport ---- +remote_server = logs.example.org +port = 60 +transport = tcp # plain | tcp | krb5 +queue_file = /var/spool/audit/remote.log +mode = immediate # immediate | forwarding +queue_depth = 10240 +format = managed # managed | ascii + +# ---- TLS (transport = tcp + use_libwrap=no recommended) ---- +enable_krb5 = no +krb5_principal = +krb5_client_name = auditd +krb5_key_file = /etc/audit/audit.key + +# ---- failure handling ---- +network_failure_action = stop # ignore | syslog | exec | suspend | single | halt | stop +disk_low_action = syslog +disk_full_action = syslog +disk_error_action = syslog +remote_ending_action = reconnect +generic_error_action = syslog +generic_warning_action = syslog +overflow_action = syslog + +# ---- heartbeat ---- +heartbeat_timeout = 60 +network_retry_time = 1 +max_tries_per_record = 3 +max_time_per_record = 5 + +# ---- formatting ---- +# `managed` wraps each event in a syslog-RFC5424 header with veilor-os +# hostname + audit facility (LOG_AUTHPRIV). Loki/Splunk prefer this. diff --git a/overlay/etc/audit/plugins.d/veilor-remote.conf b/overlay/etc/audit/plugins.d/veilor-remote.conf new file mode 100644 index 0000000..e308885 --- /dev/null +++ b/overlay/etc/audit/plugins.d/veilor-remote.conf @@ -0,0 +1,23 @@ +# veilor-os audit remote shipping (DISABLED by default) +# +# IMPORTANT: enabling remote audit shipping leaks security events off-device. +# Only enable if you have a trusted log collector (Loki / Wazuh / Splunk). +# The remote endpoint will see every privileged syscall, file watch hit, +# auth event, and sudoers change. Treat the collector with the same trust +# level as the host root account. +# +# Enable: +# 1. Edit `active = yes` below. +# 2. Configure /etc/audisp/audisp-remote.conf (see audisp-remote.conf.disabled). +# 3. systemctl restart auditd. +# 4. Verify with: auditctl -s | grep enabled +# +# Plugin pipes audit events out of auditd via a UNIX socket; audisp-remote +# reads from that socket and forwards to the configured remote_server. + +active = no +direction = out +path = builtin_af_unix +type = builtin +args = /var/run/audit_events +format = string diff --git a/scripts/apparmor/usr.bin.thorium b/scripts/apparmor/usr.bin.thorium new file mode 100644 index 0000000..8b5dbca --- /dev/null +++ b/scripts/apparmor/usr.bin.thorium @@ -0,0 +1,114 @@ +# veilor-os AppArmor profile — Thorium browser (Chromium fork) +# +# Scope: +# Confine the Thorium browser binary at /usr/bin/thorium. Thorium is a +# Chromium derivative; it sandboxes its own renderer/GPU/utility processes, +# but the *browser* process itself runs with the full user's permissions +# unless an MAC layer scopes it down. This profile is that scope. +# +# Mode: +# complain — log violations to audit.log but do NOT block. This is the +# first-fit profile; the user is expected to refine it from observed +# denials before flipping to enforce. See `aa-logprof` to convert audit +# denials into rule additions. +# +# Manual enable: +# sudo install -m 0644 scripts/apparmor/usr.bin.thorium /etc/apparmor.d/ +# sudo apparmor_parser -r /etc/apparmor.d/usr.bin.thorium +# sudo aa-complain /etc/apparmor.d/usr.bin.thorium # log only +# sudo aa-enforce /etc/apparmor.d/usr.bin.thorium # block +# +# NOT enabled in kickstart by default. v0.5 work. + +#include + +profile thorium /usr/bin/thorium flags=(complain) { + #include + #include + #include + #include + #include + #include + #include + #include + #include + + # ---- network: outbound HTTP/HTTPS only ---- + network inet stream, + network inet6 stream, + network inet dgram, # DNS resolution + network inet6 dgram, + network netlink raw, # NetworkManager state queries + deny network raw, + deny network packet, + deny network bluetooth, + deny network can, + deny network rds, + deny network sctp, + + # ---- binary + libs ---- + /usr/bin/thorium mr, + /usr/lib/thorium/** mr, + /usr/share/thorium/** r, + /opt/thorium/** mr, + /etc/thorium/** r, + + # ---- per-user state ---- + owner @{HOME}/.config/thorium/** rwk, + owner @{HOME}/.cache/thorium/** rwk, + owner @{HOME}/.local/share/thorium/** rwk, + + # ---- file pickers: only Downloads is writable ---- + owner @{HOME}/Downloads/ rw, + owner @{HOME}/Downloads/** rwk, + owner @{HOME}/Documents/ r, + owner @{HOME}/Documents/** r, + owner @{HOME}/Pictures/ r, + owner @{HOME}/Pictures/** r, + + # ---- /proc: own process only, deny memory peeking ---- + owner /proc/@{pid}/** r, + deny /proc/*/mem rwk, + deny /proc/*/maps r, + deny /proc/sys/kernel/** w, + + # ---- ptrace: forbidden ---- + deny ptrace, + deny capability sys_ptrace, + + # ---- kernel: no module load, no /dev/kmem, no /dev/mem ---- + deny capability sys_module, + deny /dev/kmem rwk, + deny /dev/mem rwk, + deny /dev/port rwk, + deny /sys/kernel/** w, + + # ---- temp ---- + /tmp/ r, + owner /tmp/** rwk, + /var/tmp/ r, + owner /var/tmp/** rwk, + + # ---- system info read-only ---- + /etc/machine-id r, + /etc/os-release r, + /etc/localtime r, + /sys/devices/system/cpu/** r, + /sys/class/net/** r, + + # ---- chrome sandbox helper (setuid/SUID-like child needs unconfined) ---- + /usr/lib/thorium/chrome-sandbox Cx -> sandbox, + /usr/bin/xdg-open Pix, + + profile sandbox { + #include + capability sys_admin, + capability sys_chroot, + capability sys_ptrace, + /usr/lib/thorium/chrome-sandbox mr, + /usr/lib/thorium/** mrix, + /proc/*/setgroups w, + /proc/*/uid_map w, + /proc/*/gid_map w, + } +} diff --git a/scripts/apparmor/usr.bin.veilor-power b/scripts/apparmor/usr.bin.veilor-power new file mode 100644 index 0000000..bcb2356 --- /dev/null +++ b/scripts/apparmor/usr.bin.veilor-power @@ -0,0 +1,78 @@ +# veilor-os AppArmor profile — veilor-power +# +# Scope: +# Confine /usr/local/bin/veilor-power, the power profile switcher. The +# script is small but invokes sudo to talk to tuned-adm; we want a tight +# surface so a compromised user shell cannot abuse the sudoers entry to +# pivot beyond profile switching. +# +# Mode: +# enforce — this binary is ours, the surface is small, no need for a +# complain runway. Verified rules at write time. +# +# Manual enable: +# sudo install -m 0644 scripts/apparmor/usr.bin.veilor-power /etc/apparmor.d/ +# sudo apparmor_parser -r /etc/apparmor.d/usr.bin.veilor-power +# sudo aa-enforce /etc/apparmor.d/usr.bin.veilor-power +# # to debug: +# sudo aa-complain /etc/apparmor.d/usr.bin.veilor-power +# +# NOT enabled in kickstart by default. v0.5 work. + +#include + +profile veilor-power /usr/local/bin/veilor-power flags=(enforce) { + #include + #include + #include + + # ---- the script itself + bash ---- + /usr/local/bin/veilor-power r, + /usr/bin/bash ix, + /usr/bin/awk ix, + /usr/bin/cat ix, + + # ---- read CPU + ASUS sysfs for status ---- + /sys/devices/system/cpu/cpufreq/ r, + /sys/devices/system/cpu/cpufreq/** r, + /sys/devices/system/cpu/cpu*/cpufreq/ r, + /sys/devices/system/cpu/cpu*/cpufreq/** r, + /sys/devices/platform/asus-nb-wmi/ r, + /sys/devices/platform/asus-nb-wmi/** r, + + # ---- sudo handoff to tuned-adm ---- + /usr/bin/sudo Cx -> sudo_tuned, + /usr/bin/tuned-adm Pix, + + # ---- forbidden ---- + deny network, + deny ptrace, + deny capability sys_ptrace, + deny capability sys_module, + deny capability sys_rawio, + deny /dev/kmem rwk, + deny /dev/mem rwk, + deny /etc/shadow r, + deny /etc/sudoers w, + deny /etc/sudoers.d/** w, + deny @{HOME}/.ssh/** rwk, + deny @{HOME}/.gnupg/** rwk, + + # ---- child profile for the sudo subprocess ---- + profile sudo_tuned { + #include + #include + #include + /usr/bin/sudo mr, + /etc/sudoers r, + /etc/sudoers.d/ r, + /etc/sudoers.d/veilor-power r, + /usr/bin/tuned-adm Pix, + /var/log/sudo* w, + /var/db/sudo/** rwk, + capability setuid, + capability setgid, + capability audit_write, + deny network, + } +} diff --git a/scripts/apparmor/usr.local.bin.lm-studio b/scripts/apparmor/usr.local.bin.lm-studio new file mode 100644 index 0000000..9ab0435 --- /dev/null +++ b/scripts/apparmor/usr.local.bin.lm-studio @@ -0,0 +1,96 @@ +# veilor-os AppArmor profile — LM Studio (local LLM runner) +# +# Scope: +# Confine LM Studio's binary. LM Studio loads arbitrary GGUF/safetensors +# weights and exposes an OpenAI-compatible HTTP server on :1234. The +# binary itself is closed-source — we don't trust it with the full home +# directory. +# +# Mode: +# complain initially. Flip to enforce once observed denials are reviewed. +# +# Manual enable: +# sudo install -m 0644 scripts/apparmor/usr.local.bin.lm-studio /etc/apparmor.d/ +# sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.lm-studio +# sudo aa-complain /etc/apparmor.d/usr.local.bin.lm-studio +# sudo aa-enforce /etc/apparmor.d/usr.local.bin.lm-studio +# +# NOT enabled in kickstart by default. v0.5 work. + +#include + +profile lm-studio /usr/local/bin/lm-studio flags=(complain) { + #include + #include + #include + #include + #include + #include + #include + + # ---- network: HTTP server :1234 + outbound model downloads ---- + network inet stream, + network inet6 stream, + network inet dgram, + network inet6 dgram, + deny network raw, + deny network packet, + deny network bluetooth, + + # ---- binary + electron runtime (LM Studio is Electron-based) ---- + /usr/local/bin/lm-studio mr, + /opt/lm-studio/** mr, + /usr/lib/lm-studio/** mr, + + # ---- model weights + metadata ---- + owner @{HOME}/.lmstudio/ rw, + owner @{HOME}/.lmstudio/** rwk, + owner @{HOME}/.cache/lm-studio/** rwk, + owner @{HOME}/.config/LMStudio/** rwk, + + # ---- temp ---- + /tmp/ r, + owner /tmp/** rwk, + /var/tmp/ r, + owner /var/tmp/** rwk, + + # ---- GPU device nodes (CUDA / ROCm / Vulkan) ---- + /dev/dri/ r, + /dev/dri/** rw, + /dev/nvidia* rw, + /dev/nvidiactl rw, + /dev/nvidia-uvm rw, + /dev/nvidia-uvm-tools rw, + /dev/kfd rw, + /dev/shm/** rwk, + + # ---- system info ---- + /etc/machine-id r, + /etc/os-release r, + /etc/localtime r, + /sys/devices/system/cpu/** r, + /sys/class/drm/** r, + /proc/cpuinfo r, + /proc/meminfo r, + /proc/stat r, + + # ---- /proc: own process only ---- + owner /proc/@{pid}/** r, + deny /proc/*/mem rwk, + + # ---- forbidden ---- + deny ptrace, + deny capability sys_ptrace, + deny capability sys_module, + deny capability sys_rawio, + deny /dev/kmem rwk, + deny /dev/mem rwk, + deny /dev/port rwk, + deny /sys/kernel/** w, + deny /etc/shadow r, + deny @{HOME}/.ssh/** rwk, + deny @{HOME}/.gnupg/** rwk, + + # ---- xdg / browser handoff for "Open in browser" UI button ---- + /usr/bin/xdg-open Pix, +} diff --git a/scripts/selinux/build-policy.sh b/scripts/selinux/build-policy.sh index c3724de..809f1ab 100755 --- a/scripts/selinux/build-policy.sh +++ b/scripts/selinux/build-policy.sh @@ -1,10 +1,43 @@ #!/usr/bin/env bash -# Build + load veilor-systemd SELinux policy module. +# Build + load veilor-os SELinux policy modules. +# +# Modules: +# veilor-systemd — capabilities for systemd-modules-load (post-boot lock) +# veilor-firstboot — confine /usr/local/sbin/veilor-firstboot one-shot +# +# Usage: +# sudo ./build-policy.sh # build + install all +# sudo ./build-policy.sh # build + install one module set -euo pipefail cd "$(dirname "$0")" -checkmodule -M -m -o veilor-systemd.mod veilor-systemd.te -semodule_package -o veilor-systemd.pp -m veilor-systemd.mod -semodule -i veilor-systemd.pp -echo "[OK] veilor-systemd SELinux module loaded" +MODULES=(veilor-systemd veilor-firstboot) +if [[ $# -gt 0 ]]; then + MODULES=("$@") +fi + +for m in "${MODULES[@]}"; do + if [[ ! -f "$m.te" ]]; then + echo "[ERR] $m.te not found" >&2 + exit 1 + fi + echo "[*] Building $m ..." + checkmodule -M -m -o "$m.mod" "$m.te" + semodule_package -o "$m.pp" -m "$m.mod" + semodule -i "$m.pp" + echo "[OK] $m loaded" +done + +# Apply file context for veilor-firstboot if module just loaded. +if printf '%s\n' "${MODULES[@]}" | grep -qx veilor-firstboot; then + if command -v restorecon >/dev/null 2>&1; then + # Mark the binary + state file with the right types. + semanage fcontext -a -t veilor_firstboot_exec_t '/usr/local/sbin/veilor-firstboot' 2>/dev/null || true + semanage fcontext -a -t veilor_firstboot_state_t '/var/lib/veilor-firstboot\.done' 2>/dev/null || true + restorecon -v /usr/local/sbin/veilor-firstboot 2>/dev/null || true + [[ -e /var/lib/veilor-firstboot.done ]] && restorecon -v /var/lib/veilor-firstboot.done 2>/dev/null || true + fi +fi + +echo "[done] all modules loaded" diff --git a/scripts/selinux/veilor-firstboot.te b/scripts/selinux/veilor-firstboot.te new file mode 100644 index 0000000..66ff42b --- /dev/null +++ b/scripts/selinux/veilor-firstboot.te @@ -0,0 +1,136 @@ +policy_module(veilor-firstboot, 1.0) +# +# veilor-os SELinux module — confine veilor-firstboot.service. +# +# The firstboot service runs once on TTY1 before SDDM, prompts for the +# admin password, then enables SDDM and self-disables. It is privileged +# (it must be — `passwd` writes /etc/shadow) but the surface is small and +# bounded. This module narrows what the service is allowed to do so that a +# bug or hostile env in firstboot.sh can't, e.g., dial out, scrape /home, +# or load a kernel module. +# +# Build + load: +# cd scripts/selinux +# ./build-policy.sh # builds & loads all .te modules +# +# Verify: +# semodule -l | grep veilor-firstboot +# ls -Z /usr/local/sbin/veilor-firstboot +# -> system_u:object_r:veilor_firstboot_exec_t:s0 +# +# Audit any denials with: +# ausearch -m AVC -ts recent -c veilor-firstboot + +require { + type init_t; + type passwd_exec_t; + type passwd_file_t; + type shadow_t; + type systemd_unit_file_t; + type systemd_passwd_var_run_t; + type sddm_unit_file_t; + type sddm_var_lib_t; + type tmp_t; + type tty_device_t; + type devtty_t; + type self_runtime_t; + type chkpwd_exec_t; + type pam_var_run_t; + type security_t; + type fs_t; + type usr_t; + type bin_t; + type lib_t; + type etc_t; + type proc_t; + type unconfined_service_t; + class file { read write create unlink getattr setattr open execute execute_no_trans map }; + class dir { read write add_name remove_name search getattr open }; + class chr_file { read write open getattr ioctl }; + class capability { setuid setgid chown dac_override dac_read_search fowner fsetid }; + class process { transition signal sigchld sigkill noatsecure rlimitinh siginh }; + class service { start stop status enable disable }; + class systemd { start }; + class lnk_file { read getattr }; + class filesystem { getattr }; +} + +# --------------------------------------------------------------------- +# 1. Define the firstboot domain + executable type +# --------------------------------------------------------------------- +type veilor_firstboot_t; +type veilor_firstboot_exec_t; +type veilor_firstboot_state_t; # /var/lib/veilor-firstboot.done + +init_daemon_domain(veilor_firstboot_t, veilor_firstboot_exec_t) +files_type(veilor_firstboot_state_t) + +# Auto-transition: when init_t executes /usr/local/sbin/veilor-firstboot, +# enter veilor_firstboot_t. +domain_auto_trans(init_t, veilor_firstboot_exec_t, veilor_firstboot_t) + +# --------------------------------------------------------------------- +# 2. Allow rules — what the service IS allowed to do +# --------------------------------------------------------------------- + +# read /etc/passwd, /etc/group, /etc/shadow (passwd needs shadow write) +allow veilor_firstboot_t passwd_file_t:file { read getattr open }; +allow veilor_firstboot_t shadow_t:file { read write open getattr setattr }; + +# exec passwd(1) +allow veilor_firstboot_t passwd_exec_t:file { read getattr open execute execute_no_trans map }; +allow veilor_firstboot_t chkpwd_exec_t:file { read getattr open execute execute_no_trans map }; + +# capabilities passwd needs +allow veilor_firstboot_t self:capability { setuid setgid chown dac_override dac_read_search fowner fsetid }; + +# write the state marker /var/lib/veilor-firstboot.done +allow veilor_firstboot_t veilor_firstboot_state_t:file { create write open getattr setattr unlink }; +allow veilor_firstboot_t veilor_firstboot_state_t:dir { search write add_name remove_name }; + +# write /etc/sddm.conf.d/ entries (autologin disable, theme, etc.) +allow veilor_firstboot_t sddm_var_lib_t:dir { read write search add_name remove_name open }; +allow veilor_firstboot_t sddm_var_lib_t:file { read write create open getattr setattr }; + +# start sddm.service via systemctl +allow veilor_firstboot_t sddm_unit_file_t:file { read getattr open }; +allow veilor_firstboot_t sddm_unit_file_t:service { start status enable disable }; +allow veilor_firstboot_t init_t:system { start }; + +# tty1 I/O +allow veilor_firstboot_t tty_device_t:chr_file { read write open getattr ioctl }; +allow veilor_firstboot_t devtty_t:chr_file { read write open getattr ioctl }; + +# usual base reads +allow veilor_firstboot_t bin_t:file { read getattr open execute execute_no_trans map }; +allow veilor_firstboot_t lib_t:file { read getattr open execute execute_no_trans map }; +allow veilor_firstboot_t usr_t:file { read getattr open }; +allow veilor_firstboot_t etc_t:file { read getattr open }; +allow veilor_firstboot_t etc_t:dir { read search getattr open }; +allow veilor_firstboot_t fs_t:filesystem getattr; +allow veilor_firstboot_t self:fifo_file { read write }; +allow veilor_firstboot_t self:unix_stream_socket { create connect read write }; + +# --------------------------------------------------------------------- +# 3. Deny rules — what the service is NOT allowed to do +# --------------------------------------------------------------------- + +# no network — firstboot must never phone home +neverallow veilor_firstboot_t self:tcp_socket *; +neverallow veilor_firstboot_t self:udp_socket *; +neverallow veilor_firstboot_t self:rawip_socket *; +neverallow veilor_firstboot_t self:packet_socket *; +neverallow veilor_firstboot_t self:netlink_route_socket *; + +# no kernel module load +neverallow veilor_firstboot_t self:capability sys_module; + +# no /home access except the bits ferror-firstboot.sh writes (admin's +# .config dir staging, if any). /home/admin general read = forbidden. +neverallow veilor_firstboot_t home_root_t:dir { read write }; +neverallow veilor_firstboot_t user_home_t:dir { read write search }; +neverallow veilor_firstboot_t user_home_t:file { read write open }; + +# no ptrace, no /dev/mem, no /dev/kmem +neverallow veilor_firstboot_t self:capability sys_ptrace; +neverallow veilor_firstboot_t self:capability sys_rawio;