Support setns via nsfs
This commit is contained in:
parent
9c023db7b5
commit
9fdb63800b
|
|
@ -502,6 +502,10 @@ impl FileIo for EvdevFile {
|
||||||
|
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for EvdevFile {
|
impl Drop for EvdevFile {
|
||||||
|
|
|
||||||
|
|
@ -517,6 +517,10 @@ impl FileIo for FbHandle {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn init_in_first_kthread() {
|
pub(super) fn init_in_first_kthread() {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
|
use core::any::Any;
|
||||||
|
|
||||||
use ostd::mm::{FallibleVmWrite, VmReader, VmWriter};
|
use ostd::mm::{FallibleVmWrite, VmReader, VmWriter};
|
||||||
|
|
||||||
|
|
@ -150,4 +151,8 @@ impl FileIo for MemFile {
|
||||||
fn is_offset_aware(&self) -> bool {
|
fn is_offset_aware(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,6 +170,10 @@ impl FileIo for TdxGuestFile {
|
||||||
_ => return_errno_with_message!(Errno::ENOTTY, "the ioctl command is unknown"),
|
_ => return_errno_with_message!(Errno::ENOTTY, "the ioctl command is unknown"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tdx_get_quote(inblob: &[u8]) -> Result<Box<[u8]>> {
|
pub fn tdx_get_quote(inblob: &[u8]) -> Result<Box<[u8]>> {
|
||||||
|
|
|
||||||
|
|
@ -91,4 +91,8 @@ impl FileIo for PtySlaveFile {
|
||||||
fn is_offset_aware(&self) -> bool {
|
fn is_offset_aware(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -252,6 +252,10 @@ impl FileIo for PtyMaster {
|
||||||
|
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for PtyMaster {
|
impl Drop for PtyMaster {
|
||||||
|
|
|
||||||
|
|
@ -151,6 +151,10 @@ impl FileIo for OpenBlockFile {
|
||||||
),
|
),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn lookup(id: DeviceId) -> Option<Arc<dyn Device>> {
|
pub(super) fn lookup(id: DeviceId) -> Option<Arc<dyn Device>> {
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,10 @@ impl<D: TtyDriver> FileIo for TtyFile<D> {
|
||||||
fn is_offset_aware(&self) -> bool {
|
fn is_offset_aware(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static TTY1: Once<Arc<Tty<VtDriver>>> = Once::new();
|
static TTY1: Once<Arc<Tty<VtDriver>>> = Once::new();
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ use crate::{
|
||||||
file_table::FdFlags,
|
file_table::FdFlags,
|
||||||
path::Path,
|
path::Path,
|
||||||
pipe::PipeHandle,
|
pipe::PipeHandle,
|
||||||
|
pseudofs::{NsCommonOps, NsFile},
|
||||||
utils::{
|
utils::{
|
||||||
AccessMode, AtomicStatusFlags, CreationFlags, DirentVisitor, FallocMode, FileRange,
|
AccessMode, AtomicStatusFlags, CreationFlags, DirentVisitor, FallocMode, FileRange,
|
||||||
FlockItem, InodeType, OFFSET_MAX, RangeLockItem, RangeLockType, SeekFrom, StatusFlags,
|
FlockItem, InodeType, OFFSET_MAX, RangeLockItem, RangeLockType, SeekFrom, StatusFlags,
|
||||||
|
|
@ -215,6 +216,11 @@ impl InodeHandle {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_ns_file<T: NsCommonOps>(&self) -> Option<&NsFile<T>> {
|
||||||
|
let file_io = self.file_io.as_ref()?;
|
||||||
|
file_io.as_any().downcast_ref::<NsFile<T>>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pollable for InodeHandle {
|
impl Pollable for InodeHandle {
|
||||||
|
|
@ -519,6 +525,8 @@ pub trait FileIo: Pollable + InodeIo + Any + Send + Sync + 'static {
|
||||||
fn ioctl(&self, _raw_ioctl: RawIoctl) -> Result<i32> {
|
fn ioctl(&self, _raw_ioctl: RawIoctl) -> Result<i32> {
|
||||||
return_errno_with_message!(Errno::ENOTTY, "ioctl is not supported");
|
return_errno_with_message!(Errno::ENOTTY, "ioctl is not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn do_seek_util(offset: &Mutex<usize>, pos: SeekFrom, end: Option<usize>) -> Result<usize> {
|
fn do_seek_util(offset: &Mutex<usize>, pos: SeekFrom, end: Option<usize>) -> Result<usize> {
|
||||||
|
|
|
||||||
|
|
@ -136,6 +136,10 @@ impl FileIo for PipeHandle {
|
||||||
fn is_offset_aware(&self) -> bool {
|
fn is_offset_aware(&self) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A pipe (FIFO) that provides inter-process communication.
|
/// A pipe (FIFO) that provides inter-process communication.
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,10 @@
|
||||||
//! 2. A `PidFile` opened by `pidfd_open` or by opening `/proc/[pid]` directory.
|
//! 2. A `PidFile` opened by `pidfd_open` or by opening `/proc/[pid]` directory.
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fs::{file_table::FileDesc, path::MountNamespace},
|
fs::{
|
||||||
|
file_handle::FileLike, file_table::FileDesc, inode_handle::InodeHandle,
|
||||||
|
path::MountNamespace, pseudofs::NsCommonOps,
|
||||||
|
},
|
||||||
net::uts_ns::UtsNamespace,
|
net::uts_ns::UtsNamespace,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::{
|
process::{
|
||||||
|
|
@ -34,13 +37,8 @@ pub fn sys_setns(fd: FileDesc, flags: u32, ctx: &Context) -> Result<SyscallRetur
|
||||||
|
|
||||||
let new_ns_proxy = if let Some(pid_file) = file.downcast_ref::<PidFile>() {
|
let new_ns_proxy = if let Some(pid_file) = file.downcast_ref::<PidFile>() {
|
||||||
build_proxy_from_pid_file(pid_file, ns_type_flags, ctx)?
|
build_proxy_from_pid_file(pid_file, ns_type_flags, ctx)?
|
||||||
}
|
} else {
|
||||||
// TODO: Support setting namespaces from `/proc/[pid]/ns`.
|
build_proxy_from_ns_file(file.as_ref(), ns_type_flags, ctx)?
|
||||||
else {
|
|
||||||
return_errno_with_message!(
|
|
||||||
Errno::EINVAL,
|
|
||||||
"the FD does not refer to a supported namespace file"
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Install the newly created `NsProxy`.
|
// Install the newly created `NsProxy`.
|
||||||
|
|
@ -105,6 +103,56 @@ fn build_proxy_from_pid_file(
|
||||||
Ok(builder.build())
|
Ok(builder.build())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn build_proxy_from_ns_file(
|
||||||
|
file: &dyn FileLike,
|
||||||
|
flags: CloneFlags,
|
||||||
|
ctx: &Context,
|
||||||
|
) -> Result<NsProxy> {
|
||||||
|
check_unsupported_ns_flags(flags)?;
|
||||||
|
|
||||||
|
let inode_handle = file
|
||||||
|
.downcast_ref::<InodeHandle>()
|
||||||
|
.ok_or_else(|| Error::with_message(Errno::EINVAL, "the file is not a ns file"))?;
|
||||||
|
|
||||||
|
let current_proxy = ctx.thread_local.borrow_ns_proxy();
|
||||||
|
let current_proxy = current_proxy.unwrap();
|
||||||
|
|
||||||
|
let mut builder = NsProxyBuilder::new(current_proxy);
|
||||||
|
|
||||||
|
let applied = try_apply_ns::<UtsNamespace>(inode_handle, flags, |ns| {
|
||||||
|
builder.uts_ns(ns);
|
||||||
|
})? || try_apply_ns::<MountNamespace>(inode_handle, flags, |ns| {
|
||||||
|
builder.mnt_ns(ns);
|
||||||
|
})?;
|
||||||
|
// TODO: Support setting other namespaces from the ns file.
|
||||||
|
|
||||||
|
if !applied {
|
||||||
|
return_errno_with_message!(Errno::EINVAL, "invalid flags are specified with a ns file");
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_apply_ns<T: NsCommonOps>(
|
||||||
|
inode_handle: &InodeHandle,
|
||||||
|
flags: CloneFlags,
|
||||||
|
apply: impl FnOnce(Arc<T>),
|
||||||
|
) -> Result<bool> {
|
||||||
|
let Some(ns_file) = inode_handle.as_ns_file::<T>() else {
|
||||||
|
return Ok(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
if !flags.is_empty() && flags != T::TYPE.into() {
|
||||||
|
return_errno_with_message!(
|
||||||
|
Errno::EINVAL,
|
||||||
|
"the flags do not match the type of the ns file"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(ns_file.ns().clone());
|
||||||
|
Ok(true)
|
||||||
|
}
|
||||||
|
|
||||||
fn set_uts_ns(
|
fn set_uts_ns(
|
||||||
builder: &mut NsProxyBuilder,
|
builder: &mut NsProxyBuilder,
|
||||||
target_ns: &Arc<UtsNamespace>,
|
target_ns: &Arc<UtsNamespace>,
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ TESTS ?= \
|
||||||
sched_yield_test \
|
sched_yield_test \
|
||||||
semaphore_test \
|
semaphore_test \
|
||||||
sendfile_test \
|
sendfile_test \
|
||||||
|
setns_test \
|
||||||
sigaction_test \
|
sigaction_test \
|
||||||
sigaltstack_test \
|
sigaltstack_test \
|
||||||
signalfd_test \
|
signalfd_test \
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
SetnsTest.ChangeIPCNamespace
|
||||||
|
SetnsTest.ChangePIDNamespace
|
||||||
Loading…
Reference in New Issue