From edc1412cc87f04e840074eb4d68362fadebe2849 Mon Sep 17 00:00:00 2001 From: Weijie Liu Date: Wed, 5 Jun 2024 22:17:19 +0800 Subject: [PATCH] Add /proc/sys/kernel/cap_last_cap support --- kernel/aster-nix/src/fs/procfs/mod.rs | 6 +++ kernel/aster-nix/src/fs/procfs/self_.rs | 8 +++- .../src/fs/procfs/sys/kernel/cap_last_cap.rs | 29 ++++++++++++ .../aster-nix/src/fs/procfs/sys/kernel/mod.rs | 46 +++++++++++++++++++ kernel/aster-nix/src/fs/procfs/sys/mod.rs | 41 +++++++++++++++++ .../src/process/credentials/capabilities.rs | 6 +++ kernel/aster-nix/src/syscall/capset.rs | 5 +- 7 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 kernel/aster-nix/src/fs/procfs/sys/kernel/cap_last_cap.rs create mode 100644 kernel/aster-nix/src/fs/procfs/sys/kernel/mod.rs create mode 100644 kernel/aster-nix/src/fs/procfs/sys/mod.rs diff --git a/kernel/aster-nix/src/fs/procfs/mod.rs b/kernel/aster-nix/src/fs/procfs/mod.rs index beecbc758..d9b9450bf 100644 --- a/kernel/aster-nix/src/fs/procfs/mod.rs +++ b/kernel/aster-nix/src/fs/procfs/mod.rs @@ -2,6 +2,8 @@ use core::sync::atomic::{AtomicU64, Ordering}; +use sys::SysDirOps; + use self::{ pid::PidDirOps, self_::SelfSymOps, @@ -16,6 +18,7 @@ use crate::{ mod pid; mod self_; +mod sys; mod template; /// Magic number. @@ -91,6 +94,8 @@ impl DirOps for RootDirOps { fn lookup_child(&self, this_ptr: Weak, name: &str) -> Result> { let child = if name == "self" { SelfSymOps::new_inode(this_ptr.clone()) + } else if name == "sys" { + SysDirOps::new_inode(this_ptr.clone()) } else if let Ok(pid) = name.parse::() { let process_ref = process_table::get_process(pid).ok_or_else(|| Error::new(Errno::ENOENT))?; @@ -108,6 +113,7 @@ impl DirOps for RootDirOps { }; let mut cached_children = this.cached_children().write(); cached_children.put_entry_if_not_found("self", || SelfSymOps::new_inode(this_ptr.clone())); + cached_children.put_entry_if_not_found("sys", || SysDirOps::new_inode(this_ptr.clone())); for process in process_table::process_table().iter() { let pid = process.pid().to_string(); diff --git a/kernel/aster-nix/src/fs/procfs/self_.rs b/kernel/aster-nix/src/fs/procfs/self_.rs index 0fa34b3f7..7008644b4 100644 --- a/kernel/aster-nix/src/fs/procfs/self_.rs +++ b/kernel/aster-nix/src/fs/procfs/self_.rs @@ -1,6 +1,12 @@ // SPDX-License-Identifier: MPL-2.0 -use super::*; +use crate::{ + fs::{ + procfs::{ProcSymBuilder, SymOps}, + utils::Inode, + }, + prelude::*, +}; /// Represents the inode at `/proc/self`. pub struct SelfSymOps; diff --git a/kernel/aster-nix/src/fs/procfs/sys/kernel/cap_last_cap.rs b/kernel/aster-nix/src/fs/procfs/sys/kernel/cap_last_cap.rs new file mode 100644 index 000000000..d730a05e7 --- /dev/null +++ b/kernel/aster-nix/src/fs/procfs/sys/kernel/cap_last_cap.rs @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MPL-2.0 + +use alloc::format; + +use crate::{ + fs::{ + procfs::template::{FileOps, ProcFileBuilder}, + utils::Inode, + }, + prelude::*, + process::credentials::capabilities::CapSet, +}; + +/// Represents the inode at `/proc/sys/kernel/cap_last_cap`. +pub struct CapLastCapFileOps; + +impl CapLastCapFileOps { + pub fn new_inode(parent: Weak) -> Arc { + ProcFileBuilder::new(Self).parent(parent).build().unwrap() + } +} + +impl FileOps for CapLastCapFileOps { + fn data(&self) -> Result> { + let cap_last_cap_value = CapSet::most_significant_bit(); + let output = format!("{}\n", cap_last_cap_value); + Ok(output.into_bytes()) + } +} diff --git a/kernel/aster-nix/src/fs/procfs/sys/kernel/mod.rs b/kernel/aster-nix/src/fs/procfs/sys/kernel/mod.rs new file mode 100644 index 000000000..c16d8f61d --- /dev/null +++ b/kernel/aster-nix/src/fs/procfs/sys/kernel/mod.rs @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MPL-2.0 + +use crate::{ + fs::{ + procfs::{ + sys::kernel::cap_last_cap::CapLastCapFileOps, + template::{DirOps, ProcDirBuilder}, + ProcDir, + }, + utils::{DirEntryVecExt, Inode}, + }, + prelude::*, +}; + +mod cap_last_cap; + +/// Represents the inode at `/proc/sys/kernel`. + +pub struct KernelDirOps; + +impl KernelDirOps { + pub fn new_inode(parent: Weak) -> Arc { + ProcDirBuilder::new(Self).parent(parent).build().unwrap() + } +} + +impl DirOps for KernelDirOps { + fn lookup_child(&self, this_ptr: Weak, name: &str) -> Result> { + let inode = match name { + "cap_last_cap" => CapLastCapFileOps::new_inode(this_ptr.clone()), + _ => return_errno!(Errno::ENOENT), + }; + Ok(inode) + } + + fn populate_children(&self, this_ptr: Weak) { + let this = { + let this = this_ptr.upgrade().unwrap(); + this.downcast_ref::>().unwrap().this() + }; + let mut cached_children = this.cached_children().write(); + cached_children.put_entry_if_not_found("cap_last_cap", || { + CapLastCapFileOps::new_inode(this_ptr.clone()) + }); + } +} diff --git a/kernel/aster-nix/src/fs/procfs/sys/mod.rs b/kernel/aster-nix/src/fs/procfs/sys/mod.rs new file mode 100644 index 000000000..b7cf3f051 --- /dev/null +++ b/kernel/aster-nix/src/fs/procfs/sys/mod.rs @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MPL-2.0 + +use self::kernel::KernelDirOps; +use crate::{ + fs::{ + procfs::template::{DirOps, ProcDir, ProcDirBuilder}, + utils::{DirEntryVecExt, Inode}, + }, + prelude::*, +}; + +mod kernel; + +/// Represents the inode at `/proc/sys`. +pub struct SysDirOps; + +impl SysDirOps { + pub fn new_inode(parent: Weak) -> Arc { + ProcDirBuilder::new(Self).parent(parent).build().unwrap() + } +} + +impl DirOps for SysDirOps { + fn lookup_child(&self, this_ptr: Weak, name: &str) -> Result> { + let inode = match name { + "kernel" => KernelDirOps::new_inode(this_ptr.clone()), + _ => return_errno!(Errno::ENOENT), + }; + Ok(inode) + } + + fn populate_children(&self, this_ptr: Weak) { + let this = { + let this = this_ptr.upgrade().unwrap(); + this.downcast_ref::>().unwrap().this() + }; + let mut cached_children = this.cached_children().write(); + cached_children + .put_entry_if_not_found("kernel", || KernelDirOps::new_inode(this_ptr.clone())) + } +} diff --git a/kernel/aster-nix/src/process/credentials/capabilities.rs b/kernel/aster-nix/src/process/credentials/capabilities.rs index 2f38eaabb..4abb3b533 100644 --- a/kernel/aster-nix/src/process/credentials/capabilities.rs +++ b/kernel/aster-nix/src/process/credentials/capabilities.rs @@ -62,6 +62,12 @@ impl CapSet { pub const fn new_root() -> Self { CapSet::SYS_ADMIN } + + /// The most significant bit in a 64-bit `CapSet` that may be set to represent a Linux capability. + pub fn most_significant_bit() -> u8 { + // CHECKPOINT_RESTORE is the Linux capability with the largest numerical value + 40 + } } #[derive(Debug)] diff --git a/kernel/aster-nix/src/syscall/capset.rs b/kernel/aster-nix/src/syscall/capset.rs index dc228b071..c7a308dd3 100644 --- a/kernel/aster-nix/src/syscall/capset.rs +++ b/kernel/aster-nix/src/syscall/capset.rs @@ -13,11 +13,8 @@ use crate::{ util::read_val_from_user, }; -const CAP_LAST_CAP: u64 = 40; // Number of the last capability (CAP_CHECKPOINT_RESTORE) -const CAP_VALID_MASK: u64 = (1u64 << (CAP_LAST_CAP + 1)) - 1; - fn make_kernel_cap(low: u32, high: u32) -> u64 { - ((low as u64) | ((high as u64) << 32)) & CAP_VALID_MASK + ((low as u64) | ((high as u64) << 32)) & ((1u64 << (CapSet::most_significant_bit() + 1)) - 1) } pub fn sys_capset(cap_user_header_addr: Vaddr, cap_user_data_addr: Vaddr) -> Result {