Clarify the UTS names in `/proc/version`
This commit is contained in:
parent
0cfc539608
commit
d299cf4db4
|
|
@ -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<usize> {
|
||||
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");
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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<UtsNamespace> {
|
||||
static INIT: Once<Arc<UtsNamespace>> = 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: <https://elixir.bootlin.com/linux/v6.16/source/init/Kconfig#L408>.
|
||||
nodename: padded(b"(none)"),
|
||||
release: padded(UtsName::RELEASE.as_bytes()),
|
||||
version: padded(UtsName::VERSION.as_bytes()),
|
||||
machine: padded(UtsName::MACHINE.as_bytes()),
|
||||
// Reference: <https://elixir.bootlin.com/linux/v6.16/source/include/linux/uts.h#L17>.
|
||||
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")
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue