Merge 1.3.0

This commit is contained in:
Andrew A. Vasilyev 2024-02-29 18:26:40 +03:00
commit e8b153031a
24 changed files with 162 additions and 177 deletions

View File

@ -1,7 +1,7 @@
[package]
name = "pve-lxc-syscalld"
edition = "2021"
version = "1.2.2"
version = "1.3.0"
authors = [
"Wolfgang Bumiller <w.bumiller@proxmox.com>",
]
@ -9,13 +9,15 @@ license = "AGPL-3"
description = "Proxmox LXC seccomp-proxy syscall handler daemon"
homepage = "https://www.proxmox.com"
exclude = [ "build", "debian" ]
rust-version = "1.64"
exclude = [ "debian" ]
[dependencies]
anyhow = "1.0"
bitflags = "1.2"
lazy_static = "1.4"
libc = "0.2"
nix = "0.24"
nix = "0.26"
num_cpus = "1"
tokio = { version = "1.0", features = [ "rt-multi-thread", "io-util", "net" ] }

View File

@ -20,7 +20,9 @@ COMPILED_BINS := \
$(addprefix $(COMPILEDIR)/,$(SERVICE_BIN))
DEB=$(PACKAGE)_$(DEB_VERSION)_$(DEB_HOST_ARCH).deb
DSC=rust-$(PACKAGE)_$(DEB_VERSION).dsc
DSC=$(PACKAGE)_$(DEB_VERSION).dsc
BUILDDIR ?= $(PACKAGE)-$(DEB_VERSION_UPSTREAM)
all: cargo-build $(SUBDIRS)
@ -39,12 +41,6 @@ test:
.PHONY: check
check: test
.PHONY: san
san:
cargo +nightly fmt -- --check
cargo clippy
cargo test
$(COMPILED_BINS): cargo-build
install: $(COMPILED_BINS)
@ -52,43 +48,38 @@ install: $(COMPILED_BINS)
$(foreach i,$(SERVICE_BIN), \
install -m755 $(COMPILEDIR)/$(i) $(DESTDIR)$(LIBEXECDIR)/pve-lxc-syscalld/ ;)
.PHONY: build
build:
rm -rf build
debcargo package \
--config debian/debcargo.toml \
--changelog-ready \
--no-overlay-write-back \
--directory build \
pve-lxc-syscalld \
$(shell dpkg-parsechangelog -l debian/changelog -SVersion | sed -e 's/-.*//')
sed -e '1,/^$$/ ! d' build/debian/control > build/debian/control.src
cat build/debian/control.src build/debian/control.in > build/debian/control
rm build/debian/control.in build/debian/control.src
rm build/Cargo.lock
find build/debian -name "*.hint" -delete
echo system >build/rust-toolchain
$(foreach i,$(SUBDIRS), \
$(MAKE) -C build/$(i) clean ;)
$(BUILDDIR): src debian etc Cargo.toml
rm -rf $(BUILDDIR) $(BUILDDIR).tmp
mkdir $(BUILDDIR).tmp
#mkdir $(BUILDDIR).tmp/.cargo
cp -a -t $(BUILDDIR).tmp $^ Makefile defines.mk
#cp -a -t $(BUILDDIR).tmp/.cargo .cargo/config
echo "git clone git://git.proxmox.com/git/pve-lxc-syscalld.git\\ngit checkout $(shell git rev-parse HEAD)" > $(BUILDDIR).tmp/debian/SOURCE
mv $(BUILDDIR).tmp $(BUILDDIR)
.PHONY: deb
deb: $(DEB)
$(DEB): build
cd build; dpkg-buildpackage -b -us -uc --no-pre-clean --build-profiles=nodoc
$(DEB): $(BUILDDIR)
cd $(BUILDDIR); dpkg-buildpackage -b -us -uc
lintian $(DEB)
upload: deb
dcmd --deb rust-pve-lxc-syscalld_*.changes \
| grep -v '.changes$$' \
| tar -cf- -T- \
| ssh -X repoman@repo.proxmox.com upload --product pve --dist bullseye
.PHONY: dsc
dsc: $(DSC)
$(DSC): build
cd build; dpkg-buildpackage -S -us -uc -d -nc
$(DSC): $(BUILDDIR)
cd $(BUILDDIR); dpkg-buildpackage -S -us -uc -d
lintian $(DSC)
sbuild: $(DSC)
sbuild $(DSC)
.PHONY: upload
upload: UPLOAD_DIST ?= $(DEB_DISTRIBUTION)
upload: $(DEB)
dcmd --deb pve-lxc-syscalld_*.changes \
| grep -v '.changes$$' \
| tar -cf- -T- \
| ssh -X repoman@repo.proxmox.com upload --product pve --dist $(UPLOAD_DIST)
.PHONY: dinstall
dinstall:
$(MAKE) deb
@ -97,5 +88,6 @@ dinstall:
clean:
$(foreach i,$(SUBDIRS), \
$(MAKE) -C $(i) clean ;)
cargo clean
rm -rf *.deb *.dsc *.tar.gz *.buildinfo *.changes build
rm -rf ./target
rm -rf ./$(BUILDDIR)
rm -f -- *.deb *.dsc *.tar.?z *.buildinfo *.build *.changes

