3.10.2 DAC Neutralisation

Linux evaluates DAC — UID, GID and mode-bit checks — before consulting LSM hooks. If DAC denies an operation the hook never fires, and KACS cannot override a DAC denial: LSM hooks are restrictive, able to further deny what DAC would allow but never to grant what DAC has refused.

KACS therefore neutralises DAC so the hooks always fire. Every process receives a set of Linux capabilities that bypass the DAC gates, and those capabilities are mandatory substrate rather than grants.

3.10.2.1 The capability switchboard #

Linux's capabilities fall into three categories, and security_capable() is authoritative for all of them — the raw capability sets on struct cred are compatibility-visible state that answers nothing.

ALLOW capabilities exist to override UID-based permission checks on operations KACS enforces through its own hooks, so DAC never blocks something KACS will evaluate independently:

CAPNameRationale
0CAP_CHOWNKACS file hooks enforce.
1CAP_DAC_OVERRIDEKACS file hooks enforce.
2CAP_DAC_READ_SEARCHKACS file hooks enforce.
3CAP_FOWNERKACS file hooks enforce.
4CAP_FSETIDKACS file hooks enforce.
5CAP_KILLThe task_kill hook enforces.
6CAP_SETGIDCosmetic under KACS.
7CAP_SETUIDCosmetic under KACS.
11CAP_NET_BROADCASTUnused in modern kernels.
15CAP_IPC_OWNERKACS IPC hooks enforce.
28CAP_LEASEKACS file hooks enforce.

PRIVILEGE capabilities gate operations no other KACS hook covers, and map to a KACS privilege:

CAPNamePrivilege
9CAP_LINUX_IMMUTABLESeTcbPrivilege
10CAP_NET_BIND_SERVICESeBindPrivilegedPortPrivilege
12CAP_NET_ADMINSeTcbPrivilege
13CAP_NET_RAWSeTcbPrivilege
14CAP_IPC_LOCKSeLockMemoryPrivilege
16CAP_SYS_MODULESeLoadDriverPrivilege
17CAP_SYS_RAWIOSeTcbPrivilege
18CAP_SYS_CHROOTSeTcbPrivilege
19CAP_SYS_PTRACESeDebugPrivilege
20CAP_SYS_PACCTSeTcbPrivilege
21CAP_SYS_ADMINSeTcbPrivilege (but see the mount note below)
22CAP_SYS_BOOTSeShutdownPrivilege
23CAP_SYS_NICESeIncreaseBasePriorityPrivilege
24CAP_SYS_RESOURCESeIncreaseQuotaPrivilege
25CAP_SYS_TIMESeSystemtimePrivilege
26CAP_SYS_TTY_CONFIGSeTcbPrivilege
27CAP_MKNODSeTcbPrivilege
29CAP_AUDIT_WRITESeAuditPrivilege
30CAP_AUDIT_CONTROLSeSecurityPrivilege
33CAP_MAC_ADMINSeSecurityPrivilege
34CAP_SYSLOGSeTcbPrivilege
35CAP_WAKE_ALARMSeTcbPrivilege
36CAP_BLOCK_SUSPENDSeTcbPrivilege
37CAP_AUDIT_READSeSecurityPrivilege
38CAP_PERFMONSeSystemProfilePrivilege or SeProfileSingleProcessPrivilege or SeLoadDriverPrivilege
39CAP_BPFSeTcbPrivilege
40CAP_CHECKPOINT_RESTORESeTcbPrivilege

CAP_PERFMON is the one OR-mapped entry: the Linux capability genuinely spans several Peios privilege tiers, and no single privilege covers everything it gates. The check succeeds if the caller holds any of the three, and every one it holds is marked used. Per-operation enforcement then happens at the relevant syscall hook, which checks the specific privilege the specific operation needs (§3.7). OR-mapping stops the capability ceiling manufacturing false denials; it grants nothing the holder does not already have.

CAP_SYS_ADMIN maps to SeTcbPrivilege and is not OR-mapped, which would be the obvious way to let administrators mount and is the wrong one: CAP_SYS_ADMIN gates dozens of unrelated operations, so widening it would hand out far more than mounting.

