Merge 1.3.0
This commit is contained in:
commit
e8b153031a
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "pve-lxc-syscalld"
|
name = "pve-lxc-syscalld"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
version = "1.2.2"
|
version = "1.3.0"
|
||||||
authors = [
|
authors = [
|
||||||
"Wolfgang Bumiller <w.bumiller@proxmox.com>",
|
"Wolfgang Bumiller <w.bumiller@proxmox.com>",
|
||||||
]
|
]
|
||||||
@ -9,13 +9,15 @@ license = "AGPL-3"
|
|||||||
description = "Proxmox LXC seccomp-proxy syscall handler daemon"
|
description = "Proxmox LXC seccomp-proxy syscall handler daemon"
|
||||||
homepage = "https://www.proxmox.com"
|
homepage = "https://www.proxmox.com"
|
||||||
|
|
||||||
exclude = [ "build", "debian" ]
|
rust-version = "1.64"
|
||||||
|
|
||||||
|
exclude = [ "debian" ]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
bitflags = "1.2"
|
bitflags = "1.2"
|
||||||
lazy_static = "1.4"
|
lazy_static = "1.4"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
nix = "0.24"
|
nix = "0.26"
|
||||||
num_cpus = "1"
|
num_cpus = "1"
|
||||||
tokio = { version = "1.0", features = [ "rt-multi-thread", "io-util", "net" ] }
|
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))
|
$(addprefix $(COMPILEDIR)/,$(SERVICE_BIN))
|
||||||
|
|
||||||
DEB=$(PACKAGE)_$(DEB_VERSION)_$(DEB_HOST_ARCH).deb
|
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)
|
all: cargo-build $(SUBDIRS)
|
||||||
|
|
||||||
@ -39,12 +41,6 @@ test:
|
|||||||
.PHONY: check
|
.PHONY: check
|
||||||
check: test
|
check: test
|
||||||
|
|
||||||
.PHONY: san
|
|
||||||
san:
|
|
||||||
cargo +nightly fmt -- --check
|
|
||||||
cargo clippy
|
|
||||||
cargo test
|
|
||||||
|
|
||||||
$(COMPILED_BINS): cargo-build
|
$(COMPILED_BINS): cargo-build
|
||||||
|
|
||||||
install: $(COMPILED_BINS)
|
install: $(COMPILED_BINS)
|
||||||
@ -52,43 +48,38 @@ install: $(COMPILED_BINS)
|
|||||||
$(foreach i,$(SERVICE_BIN), \
|
$(foreach i,$(SERVICE_BIN), \
|
||||||
install -m755 $(COMPILEDIR)/$(i) $(DESTDIR)$(LIBEXECDIR)/pve-lxc-syscalld/ ;)
|
install -m755 $(COMPILEDIR)/$(i) $(DESTDIR)$(LIBEXECDIR)/pve-lxc-syscalld/ ;)
|
||||||
|
|
||||||
.PHONY: build
|
$(BUILDDIR): src debian etc Cargo.toml
|
||||||
build:
|
rm -rf $(BUILDDIR) $(BUILDDIR).tmp
|
||||||
rm -rf build
|
mkdir $(BUILDDIR).tmp
|
||||||
debcargo package \
|
#mkdir $(BUILDDIR).tmp/.cargo
|
||||||
--config debian/debcargo.toml \
|
cp -a -t $(BUILDDIR).tmp $^ Makefile defines.mk
|
||||||
--changelog-ready \
|
#cp -a -t $(BUILDDIR).tmp/.cargo .cargo/config
|
||||||
--no-overlay-write-back \
|
echo "git clone git://git.proxmox.com/git/pve-lxc-syscalld.git\\ngit checkout $(shell git rev-parse HEAD)" > $(BUILDDIR).tmp/debian/SOURCE
|
||||||
--directory build \
|
mv $(BUILDDIR).tmp $(BUILDDIR)
|
||||||
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 ;)
|
|
||||||
|
|
||||||
.PHONY: deb
|
.PHONY: deb
|
||||||
deb: $(DEB)
|
deb: $(DEB)
|
||||||
$(DEB): build
|
$(DEB): $(BUILDDIR)
|
||||||
cd build; dpkg-buildpackage -b -us -uc --no-pre-clean --build-profiles=nodoc
|
cd $(BUILDDIR); dpkg-buildpackage -b -us -uc
|
||||||
lintian $(DEB)
|
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
|
.PHONY: dsc
|
||||||
dsc: $(DSC)
|
dsc: $(DSC)
|
||||||
$(DSC): build
|
$(DSC): $(BUILDDIR)
|
||||||
cd build; dpkg-buildpackage -S -us -uc -d -nc
|
cd $(BUILDDIR); dpkg-buildpackage -S -us -uc -d
|
||||||
lintian $(DSC)
|
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
|
.PHONY: dinstall
|
||||||
dinstall:
|
dinstall:
|
||||||
$(MAKE) deb
|
$(MAKE) deb
|
||||||
@ -97,5 +88,6 @@ dinstall:
|
|||||||
clean:
|
clean:
|
||||||
$(foreach i,$(SUBDIRS), \
|
$(foreach i,$(SUBDIRS), \
|
||||||
$(MAKE) -C $(i) clean ;)
|
$(MAKE) -C $(i) clean ;)
|
||||||
cargo clean
|
rm -rf ./target
|
||||||
rm -rf *.deb *.dsc *.tar.gz *.buildinfo *.changes build
|
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
|
rust-pve-lxc-syscalld (1.2.2-1) pve; urgency=medium
|
||||||
|
|
||||||
* remove old poll/event handling for SEQPACKET socket
|
* 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>
|
Files:
|
||||||
|
*
|
||||||
This program is free software: you can redistribute it and/or modify
|
Copyright: 2019 - 2023 Proxmox Server Solutions GmbH <support@proxmox.com>
|
||||||
it under the terms of the GNU Affero General Public License as published by
|
License: AGPL-3.0-or-later
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
This program is free software: you can redistribute it and/or modify it under
|
||||||
(at your option) any later version.
|
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
|
||||||
This program is distributed in the hope that it will be useful,
|
later version.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
.
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
GNU Affero General Public License for more details.
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||||
You should have received a copy of the GNU Affero General Public License
|
details.
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
.
|
||||||
|
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 $@
|
dh $@
|
||||||
|
|
||||||
override_dh_auto_configure:
|
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
|
$(CARGO) prepare-debian $(CURDIR)/debian/cargo_registry --link-from-system
|
||||||
dh_auto_configure
|
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>>,
|
F: std::future::Future<Output = Result<(), Error>>,
|
||||||
{
|
{
|
||||||
if let Err(err) = fut.await {
|
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) {
|
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() });
|
let pid = c_try!(unsafe { libc::fork() });
|
||||||
if pid == 0 {
|
if pid == 0 {
|
||||||
drop(pipe_r);
|
drop(pipe_r);
|
||||||
let mut pipe_w = pipe_w.into_fd();
|
let pipe_w = pipe_w.into_fd();
|
||||||
let _ = std::panic::catch_unwind(move || {
|
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 mut pipe_w = unsafe { std::fs::File::from_raw_fd(pipe_w.into_raw_fd()) };
|
||||||
let out = match func() {
|
let out = match func() {
|
||||||
Ok(SyscallStatus::Ok(val)) => Data {
|
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 hdr: cmsghdr = unsafe { std::ptr::read_unaligned(buf.as_ptr() as *const cmsghdr) };
|
||||||
let data_off = mem::size_of::<cmsghdr>();
|
let data_off = mem::size_of::<cmsghdr>();
|
||||||
let data_end = hdr.cmsg_len;
|
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 data = &buf[data_off..data_end];
|
||||||
let item = ControlMessageRef {
|
let item = ControlMessageRef {
|
||||||
cmsg_level: hdr.cmsg_level,
|
cmsg_level: hdr.cmsg_level,
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::os::unix::io::{AsRawFd, RawFd};
|
use std::os::unix::io::{AsRawFd, OwnedFd, RawFd};
|
||||||
|
|
||||||
use tokio::io::unix::AsyncFd;
|
use tokio::io::unix::AsyncFd;
|
||||||
|
|
||||||
use crate::tools::Fd;
|
|
||||||
|
|
||||||
pub mod cmsg;
|
pub mod cmsg;
|
||||||
pub mod pipe;
|
pub mod pipe;
|
||||||
pub mod rw_traits;
|
pub mod rw_traits;
|
||||||
pub mod seq_packet;
|
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
|
where
|
||||||
F: FnMut(RawFd) -> io::Result<R>,
|
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
|
where
|
||||||
F: FnMut(RawFd) -> io::Result<R>,
|
F: FnMut(RawFd) -> io::Result<R>,
|
||||||
{
|
{
|
||||||
|
@ -1,15 +1,14 @@
|
|||||||
use std::convert::{TryFrom, TryInto};
|
use std::convert::{TryFrom, TryInto};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::marker::PhantomData;
|
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::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{ready, Context, Poll};
|
||||||
|
|
||||||
use tokio::io::unix::AsyncFd;
|
use tokio::io::unix::AsyncFd;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
|
|
||||||
use crate::io::rw_traits;
|
use crate::io::rw_traits;
|
||||||
use crate::tools::Fd;
|
|
||||||
|
|
||||||
pub use rw_traits::{Read, Write};
|
pub use rw_traits::{Read, Write};
|
||||||
|
|
||||||
@ -20,15 +19,15 @@ pub use rw_traits::{Read, Write};
|
|||||||
/// from the reactor, which will just break.
|
/// 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
|
/// So we start out with this type which can be "upgraded" or "downgraded" into a `Pipe<T>` or
|
||||||
/// `Fd`.
|
/// `OwnedFd`.
|
||||||
pub struct PipeFd<RW>(Fd, PhantomData<RW>);
|
pub struct PipeFd<RW>(OwnedFd, PhantomData<RW>);
|
||||||
|
|
||||||
impl<RW> PipeFd<RW> {
|
impl<RW> PipeFd<RW> {
|
||||||
pub fn new(fd: Fd) -> Self {
|
pub fn new(fd: OwnedFd) -> Self {
|
||||||
Self(fd, PhantomData)
|
Self(fd, PhantomData)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_fd(self) -> Fd {
|
pub fn into_fd(self) -> OwnedFd {
|
||||||
self.0
|
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) });
|
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)))
|
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
|
/// Tokio supported pipe file descriptor. `tokio::fs::File` requires tokio's complete file system
|
||||||
/// feature gate, so we just use this `AsyncFd` wrapper.
|
/// feature gate, so we just use this `AsyncFd` wrapper.
|
||||||
pub struct Pipe<RW> {
|
pub struct Pipe<RW> {
|
||||||
fd: AsyncFd<Fd>,
|
fd: AsyncFd<OwnedFd>,
|
||||||
_phantom: PhantomData<RW>,
|
_phantom: PhantomData<RW>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::io::{self, IoSlice, IoSliceMut};
|
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 std::ptr;
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
@ -7,20 +7,19 @@ use nix::sys::socket::{self, AddressFamily, SockFlag, SockType, SockaddrLike};
|
|||||||
use tokio::io::unix::AsyncFd;
|
use tokio::io::unix::AsyncFd;
|
||||||
|
|
||||||
use crate::tools::AssertSendSync;
|
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(
|
let fd = socket::socket(
|
||||||
AddressFamily::Unix,
|
AddressFamily::Unix,
|
||||||
SockType::SeqPacket,
|
SockType::SeqPacket,
|
||||||
flags | SockFlag::SOCK_CLOEXEC,
|
flags | SockFlag::SOCK_CLOEXEC,
|
||||||
None,
|
None,
|
||||||
)?;
|
)?;
|
||||||
Ok(unsafe { Fd::from_raw_fd(fd) })
|
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SeqPacketListener {
|
pub struct SeqPacketListener {
|
||||||
fd: AsyncFd<Fd>,
|
fd: AsyncFd<OwnedFd>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for SeqPacketListener {
|
impl AsRawFd for SeqPacketListener {
|
||||||
@ -54,13 +53,13 @@ impl SeqPacketListener {
|
|||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let fd = unsafe { Fd::from_raw_fd(fd as RawFd) };
|
let fd = unsafe { OwnedFd::from_raw_fd(fd as RawFd) };
|
||||||
SeqPacketSocket::new(fd)
|
SeqPacketSocket::new(fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct SeqPacketSocket {
|
pub struct SeqPacketSocket {
|
||||||
fd: AsyncFd<Fd>,
|
fd: AsyncFd<OwnedFd>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for SeqPacketSocket {
|
impl AsRawFd for SeqPacketSocket {
|
||||||
@ -71,7 +70,7 @@ impl AsRawFd for SeqPacketSocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SeqPacketSocket {
|
impl SeqPacketSocket {
|
||||||
pub fn new(fd: Fd) -> io::Result<Self> {
|
pub fn new(fd: OwnedFd) -> io::Result<Self> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
fd: AsyncFd::new(fd)?,
|
fd: AsyncFd::new(fd)?,
|
||||||
})
|
})
|
||||||
@ -125,7 +124,7 @@ impl SeqPacketSocket {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let data_size = self.recvmsg(&mut msg).await?;
|
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]
|
#[inline]
|
||||||
|
@ -6,7 +6,7 @@ use std::io::{self, IoSlice, IoSliceMut};
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
use std::os::raw::{c_int, c_uint};
|
use std::os::raw::{c_int, c_uint};
|
||||||
use std::os::unix::fs::FileExt;
|
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 anyhow::{bail, format_err, Error};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
@ -17,7 +17,7 @@ use crate::io::cmsg;
|
|||||||
use crate::io::seq_packet::SeqPacketSocket;
|
use crate::io::seq_packet::SeqPacketSocket;
|
||||||
use crate::process::PidFd;
|
use crate::process::PidFd;
|
||||||
use crate::seccomp::{SeccompNotif, SeccompNotifResp, SeccompNotifSizes};
|
use crate::seccomp::{SeccompNotif, SeccompNotifResp, SeccompNotifSizes};
|
||||||
use crate::tools::{Fd, FromFd};
|
use crate::tools::FromFd;
|
||||||
|
|
||||||
/// Seccomp notification proxy message sent by the lxc monitor.
|
/// Seccomp notification proxy message sent by the lxc monitor.
|
||||||
///
|
///
|
||||||
@ -82,7 +82,7 @@ unsafe fn io_vec<T>(value: &T) -> IoSlice {
|
|||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref SECCOMP_SIZES: SeccompNotifSizes = SeccompNotifSizes::get_checked()
|
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();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,13 +153,13 @@ impl ProxyMessageBuffer {
|
|||||||
bail!("expected SCM_RIGHTS control message");
|
bail!("expected SCM_RIGHTS control message");
|
||||||
}
|
}
|
||||||
|
|
||||||
let fds: Vec<Fd> = cmsg
|
let fds: Vec<OwnedFd> = cmsg
|
||||||
.data
|
.data
|
||||||
.chunks_exact(mem::size_of::<RawFd>())
|
.chunks_exact(mem::size_of::<RawFd>())
|
||||||
.map(|chunk| unsafe {
|
.map(|chunk| unsafe {
|
||||||
// clippy bug
|
// clippy bug
|
||||||
#[allow(clippy::cast_ptr_alignment)]
|
#[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();
|
.collect();
|
||||||
|
|
||||||
@ -394,7 +394,7 @@ impl ProxyMessageBuffer {
|
|||||||
|
|
||||||
/// Checked way to get a file descriptor argument.
|
/// Checked way to get a file descriptor argument.
|
||||||
#[inline]
|
#[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;
|
let fd = self.arg(arg)? as RawFd;
|
||||||
// we pass negative ones 'as-is', others get opened via the pidfd
|
// we pass negative ones 'as-is', others get opened via the pidfd
|
||||||
Ok(if fd == libc::AT_FDCWD {
|
Ok(if fd == libc::AT_FDCWD {
|
||||||
@ -402,7 +402,7 @@ impl ProxyMessageBuffer {
|
|||||||
// might want to reuse this one?
|
// might want to reuse this one?
|
||||||
self.pid_fd().fd_cwd()?
|
self.pid_fd().fd_cwd()?
|
||||||
} else if fd < 0 {
|
} else if fd < 0 {
|
||||||
Fd(fd)
|
unsafe { OwnedFd::from_raw_fd(fd) }
|
||||||
} else {
|
} else {
|
||||||
self.pid_fd().fd_num(fd, flags)?
|
self.pid_fd().fd_num(fd, flags)?
|
||||||
})
|
})
|
||||||
|
@ -10,12 +10,12 @@ macro_rules! c_str {
|
|||||||
macro_rules! file_descriptor_type {
|
macro_rules! file_descriptor_type {
|
||||||
($type:ident) => {
|
($type:ident) => {
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct $type(RawFd);
|
pub struct $type(::std::os::unix::io::RawFd);
|
||||||
|
|
||||||
file_descriptor_impl!($type);
|
file_descriptor_impl!($type);
|
||||||
|
|
||||||
impl FromRawFd for $type {
|
impl ::std::os::unix::io::FromRawFd for $type {
|
||||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
unsafe fn from_raw_fd(fd: ::std::os::unix::io::RawFd) -> Self {
|
||||||
Self(fd)
|
Self(fd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,14 +34,20 @@ macro_rules! file_descriptor_impl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for $type {
|
impl ::std::os::unix::io::AsFd for $type {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
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
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoRawFd for $type {
|
impl ::std::os::unix::io::IntoRawFd for $type {
|
||||||
fn into_raw_fd(mut self) -> RawFd {
|
fn into_raw_fd(mut self) -> ::std::os::unix::io::RawFd {
|
||||||
let fd = self.0;
|
let fd = self.0;
|
||||||
self.0 = -libc::EBADF;
|
self.0 = -libc::EBADF;
|
||||||
fd
|
fd
|
||||||
@ -78,13 +84,3 @@ macro_rules! io_bail {
|
|||||||
return Err(::std::io::Error::new(::std::io::ErrorKind::Other, format!($($msg)*)));
|
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()
|
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
.worker_threads(cpus.max(2).min(4))
|
.worker_threads(cpus.clamp(2, 4))
|
||||||
.build()
|
.build()
|
||||||
.expect("failed to spawn tokio runtime");
|
.expect("failed to spawn tokio runtime");
|
||||||
|
|
||||||
if let Err(err) = rt.block_on(do_main(use_sd_notify, path)) {
|
if let Err(err) = rt.block_on(do_main(use_sd_notify, path)) {
|
||||||
eprintln!("error: {}", err);
|
eprintln!("error: {err}");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@ use std::ffi::CStr;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::os::raw::c_int;
|
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 mod ns_type {
|
||||||
pub trait NsType {
|
pub trait NsType {
|
||||||
|
@ -4,7 +4,7 @@ use std::ffi::{CStr, CString, OsString};
|
|||||||
use std::io::{self, BufRead, BufReader};
|
use std::io::{self, BufRead, BufReader};
|
||||||
use std::os::raw::c_int;
|
use std::os::raw::c_int;
|
||||||
use std::os::unix::ffi::OsStringExt;
|
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 anyhow::{bail, Error};
|
||||||
use libc::pid_t;
|
use libc::pid_t;
|
||||||
@ -12,7 +12,6 @@ use libc::pid_t;
|
|||||||
use crate::capability::Capabilities;
|
use crate::capability::Capabilities;
|
||||||
use crate::error::io_err_other;
|
use crate::error::io_err_other;
|
||||||
use crate::nsfd::{ns_type, NsFd};
|
use crate::nsfd::{ns_type, NsFd};
|
||||||
use crate::tools::Fd;
|
|
||||||
|
|
||||||
use super::{CGroups, IdMap, IdMapEntry, ProcStatus, Uids, UserCaps};
|
use super::{CGroups, IdMap, IdMapEntry, ProcStatus, Uids, UserCaps};
|
||||||
|
|
||||||
@ -25,7 +24,7 @@ impl PidFd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn open(pid: pid_t) -> io::Result<Self> {
|
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) });
|
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
|
/// 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.
|
/// 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
|
#[allow(clippy::unnecessary_cast)] // pid_t is a type alias
|
||||||
let mut this = Self(fd.into_raw_fd(), -1 as pid_t);
|
let mut this = Self(fd.into_raw_fd(), -1 as pid_t);
|
||||||
let pid = this.read_pid()?;
|
let pid = this.read_pid()?;
|
||||||
@ -58,23 +57,23 @@ impl PidFd {
|
|||||||
NsFd::openat(self.0, c_str!("ns/user"))
|
NsFd::openat(self.0, c_str!("ns/user"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fd(&self, path: &CStr, flags: c_int, mode: c_int) -> io::Result<Fd> {
|
fn fd(&self, path: &CStr, flags: c_int, mode: c_int) -> io::Result<OwnedFd> {
|
||||||
Ok(Fd(c_try!(unsafe {
|
Ok(unsafe {
|
||||||
libc::openat(
|
OwnedFd::from_raw_fd(c_try!(libc::openat(
|
||||||
self.as_raw_fd(),
|
self.as_raw_fd(),
|
||||||
path.as_ptr() as *const _,
|
path.as_ptr() as *const _,
|
||||||
flags | libc::O_CLOEXEC,
|
flags | libc::O_CLOEXEC,
|
||||||
mode,
|
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)
|
self.fd(c_str!("cwd"), libc::O_DIRECTORY, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fd_num(&self, num: RawFd, flags: c_int) -> io::Result<Fd> {
|
pub fn fd_num(&self, num: RawFd, flags: c_int) -> io::Result<OwnedFd> {
|
||||||
let path = format!("fd/{}\0", num);
|
let path = format!("fd/{num}\0");
|
||||||
self.fd(
|
self.fd(
|
||||||
unsafe { CStr::from_bytes_with_nul_unchecked(path.as_bytes()) },
|
unsafe { CStr::from_bytes_with_nul_unchecked(path.as_bytes()) },
|
||||||
flags,
|
flags,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::os::unix::io::AsRawFd;
|
use std::os::unix::io::{AsRawFd, OwnedFd};
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use nix::errno::Errno;
|
use nix::errno::Errno;
|
||||||
@ -10,7 +10,6 @@ use crate::lxcseccomp::ProxyMessageBuffer;
|
|||||||
use crate::process::PidFd;
|
use crate::process::PidFd;
|
||||||
use crate::sc_libc_try;
|
use crate::sc_libc_try;
|
||||||
use crate::syscall::SyscallStatus;
|
use crate::syscall::SyscallStatus;
|
||||||
use crate::tools::Fd;
|
|
||||||
|
|
||||||
pub async fn mknod(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> {
|
pub async fn mknod(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> {
|
||||||
let mode = msg.arg_mode_t(1)?;
|
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(
|
async fn do_mknodat(
|
||||||
pidfd: &PidFd,
|
pidfd: &PidFd,
|
||||||
dirfd: Fd,
|
dirfd: OwnedFd,
|
||||||
pathname: CString,
|
pathname: CString,
|
||||||
mode: stat::mode_t,
|
mode: stat::mode_t,
|
||||||
dev: stat::dev_t,
|
dev: stat::dev_t,
|
||||||
|
39
src/tools.rs
39
src/tools.rs
@ -3,37 +3,14 @@
|
|||||||
//! Note that this should stay small, otherwise we should introduce a dependency on our `proxmox`
|
//! 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...
|
//! 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
|
pub fn set_fd_nonblocking<T: AsRawFd + ?Sized>(fd: &T, on: bool) -> nix::Result<libc::c_int> {
|
||||||
/// `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;
|
use nix::fcntl;
|
||||||
let mut flags =
|
let fd = fd.as_raw_fd();
|
||||||
fcntl::OFlag::from_bits(fcntl::fcntl(self.0, fcntl::FcntlArg::F_GETFL)?).unwrap();
|
let mut flags = fcntl::OFlag::from_bits(fcntl::fcntl(fd, fcntl::FcntlArg::F_GETFL)?).unwrap();
|
||||||
flags.set(fcntl::OFlag::O_NONBLOCK, nb);
|
flags.set(fcntl::OFlag::O_NONBLOCK, on);
|
||||||
fcntl::fcntl(self.0, fcntl::FcntlArg::F_SETFL(flags))
|
fcntl::fcntl(fd, fcntl::FcntlArg::F_SETFL(flags))
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AsRef<RawFd> for Fd {
|
|
||||||
#[inline]
|
|
||||||
fn as_ref(&self) -> &RawFd {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Byte vector utilities.
|
/// Byte vector utilities.
|
||||||
@ -62,11 +39,11 @@ pub mod vec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait FromFd {
|
pub trait FromFd {
|
||||||
fn from_fd(fd: Fd) -> Self;
|
fn from_fd<T: IntoRawFd>(fd: T) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromRawFd> FromFd for T {
|
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()) }
|
unsafe { Self::from_raw_fd(fd.into_raw_fd()) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user