6
debian/changelog vendored
View File

@ -1,3 +1,9 @@
pve-lxc-syscalld (1.3.0) bookworm; urgency=medium
* rebuild for Debian 12 bookworm based release series
-- Proxmox Support Team <support@proxmox.com> Wed, 24 May 2023 13:33:14 +0200
rust-pve-lxc-syscalld (1.2.2-1) pve; urgency=medium
* remove old poll/event handling for SEQPACKET socket

1
debian/compat vendored
View File

@ -1 +0,0 @@
12

33
debian/control vendored Normal file
View File

@ -0,0 +1,33 @@
Source: pve-lxc-syscalld
Section: admin
Priority: optional
Build-Depends: debhelper-compat (= 13),
bash-completion,
libsystemd-dev,
dh-cargo (>= 25),
cargo:native,
rustc:native,
libstd-rust-dev,
librust-anyhow-1+default-dev,
librust-bitflags-1+default-dev (>= 1.2-~~),
librust-lazy-static-1+default-dev (>= 1.4-~~),
librust-libc-0.2+default-dev,
librust-nix-0.26+default-dev,
librust-num-cpus-1+default-dev,
librust-tokio-1+default-dev,
librust-tokio-1+io-util-dev,
librust-tokio-1+net-dev,
librust-tokio-1+rt-multi-thread-dev,
Maintainer: Proxmox Support Team <support@proxmox.com>
Standards-Version: 4.6.1
Vcs-Git: git://git.proxmox.com/git/pve-lxc-syscalld.git
Vcs-Browser: https://git.proxmox.com/?p=pve-lxc-syscalld.git;a=summary
Homepage: https://www.proxmox.com
Rules-Requires-Root: no
Package: pve-lxc-syscalld
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends},
Description: PVE LXC syscall daemon
A daemon which handles a selected subset of syscalls for unprivileged
containers.

6
debian/control.in vendored
View File

@ -1,6 +0,0 @@
Package: pve-lxc-syscalld
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends},
Description: PVE LXC syscall daemon
A daemon which handles a selected subset of syscalls for unprivileged
containers.

32
debian/copyright vendored
View File

@ -1,16 +1,18 @@
Copyright (C) 2019,2020 Proxmox Server Solutions GmbH
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
This software is written by Proxmox Server Solutions GmbH <support@proxmox.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Files:
*
Copyright: 2019 - 2023 Proxmox Server Solutions GmbH <support@proxmox.com>
License: AGPL-3.0-or-later
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option) any
later version.
.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
details.
.
You should have received a copy of the GNU Affero General Public License along
with this program. If not, see <https://www.gnu.org/licenses/>.

