diff --git a/src/context/context.rs b/src/context/context.rs index 6d723f4..a0825ac 100644 --- a/src/context/context.rs +++ b/src/context/context.rs @@ -153,0 +154,3 @@ pub struct Context { + /// Capability bitmask — derived from euid by procmgr: euid==0 → CAP_ALL, else 0. + pub caps: u64, + @@ -159,0 +163,6 @@ pub struct Context { +impl Context { + pub fn has_cap(&self, cap: u64) -> bool { + self.caps & cap == cap + } +} + @@ -485,0 +495 @@ impl Context { + caps: self.caps, diff --git a/src/scheme/acpi.rs b/src/scheme/acpi.rs index 5d73469..7e1558a 100644 --- a/src/scheme/acpi.rs +++ b/src/scheme/acpi.rs @@ -142 +142 @@ impl KernelScheme for AcpiScheme { - if ctx.uid != 0 { + if !ctx.has_cap(crate::scheme::caps::CAP_ACPI) { diff --git a/src/scheme/caps.rs b/src/scheme/caps.rs new file mode 100644 index 0000000..6886e88 --- /dev/null +++ b/src/scheme/caps.rs @@ -0,0 +1,29 @@ +//! Kernel capability bitmask for fine-grained privilege control. +//! +//! Each capability is a single bit in a `u64`. Processes with `euid == 0` +//! (via procmgr SetResugid) receive `CAP_ALL`. Non-root processes receive `0` +//! by default. Future work: explicit capability assignment via proc scheme. + +/// Register or unregister kernel schemes. +pub const CAP_SCHEME_REGISTER: u64 = 1 << 0; +/// Map physical memory (scheme:memory/physical). +pub const CAP_PHYS_MEM: u64 = 1 << 1; +/// Allocate IRQ vectors (scheme:irq). +pub const CAP_IRQ: u64 = 1 << 2; +/// Access ACPI tables (scheme:acpi). +pub const CAP_ACPI: u64 = 1 << 3; +/// Use kernel debugger (scheme:debug). +pub const CAP_SYS_DEBUG: u64 = 1 << 4; +/// Write to arbitrary files / sys:action (scheme:sys write). +pub const CAP_SYS_WRITE: u64 = 1 << 5; +/// Read/write model-specific registers (scheme:msr). +pub const CAP_SYS_MSR: u64 = 1 << 6; +/// Access PS/2 keyboard/mouse (scheme:serio). +pub const CAP_SERIO: u64 = 1 << 7; +/// Change file ownership (scheme:user chown). +pub const CAP_CHOWN: u64 = 1 << 8; +/// Modify process attributes: setuid/setgid, ptrace, signal to arbitrary procs. +pub const CAP_PROC_ATTR: u64 = 1 << 9; + +/// All capabilities set — assigned to euid == 0 processes. +pub const CAP_ALL: u64 = !0u64; diff --git a/src/scheme/debug.rs b/src/scheme/debug.rs index 4a23b3c..ae9a96a 100644 --- a/src/scheme/debug.rs +++ b/src/scheme/debug.rs @@ -76 +76 @@ impl KernelScheme for DebugScheme { - if ctx.uid != 0 { + if !ctx.has_cap(crate::scheme::caps::CAP_SYS_DEBUG) { diff --git a/src/scheme/irq.rs b/src/scheme/irq.rs index 4222960..bf99a85 100644 --- a/src/scheme/irq.rs +++ b/src/scheme/irq.rs @@ -259 +259 @@ impl crate::scheme::KernelScheme for IrqScheme { - if ctx.uid != 0 { + if !ctx.has_cap(crate::scheme::caps::CAP_IRQ) { diff --git a/src/scheme/memory.rs b/src/scheme/memory.rs index c2f9f47..146c461 100644 --- a/src/scheme/memory.rs +++ b/src/scheme/memory.rs @@ -235 +235 @@ impl KernelScheme for MemoryScheme { - if ctx.uid != 0 + if !ctx.has_cap(crate::scheme::caps::CAP_PHYS_MEM) diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 765e547..96826de 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -81,0 +82,2 @@ pub mod sys; +pub mod caps; + @@ -356 +358 @@ impl KernelScheme for SchemeList { - if caller.uid != 0 { + if !caller.has_cap(caps::CAP_SCHEME_REGISTER) { @@ -813,0 +816 @@ pub struct CallerCtx { + pub caps: u64, @@ -815,0 +819,3 @@ impl CallerCtx { + pub fn has_cap(&self, cap: u64) -> bool { + self.caps & cap == cap + } @@ -822,0 +829 @@ impl CallerCtx { + caps: self.caps, diff --git a/src/scheme/serio.rs b/src/scheme/serio.rs index 2650502..8e32c98 100644 --- a/src/scheme/serio.rs +++ b/src/scheme/serio.rs @@ -82 +82 @@ impl KernelScheme for SerioScheme { - if ctx.uid != 0 { + if !ctx.has_cap(crate::scheme::caps::CAP_SERIO) { diff --git a/src/scheme/sys/mod.rs b/src/scheme/sys/mod.rs index 9eb3564..902ab5a 100644 --- a/src/scheme/sys/mod.rs +++ b/src/scheme/sys/mod.rs @@ -144 +144 @@ impl KernelScheme for SysScheme { - if ctx.uid != 0 { + if !ctx.has_cap(crate::scheme::caps::CAP_SYS_MSR) { @@ -170 +170 @@ impl KernelScheme for SysScheme { - if matches!(entry.1, Wr(_)) && ctx.uid != 0 { + if matches!(entry.1, Wr(_)) && !ctx.has_cap(crate::scheme::caps::CAP_SYS_WRITE) { diff --git a/src/scheme/user.rs b/src/scheme/user.rs index dfbf66b..e215b8d 100644 --- a/src/scheme/user.rs +++ b/src/scheme/user.rs @@ -1593 +1593 @@ impl KernelScheme for UserScheme { - if cx.euid != 0 && (uid != cx.euid || gid != cx.egid) { + if !cx.has_cap(crate::scheme::caps::CAP_CHOWN) && (uid != cx.euid || gid != cx.egid) { diff --git a/src/startup/mod.rs b/src/startup/mod.rs index 86aabc2..4af65a3 100644 --- a/src/startup/mod.rs +++ b/src/startup/mod.rs @@ -190,0 +191 @@ pub(crate) fn kmain(bootstrap: Bootstrap) -> ! { + context.caps = crate::scheme::caps::CAP_ALL;