Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/sandlock-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ libc = "0.2.191"
log = "0.4"
syscalls = { version = "0.8", default-features = false }
nix = { version = "0.29", features = ["dir", "user"] }
tokio = { version = "1", features = ["rt", "net", "time", "sync", "macros", "io-util", "fs"] }
tokio = { version = "1.53.3", features = ["rt", "net", "time", "sync", "macros", "io-util", "fs"] }
tokio-util = "0.7"
serde = { version = "1", features = ["derive"] }
thiserror = "2"
Expand Down
6 changes: 4 additions & 2 deletions crates/sandlock-core/src/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,8 @@ fn peer_cred(fd: RawFd) -> Option<libc::ucred> {

fn into_async(fd: ControlFd) -> Option<AsyncFd<ControlFd>> {
fd.set_nonblocking().ok()?;
AsyncFd::new(fd).ok()
// SAFETY: the AsyncFd owns the ControlFd, which closes only on drop.
unsafe { AsyncFd::register(fd) }.ok()
}

async fn accept(listener: &AsyncFd<ControlFd>) -> std::io::Result<ControlFd> {
Expand Down Expand Up @@ -311,7 +312,8 @@ async fn control_loop(
if peer_cred(stream.as_raw_fd()).map(|c| c.uid) != Some(my_uid) {
continue;
}
let Ok(stream) = AsyncFd::new(stream).map(ControlStream) else {
// SAFETY: the AsyncFd owns the ControlFd, which closes only on drop.
let Ok(stream) = unsafe { AsyncFd::register(stream) }.map(ControlStream) else {
continue;
};
let _ = tokio::time::timeout(
Expand Down
9 changes: 7 additions & 2 deletions crates/sandlock-core/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,13 @@ impl MainExit {
let Some(fd) = &self.pipe else {
return Err(std::io::Error::other("main's exit has no status pipe"));
};
let ready =
tokio::io::unix::AsyncFd::with_interest(fd.as_raw_fd(), tokio::io::Interest::READABLE)?;
// SAFETY: the AsyncFd owns its own dup of the pipe.
let ready = unsafe {
tokio::io::unix::AsyncFd::register_with_interest(
fd.try_clone()?,
tokio::io::Interest::READABLE,
)
}?;
loop {
if let Some(exit) = self.get() {
return Ok(exit);
Expand Down
3 changes: 2 additions & 1 deletion crates/sandlock-core/src/netlink/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ pub fn spawn_responder(
}

async fn responder_loop(fd: OwnedFd, reply_pid: u32) -> std::io::Result<()> {
let async_fd = AsyncFd::with_interest(fd, Interest::READABLE)?;
// SAFETY: the AsyncFd owns the fd.
let async_fd = unsafe { AsyncFd::register_with_interest(fd, Interest::READABLE) }?;
let mut buf = vec![0u8; RECV_BUF];

loop {
Expand Down
7 changes: 5 additions & 2 deletions crates/sandlock-core/src/network/send_engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,11 @@ async fn push_until_done(
flags: i32,
mut offset: usize,
) -> Result<usize, i32> {
let afd = tokio::io::unix::AsyncFd::with_interest(dup_fd, tokio::io::Interest::WRITABLE)
.map_err(|_| libc::EIO)?;
// SAFETY: the AsyncFd owns the fd.
let afd = unsafe {
tokio::io::unix::AsyncFd::register_with_interest(dup_fd, tokio::io::Interest::WRITABLE)
}
.map_err(|_| libc::EIO)?;
loop {
let mut guard = afd.writable().await.map_err(|_| libc::EIO)?;
let ret = send_materialized_at(
Expand Down
6 changes: 5 additions & 1 deletion crates/sandlock-core/src/reaper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ impl Reaper {

/// The reaper exits once the session has no process left.
pub async fn exit(&self) {
if let Ok(fd) = tokio::io::unix::AsyncFd::new(self.pidfd.as_raw_fd()) {
let Ok(pidfd) = self.pidfd.try_clone() else {
return;
};
// SAFETY: the AsyncFd owns its own dup of the pidfd.
if let Ok(fd) = unsafe { tokio::io::unix::AsyncFd::register(pidfd) } {
let _ = fd.readable().await;
}
}
Expand Down
12 changes: 7 additions & 5 deletions crates/sandlock-core/src/sandbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3587,11 +3587,13 @@ async fn wait_child_exit_via_pidfd(
) -> crate::result::ExitStatus {
use crate::result::ExitStatus;

let async_fd =
match tokio::io::unix::AsyncFd::with_interest(pidfd, tokio::io::Interest::READABLE) {
Ok(fd) => fd,
Err(_) => return wait_child_exit_blocking(pid).await,
};
// SAFETY: the AsyncFd owns the pidfd.
let async_fd = match unsafe {
tokio::io::unix::AsyncFd::register_with_interest(pidfd, tokio::io::Interest::READABLE)
} {
Ok(fd) => fd,
Err(_) => return wait_child_exit_blocking(pid).await,
};

loop {
// pidfd becomes readable when the process exits; no data is read.
Expand Down
39 changes: 22 additions & 17 deletions crates/sandlock-core/src/seccomp/notif.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3369,13 +3369,16 @@ pub async fn supervisor(
) {
// Register the notif fd with the Tokio IO driver so we can wait for
// readiness via epoll instead of a dedicated blocking thread.
let async_fd = match tokio::io::unix::AsyncFd::with_interest(
Arc::new(notif_fd),
tokio::io::Interest::READABLE,
) {
// SAFETY: the AsyncFd holds a strong reference, so the fd outlives it.
let async_fd = match unsafe {
tokio::io::unix::AsyncFd::register_with_interest(
Arc::new(notif_fd),
tokio::io::Interest::READABLE,
)
} {
Ok(fd) => fd,
Err(err) => {
let _ = startup.send(Err(err));
let _ = startup.send(Err(err.into()));
return;
}
};
Expand Down Expand Up @@ -3499,18 +3502,20 @@ pub(crate) fn spawn_pid_watcher(
pidfd: Arc<std::os::unix::io::OwnedFd>,
) {
tokio::spawn(async move {
let async_fd =
match tokio::io::unix::AsyncFd::with_interest(pidfd, tokio::io::Interest::READABLE) {
Ok(f) => f,
Err(_) => {
// AsyncFd registration failed (extremely unusual);
// fall back to immediate cleanup so we don't leak the
// index entry. The process is still alive, so its slot
// stays held until `release_exited_slots` sees it die.
cleanup_pid(&ctx, key).await;
return;
}
};
// SAFETY: the AsyncFd holds a strong reference, so the fd outlives it.
let async_fd = match unsafe {
tokio::io::unix::AsyncFd::register_with_interest(pidfd, tokio::io::Interest::READABLE)
} {
Ok(f) => f,
Err(_) => {
// AsyncFd registration failed (extremely unusual);
// fall back to immediate cleanup so we don't leak the
// index entry. The process is still alive, so its slot
// stays held until `release_exited_slots` sees it die.
cleanup_pid(&ctx, key).await;
return;
}
};
// pidfd becomes readable when the process exits; we don't
// read any data, so `readable()` is just an await point.
let _ = async_fd.readable().await;
Expand Down
2 changes: 1 addition & 1 deletion crates/sandlock-oci/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ http = ["sandlock-core/http"]
sandlock-core = { version = "0.9.1", path = "../sandlock-core", default-features = false }
anyhow = "1"
clap = { version = "4", features = ["derive"] }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "net", "io-util"] }
tokio = { version = "1.53.3", features = ["rt-multi-thread", "macros", "net", "io-util"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
libc = "0.2"
Expand Down
4 changes: 3 additions & 1 deletion crates/sandlock-oci/src/supervisor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,9 @@ fn exit_watcher(pid: i32) -> Option<tokio::io::unix::AsyncFd<std::os::unix::io::
return None;
}
let fd = unsafe { OwnedFd::from_raw_fd(raw as i32) };
tokio::io::unix::AsyncFd::with_interest(fd, tokio::io::Interest::READABLE).ok()
// SAFETY: the AsyncFd owns the pidfd.
unsafe { tokio::io::unix::AsyncFd::register_with_interest(fd, tokio::io::Interest::READABLE) }
.ok()
}

/// Outcome of handling one running-container control command.
Expand Down
Loading