11
debian/debcargo.toml vendored
View File

@ -1,11 +0,0 @@
overlay = "."
crate_src_path = ".."
maintainer = "Proxmox Support Team <support@proxmox.com>"
[source]
section = "admin"
build_depends = [ "debhelper (>= 12~)", "bash-completion" ]
build_depends_excludes = [ "debhelper (>=11)" ]
# TODO:
vcs_git = ""
vcs_browser = ""

2
debian/rules vendored
View File

@ -21,6 +21,8 @@ export DEB_CARGO_PACKAGE=pve-lxc-syscalld
dh $@
override_dh_auto_configure:
@perl -ne 'if (/^version\s*=\s*"(\d+(?:\.\d+)+)"/) { my $$v_cargo = $$1; my $$v_deb = "$(DEB_VERSION_UPSTREAM)"; \
die "ERROR: d/changelog <-> Cargo.toml version mismatch: $$v_cargo != $$v_deb\n" if $$v_cargo ne $$v_deb; exit(0); }' Cargo.toml
$(CARGO) prepare-debian $(CURDIR)/debian/cargo_registry --link-from-system
dh_auto_configure

View File

@ -1 +1 @@
3.0 (quilt)
3.0 (native)

View File

@ -1 +0,0 @@
edition = "2018"

View File

