[starnix][selinux] Create a clearer layout for the LSM/SELinux impl
The kernel's "selinux" subdirectory is renamed "security" to reflect
that the hooks and data structures it provides are in principle generic,
not tied to a specific choice of Linux Security Module.
Within the "security" directory a subdirectory holds the SELinux-specific
integration for the various hooks; since SELinux is the only LSM built
into Starnix some aspects are currently (re)published from the "security"
module.
The SELinux and procattr filesystems remain in the "security" directory
for now; the latter will be migrated to interface to SELinux via hooks,
similar to other parts of the kernel, and moved into the kernel's "fs"
module.
Bug: 335397745
Change-Id: Ia6ac8d0d794da5c2aed56d8f1b06d49235ba0d32
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1030212
Reviewed-by: Mark Dittmer <markdittmer@google.com>
Fuchsia-Auto-Submit: Wez <wez@google.com>
Reviewed-by: James Robinson <jamesr@google.com>
Commit-Queue: Wez <wez@google.com>
diff --git a/src/starnix/kernel/BUILD.gn b/src/starnix/kernel/BUILD.gn
index f5707a2..f113830 100644
--- a/src/starnix/kernel/BUILD.gn
+++ b/src/starnix/kernel/BUILD.gn
@@ -175,11 +175,10 @@
"power/suspend_stats.rs",
"power/sync_on_suspend.rs",
"power/wakeup_count.rs",
- "selinux/fs.rs",
- "selinux/hooks/current_task_hooks.rs",
- "selinux/hooks/mod.rs",
- "selinux/hooks/thread_group_hooks.rs",
- "selinux/mod.rs",
+ "security/fs.rs",
+ "security/hooks.rs",
+ "security/mod.rs",
+ "security/selinux_hooks/mod.rs",
"signals/mod.rs",
"signals/signal_handling.rs",
"signals/signalfd.rs",
diff --git a/src/starnix/kernel/device/binder.rs b/src/starnix/kernel/device/binder.rs
index 1368f95..4188c05 100644
--- a/src/starnix/kernel/device/binder.rs
+++ b/src/starnix/kernel/device/binder.rs
@@ -12,6 +12,7 @@
MemoryAccessorExt, ProtectionFlags,
},
mutable_state::Guard,
+ security,
task::{
CurrentTask, EventHandler, Kernel, SchedulerPolicy, SimpleWaiter, Task, WaitCanceler,
WaitQueue, Waiter,
@@ -3504,15 +3505,10 @@
let target_task = weak_task.upgrade().ok_or_else(|| TransactionError::Dead)?;
let security_context: Option<FsString> =
if object.flags.contains(BinderObjectFlags::TXN_SECURITY_CTX) {
- let security_server = target_task
- .kernel()
- .security_server
- .as_ref()
- .expect("SELinux is not enabled");
- let sid = target_task.thread_group.read().selinux_state.current_sid.clone();
- let mut security_context = security_server
- .sid_to_security_context(sid)
- .map_or(FsString::default(), FsString::from);
+ let mut security_context = FsString::from(
+ security::get_task_context(¤t_task, &target_task)
+ .unwrap_or_default(),
+ );
security_context.push(b'\0');
Some(security_context)
} else {
diff --git a/src/starnix/kernel/fs/proc/pid_directory.rs b/src/starnix/kernel/fs/proc/pid_directory.rs
index c79c249..d534c90 100644
--- a/src/starnix/kernel/fs/proc/pid_directory.rs
+++ b/src/starnix/kernel/fs/proc/pid_directory.rs
@@ -4,7 +4,7 @@
use crate::{
mm::{MemoryAccessor, MemoryAccessorExt, ProcMapsFile, ProcSmapsFile, PAGE_SIZE},
- selinux::fs::selinux_proc_attrs,
+ security::fs::selinux_proc_attrs,
task::{CurrentTask, Task, TaskPersistentInfo, TaskStateCode, ThreadGroup},
vfs::{
buffers::{InputBuffer, OutputBuffer},
@@ -276,6 +276,7 @@
// owned by the effective user and effective group ID of the process."
dir.entry_creds(task.creds().euid_as_fscred());
dir.dir_creds(task.creds().euid_as_fscred());
+ // TODO(b/322850635): Add get/set_procattr hooks and move procattr impl here.
selinux_proc_attrs(current_task, task, dir);
});
dir.entry(current_task, "ns", NsDirectory { task: task.into() }, mode!(IFDIR, 0o777));
diff --git a/src/starnix/kernel/lib.rs b/src/starnix/kernel/lib.rs
index bb328a8..5446dace 100644
--- a/src/starnix/kernel/lib.rs
+++ b/src/starnix/kernel/lib.rs
@@ -15,7 +15,7 @@
pub mod mm;
pub mod mutable_state;
pub mod power;
-pub mod selinux;
+pub mod security;
pub mod signals;
pub mod syscalls;
pub mod task;
diff --git a/src/starnix/kernel/loader.rs b/src/starnix/kernel/loader.rs
index 7965427..b143bfe2 100644
--- a/src/starnix/kernel/loader.rs
+++ b/src/starnix/kernel/loader.rs
@@ -7,7 +7,7 @@
vmo::round_up_to_system_page_size, DesiredAddress, MappingName, MappingOptions,
MemoryAccessor, MemoryManager, ProtectionFlags, PAGE_SIZE, VMEX_RESOURCE,
},
- selinux::hooks::thread_group_hooks::SeLinuxResolvedElfState,
+ security,
task::CurrentTask,
vfs::{FileHandle, FileWriteGuardMode, FileWriteGuardRef},
};
@@ -249,7 +249,7 @@
/// The environment to initialize for the new process.
pub environ: Vec<CString>,
/// The SELinux state for the new process. None if SELinux is disabled.
- pub selinux_state: Option<SeLinuxResolvedElfState>,
+ pub security_state: Option<security::ResolvedElfState>,
/// Exec/write lock.
pub file_write_guard: FileWriteGuardRef,
}
@@ -278,13 +278,13 @@
path: CString,
argv: Vec<CString>,
environ: Vec<CString>,
- selinux_state: Option<SeLinuxResolvedElfState>,
+ security_state: Option<security::ResolvedElfState>,
) -> Result<ResolvedElf, Errno>
where
L: LockBefore<FileOpsCore>,
L: LockBefore<DeviceOpen>,
{
- resolve_executable_impl(locked, current_task, file, path, argv, environ, 0, selinux_state)
+ resolve_executable_impl(locked, current_task, file, path, argv, environ, 0, security_state)
}
/// Resolves a file into a validated executable ELF, following script interpreters to a fixed
@@ -297,7 +297,7 @@
argv: Vec<CString>,
environ: Vec<CString>,
recursion_depth: usize,
- selinux_state: Option<SeLinuxResolvedElfState>,
+ security_state: Option<security::ResolvedElfState>,
) -> Result<ResolvedElf, Errno>
where
L: LockBefore<FileOpsCore>,
@@ -324,10 +324,10 @@
argv,
environ,
recursion_depth,
- selinux_state,
+ security_state,
)
} else {
- resolve_elf(locked, current_task, file, vmo, argv, environ, selinux_state)
+ resolve_elf(locked, current_task, file, vmo, argv, environ, security_state)
}
}
@@ -340,7 +340,7 @@
argv: Vec<CString>,
environ: Vec<CString>,
recursion_depth: usize,
- selinux_state: Option<SeLinuxResolvedElfState>,
+ security_state: Option<security::ResolvedElfState>,
) -> Result<ResolvedElf, Errno>
where
L: LockBefore<FileOpsCore>,
@@ -374,7 +374,7 @@
args,
environ,
recursion_depth + 1,
- selinux_state,
+ security_state,
)
}
@@ -424,7 +424,7 @@
vmo: Arc<zx::Vmo>,
argv: Vec<CString>,
environ: Vec<CString>,
- selinux_state: Option<SeLinuxResolvedElfState>,
+ security_state: Option<security::ResolvedElfState>,
) -> Result<ResolvedElf, Errno>
where
L: LockBefore<FileOpsCore>,
@@ -456,7 +456,7 @@
};
let file_write_guard =
file.name.entry.node.create_write_guard(FileWriteGuardMode::Exec)?.into_ref();
- Ok(ResolvedElf { file, vmo, interp, argv, environ, selinux_state, file_write_guard })
+ Ok(ResolvedElf { file, vmo, interp, argv, environ, security_state, file_write_guard })
}
/// Loads a resolved ELF into memory, along with an interpreter if one is defined, and initializes
diff --git a/src/starnix/kernel/selinux/OWNERS b/src/starnix/kernel/security/OWNERS
similarity index 100%
rename from src/starnix/kernel/selinux/OWNERS
rename to src/starnix/kernel/security/OWNERS
diff --git a/src/starnix/kernel/selinux/fs.rs b/src/starnix/kernel/security/fs.rs
similarity index 96%
rename from src/starnix/kernel/selinux/fs.rs
rename to src/starnix/kernel/security/fs.rs
index 117af40..9daaba9 100644
--- a/src/starnix/kernel/selinux/fs.rs
+++ b/src/starnix/kernel/security/fs.rs
@@ -663,20 +663,20 @@
}
};
- // SELinux is enabled, so the task must have `selinux_state`. Lock it for writing
+ // SELinux is enabled, so the task must have `security_state`. Lock it for writing
// and update it.
let mut tg = task.thread_group.write();
use SeProcAttrNodeType::*;
match self.attr {
- Current => tg.selinux_state.current_sid = sid.ok_or(errno!(EINVAL))?,
- Exec => tg.selinux_state.exec_sid = sid,
- FsCreate => tg.selinux_state.fscreate_sid = sid,
- KeyCreate => tg.selinux_state.keycreate_sid = sid,
+ Current => tg.security_state.0.current_sid = sid.ok_or(errno!(EINVAL))?,
+ Exec => tg.security_state.0.exec_sid = sid,
+ FsCreate => tg.security_state.0.fscreate_sid = sid,
+ KeyCreate => tg.security_state.0.keycreate_sid = sid,
Previous => {
return error!(EINVAL);
}
- SockCreate => tg.selinux_state.sockcreate_sid = sid,
+ SockCreate => tg.security_state.0.sockcreate_sid = sid,
};
Ok(())
@@ -693,12 +693,12 @@
let sid = {
let tg = task.thread_group.read();
match self.attr {
- Current => Some(tg.selinux_state.current_sid),
- Exec => tg.selinux_state.exec_sid,
- FsCreate => tg.selinux_state.fscreate_sid,
- KeyCreate => tg.selinux_state.keycreate_sid,
- Previous => Some(tg.selinux_state.previous_sid),
- SockCreate => tg.selinux_state.sockcreate_sid,
+ Current => Some(tg.security_state.0.current_sid),
+ Exec => tg.security_state.0.exec_sid,
+ FsCreate => tg.security_state.0.fscreate_sid,
+ KeyCreate => tg.security_state.0.keycreate_sid,
+ Previous => Some(tg.security_state.0.previous_sid),
+ SockCreate => tg.security_state.0.sockcreate_sid,
}
};
diff --git a/src/starnix/kernel/selinux/hooks/current_task_hooks.rs b/src/starnix/kernel/security/hooks.rs
similarity index 86%
rename from src/starnix/kernel/selinux/hooks/current_task_hooks.rs
rename to src/starnix/kernel/security/hooks.rs
index 73b7f18f..ff0f54c 100644
--- a/src/starnix/kernel/selinux/hooks/current_task_hooks.rs
+++ b/src/starnix/kernel/security/hooks.rs
@@ -2,19 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-use std::sync::Arc;
-
-use super::thread_group_hooks::{self, SeLinuxResolvedElfState};
+use super::{selinux_hooks, ResolvedElfState, ThreadGroupState};
use crate::{
- task::{CurrentTask, Task, ThreadGroup},
+ task::{CurrentTask, Kernel, Task, ThreadGroup},
vfs::{FsNode, FsNodeHandle, FsStr, ValueOrSize},
};
-use selinux::{
- security_server::{SecurityServer, SecurityServerStatus},
- InitialSid, SecurityId,
+use {
+ selinux::{
+ security_server::{SecurityServer, SecurityServerStatus},
+ InitialSid, SecurityId,
+ },
+ starnix_uapi::{error, errors::Errno, signals::Signal},
+ std::sync::Arc,
};
-use starnix_uapi::{errors::Errno, signals::Signal};
/// Maximum supported size for the `"security.selinux"` value used to store SELinux security
/// contexts in a filesystem node extended attributes.
@@ -73,11 +74,38 @@
})
}
+/// Returns an `ThreadGroupState` instance for a new task.
+pub fn alloc_security(kernel: &Kernel, parent: Option<&ThreadGroupState>) -> ThreadGroupState {
+ ThreadGroupState(if kernel.security_server.is_none() {
+ selinux_hooks::ThreadGroupState::for_selinux_disabled()
+ } else {
+ selinux_hooks::alloc_security(parent.map(|tgs| &tgs.0))
+ })
+}
+
+fn get_current_sid(thread_group: &Arc<ThreadGroup>) -> SecurityId {
+ thread_group.read().security_state.0.current_sid
+}
+
+/// Returns the serialized Security Context associated with the specified task.
+/// If the task's current SID cannot be resolved then an empty string is returned.
+/// This combines the `task_getsecid()` and `secid_to_secctx()` hooks, in effect.
+pub fn get_task_context(current_task: &CurrentTask, target: &Task) -> Result<Vec<u8>, Errno> {
+ run_if_selinux_else(
+ current_task,
+ |security_server| {
+ let sid = get_current_sid(&target.thread_group);
+ Ok(security_server.sid_to_security_context(sid).unwrap_or_default())
+ },
+ || error!(ENOTSUP),
+ )
+}
+
/// Check if creating a task is allowed.
pub fn check_task_create_access(current_task: &CurrentTask) -> Result<(), Errno> {
check_if_selinux(current_task, |security_server| {
- let sid = current_task.get_current_sid();
- thread_group_hooks::check_task_create_access(&security_server.as_permission_check(), sid)
+ let sid = get_current_sid(¤t_task.thread_group);
+ selinux_hooks::check_task_create_access(&security_server.as_permission_check(), sid)
})
}
@@ -85,28 +113,29 @@
pub fn check_exec_access(
current_task: &CurrentTask,
executable_node: &FsNodeHandle,
-) -> Result<Option<SeLinuxResolvedElfState>, Errno> {
+) -> Result<Option<ResolvedElfState>, Errno> {
check_if_selinux(current_task, |security_server| {
let executable_sid = executable_node.effective_sid(current_task);
let group_state = current_task.thread_group.read();
- thread_group_hooks::check_exec_access(
+ selinux_hooks::check_exec_access(
&security_server,
- &group_state.selinux_state,
+ &group_state.security_state.0,
executable_sid,
)
+ .map(|s| s.map(|s| ResolvedElfState(s)))
})
}
/// Updates the SELinux thread group state on exec.
pub fn update_state_on_exec(
current_task: &mut CurrentTask,
- elf_selinux_state: &Option<SeLinuxResolvedElfState>,
+ elf_security_state: &Option<ResolvedElfState>,
) {
run_if_selinux(current_task, |_| {
let mut thread_group_state = current_task.thread_group.write();
- thread_group_hooks::update_state_on_exec(
- &mut thread_group_state.selinux_state,
- elf_selinux_state,
+ selinux_hooks::update_state_on_exec(
+ &mut thread_group_state.security_state.0,
+ elf_security_state.as_ref().map(|s| s.0),
);
});
}
@@ -116,9 +145,9 @@
check_if_selinux(source, |security_server| {
// TODO(b/323856891): Consider holding `source.thread_group` and `target.thread_group`
// read locks for duration of access check.
- let source_sid = source.get_current_sid();
- let target_sid = target.get_current_sid();
- thread_group_hooks::check_getsched_access(
+ let source_sid = get_current_sid(&source.thread_group);
+ let target_sid = get_current_sid(&target.thread_group);
+ selinux_hooks::check_getsched_access(
&security_server.as_permission_check(),
source_sid,
target_sid,
@@ -129,9 +158,9 @@
/// Checks if setsched is allowed.
pub fn check_setsched_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
check_if_selinux(source, |security_server| {
- let source_sid = source.get_current_sid();
- let target_sid = target.get_current_sid();
- thread_group_hooks::check_setsched_access(
+ let source_sid = get_current_sid(&source.thread_group);
+ let target_sid = get_current_sid(&target.thread_group);
+ selinux_hooks::check_setsched_access(
&security_server.as_permission_check(),
source_sid,
target_sid,
@@ -140,11 +169,11 @@
}
/// Checks if getpgid is allowed.
-pub fn check_getpgid_access(source_task: &CurrentTask, target_task: &Task) -> Result<(), Errno> {
- check_if_selinux(source_task, |security_server| {
- let source_sid = source_task.get_current_sid();
- let target_sid = target_task.get_current_sid();
- thread_group_hooks::check_getpgid_access(
+pub fn check_getpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
+ check_if_selinux(source, |security_server| {
+ let source_sid = get_current_sid(&source.thread_group);
+ let target_sid = get_current_sid(&target.thread_group);
+ selinux_hooks::check_getpgid_access(
&security_server.as_permission_check(),
source_sid,
target_sid,
@@ -153,11 +182,11 @@
}
/// Checks if setpgid is allowed.
-pub fn check_setpgid_access(source_task: &CurrentTask, target_task: &Task) -> Result<(), Errno> {
- check_if_selinux(source_task, |security_server| {
- let source_sid = source_task.get_current_sid();
- let target_sid = target_task.get_current_sid();
- thread_group_hooks::check_setpgid_access(
+pub fn check_setpgid_access(source: &CurrentTask, target: &Task) -> Result<(), Errno> {
+ check_if_selinux(source, |security_server| {
+ let source_sid = get_current_sid(&source.thread_group);
+ let target_sid = get_current_sid(&target.thread_group);
+ selinux_hooks::check_setpgid_access(
&security_server.as_permission_check(),
source_sid,
target_sid,
@@ -167,14 +196,14 @@
/// Checks if sending a signal is allowed.
pub fn check_signal_access(
- source_task: &CurrentTask,
- target_task: &Task,
+ source: &CurrentTask,
+ target: &Task,
signal: Signal,
) -> Result<(), Errno> {
- check_if_selinux(source_task, |security_server| {
- let source_sid = source_task.get_current_sid();
- let target_sid = target_task.get_current_sid();
- thread_group_hooks::check_signal_access(
+ check_if_selinux(source, |security_server| {
+ let source_sid = get_current_sid(&source.thread_group);
+ let target_sid = get_current_sid(&target.thread_group);
+ selinux_hooks::check_signal_access(
&security_server.as_permission_check(),
source_sid,
target_sid,
@@ -190,12 +219,12 @@
current_task: &CurrentTask,
) -> Result<(), Errno> {
check_if_selinux(current_task, |security_server| {
- let tracer_sid = parent.get_current_sid();
+ let tracer_sid = get_current_sid(parent);
let mut thread_group_state = current_task.thread_group.write();
- thread_group_hooks::check_ptrace_access_and_update_state(
+ selinux_hooks::check_ptrace_access_and_update_state(
&security_server.as_permission_check(),
tracer_sid,
- &mut thread_group_state.selinux_state,
+ &mut thread_group_state.security_state.0,
)
})
}
@@ -207,12 +236,12 @@
tracee_task: &Task,
) -> Result<(), Errno> {
check_if_selinux(current_task, |security_server| {
- let tracer_sid = current_task.get_current_sid();
+ let tracer_sid = get_current_sid(¤t_task.thread_group);
let mut thread_group_state = tracee_task.thread_group.write();
- thread_group_hooks::check_ptrace_access_and_update_state(
+ selinux_hooks::check_ptrace_access_and_update_state(
&security_server.as_permission_check(),
tracer_sid,
- &mut thread_group_state.selinux_state,
+ &mut thread_group_state.security_state.0,
)
})
}
@@ -221,7 +250,7 @@
pub fn clear_ptracer_sid(tracee_task: &Task) {
run_if_selinux(tracee_task, |_| {
let mut thread_group_state = tracee_task.thread_group.write();
- thread_group_state.selinux_state.ptracer_sid = None;
+ thread_group_state.security_state.0.ptracer_sid = None;
});
}
@@ -308,13 +337,12 @@
use selinux::security_server::Mode;
use starnix_sync::{Locked, Unlocked};
use starnix_uapi::{device_type::DeviceType, error, file_mode::FileMode, signals::SIGTERM};
- use tests::thread_group_hooks::SeLinuxThreadGroupState;
const VALID_SECURITY_CONTEXT: &'static str = "u:object_r:test_valid_t:s0";
const DIFFERENT_VALID_SECURITY_CONTEXT: &'static str = "u:object_r:test_different_valid_t:s0";
const HOOKS_TESTS_BINARY_POLICY: &[u8] =
- include_bytes!("../../../lib/selinux/testdata/micro_policies/hooks_tests_policy.pp");
+ include_bytes!("../../lib/selinux/testdata/micro_policies/hooks_tests_policy.pp");
fn security_server_with_policy(mode: Mode) -> Arc<SecurityServer> {
let policy_bytes = HOOKS_TESTS_BINARY_POLICY.to_vec();
@@ -415,6 +443,13 @@
assert_eq!(run_else_result, TestHookResult::WasRun);
}
+ #[fuchsia::test]
+ async fn alloc_security_selinux_disabled() {
+ let (kernel, _current_task) = create_kernel_and_task();
+
+ alloc_security(&kernel, None);
+ }
+
fn failing_hook(_: &Arc<SecurityServer>) -> Result<(), Errno> {
error!(EINVAL)
}
@@ -506,13 +541,13 @@
// Without SELinux enabled and a policy loaded, only `InitialSid` values exist
// in the system.
let kernel_sid = SecurityId::initial(InitialSid::Kernel);
- let elf_state = SeLinuxResolvedElfState { sid: kernel_sid };
+ let elf_state = ResolvedElfState(kernel_sid);
- assert!(task.thread_group.read().selinux_state.current_sid != kernel_sid);
+ assert!(task.thread_group.read().security_state.0.current_sid != kernel_sid);
- let before_hook_sid = task.thread_group.read().selinux_state.current_sid;
+ let before_hook_sid = task.thread_group.read().security_state.0.current_sid;
update_state_on_exec(&mut task, &Some(elf_state));
- assert_eq!(task.thread_group.read().selinux_state.current_sid, before_hook_sid);
+ assert_eq!(task.thread_group.read().security_state.0.current_sid, before_hook_sid);
}
#[fuchsia::test]
@@ -523,21 +558,21 @@
// Without SELinux enabled and a policy loaded, only `InitialSid` values exist
// in the system.
- let initial_state = SeLinuxThreadGroupState::for_kernel();
+ let initial_state = selinux_hooks::ThreadGroupState::for_kernel();
let elf_sid = SecurityId::initial(InitialSid::Unlabeled);
- let elf_state = SeLinuxResolvedElfState { sid: elf_sid };
+ let elf_state = ResolvedElfState(elf_sid);
assert_ne!(elf_sid, initial_state.current_sid);
update_state_on_exec(&mut task, &Some(elf_state));
- assert_eq!(task.thread_group.read().selinux_state, initial_state);
+ assert_eq!(task.thread_group.read().security_state.0, initial_state);
}
#[fuchsia::test]
async fn state_update_for_fake_mode() {
let security_server = security_server_with_policy(Mode::Fake);
- let initial_state = SeLinuxThreadGroupState::for_kernel();
+ let initial_state = selinux_hooks::ThreadGroupState::for_kernel();
let (kernel, task) = create_kernel_and_task_with_selinux(security_server);
let mut task = task;
- task.thread_group.write().selinux_state = initial_state.clone();
+ task.thread_group.write().security_state.0 = initial_state.clone();
let elf_sid = kernel
.security_server
@@ -545,30 +580,30 @@
.expect("missing security server")
.security_context_to_sid(b"u:object_r:fork_no_t:s0")
.expect("invalid security context");
- let elf_state = SeLinuxResolvedElfState { sid: elf_sid };
+ let elf_state = ResolvedElfState(elf_sid);
assert_ne!(elf_sid, initial_state.current_sid);
update_state_on_exec(&mut task, &Some(elf_state));
- assert_eq!(task.thread_group.read().selinux_state.current_sid, elf_sid);
+ assert_eq!(task.thread_group.read().security_state.0.current_sid, elf_sid);
}
#[fuchsia::test]
async fn state_update_for_permissive_mode() {
let security_server = security_server_with_policy(Mode::Enable);
security_server.set_enforcing(false);
- let initial_state = SeLinuxThreadGroupState::for_kernel();
+ let initial_state = selinux_hooks::ThreadGroupState::for_kernel();
let (kernel, task) = create_kernel_and_task_with_selinux(security_server);
let mut task = task;
- task.thread_group.write().selinux_state = initial_state.clone();
+ task.thread_group.write().security_state.0 = initial_state.clone();
let elf_sid = kernel
.security_server
.as_ref()
.expect("missing security server")
.security_context_to_sid(b"u:object_r:fork_no_t:s0")
.expect("invalid security context");
- let elf_state = SeLinuxResolvedElfState { sid: elf_sid };
+ let elf_state = ResolvedElfState(elf_sid);
assert_ne!(elf_sid, initial_state.current_sid);
update_state_on_exec(&mut task, &Some(elf_state));
- assert_eq!(task.thread_group.read().selinux_state.current_sid, elf_sid);
+ assert_eq!(task.thread_group.read().security_state.0.current_sid, elf_sid);
}
#[fuchsia::test]
@@ -711,11 +746,11 @@
let security_server = security_server_with_policy(Mode::Enable);
security_server.set_enforcing(true);
let (_kernel, tracee_task) = create_kernel_and_task_with_selinux(security_server);
- tracee_task.thread_group.write().selinux_state.ptracer_sid =
+ tracee_task.thread_group.write().security_state.0.ptracer_sid =
Some(SecurityId::initial(InitialSid::Unlabeled));
clear_ptracer_sid(tracee_task.as_ref());
- assert!(tracee_task.thread_group.read().selinux_state.ptracer_sid.is_none());
+ assert!(tracee_task.thread_group.read().security_state.0.ptracer_sid.is_none());
}
#[fuchsia::test]
diff --git a/src/starnix/kernel/security/mod.rs b/src/starnix/kernel/security/mod.rs
new file mode 100644
index 0000000..7c106c9
--- /dev/null
+++ b/src/starnix/kernel/security/mod.rs
@@ -0,0 +1,32 @@
+// Copyright 2024 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/// This module provides types and hook APIs supporting Linux Security Modules
+/// functionality in Starnix. LSM provides a generic set of hooks, and opaque
+/// types, used to decouple the rest of the kernel from the details of any
+/// specific security enforcement subsystem (e.g. SELinux, POSIX.1e, etc).
+///
+/// Although this module is hard-wired to the SELinux implementation, callers
+/// should treat the types as opaque; hook implementations necessarily have access
+/// to kernel structures, but not the other way around.
+use selinux::SecurityId;
+
+/// SELinux implementations called by the LSM hooks.
+mod selinux_hooks;
+
+/// Linux Security Modules hooks for use within the Starnix kernel.
+mod hooks;
+pub use hooks::*;
+
+/// Opaque structure encapsulating security state for a `ThreadGroup`.
+#[derive(Debug)]
+pub struct ThreadGroupState(selinux_hooks::ThreadGroupState);
+
+/// Opaque structure holding security state associated with a `ResolvedElf` instance.
+#[derive(Debug, PartialEq)]
+pub struct ResolvedElfState(SecurityId);
+
+// TODO(b/322850635): Create a clean separation between the procattr filesystem, and LSM hooks.
+// TODO(b/335397745): Move the SELinux filesystem bits under the selinux directory.
+pub mod fs;
diff --git a/src/starnix/kernel/selinux/hooks/thread_group_hooks.rs b/src/starnix/kernel/security/selinux_hooks/mod.rs
similarity index 84%
rename from src/starnix/kernel/selinux/hooks/thread_group_hooks.rs
rename to src/starnix/kernel/security/selinux_hooks/mod.rs
index f65df7c..840bf64 100644
--- a/src/starnix/kernel/selinux/hooks/thread_group_hooks.rs
+++ b/src/starnix/kernel/security/selinux_hooks/mod.rs
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-use crate::task::Kernel;
-
use selinux::{
permission_check::PermissionCheck, security_server::SecurityServer, InitialSid, SecurityId,
};
@@ -17,7 +15,7 @@
use std::sync::Arc;
/// Checks if creating a task is allowed.
-pub(crate) fn check_task_create_access(
+pub(super) fn check_task_create_access(
permission_check: &impl PermissionCheck,
task_sid: SecurityId,
) -> Result<(), Errno> {
@@ -29,13 +27,13 @@
/// Checks the SELinux permissions required for exec. Returns the SELinux state of a resolved
/// elf if all required permissions are allowed.
-pub(crate) fn check_exec_access(
+pub(super) fn check_exec_access(
security_server: &Arc<SecurityServer>,
- selinux_state: &SeLinuxThreadGroupState,
+ security_state: &ThreadGroupState,
executable_sid: SecurityId,
-) -> Result<Option<SeLinuxResolvedElfState>, Errno> {
- let current_sid = selinux_state.current_sid;
- let new_sid = if let Some(exec_sid) = selinux_state.exec_sid {
+) -> Result<Option<SecurityId>, Errno> {
+ let current_sid = security_state.current_sid;
+ let new_sid = if let Some(exec_sid) = security_state.exec_sid {
// Use the proc exec SID if set.
exec_sid
} else {
@@ -67,32 +65,32 @@
log_debug!("entrypoint permission is denied, ignoring.");
}
// Check that ptrace permission is allowed if the process is traced.
- if let Some(ptracer_sid) = selinux_state.ptracer_sid {
+ if let Some(ptracer_sid) = security_state.ptracer_sid {
if !security_server.has_permission(ptracer_sid, new_sid, ProcessPermission::Ptrace) {
return error!(EACCES);
}
}
}
- Ok(Some(SeLinuxResolvedElfState { sid: new_sid }))
+ Ok(Some(new_sid))
}
/// Updates the SELinux thread group state on exec, using the security ID associated with the
/// resolved elf.
-pub(crate) fn update_state_on_exec(
- selinux_state: &mut SeLinuxThreadGroupState,
- elf_selinux_state: &Option<SeLinuxResolvedElfState>,
+pub(super) fn update_state_on_exec(
+ security_state: &mut ThreadGroupState,
+ elf_security_state: Option<SecurityId>,
) {
// TODO(http://b/316181721): check if the previous state needs to be updated regardless.
- if let Some(elf_selinux_state) = elf_selinux_state {
- selinux_state.previous_sid = selinux_state.current_sid;
- selinux_state.current_sid = elf_selinux_state.sid;
+ if let Some(elf_security_state) = elf_security_state {
+ security_state.previous_sid = security_state.current_sid;
+ security_state.current_sid = elf_security_state;
}
}
/// Checks if source with `source_sid` may exercise the "getsched" permission on target with
/// `target_sid` according to SELinux server status `status` and permission checker
/// `permission`.
-pub fn check_getsched_access(
+pub(super) fn check_getsched_access(
permission_check: &impl PermissionCheck,
source_sid: SecurityId,
target_sid: SecurityId,
@@ -102,7 +100,7 @@
/// Checks if the task with `source_sid` is allowed to set scheduling parameters for the task with
/// `target_sid`.
-pub(crate) fn check_setsched_access(
+pub(super) fn check_setsched_access(
permission_check: &impl PermissionCheck,
source_sid: SecurityId,
target_sid: SecurityId,
@@ -112,7 +110,7 @@
/// Checks if the task with `source_sid` is allowed to get the process group ID of the task with
/// `target_sid`.
-pub(crate) fn check_getpgid_access(
+pub(super) fn check_getpgid_access(
permission_check: &impl PermissionCheck,
source_sid: SecurityId,
target_sid: SecurityId,
@@ -122,7 +120,7 @@
/// Checks if the task with `source_sid` is allowed to set the process group ID of the task with
/// `target_sid`.
-pub(crate) fn check_setpgid_access(
+pub(super) fn check_setpgid_access(
permission_check: &impl PermissionCheck,
source_sid: SecurityId,
target_sid: SecurityId,
@@ -131,7 +129,7 @@
}
/// Checks if the task with `source_sid` is allowed to send `signal` to the task with `target_sid`.
-pub(crate) fn check_signal_access(
+pub(super) fn check_signal_access(
permission_check: &impl PermissionCheck,
source_sid: SecurityId,
target_sid: SecurityId,
@@ -157,20 +155,20 @@
}
/// Checks if the task with `source_sid` is allowed to trace the task with `target_sid`.
-pub(crate) fn check_ptrace_access_and_update_state(
+pub(super) fn check_ptrace_access_and_update_state(
permission_check: &impl PermissionCheck,
tracer_sid: SecurityId,
- tracee_selinux_state: &mut SeLinuxThreadGroupState,
+ tracee_security_state: &mut ThreadGroupState,
) -> Result<(), Errno> {
check_permission(
permission_check,
tracer_sid,
- tracee_selinux_state.current_sid,
+ tracee_security_state.current_sid,
ProcessPermission::Ptrace,
)
.and_then(|_| {
// If tracing is allowed, set the `ptracer_sid` of the tracee with the tracer's SID.
- tracee_selinux_state.ptracer_sid = Some(tracer_sid);
+ tracee_security_state.ptracer_sid = Some(tracer_sid);
Ok(())
})
}
@@ -188,23 +186,17 @@
}
}
-/// Returns an `SeLinuxThreadGroupState` instance for a new task.
-pub fn alloc_security(
- kernel: &Kernel,
- parent: Option<&SeLinuxThreadGroupState>,
-) -> SeLinuxThreadGroupState {
- if kernel.security_server.is_none() {
- return SeLinuxThreadGroupState::for_selinux_disabled();
- };
+/// Returns a `ThreadGroupState` instance for a new task.
+pub(super) fn alloc_security(parent: Option<&ThreadGroupState>) -> ThreadGroupState {
match parent {
Some(parent) => parent.clone(),
- None => SeLinuxThreadGroupState::for_kernel(),
+ None => ThreadGroupState::for_kernel(),
}
}
/// The SELinux security structure for `ThreadGroup`.
#[derive(Clone, Debug, PartialEq)]
-pub struct SeLinuxThreadGroupState {
+pub(super) struct ThreadGroupState {
/// Current SID for the task.
pub current_sid: SecurityId,
@@ -227,9 +219,9 @@
pub ptracer_sid: Option<SecurityId>,
}
-impl SeLinuxThreadGroupState {
+impl ThreadGroupState {
/// Returns initial state for the kernel's root thread group.
- pub(crate) fn for_kernel() -> Self {
+ pub(super) fn for_kernel() -> Self {
Self {
current_sid: SecurityId::initial(InitialSid::Kernel),
previous_sid: SecurityId::initial(InitialSid::Kernel),
@@ -242,7 +234,7 @@
}
/// Returns placeholder state for use when SELinux is not enabled.
- fn for_selinux_disabled() -> Self {
+ pub(super) fn for_selinux_disabled() -> Self {
Self {
current_sid: SecurityId::initial(InitialSid::Unlabeled),
previous_sid: SecurityId::initial(InitialSid::Unlabeled),
@@ -255,17 +247,9 @@
}
}
-/// The SELinux security structure for `ResolvedElf`.
-#[derive(Clone, Eq, PartialEq, Debug)]
-pub struct SeLinuxResolvedElfState {
- /// Security ID for the transformed process.
- pub sid: SecurityId,
-}
-
#[cfg(test)]
mod tests {
use super::*;
- use crate::testing::{create_kernel_and_task, create_kernel_and_task_with_selinux};
use selinux::security_server::Mode;
use starnix_uapi::signals::SIGTERM;
@@ -315,7 +299,7 @@
let executable_sid = security_server
.security_context_to_sid(b"u:object_r:executable_file_trans_t:s0")
.expect("invalid security context");
- let selinux_state = SeLinuxThreadGroupState {
+ let security_state = ThreadGroupState {
current_sid: current_sid,
exec_sid: Some(exec_sid),
fscreate_sid: None,
@@ -326,8 +310,8 @@
};
assert_eq!(
- check_exec_access(&security_server, &selinux_state, executable_sid),
- Ok(Some(SeLinuxResolvedElfState { sid: exec_sid }))
+ check_exec_access(&security_server, &security_state, executable_sid),
+ Ok(Some(exec_sid))
);
}
@@ -343,7 +327,7 @@
let executable_sid = security_server
.security_context_to_sid(b"u:object_r:executable_file_trans_t:s0")
.expect("invalid security context");
- let selinux_state = SeLinuxThreadGroupState {
+ let security_state = ThreadGroupState {
current_sid: current_sid,
exec_sid: Some(exec_sid),
fscreate_sid: None,
@@ -354,7 +338,7 @@
};
assert_eq!(
- check_exec_access(&security_server, &selinux_state, executable_sid),
+ check_exec_access(&security_server, &security_state, executable_sid),
error!(EACCES)
);
}
@@ -373,7 +357,7 @@
let executable_sid = security_server
.security_context_to_sid(b"u:object_r:executable_file_trans_no_entrypoint_t:s0")
.expect("invalid security context");
- let selinux_state = SeLinuxThreadGroupState {
+ let security_state = ThreadGroupState {
current_sid: current_sid,
exec_sid: Some(exec_sid),
fscreate_sid: None,
@@ -384,7 +368,7 @@
};
assert_eq!(
- check_exec_access(&security_server, &selinux_state, executable_sid),
+ check_exec_access(&security_server, &security_state, executable_sid),
error!(EACCES)
);
}
@@ -399,7 +383,7 @@
let executable_sid = security_server
.security_context_to_sid(b"u:object_r:executable_file_no_trans_t:s0")
.expect("invalid security context");
- let selinux_state = SeLinuxThreadGroupState {
+ let security_state = ThreadGroupState {
current_sid: current_sid,
exec_sid: None,
fscreate_sid: None,
@@ -410,8 +394,8 @@
};
assert_eq!(
- check_exec_access(&security_server, &selinux_state, executable_sid),
- Ok(Some(SeLinuxResolvedElfState { sid: current_sid }))
+ check_exec_access(&security_server, &security_state, executable_sid),
+ Ok(Some(current_sid))
);
}
@@ -426,7 +410,7 @@
let executable_sid = security_server
.security_context_to_sid(b"u:object_r:executable_file_no_trans_t:s0")
.expect("invalid security context");
- let selinux_state = SeLinuxThreadGroupState {
+ let security_state = ThreadGroupState {
current_sid: current_sid,
exec_sid: None,
fscreate_sid: None,
@@ -439,34 +423,33 @@
// There is no `execute_no_trans` allow statement from `current_sid` to `executable_sid`,
// expect access denied.
assert_eq!(
- check_exec_access(&security_server, &selinux_state, executable_sid),
+ check_exec_access(&security_server, &security_state, executable_sid),
error!(EACCES)
);
}
#[fuchsia::test]
fn no_state_update_if_no_elf_state() {
- let initial_state = SeLinuxThreadGroupState::for_kernel();
- let mut selinux_state = initial_state.clone();
- update_state_on_exec(&mut selinux_state, &None);
- assert_eq!(selinux_state, initial_state);
+ let initial_state = ThreadGroupState::for_kernel();
+ let mut security_state = initial_state.clone();
+ update_state_on_exec(&mut security_state, None);
+ assert_eq!(security_state, initial_state);
}
#[fuchsia::test]
fn state_is_updated_on_exec() {
let security_server = security_server_with_policy();
- let initial_state = SeLinuxThreadGroupState::for_kernel();
- let mut selinux_state = initial_state.clone();
+ let initial_state = ThreadGroupState::for_kernel();
+ let mut security_state = initial_state.clone();
let elf_sid = security_server
.security_context_to_sid(b"u:object_r:test_valid_t:s0")
.expect("invalid security context");
- let elf_state = SeLinuxResolvedElfState { sid: elf_sid };
assert_ne!(elf_sid, initial_state.current_sid);
- update_state_on_exec(&mut selinux_state, &Some(elf_state));
+ update_state_on_exec(&mut security_state, Some(elf_sid));
assert_eq!(
- selinux_state,
- SeLinuxThreadGroupState {
+ security_state,
+ ThreadGroupState {
current_sid: elf_sid,
exec_sid: initial_state.exec_sid,
fscreate_sid: initial_state.fscreate_sid,
@@ -692,7 +675,7 @@
let tracee_sid = security_server
.security_context_to_sid(b"u:object_r:test_ptrace_traced_t:s0")
.expect("invalid security context");
- let initial_state = SeLinuxThreadGroupState {
+ let initial_state = ThreadGroupState {
current_sid: tracee_sid.clone(),
exec_sid: None,
fscreate_sid: None,
@@ -713,7 +696,7 @@
);
assert_eq!(
tracee_state,
- SeLinuxThreadGroupState {
+ ThreadGroupState {
current_sid: initial_state.current_sid,
exec_sid: initial_state.exec_sid,
fscreate_sid: initial_state.fscreate_sid,
@@ -734,7 +717,7 @@
let tracee_sid = security_server
.security_context_to_sid(b"u:object_r:test_ptrace_traced_t:s0")
.expect("invalid security context");
- let initial_state = SeLinuxThreadGroupState {
+ let initial_state = ThreadGroupState {
current_sid: tracee_sid.clone(),
exec_sid: None,
fscreate_sid: None,
@@ -757,20 +740,11 @@
}
#[fuchsia::test]
- async fn alloc_security_selinux_disabled() {
- let (kernel, _current_task) = create_kernel_and_task();
-
- alloc_security(&kernel, None);
- }
-
- #[fuchsia::test]
async fn alloc_security_no_parent() {
- let security_server = SecurityServer::new(Mode::Fake);
- let (kernel, _current_task) = create_kernel_and_task_with_selinux(security_server);
- let selinux_state = alloc_security(&kernel, None);
+ let security_state = alloc_security(None);
assert_eq!(
- selinux_state,
- SeLinuxThreadGroupState {
+ security_state,
+ ThreadGroupState {
current_sid: SecurityId::initial(InitialSid::Kernel),
previous_sid: SecurityId::initial(InitialSid::Kernel),
exec_sid: None,
@@ -784,18 +758,15 @@
#[fuchsia::test]
async fn alloc_security_from_parent() {
- let security_server = SecurityServer::new(Mode::Fake);
- let (kernel, _current_task) = create_kernel_and_task_with_selinux(security_server);
-
// Create a fake parent state, with values for some fields, to check for.
- let mut parent_selinux_state = alloc_security(&kernel, None);
- parent_selinux_state.current_sid = SecurityId::initial(InitialSid::Unlabeled);
- parent_selinux_state.exec_sid = Some(SecurityId::initial(InitialSid::Unlabeled));
- parent_selinux_state.fscreate_sid = Some(SecurityId::initial(InitialSid::Unlabeled));
- parent_selinux_state.keycreate_sid = Some(SecurityId::initial(InitialSid::Unlabeled));
- parent_selinux_state.sockcreate_sid = Some(SecurityId::initial(InitialSid::Unlabeled));
+ let mut parent_security_state = alloc_security(None);
+ parent_security_state.current_sid = SecurityId::initial(InitialSid::Unlabeled);
+ parent_security_state.exec_sid = Some(SecurityId::initial(InitialSid::Unlabeled));
+ parent_security_state.fscreate_sid = Some(SecurityId::initial(InitialSid::Unlabeled));
+ parent_security_state.keycreate_sid = Some(SecurityId::initial(InitialSid::Unlabeled));
+ parent_security_state.sockcreate_sid = Some(SecurityId::initial(InitialSid::Unlabeled));
- let selinux_state = alloc_security(&kernel, Some(&parent_selinux_state));
- assert_eq!(selinux_state, parent_selinux_state);
+ let security_state = alloc_security(Some(&parent_security_state));
+ assert_eq!(security_state, parent_security_state);
}
}
diff --git a/src/starnix/kernel/selinux/hooks/mod.rs b/src/starnix/kernel/selinux/hooks/mod.rs
deleted file mode 100644
index e8cfdfe..0000000
--- a/src/starnix/kernel/selinux/hooks/mod.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2024 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// The hooks modules implement SELinux hooks to control and enforce access decisions, and define
-// SELinux security structs associated to objects in the system, holding state information used
-// by hooks to make access decisions.
-
-pub mod current_task_hooks;
-pub mod thread_group_hooks;
diff --git a/src/starnix/kernel/selinux/mod.rs b/src/starnix/kernel/selinux/mod.rs
deleted file mode 100644
index d71555f..0000000
--- a/src/starnix/kernel/selinux/mod.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright 2023 The Fuchsia Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-pub mod fs;
-pub mod hooks;
diff --git a/src/starnix/kernel/signals/syscalls.rs b/src/starnix/kernel/signals/syscalls.rs
index 8f15f46..b9a8fa6 100644
--- a/src/starnix/kernel/signals/syscalls.rs
+++ b/src/starnix/kernel/signals/syscalls.rs
@@ -6,7 +6,7 @@
use super::signalfd::SignalFd;
use crate::{
mm::{MemoryAccessor, MemoryAccessorExt},
- selinux::hooks::current_task_hooks as selinux_hooks,
+ security,
signals::{
restore_from_signal_handler, send_signal, SignalDetail, SignalInfo, SignalInfoHeader,
SI_HEADER_SIZE,
@@ -338,7 +338,7 @@
}
let signal = Signal::try_from(unchecked_signal)?;
- selinux_hooks::check_signal_access(current_task, &target, signal)?;
+ security::check_signal_access(current_task, &target, signal)?;
send_signal(
target,
@@ -371,7 +371,7 @@
}
let signal = Signal::try_from(unchecked_signal)?;
- selinux_hooks::check_signal_access(current_task, &target, signal)?;
+ security::check_signal_access(current_task, &target, signal)?;
let siginfo = read_siginfo(current_task, signal, siginfo_ref)?;
if target.get_pid() != current_task.get_pid() && (siginfo.code >= 0 || siginfo.code == SI_TKILL)
diff --git a/src/starnix/kernel/task/current_task.rs b/src/starnix/kernel/task/current_task.rs
index 3bd6eda..33ffe3a 100644
--- a/src/starnix/kernel/task/current_task.rs
+++ b/src/starnix/kernel/task/current_task.rs
@@ -11,7 +11,7 @@
fs::proc::pid_directory::TaskDirectory,
loader::{load_executable, resolve_executable, ResolvedElf},
mm::{MemoryAccessor, MemoryAccessorExt, MemoryManager, TaskMemoryAccessor},
- selinux::hooks::current_task_hooks as selinux_hooks,
+ security,
signals::{send_signal_first, send_standard_signal, RunState, SignalActions, SignalInfo},
task::{
ExitStatus, Kernel, PidTable, ProcessGroup, PtraceCoreState, PtraceEvent, PtraceEventData,
@@ -831,7 +831,7 @@
// used in the `open` call.
executable.name.check_access(self, Access::EXEC)?;
- let elf_selinux_state = selinux_hooks::check_exec_access(self, executable.node())?;
+ let elf_security_state = security::check_exec_access(self, executable.node())?;
let resolved_elf = resolve_executable(
locked,
@@ -840,7 +840,7 @@
path.clone(),
argv,
environ,
- elf_selinux_state,
+ elf_security_state,
)?;
if self.thread_group.read().tasks_count() > 1 {
@@ -878,7 +878,7 @@
.map_err(|status| from_status_like_fdio!(status))?;
// Update the SELinux state, if enabled.
- selinux_hooks::update_state_on_exec(self, &resolved_elf.selinux_state);
+ security::update_state_on_exec(self, &resolved_elf.security_state);
let start_info = load_executable(self, resolved_elf, &path)?;
let regs: zx_thread_state_general_regs_t = start_info.into();
diff --git a/src/starnix/kernel/task/ptrace.rs b/src/starnix/kernel/task/ptrace.rs
index 3a19af7..4268557 100644
--- a/src/starnix/kernel/task/ptrace.rs
+++ b/src/starnix/kernel/task/ptrace.rs
@@ -5,7 +5,7 @@
use crate::{
arch::execution::new_syscall_from_state,
mm::{DumpPolicy, MemoryAccessor, MemoryAccessorExt},
- selinux::hooks::current_task_hooks as selinux_hooks,
+ security,
signals::{
send_signal_first, send_standard_signal, syscalls::WaitingOptions, SignalDetail,
SignalInfo, SignalInfoHeader, SI_HEADER_SIZE,
@@ -703,7 +703,7 @@
if let Err(x) = ptrace_cont(&tracee, &data, true) {
return Err(x);
}
- selinux_hooks::clear_ptracer_sid(tracee);
+ security::clear_ptracer_sid(tracee);
let tid = tracee.get_tid();
thread_group.ptracees.lock().remove(&tid);
thread_group.write().zombie_ptracees.retain(&mut |zombie: &ZombieProcess| zombie.pid != tid);
@@ -1038,7 +1038,7 @@
let parent = current_task.thread_group.read().parent.clone();
if let Some(parent) = parent {
- selinux_hooks::check_ptrace_traceme_access_and_update_state(&parent, current_task)?;
+ security::check_ptrace_traceme_access_and_update_state(&parent, current_task)?;
let task_ref = OwnedRef::temp(¤t_task.task);
do_attach(&parent, (&task_ref).into(), PtraceAttachType::Attach, PtraceOptions::empty())?;
Ok(starnix_syscalls::SUCCESS)
@@ -1062,7 +1062,7 @@
let weak_task = current_task.kernel().pids.read().get_task(pid);
let tracee = weak_task.upgrade().ok_or_else(|| errno!(ESRCH))?;
- selinux_hooks::check_ptrace_attach_access_and_update_state(¤t_task, &tracee)?;
+ security::check_ptrace_attach_access_and_update_state(¤t_task, &tracee)?;
if tracee.thread_group == current_task.thread_group {
return error!(EPERM);
diff --git a/src/starnix/kernel/task/syscalls.rs b/src/starnix/kernel/task/syscalls.rs
index 7148b4c..59f5dfd 100644
--- a/src/starnix/kernel/task/syscalls.rs
+++ b/src/starnix/kernel/task/syscalls.rs
@@ -12,7 +12,7 @@
use crate::{
execution::execute_task,
mm::{DumpPolicy, MemoryAccessor, MemoryAccessorExt, PAGE_SIZE},
- selinux::hooks::current_task_hooks as selinux_hooks,
+ security,
task::{
max_priority_for_sched_policy, min_priority_for_sched_policy, ptrace_attach,
ptrace_dispatch, ptrace_traceme, CurrentTask, ExitStatus, PtraceAllowedPtracers,
@@ -73,7 +73,7 @@
L: LockBefore<MmDumpable>,
L: LockBefore<TaskRelease>,
{
- selinux_hooks::check_task_create_access(current_task)?;
+ security::check_task_create_access(current_task)?;
let child_exit_signal = if args.exit_signal == 0 {
None
@@ -394,7 +394,7 @@
let weak = get_task_or_current(current_task, pid);
let task = Task::from_weak(&weak)?;
- selinux_hooks::check_getpgid_access(current_task, &task)?;
+ security::check_getpgid_access(current_task, &task)?;
let pgid = task.thread_group.read().process_group.leader;
Ok(pgid)
}
@@ -408,7 +408,7 @@
let weak = get_task_or_current(current_task, pid);
let task = Task::from_weak(&weak)?;
- selinux_hooks::check_setpgid_access(current_task, &task)?;
+ security::check_setpgid_access(current_task, &task)?;
current_task.thread_group.setpgid(locked, &task, pgid)?;
Ok(())
}
@@ -734,7 +734,7 @@
let weak = get_task_or_current(current_task, pid);
let target_task = Task::from_weak(&weak)?;
- selinux_hooks::check_getsched_access(current_task, target_task.as_ref())?;
+ security::check_getsched_access(current_task, target_task.as_ref())?;
let current_policy = target_task.read().scheduler_policy;
Ok(current_policy.raw_policy())
}
@@ -754,7 +754,7 @@
let target_task = Task::from_weak(&weak)?;
let rlimit = target_task.thread_group.get_rlimit(Resource::RTPRIO);
- selinux_hooks::check_setsched_access(current_task, &target_task)?;
+ security::check_setsched_access(current_task, &target_task)?;
let param: sched_param = current_task.read_object(param.into())?;
let policy = SchedulerPolicy::from_sched_params(policy, param, rlimit)?;
target_task.set_scheduler_policy(policy)?;
diff --git a/src/starnix/kernel/task/task.rs b/src/starnix/kernel/task/task.rs
index 915a7cc..ebe5a5d 100644
--- a/src/starnix/kernel/task/task.rs
+++ b/src/starnix/kernel/task/task.rs
@@ -21,7 +21,6 @@
};
use macro_rules_attribute::apply;
use once_cell::sync::OnceCell;
-use selinux::SecurityId;
use starnix_logging::{log_debug, log_warn, set_zx_name};
use starnix_sync::{LockBefore, Locked, MmDumpable, Mutex, RwLock, TaskRelease};
use starnix_uapi::{
@@ -1265,11 +1264,6 @@
logging_span.clone()
}
- /// Get the SELinux security ID of the current task, or `None` if not set.
- pub fn get_current_sid(&self) -> SecurityId {
- self.thread_group.read().selinux_state.current_sid
- }
-
fn update_logging_span(&self, debug_info: &starnix_logging::TaskDebugInfo) {
let logging_span =
self.logging_span.get_or_init(|| starnix_logging::Span::new(&debug_info));
diff --git a/src/starnix/kernel/task/thread_group.rs b/src/starnix/kernel/task/thread_group.rs
index 3a0a618..71dc4bd 100644
--- a/src/starnix/kernel/task/thread_group.rs
+++ b/src/starnix/kernel/task/thread_group.rs
@@ -5,7 +5,7 @@
use crate::{
device::terminal::{ControllingSession, Terminal},
mutable_state::{state_accessor, state_implementation},
- selinux::hooks::thread_group_hooks,
+ security,
signals::{
send_signal, send_standard_signal, syscalls::WaitingOptions, SignalActions, SignalDetail,
SignalInfo,
@@ -22,7 +22,6 @@
use fuchsia_zircon as zx;
use itertools::Itertools;
use macro_rules_attribute::apply;
-use selinux::SecurityId;
use starnix_lifecycle::{AtomicU64Counter, DropNotifier};
use starnix_logging::{log_error, log_warn, track_stub};
use starnix_sync::{LockBefore, Locked, Mutex, MutexGuard, ProcessGroupState, RwLock};
@@ -112,8 +111,8 @@
pub terminating: bool,
- /// The SELinux operations for this thread group.
- pub selinux_state: thread_group_hooks::SeLinuxThreadGroupState,
+ /// The Linux Security Modules state for this thread group.
+ pub security_state: security::ThreadGroupState,
/// Time statistics accumulated from the children.
pub children_time_stats: TaskTimeStats,
@@ -376,8 +375,8 @@
{
let timers = TimerTable::new();
let itimer_real_id = timers.create(CLOCK_REALTIME as ClockId, None).unwrap();
- let selinux_state =
- thread_group_hooks::alloc_security(&kernel, parent.as_ref().map(|p| &p.selinux_state));
+ let security_state =
+ security::alloc_security(&kernel, parent.as_ref().map(|p| &p.security_state));
let mut thread_group = ThreadGroup {
kernel,
process,
@@ -409,7 +408,7 @@
last_signal: None,
leader_exit_info: None,
terminating: false,
- selinux_state,
+ security_state,
children_time_stats: Default::default(),
personality: parent.as_ref().map(|p| p.personality).unwrap_or(Default::default()),
allowed_ptracers: PtraceAllowedPtracers::None,
@@ -1294,15 +1293,6 @@
}
None
}
-
- /// Get the SELinux security ID of the thread group.
- /// Returns a placeholder value if SELinux is not enabled.
- pub fn get_current_sid(&self) -> SecurityId {
- // TODO(http://b/316181721): to avoid TOCTOU issues, once initial security contexts are
- // propagated to tasks in the system, in some cases using this API will need to be replaced
- // with call sites holding the state lock while making updates.
- self.mutable_state.read().selinux_state.current_sid
- }
}
#[apply(state_implementation!)]
diff --git a/src/starnix/kernel/vfs/fs_node.rs b/src/starnix/kernel/vfs/fs_node.rs
index acd2c4b..16a6093 100644
--- a/src/starnix/kernel/vfs/fs_node.rs
+++ b/src/starnix/kernel/vfs/fs_node.rs
@@ -5,7 +5,7 @@
use crate::{
device::DeviceMode,
mm::PAGE_SIZE,
- selinux::hooks::current_task_hooks::{get_fs_node_security_id, post_setxattr},
+ security::{get_fs_node_security_id, post_setxattr},
signals::{send_standard_signal, SignalInfo},
task::{CurrentTask, Kernel, WaitQueue, Waiter},
time::utc,
diff --git a/src/starnix/kernel/vfs/namespace.rs b/src/starnix/kernel/vfs/namespace.rs
index a95c3ac..069148f 100644
--- a/src/starnix/kernel/vfs/namespace.rs
+++ b/src/starnix/kernel/vfs/namespace.rs
@@ -10,7 +10,7 @@
overlayfs::OverlayFs, proc::proc_fs, sysfs::sys_fs, tmpfs::TmpFs, tracefs::trace_fs,
},
mutable_state::{state_accessor, state_implementation},
- selinux::fs::selinux_fs,
+ security::fs::selinux_fs,
task::{CurrentTask, EventHandler, Kernel, Task, WaitCanceler, Waiter},
time::utc,
vfs::{