From d299cf4db482aa8fc6e32cd6b349270e19199da1 Mon Sep 17 00:00:00 2001 From: Ruihan Li Date: Thu, 11 Dec 2025 13:46:46 +0800 Subject: [PATCH] Clarify the UTS names in `/proc/version` --- kernel/src/fs/procfs/version.rs | 14 ++- kernel/src/net/mod.rs | 4 +- kernel/src/net/uts_ns.rs | 129 +++++++++++------------- kernel/src/process/namespace/nsproxy.rs | 2 +- kernel/src/syscall/setns.rs | 2 +- 5 files changed, 70 insertions(+), 81 deletions(-) diff --git a/kernel/src/fs/procfs/version.rs b/kernel/src/fs/procfs/version.rs index 04f6f9a9e..52179374e 100644 --- a/kernel/src/fs/procfs/version.rs +++ b/kernel/src/fs/procfs/version.rs @@ -12,7 +12,7 @@ use crate::{ procfs::template::{FileOps, ProcFileBuilder}, utils::{Inode, mkmod}, }, - net::UtsNamespace, + net::uts_ns::UtsName, prelude::*, }; @@ -35,14 +35,12 @@ impl FileOps for VersionFileOps { fn read_at(&self, offset: usize, writer: &mut VmWriter) -> Result { let mut printer = VmPrinter::new_skip(writer, offset); - // Get UTS namespace information from the init namespace - let uts_name = UtsNamespace::get_init_singleton().uts_name(); + // Get information from `UtsName`. + let sysname = UtsName::SYSNAME; + let release = UtsName::RELEASE; + let version = UtsName::VERSION; - let sysname = uts_name.sysname()?; - let release = uts_name.release()?; - let version = uts_name.version()?; - - // Get info from compile environment variables + // Get information from compile-time environment variables. let compile_by = option_env!("OSDK_BUILD_USERNAME").unwrap_or("unknown"); let compile_host = option_env!("OSDK_BUILD_HOSTNAME").unwrap_or("unknown"); let compiler = option_env!("OSDK_BUILD_RUSTC").unwrap_or("unknown"); diff --git a/kernel/src/net/mod.rs b/kernel/src/net/mod.rs index 146d9cad1..b7f157450 100644 --- a/kernel/src/net/mod.rs +++ b/kernel/src/net/mod.rs @@ -2,9 +2,7 @@ pub mod iface; pub mod socket; -mod uts_ns; - -pub use uts_ns::UtsNamespace; +pub mod uts_ns; pub fn init() { iface::init(); diff --git a/kernel/src/net/uts_ns.rs b/kernel/src/net/uts_ns.rs index 880730531..76da0374a 100644 --- a/kernel/src/net/uts_ns.rs +++ b/kernel/src/net/uts_ns.rs @@ -16,40 +16,18 @@ pub struct UtsNamespace { } impl UtsNamespace { - /// Returns the Linux machine name for the current architecture. - const fn machine_name() -> &'static [u8] { - #[cfg(target_arch = "x86_64")] - return b"x86_64"; - #[cfg(target_arch = "riscv64")] - return b"riscv64"; - #[cfg(target_arch = "loongarch64")] - return b"loongarch64"; - #[cfg(target_arch = "aarch64")] - return b"aarch64"; - #[cfg(not(any( - target_arch = "x86_64", - target_arch = "riscv64", - target_arch = "loongarch64", - target_arch = "aarch64" - )))] - compile_error!("Unsupported architecture for UTS namespace machine name"); - } - /// Returns a reference to the singleton initial UTS namespace. pub fn get_init_singleton() -> &'static Arc { static INIT: Once> = Once::new(); INIT.call_once(|| { - // We intentionally report Linux-like UTS values instead of Asterinas' real - // name and version. These spoofed values satisfy glibc, which inspects - // uname fields (sysname, release, version, etc.) and expects Linux-compatible data. - let version_str = option_env!("OSDK_BUILD_TIMESTAMP").unwrap_or("unknown"); let uts_name = UtsName { - sysname: padded(b"Linux"), - nodename: padded(b"WHITLEY"), - release: padded(b"5.13.0"), - version: padded(version_str.as_bytes()), - machine: padded(Self::machine_name()), + sysname: padded(UtsName::SYSNAME.as_bytes()), + // Reference: . + nodename: padded(b"(none)"), + release: padded(UtsName::RELEASE.as_bytes()), + version: padded(UtsName::VERSION.as_bytes()), + machine: padded(UtsName::MACHINE.as_bytes()), // Reference: . domainname: padded(b"(none)"), }; @@ -119,46 +97,6 @@ impl UtsNamespace { } } -const UTS_FIELD_LEN: usize = 65; - -#[derive(Debug, Clone, Copy, Pod)] -#[repr(C)] -pub struct UtsName { - sysname: [u8; UTS_FIELD_LEN], - nodename: [u8; UTS_FIELD_LEN], - release: [u8; UTS_FIELD_LEN], - version: [u8; UTS_FIELD_LEN], - machine: [u8; UTS_FIELD_LEN], - domainname: [u8; UTS_FIELD_LEN], -} - -impl UtsName { - /// Returns the system name as UTF-8 string. - pub fn sysname(&self) -> Result<&str> { - Self::cstr_bytes_to_str(&self.sysname) - } - - /// Returns the release name as UTF-8 string. - pub fn release(&self) -> Result<&str> { - Self::cstr_bytes_to_str(&self.release) - } - - /// Returns the version name as UTF-8 string. - pub fn version(&self) -> Result<&str> { - Self::cstr_bytes_to_str(&self.version) - } - - /// Converts a C string bytes to a UTF-8 string. - fn cstr_bytes_to_str(cstr_bytes: &[u8]) -> Result<&str> { - CStr::from_bytes_until_nul(cstr_bytes) - .map_err(|_| Error::with_message(Errno::EINVAL, "not a null-terminated C string")) - .and_then(|cstr| { - cstr.to_str() - .map_err(|_| Error::with_message(Errno::EINVAL, "not a UTF-8 string")) - }) - } -} - fn copy_uts_field_from_user(addr: Vaddr, len: u32, ctx: &Context) -> Result<[u8; UTS_FIELD_LEN]> { if len.cast_signed() < 0 { return_errno_with_message!(Errno::EINVAL, "the buffer length cannot be negative"); @@ -184,3 +122,58 @@ fn copy_uts_field_from_user(addr: Vaddr, len: u32, ctx: &Context) -> Result<[u8; Ok(buffer) } + +const UTS_FIELD_LEN: usize = 65; + +#[derive(Debug, Clone, Copy, Pod)] +#[repr(C)] +pub struct UtsName { + sysname: [u8; UTS_FIELD_LEN], + nodename: [u8; UTS_FIELD_LEN], + release: [u8; UTS_FIELD_LEN], + version: [u8; UTS_FIELD_LEN], + machine: [u8; UTS_FIELD_LEN], + domainname: [u8; UTS_FIELD_LEN], +} + +impl UtsName { + // Note that the following names remain constant across all UTS namespaces. They are immutable, + // meaning the user space cannot change them. They are stored in the UTS namespace for ease of + // implementing related system calls. + // + // In addition, we intentionally report Linux-like UTS values instead of Asterinas' real name + // and version. These spoofed values satisfy glibc, which inspects uname fields (sysname, + // release, version, etc.) and expects Linux-compatible data. + + /// The system name. + pub const SYSNAME: &str = "Linux"; + + /// The release name. + pub const RELEASE: &str = "5.13.0"; + + /// The version name. + pub const VERSION: &str = { + if let Some(version) = option_env!("OSDK_BUILD_TIMESTAMP") { + version + } else { + "unknown" + } + }; + + /// The machine name. + pub const MACHINE: &str = { + cfg_if::cfg_if! { + if #[cfg(target_arch = "x86_64")] { + "x86_64" + } else if #[cfg(target_arch = "riscv64")] { + "riscv64" + } else if #[cfg(target_arch = "loongarch64")] { + "loongarch64" + } else if #[cfg(target_arch = "aarch64")] { + "aarch64" + } else { + compile_error!("unsupported target") + } + } + }; +} diff --git a/kernel/src/process/namespace/nsproxy.rs b/kernel/src/process/namespace/nsproxy.rs index 0158e0c16..692ba0c09 100644 --- a/kernel/src/process/namespace/nsproxy.rs +++ b/kernel/src/process/namespace/nsproxy.rs @@ -4,7 +4,7 @@ use spin::Once; use crate::{ fs::path::MountNamespace, - net::UtsNamespace, + net::uts_ns::UtsNamespace, prelude::*, process::{CloneFlags, UserNamespace, posix_thread::PosixThread}, }; diff --git a/kernel/src/syscall/setns.rs b/kernel/src/syscall/setns.rs index 4410d021f..d3aade871 100644 --- a/kernel/src/syscall/setns.rs +++ b/kernel/src/syscall/setns.rs @@ -12,7 +12,7 @@ use crate::{ fs::{file_table::FileDesc, path::MountNamespace}, - net::UtsNamespace, + net::uts_ns::UtsNamespace, prelude::*, process::{ CloneFlags, ContextSetNsAdminApi, NsProxy, NsProxyBuilder, PidFile,