@ -23,9 +23,9 @@ impl Client {
F: std::future::Future<Output = Result<(), Error>>,
{
if let Err(err) = fut.await {
eprintln!("client error, dropping connection: {}", err);
eprintln!("client error, dropping connection: {err}");
if let Err(err) = self.socket.shutdown(nix::sys::socket::Shutdown::Both) {
eprintln!(" (error shutting down client socket: {})", err);
eprintln!(" (error shutting down client socket: {err})");
}
}
}

View File

@ -57,9 +57,9 @@ impl Fork {
let pid = c_try!(unsafe { libc::fork() });
if pid == 0 {
drop(pipe_r);
let mut pipe_w = pipe_w.into_fd();
let pipe_w = pipe_w.into_fd();
let _ = std::panic::catch_unwind(move || {
pipe_w.set_nonblocking(false).unwrap();
crate::tools::set_fd_nonblocking(&pipe_w, false).unwrap();
let mut pipe_w = unsafe { std::fs::File::from_raw_fd(pipe_w.into_raw_fd()) };
let out = match func() {
Ok(SyscallStatus::Ok(val)) => Data {

View File

@ -47,7 +47,7 @@ impl<'a> Iterator for RawCmsgIterator<'a> {
let hdr: cmsghdr = unsafe { std::ptr::read_unaligned(buf.as_ptr() as *const cmsghdr) };
let data_off = mem::size_of::<cmsghdr>();
let data_end = hdr.cmsg_len;
let next_hdr = align(hdr.cmsg_len as usize);
let next_hdr = align(hdr.cmsg_len);
let data = &buf[data_off..data_end];
let item = ControlMessageRef {
cmsg_level: hdr.cmsg_level,

View File

@ -1,16 +1,14 @@
use std::io;
use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::io::{AsRawFd, OwnedFd, RawFd};
use tokio::io::unix::AsyncFd;
use crate::tools::Fd;
pub mod cmsg;
pub mod pipe;
pub mod rw_traits;
pub mod seq_packet;
pub async fn wrap_read<R, F>(async_fd: &AsyncFd<Fd>, mut call: F) -> io::Result<R>
pub async fn wrap_read<R, F>(async_fd: &AsyncFd<OwnedFd>, mut call: F) -> io::Result<R>
where
F: FnMut(RawFd) -> io::Result<R>,
{
@ -28,7 +26,7 @@ where
}
}
pub async fn wrap_write<R, F>(async_fd: &AsyncFd<Fd>, mut call: F) -> io::Result<R>
pub async fn wrap_write<R, F>(async_fd: &AsyncFd<OwnedFd>, mut call: F) -> io::Result<R>
where
F: FnMut(RawFd) -> io::Result<R>,
{

View File

@ -1,15 +1,14 @@
use std::convert::{TryFrom, TryInto};
use std::io;
use std::marker::PhantomData;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use std::pin::Pin;
use std::task::{Context, Poll};
use std::task::{ready, Context, Poll};
use tokio::io::unix::AsyncFd;
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
use crate::io::rw_traits;
use crate::tools::Fd;
pub use rw_traits::{Read, Write};
@ -20,15 +19,15 @@ pub use rw_traits::{Read, Write};
/// from the reactor, which will just break.
///
/// So we start out with this type which can be "upgraded" or "downgraded" into a `Pipe<T>` or
/// `Fd`.
pub struct PipeFd<RW>(Fd, PhantomData<RW>);
/// `OwnedFd`.
pub struct PipeFd<RW>(OwnedFd, PhantomData<RW>);
impl<RW> PipeFd<RW> {
pub fn new(fd: Fd) -> Self {
pub fn new(fd: OwnedFd) -> Self {
Self(fd, PhantomData)
}
pub fn into_fd(self) -> Fd {
pub fn into_fd(self) -> OwnedFd {
self.0
}
}
@ -38,7 +37,7 @@ pub fn pipe_fds() -> io::Result<(PipeFd<rw_traits::Read>, PipeFd<rw_traits::Writ
c_try!(unsafe { libc::pipe2(pfd.as_mut_ptr(), libc::O_CLOEXEC) });
let (fd_in, fd_out) = unsafe { (Fd::from_raw_fd(pfd[0]), Fd::from_raw_fd(pfd[1])) };
let (fd_in, fd_out) = unsafe { (OwnedFd::from_raw_fd(pfd[0]), OwnedFd::from_raw_fd(pfd[1])) };
Ok((PipeFd::new(fd_in), PipeFd::new(fd_out)))
}
@ -46,7 +45,7 @@ pub fn pipe_fds() -> io::Result<(PipeFd<rw_traits::Read>, PipeFd<rw_traits::Writ
/// Tokio supported pipe file descriptor. `tokio::fs::File` requires tokio's complete file system
/// feature gate, so we just use this `AsyncFd` wrapper.
pub struct Pipe<RW> {
fd: AsyncFd<Fd>,
fd: AsyncFd<OwnedFd>,
_phantom: PhantomData<RW>,
}

View File

@ -1,5 +1,5 @@
use std::io::{self, IoSlice, IoSliceMut};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::os::unix::io::{AsRawFd, FromRawFd, OwnedFd, RawFd};
use std::ptr;
use anyhow::Error;
@ -7,20 +7,19 @@ use nix::sys::socket::{self, AddressFamily, SockFlag, SockType, SockaddrLike};
use tokio::io::unix::AsyncFd;
use crate::tools::AssertSendSync;
use crate::tools::Fd;
fn seq_packet_socket(flags: SockFlag) -> nix::Result<Fd> {
fn seq_packet_socket(flags: SockFlag) -> nix::Result<OwnedFd> {
let fd = socket::socket(
AddressFamily::Unix,
SockType::SeqPacket,
flags | SockFlag::SOCK_CLOEXEC,
None,
)?;
Ok(unsafe { Fd::from_raw_fd(fd) })
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
}
pub struct SeqPacketListener {
fd: AsyncFd<Fd>,
fd: AsyncFd<OwnedFd>,
}
impl AsRawFd for SeqPacketListener {
@ -54,13 +53,13 @@ impl SeqPacketListener {
})
.await?;
let fd = unsafe { Fd::from_raw_fd(fd as RawFd) };
let fd = unsafe { OwnedFd::from_raw_fd(fd as RawFd) };
SeqPacketSocket::new(fd)
}
}
pub struct SeqPacketSocket {
fd: AsyncFd<Fd>,
fd: AsyncFd<OwnedFd>,
}
impl AsRawFd for SeqPacketSocket {
@ -71,7 +70,7 @@ impl AsRawFd for SeqPacketSocket {
}
impl SeqPacketSocket {
pub fn new(fd: Fd) -> io::Result<Self> {
pub fn new(fd: OwnedFd) -> io::Result<Self> {
Ok(Self {
fd: AsyncFd::new(fd)?,
})
@ -125,7 +124,7 @@ impl SeqPacketSocket {
});
let data_size = self.recvmsg(&mut msg).await?;
Ok((data_size, msg.0.msg_controllen as usize))
Ok((data_size, msg.0.msg_controllen))
}
#[inline]

View File

@ -6,7 +6,7 @@ use std::io::{self, IoSlice, IoSliceMut};
use std::mem;
use std::os::raw::{c_int, c_uint};
use std::os::unix::fs::FileExt;
use std::os::unix::io::{FromRawFd, RawFd};
use std::os::unix::io::{FromRawFd, OwnedFd, RawFd};
use anyhow::{bail, format_err, Error};
use lazy_static::lazy_static;
@ -17,7 +17,7 @@ use crate::io::cmsg;
use crate::io::seq_packet::SeqPacketSocket;
use crate::process::PidFd;
use crate::seccomp::{SeccompNotif, SeccompNotifResp, SeccompNotifSizes};
use crate::tools::{Fd, FromFd};
use crate::tools::FromFd;
/// Seccomp notification proxy message sent by the lxc monitor.
///
@ -82,7 +82,7 @@ unsafe fn io_vec<T>(value: &T) -> IoSlice {
lazy_static! {
static ref SECCOMP_SIZES: SeccompNotifSizes = SeccompNotifSizes::get_checked()
.map_err(|e| panic!("{}\nrefusing to run", e))
.map_err(|e| panic!("{e}\nrefusing to run"))
.unwrap();
}
@ -153,13 +153,13 @@ impl ProxyMessageBuffer {
bail!("expected SCM_RIGHTS control message");
}
let fds: Vec<Fd> = cmsg
let fds: Vec<OwnedFd> = cmsg
.data
.chunks_exact(mem::size_of::<RawFd>())
.map(|chunk| unsafe {
// clippy bug
#[allow(clippy::cast_ptr_alignment)]
Fd::from_raw_fd(std::ptr::read_unaligned(chunk.as_ptr() as _))
OwnedFd::from_raw_fd(std::ptr::read_unaligned(chunk.as_ptr() as _))
})
.collect();
@ -394,7 +394,7 @@ impl ProxyMessageBuffer {
/// Checked way to get a file descriptor argument.
#[inline]
pub fn arg_fd(&self, arg: u32, flags: c_int) -> Result<Fd, Error> {
pub fn arg_fd(&self, arg: u32, flags: c_int) -> Result<OwnedFd, Error> {
let fd = self.arg(arg)? as RawFd;
// we pass negative ones 'as-is', others get opened via the pidfd
Ok(if fd == libc::AT_FDCWD {
@ -402,7 +402,7 @@ impl ProxyMessageBuffer {
// might want to reuse this one?
self.pid_fd().fd_cwd()?
} else if fd < 0 {
Fd(fd)
unsafe { OwnedFd::from_raw_fd(fd) }
} else {
self.pid_fd().fd_num(fd, flags)?
})

View File

@ -10,12 +10,12 @@ macro_rules! c_str {
macro_rules! file_descriptor_type {
($type:ident) => {
#[repr(transparent)]
pub struct $type(RawFd);
pub struct $type(::std::os::unix::io::RawFd);
file_descriptor_impl!($type);
impl FromRawFd for $type {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
impl ::std::os::unix::io::FromRawFd for $type {
unsafe fn from_raw_fd(fd: ::std::os::unix::io::RawFd) -> Self {
Self(fd)
}
}
@ -34,14 +34,20 @@ macro_rules! file_descriptor_impl {
}
}
impl AsRawFd for $type {
fn as_raw_fd(&self) -> RawFd {
impl ::std::os::unix::io::AsFd for $type {
fn as_fd(&self) -> ::std::os::unix::io::BorrowedFd<'_> {
unsafe { ::std::os::unix::io::BorrowedFd::borrow_raw(self.0) }
}
}
impl ::std::os::unix::io::AsRawFd for $type {
fn as_raw_fd(&self) -> ::std::os::unix::io::RawFd {
self.0
}
}
impl IntoRawFd for $type {
fn into_raw_fd(mut self) -> RawFd {
impl ::std::os::unix::io::IntoRawFd for $type {
fn into_raw_fd(mut self) -> ::std::os::unix::io::RawFd {
let fd = self.0;
self.0 = -libc::EBADF;
fd
@ -78,13 +84,3 @@ macro_rules! io_bail {
return Err(::std::io::Error::new(::std::io::ErrorKind::Other, format!($($msg)*)));
};
}
macro_rules! ready {
($expr:expr) => {{
use std::task::Poll;
match $expr {
Poll::Ready(v) => v,
Poll::Pending => return Poll::Pending,
}
}};
}

View File

@ -106,12 +106,12 @@ fn main() {
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.worker_threads(cpus.max(2).min(4))
.worker_threads(cpus.clamp(2, 4))
.build()
.expect("failed to spawn tokio runtime");
if let Err(err) = rt.block_on(do_main(use_sd_notify, path)) {
eprintln!("error: {}", err);
eprintln!("error: {err}");
std::process::exit(1);
}
}

View File

@ -4,7 +4,7 @@ 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::os::unix::io::RawFd;
pub mod ns_type {
pub trait NsType {

View File

@ -4,7 +4,7 @@ use std::ffi::{CStr, CString, OsString};
use std::io::{self, BufRead, BufReader};
use std::os::raw::c_int;
use std::os::unix::ffi::OsStringExt;
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
use anyhow::{bail, Error};
use libc::pid_t;
@ -12,7 +12,6 @@ use libc::pid_t;
use crate::capability::Capabilities;
use crate::error::io_err_other;
use crate::nsfd::{ns_type, NsFd};
use crate::tools::Fd;
use super::{CGroups, IdMap, IdMapEntry, ProcStatus, Uids, UserCaps};
@ -25,7 +24,7 @@ impl PidFd {
}
pub fn open(pid: pid_t) -> io::Result<Self> {
let path = CString::new(format!("/proc/{}", pid)).unwrap();
let path = CString::new(format!("/proc/{pid}")).unwrap();
let fd = c_try!(unsafe { libc::open(path.as_ptr(), libc::O_DIRECTORY | libc::O_CLOEXEC) });
@ -38,7 +37,7 @@ impl PidFd {
///
/// The file descriptor must already be a valid pidfd, this is not checked. This function only
/// fails if reading the pid from the pidfd's proc entry fails.
pub unsafe fn try_from_fd(fd: Fd) -> io::Result<Self> {
pub unsafe fn try_from_fd(fd: OwnedFd) -> io::Result<Self> {
#[allow(clippy::unnecessary_cast)] // pid_t is a type alias
let mut this = Self(fd.into_raw_fd(), -1 as pid_t);
let pid = this.read_pid()?;
@ -58,23 +57,23 @@ impl PidFd {
NsFd::openat(self.0, c_str!("ns/user"))
}
fn fd(&self, path: &CStr, flags: c_int, mode: c_int) -> io::Result<Fd> {
Ok(Fd(c_try!(unsafe {
libc::openat(
fn fd(&self, path: &CStr, flags: c_int, mode: c_int) -> io::Result<OwnedFd> {
Ok(unsafe {
OwnedFd::from_raw_fd(c_try!(libc::openat(
self.as_raw_fd(),
path.as_ptr() as *const _,
flags | libc::O_CLOEXEC,
mode,
)
})))
)))
})
}
pub fn fd_cwd(&self) -> io::Result<Fd> {
pub fn fd_cwd(&self) -> io::Result<OwnedFd> {
self.fd(c_str!("cwd"), libc::O_DIRECTORY, 0)
}
pub fn fd_num(&self, num: RawFd, flags: c_int) -> io::Result<Fd> {
let path = format!("fd/{}\0", num);
pub fn fd_num(&self, num: RawFd, flags: c_int) -> io::Result<OwnedFd> {
let path = format!("fd/{num}\0");
self.fd(
unsafe { CStr::from_bytes_with_nul_unchecked(path.as_bytes()) },
flags,

View File

@ -1,5 +1,5 @@
use std::ffi::CString;
use std::os::unix::io::AsRawFd;
use std::os::unix::io::{AsRawFd, OwnedFd};
use anyhow::Error;
use nix::errno::Errno;
@ -10,7 +10,6 @@ use crate::lxcseccomp::ProxyMessageBuffer;
use crate::process::PidFd;
use crate::sc_libc_try;
use crate::syscall::SyscallStatus;
use crate::tools::Fd;
pub async fn mknod(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> {
let mode = msg.arg_mode_t(1)?;
@ -61,7 +60,7 @@ fn check_mknod_dev(mode: stat::mode_t, dev: stat::dev_t) -> bool {
async fn do_mknodat(
pidfd: &PidFd,
dirfd: Fd,
dirfd: OwnedFd,
pathname: CString,
mode: stat::mode_t,
dev: stat::dev_t,

View File

@ -3,37 +3,14 @@
//! Note that this should stay small, otherwise we should introduce a dependency on our `proxmox`
//! crate as that's where we have all this stuff usually...
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
/// Guard a raw file descriptor with a drop handler. This is mostly useful when access to an owned
/// `RawFd` is required without the corresponding handler object (such as when only the file
/// descriptor number is required in a closure which may be dropped instead of being executed).
#[repr(transparent)]
pub struct Fd(pub RawFd);
file_descriptor_impl!(Fd);
impl FromRawFd for Fd {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
Self(fd)
}
}
impl Fd {
pub fn set_nonblocking(&mut self, nb: bool) -> nix::Result<libc::c_int> {
use nix::fcntl;
let mut flags =
fcntl::OFlag::from_bits(fcntl::fcntl(self.0, fcntl::FcntlArg::F_GETFL)?).unwrap();
flags.set(fcntl::OFlag::O_NONBLOCK, nb);
fcntl::fcntl(self.0, fcntl::FcntlArg::F_SETFL(flags))
}
}
impl AsRef<RawFd> for Fd {
#[inline]
fn as_ref(&self) -> &RawFd {
&self.0
}
pub fn set_fd_nonblocking<T: AsRawFd + ?Sized>(fd: &T, on: bool) -> nix::Result<libc::c_int> {
use nix::fcntl;
let fd = fd.as_raw_fd();
let mut flags = fcntl::OFlag::from_bits(fcntl::fcntl(fd, fcntl::FcntlArg::F_GETFL)?).unwrap();
flags.set(fcntl::OFlag::O_NONBLOCK, on);
fcntl::fcntl(fd, fcntl::FcntlArg::F_SETFL(flags))
}
/// Byte vector utilities.
@ -62,11 +39,11 @@ pub mod vec {
}
pub trait FromFd {
fn from_fd(fd: Fd) -> Self;
fn from_fd<T: IntoRawFd>(fd: T) -> Self;
}
impl<T: FromRawFd> FromFd for T {
fn from_fd(fd: Fd) -> Self {
fn from_fd<F: IntoRawFd>(fd: F) -> Self {
unsafe { Self::from_raw_fd(fd.into_raw_fd()) }
}
}