Mounting is handled outside the capability table instead. may_mount() (fs/namespace.c, patched) calls pkm_kacs_may_manage_volumes(), which accepts SeManageVolumePrivilege or SeTcbPrivilege, before falling back to the ordinary CAP_SYS_ADMIN check. Every other CAP_SYS_ADMIN caller still needs the TCB.

It has to be asked there rather than through the sb_mount LSM hook: may_mount()'s capability check runs before security_sb_mount(), so an LSM is never consulted about a mount the capability check already refused. A hook can narrow that decision; it cannot widen it.

CAP_SYS_BOOT carries an extra condition the table cannot express: a token whose logon session is of a remote origin — Network, NetworkCleartext or NewCredentials — additionally requires SeRemoteShutdownPrivilege.

DENY capabilities are refused unconditionally, whatever privilege the caller holds: CAP_SETPCAP (8) and CAP_SETFCAP (31), because capabilities are dead under KACS, and CAP_MAC_OVERRIDE (32), because KACS is the active LSM and must not be bypassable.

An unmapped or unknown capability is denied by default. The switchboard fails closed.

3.10.2.2 Compatibility state #

Programs may inspect the credential capability sets with capget() or /proc/<pid>/status, and may attempt to mutate the non-ALLOW subset with capset() or prctl(). None of that is authoritative.

capget() and /proc/<pid>/status report the ALLOW substrate as present in the effective, permitted and inheritable sets — reported as CapEff, CapPrm and CapInh, and additionally CapBnd, by the proc interface. Non-ALLOW bits present in the credential state may also be reported, but grant no authority. CapAmb reports raw Linux ambient state; the ALLOW substrate does not depend on ambient capabilities.

The strict invariant is that the ALLOW set is mandatory substrate and has to survive wherever Linux capability mechanics would otherwise drop it out from under KACS. capset() rejects any request clearing an ALLOW capability from the effective, permitted or inheritable sets, and bounding-set drops and ambient manipulation reject anything that would clear or exclude one. The implementation is slightly stricter than that: an ambient raise of an ALLOW capability is refused too, not only a clear.

After that validation, capset() follows ordinary Linux ambient behaviour — ambient bits no longer present in both the requested permitted and inheritable sets may be cleared. Because requests clearing ALLOW bits from permitted or inheritable are denied outright, that intersection can never indirectly clear an existing ALLOW ambient bit.

Direct mutation of non-ALLOW state is therefore compatibility-only. It may change what capget() reports and cannot change the authority answer for any capability-gated operation.

3.10.2.3 Neutralised native paths #

Native commoncap helpers that make raw capability-subset decisions before a KACS hook are neutralised where KACS has an authoritative hook of its own. That covers the subset gates in ptrace access, PTRACE_TRACEME, and task_setnice, task_setscheduler and task_setioprio — each replaced by an unconditional allow, leaving the KACS process-descriptor and PIP hooks to decide. Capability checks that reach security_capable() directly stay under the switchboard.

For raw xattr operations the FACS metadata hooks are authoritative, so the native security-xattr capability prechecks that would run first are skipped. This does not revive Linux file capabilities: installing or replacing non-empty security.capability data stays denied by the dead CAP_SETFCAP policy, with the single exception of the KACS-owned StrataFS clone (§3.9.7), and exec-time file-capability grants remain suppressed. Removing stale metadata goes through the ordinary FILE_WRITE_EA path.

One structural wrinkle: security_capable() reaches the KACS switchboard twice — once through the patched commoncap entry point and once through the KACS capable hook — so a privilege consulted this way is marked used twice. The authorization answer is unaffected; the privilege-use accounting double-counts.

3.10.2.4 The LSM stack #

MAC LSMs — SELinux, AppArmor, SMACK, TOMOYO — and the BPF LSM have to be disabled. They would independently deny operations from their own label and policy systems, undermining KACS's claim to be the sole identity-based authorization mechanism and FACS's to be the sole file access authority. Non-MAC LSMs are permitted: landlock, lockdown, yama and integrity make no identity-based access decisions and stack safely.

The check is made at initialisation and KACS refuses to activate if it fails — but it is a build-configuration test rather than an inspection of the live LSM stack. It tests whether each conflicting LSM is enabled in the kernel config, and never parses CONFIG_LSM or enumerates what is actually registered.

Edit this page