Merge 1.3.0
This commit is contained in:
commit
e8b153031a
@ -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" ] }
|
||||
|
66
Makefile
66
Makefile
@ -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
6
debian/changelog
vendored
@ -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
1
debian/compat
vendored
@ -1 +0,0 @@
|
||||
12
|
33
debian/control
vendored
Normal file
33
debian/control
vendored
Normal 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
6
debian/control.in
vendored
@ -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
32
debian/copyright
vendored
@ -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
11
debian/debcargo.toml
vendored
@ -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
2
debian/rules
vendored
@ -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
|
||||
|
||||
|
2
debian/source/format
vendored
2
debian/source/format
vendored
@ -1 +1 @@
|
||||
3.0 (quilt)
|
||||
3.0 (native)
|
||||
|
@ -1 +0,0 @@
|
||||
edition = "2018"
|
@ -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})");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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>,
|
||||
{
|
||||
|
@ -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>,
|
||||
}
|
||||
|
||||
|
@ -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]
|
||||
|
@ -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)?
|
||||
})
|
||||
|
@ -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,
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
41
src/tools.rs
41
src/tools.rs
@ -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()) }
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user