Add syscall sethostname
This commit is contained in:
parent
66356e133d
commit
87091aa19c
|
|
@ -190,7 +190,7 @@ provided by Linux on x86-64 architecture.
|
|||
| 167 | swapon | ❌ | |
|
||||
| 168 | swapoff | ❌ | |
|
||||
| 169 | reboot | ❌ | |
|
||||
| 170 | sethostname | ❌ | |
|
||||
| 170 | sethostname | ✅ | |
|
||||
| 171 | setdomainname | ❌ | |
|
||||
| 172 | iopl | ❌ | |
|
||||
| 173 | ioperm | ❌ | |
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use ostd::sync::RwMutexReadGuard;
|
||||
use spin::Once;
|
||||
|
||||
use crate::{
|
||||
|
|
@ -10,7 +11,7 @@ use crate::{
|
|||
|
||||
/// The UTS namespace.
|
||||
pub struct UtsNamespace {
|
||||
uts_name: UtsName,
|
||||
uts_name: RwMutex<UtsName>,
|
||||
owner: Arc<UserNamespace>,
|
||||
}
|
||||
|
||||
|
|
@ -34,7 +35,10 @@ impl UtsNamespace {
|
|||
|
||||
let owner = UserNamespace::get_init_singleton().clone();
|
||||
|
||||
Arc::new(Self { uts_name, owner })
|
||||
Arc::new(Self {
|
||||
uts_name: RwMutex::new(uts_name),
|
||||
owner,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +50,7 @@ impl UtsNamespace {
|
|||
) -> Result<Arc<Self>> {
|
||||
owner.check_cap(CapSet::SYS_ADMIN, posix_thread)?;
|
||||
Ok(Arc::new(Self {
|
||||
uts_name: self.uts_name,
|
||||
uts_name: RwMutex::new(*self.uts_name.read()),
|
||||
owner,
|
||||
}))
|
||||
}
|
||||
|
|
@ -56,9 +60,25 @@ impl UtsNamespace {
|
|||
&self.owner
|
||||
}
|
||||
|
||||
/// Returns the UTS name.
|
||||
pub fn uts_name(&self) -> &UtsName {
|
||||
&self.uts_name
|
||||
/// Returns a read-only lock guard for accessing the UTS name.
|
||||
pub fn uts_name(&self) -> RwMutexReadGuard<'_, UtsName> {
|
||||
self.uts_name.read()
|
||||
}
|
||||
|
||||
/// Sets a new hostname for the UTS namespace.
|
||||
///
|
||||
/// This method will fail with `EPERM` if the caller does not have the SYS_ADMIN capability
|
||||
/// in the owner user namespace.
|
||||
pub fn set_hostname(&self, addr: Vaddr, len: usize, ctx: &Context) -> Result<()> {
|
||||
self.owner.check_cap(CapSet::SYS_ADMIN, ctx.posix_thread)?;
|
||||
|
||||
let new_host_name = copy_uts_field_from_user(addr, len as _, ctx)?;
|
||||
debug!(
|
||||
"set host name: {:?}",
|
||||
CStr::from_bytes_until_nul(new_host_name.as_bytes()).unwrap()
|
||||
);
|
||||
self.uts_name.write().nodename = new_host_name;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -74,3 +94,29 @@ pub struct UtsName {
|
|||
machine: [u8; UTS_FIELD_LEN],
|
||||
domainname: [u8; UTS_FIELD_LEN],
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
let user_space = ctx.user_space();
|
||||
let mut reader = user_space.reader(addr, len as usize)?;
|
||||
|
||||
// UTS fields represent C strings, which must be nul-terminated.
|
||||
// Therefore, the user-provided buffer length cannot exceed `UTS_FIELD_LEN - 1`
|
||||
// to ensure space for the terminating nul byte.
|
||||
if reader.remain() > UTS_FIELD_LEN - 1 {
|
||||
return_errno_with_message!(Errno::EINVAL, "the UTS name is too long");
|
||||
}
|
||||
|
||||
let mut buffer = [0u8; UTS_FIELD_LEN];
|
||||
|
||||
// Partial reads are acceptable,
|
||||
// but an error is returned if no bytes can be read successfully.
|
||||
if let Err((err, 0)) = reader.read_fallible(&mut VmWriter::from(buffer.as_mut_slice())) {
|
||||
return Err(err.into());
|
||||
}
|
||||
|
||||
Ok(buffer)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ use super::{
|
|||
setfsuid::sys_setfsuid,
|
||||
setgid::sys_setgid,
|
||||
setgroups::sys_setgroups,
|
||||
sethostname::sys_sethostname,
|
||||
setitimer::{sys_getitimer, sys_setitimer},
|
||||
setns::sys_setns,
|
||||
setpgid::sys_setpgid,
|
||||
|
|
@ -283,6 +284,7 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||
SYS_GETGROUPS = 158 => sys_getgroups(args[..2]);
|
||||
SYS_SETGROUPS = 159 => sys_setgroups(args[..2]);
|
||||
SYS_NEWUNAME = 160 => sys_uname(args[..1]);
|
||||
SYS_SETHOSTNAME = 161 => sys_sethostname(args[..2]);
|
||||
SYS_GETRUSAGE = 165 => sys_getrusage(args[..2]);
|
||||
SYS_UMASK = 166 => sys_umask(args[..1]);
|
||||
SYS_PRCTL = 167 => sys_prctl(args[..5]);
|
||||
|
|
|
|||
|
|
@ -117,6 +117,7 @@ use super::{
|
|||
setfsuid::sys_setfsuid,
|
||||
setgid::sys_setgid,
|
||||
setgroups::sys_setgroups,
|
||||
sethostname::sys_sethostname,
|
||||
setitimer::{sys_getitimer, sys_setitimer},
|
||||
setns::sys_setns,
|
||||
setpgid::sys_setpgid,
|
||||
|
|
@ -283,6 +284,7 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||
SYS_GETGROUPS = 158 => sys_getgroups(args[..2]);
|
||||
SYS_SETGROUPS = 159 => sys_setgroups(args[..2]);
|
||||
SYS_NEWUNAME = 160 => sys_uname(args[..1]);
|
||||
SYS_SETHOSTNAME = 161 => sys_sethostname(args[..2]);
|
||||
SYS_GETRLIMIT = 163 => sys_getrlimit(args[..2]);
|
||||
SYS_SETRLIMIT = 164 => sys_setrlimit(args[..2]);
|
||||
SYS_GETRUSAGE = 165 => sys_getrusage(args[..2]);
|
||||
|
|
|
|||
|
|
@ -128,6 +128,7 @@ use super::{
|
|||
setfsuid::sys_setfsuid,
|
||||
setgid::sys_setgid,
|
||||
setgroups::sys_setgroups,
|
||||
sethostname::sys_sethostname,
|
||||
setitimer::{sys_getitimer, sys_setitimer},
|
||||
setns::sys_setns,
|
||||
setpgid::sys_setpgid,
|
||||
|
|
@ -306,7 +307,8 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||
SYS_CHROOT = 161 => sys_chroot(args[..1]);
|
||||
SYS_SYNC = 162 => sys_sync(args[..0]);
|
||||
SYS_MOUNT = 165 => sys_mount(args[..5]);
|
||||
SYS_UMOUNT2 = 166 => sys_umount(args[..2]);
|
||||
SYS_UMOUNT2 = 166 => sys_umount(args[..2]);
|
||||
SYS_SETHOSTNAME = 170 => sys_sethostname(args[..2]);
|
||||
SYS_GETTID = 186 => sys_gettid(args[..0]);
|
||||
SYS_SETXATTR = 188 => sys_setxattr(args[..5]);
|
||||
SYS_LSETXATTR = 189 => sys_lsetxattr(args[..5]);
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ mod setfsgid;
|
|||
mod setfsuid;
|
||||
mod setgid;
|
||||
mod setgroups;
|
||||
mod sethostname;
|
||||
mod setitimer;
|
||||
mod setns;
|
||||
mod setpgid;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
use crate::{prelude::*, syscall::SyscallReturn};
|
||||
|
||||
pub fn sys_sethostname(addr: Vaddr, len: usize, ctx: &Context) -> Result<SyscallReturn> {
|
||||
let ns_proxy_ref = ctx.thread_local.borrow_ns_proxy();
|
||||
let ns_proxy = ns_proxy_ref.unwrap();
|
||||
ns_proxy.uts_ns().set_hostname(addr, len, ctx)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
|
@ -6,6 +6,6 @@ pub fn sys_uname(old_uname_addr: Vaddr, ctx: &Context) -> Result<SyscallReturn>
|
|||
debug!("old uname addr = 0x{:x}", old_uname_addr);
|
||||
let ns_proxy = ctx.thread_local.borrow_ns_proxy();
|
||||
let uts_name = ns_proxy.unwrap().uts_ns().uts_name();
|
||||
ctx.user_space().write_val(old_uname_addr, uts_name)?;
|
||||
ctx.user_space().write_val(old_uname_addr, &*uts_name)?;
|
||||
Ok(SyscallReturn::Return(0))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1379,8 +1379,9 @@ setgroups02
|
|||
# setgroups03
|
||||
# setgroups03_16
|
||||
|
||||
# sethostname01
|
||||
# sethostname02
|
||||
sethostname01
|
||||
sethostname02
|
||||
# TODO: Drop capabilities on UID changes, so that sethostname() will fail with EPERM.
|
||||
# sethostname03
|
||||
|
||||
# setitimer01
|
||||
|
|
|
|||
Loading…
Reference in New Issue