Some CStr related changes

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2019-07-09 14:56:51 +02:00
parent 61bfa35549
commit 275009ec68
5 changed files with 63 additions and 37 deletions

View File

@ -20,7 +20,7 @@ use crate::{libc_try, libc_wrap};
pub async fn forking_syscall<F>(func: F) -> io::Result<SyscallStatus>
where
F: FnOnce() -> Result<i64, Errno> + UnwindSafe,
F: FnOnce() -> io::Result<SyscallStatus> + UnwindSafe,
{
let mut fork = Fork::new(func)?;
let result = fork.get_result().await?;
@ -47,12 +47,13 @@ impl Drop for Fork {
struct Data {
val: i64,
error: i32,
failure: i32,
}
impl Fork {
pub fn new<F>(func: F) -> io::Result<Self>
where
F: FnOnce() -> Result<i64, Errno> + UnwindSafe,
F: FnOnce() -> io::Result<SyscallStatus> + UnwindSafe,
{
let mut pipe: [c_int; 2] = [0, 0];
libc_try!(unsafe { libc::pipe2(pipe.as_mut_ptr(), libc::O_CLOEXEC | libc::O_NONBLOCK) });
@ -65,13 +66,20 @@ impl Fork {
let _ = std::panic::catch_unwind(move || {
let out = match func() {
Ok(val) => Data {
Ok(SyscallStatus::Ok(val)) => Data {
val,
error: 0,
failure: 0,
},
Err(error) => Data {
Ok(SyscallStatus::Err(error)) => Data {
val: -1,
error: error as _,
failure: 0,
},
Err(err) => Data {
val: -1,
error: -1,
failure: err.raw_os_error().unwrap_or(libc::EFAULT),
},
};
@ -118,7 +126,10 @@ impl Fork {
}
if status != 0 {
Err(io::Error::new(io::ErrorKind::Other, "error in child process"))
Err(io::Error::new(
io::ErrorKind::Other,
"error in child process",
))
} else {
Ok(())
}
@ -133,8 +144,11 @@ impl Fork {
&mut data as *mut Data as *mut u8,
std::mem::size_of::<Data>(),
)
}).await?;
if data.error == 0 {
})
.await?;
if data.failure != 0 {
Err(io::Error::from_raw_os_error(data.failure))
} else if data.error == 0 {
Ok(SyscallStatus::Ok(data.val))
} else {
Ok(SyscallStatus::Err(data.error))

View File

@ -1,10 +1,10 @@
use std::ffi::CStr;
use std::io;
use std::marker::PhantomData;
use std::os::raw::c_int;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::path::Path;
use crate::tools::path_ptr;
use crate::{file_descriptor_type, libc_try};
pub mod ns_type {
@ -31,18 +31,13 @@ pub use ns_type::NsType;
file_descriptor_type!(RawNsFd);
impl RawNsFd {
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
Self::openat(libc::AT_FDCWD, path.as_ref())
pub fn open(path: &CStr) -> io::Result<Self> {
Self::openat(libc::AT_FDCWD, path)
}
pub fn openat<P: AsRef<Path>>(fd: RawFd, path: P) -> io::Result<Self> {
let fd = libc_try!(unsafe {
libc::openat(
fd,
path_ptr(path.as_ref()),
libc::O_RDONLY | libc::O_CLOEXEC,
)
});
pub fn openat(fd: RawFd, path: &CStr) -> io::Result<Self> {
let fd =
libc_try!(unsafe { libc::openat(fd, path.as_ptr(), libc::O_RDONLY | libc::O_CLOEXEC) });
Ok(Self(fd))
}
@ -65,12 +60,12 @@ impl<T: NsType> std::ops::Deref for NsFd<T> {
}
impl<T: NsType> NsFd<T> {
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<Self> {
Ok(Self(RawNsFd::open(path.as_ref())?, PhantomData))
pub fn open(path: &CStr) -> io::Result<Self> {
Ok(Self(RawNsFd::open(path)?, PhantomData))
}
pub fn openat<P: AsRef<Path>>(fd: RawFd, path: P) -> io::Result<Self> {
Ok(Self(RawNsFd::openat(fd, path.as_ref())?, PhantomData))
pub fn openat(fd: RawFd, path: &CStr) -> io::Result<Self> {
Ok(Self(RawNsFd::openat(fd, path)?, PhantomData))
}
pub fn setns(&self) -> io::Result<()> {

View File

@ -1,6 +1,6 @@
//! pidfd helper functionality
use std::ffi::CString;
use std::ffi::{CStr, CString};
use std::io;
use std::os::raw::c_int;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
@ -22,15 +22,21 @@ impl PidFd {
}
pub fn mount_namespace(&self) -> io::Result<NsFd<ns_type::Mount>> {
NsFd::openat(self.0, "ns/mnt")
NsFd::openat(self.0, unsafe {
CStr::from_bytes_with_nul_unchecked(b"ns/mnt\0")
})
}
pub fn cgroup_namespace(&self) -> io::Result<NsFd<ns_type::Cgroup>> {
NsFd::openat(self.0, "ns/cgroup")
NsFd::openat(self.0, unsafe {
CStr::from_bytes_with_nul_unchecked(b"ns/cgroup\0")
})
}
pub fn user_namespace(&self) -> io::Result<NsFd<ns_type::User>> {
NsFd::openat(self.0, "ns/user")
NsFd::openat(self.0, unsafe {
CStr::from_bytes_with_nul_unchecked(b"ns/user\0")
})
}
fn fd(&self, path: &[u8], flags: c_int) -> io::Result<Fd> {
@ -50,4 +56,10 @@ impl PidFd {
pub fn fd_num(&self, num: RawFd, flags: c_int) -> io::Result<Fd> {
self.fd(format!("fd/{}\0", num).as_bytes(), flags)
}
//pub fn dup(&self) -> io::Result<Self> {
// Ok(Self(libc_try!(unsafe {
// libc::fcntl(self.as_raw_fd(), libc::F_DUPFD_CLOEXEC, 0)
// })))
//}
}

View File

@ -1,4 +1,5 @@
use std::ffi::CString;
use std::os::unix::io::{AsRawFd, FromRawFd};
use failure::Error;
use nix::errno::Errno;
@ -6,6 +7,7 @@ use nix::sys::stat;
use crate::fork::forking_syscall;
use crate::lxcseccomp::ProxyMessageBuffer;
use crate::pidfd::PidFd;
use crate::syscall::SyscallStatus;
use crate::tools::Fd;
@ -14,7 +16,9 @@ pub async fn mknod(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> {
let mode = msg.arg_mode_t(1)?;
let dev = msg.arg_dev_t(2)?;
let cwd = msg.pid_fd().fd_cwd()?;
do_mknodat(cwd, pathname, mode, dev).await
let pidfd = unsafe { PidFd::from_raw_fd(msg.pid_fd().as_raw_fd()) };
do_mknodat(pidfd, cwd, pathname, mode, dev).await
}
pub async fn mknodat(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> {
@ -22,17 +26,24 @@ pub async fn mknodat(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> {
let pathname = msg.arg_c_string(1)?;
let mode = msg.arg_mode_t(2)?;
let dev = msg.arg_dev_t(3)?;
do_mknodat(dirfd, pathname, mode, dev).await
let pidfd = unsafe { PidFd::from_raw_fd(msg.pid_fd().as_raw_fd()) };
do_mknodat(pidfd, dirfd, pathname, mode, dev).await
}
async fn do_mknodat(
_dirfd: Fd,
pidfd: PidFd,
dirfd: Fd,
_pathname: CString,
_mode: stat::mode_t,
_dev: stat::dev_t,
) -> Result<SyscallStatus, Error> {
println!("=> Responding with ENOENT");
Ok(forking_syscall(move || {
Err(Errno::ENOENT)
}).await?)
pidfd.mount_namespace()?.setns()?;
std::mem::drop(pidfd);
std::mem::drop(dirfd);
Ok(SyscallStatus::Err(libc::ENOENT))
})
.await?)
}

View File

@ -299,9 +299,3 @@ macro_rules! libc_try {
}
}};
}
pub fn path_ptr(path: &std::path::Path) -> *const libc::c_char {
use std::os::unix::ffi::OsStrExt;
path.as_os_str().as_bytes().as_ptr() as *const libc::c_char
}