Skip to content

Commit cd2ece8

Browse files
committed
Update nix to v0.31.2 & associated API changes
No longer NO_FOLLOW_SYMLINK in linkat() in blit_element_item to prevent EINVAL errors. This mirrors what was previously required for io-uring and rustix experiments. Avoid using deprecated flock API and adjust as neccessary linkat now needs directory fds passed to it to more closly match the syscall, adjust as neccessary. No longer close() after entering a new container, this appears to no longer be neccessary now we're using an &OwnedFd instead of i32.
1 parent 4d3dc13 commit cd2ece8

File tree

7 files changed

+97
-77
lines changed

7 files changed

+97
-77
lines changed

Cargo.lock

Lines changed: 13 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ libsqlite3-sys = { version = "0.35.0", features = ["bundled"] }
4646
log = "0.4.22"
4747
nc = "0.9.7"
4848
nom = "7.1.3"
49-
nix = { version = "0.27.1", features = [
49+
nix = { version = "0.31.1", features = [
5050
"user",
5151
"fs",
5252
"sched",

boulder/src/build/upstream.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ use std::{
1212
use fs_err as fs;
1313
use futures_util::{StreamExt, TryStreamExt, stream};
1414
use moss::{runtime, util};
15-
use nix::unistd::{LinkatFlags, linkat};
15+
use nix::{
16+
fcntl::{AtFlags, OFlag, open},
17+
sys::stat::Mode,
18+
unistd::linkat,
19+
};
1620
use sha2::{Digest, Sha256};
1721
use stone_recipe::upstream;
1822
use thiserror::Error;
@@ -150,8 +154,14 @@ impl Installed {
150154
Installed::Plain { name, path, .. } => {
151155
let target = dest_dir.join(name);
152156

157+
let old_parent = path.parent().unwrap_or(Path::new("."));
158+
let new_parent = target.parent().unwrap_or(Path::new("."));
159+
160+
let old_dirfd = open(old_parent, OFlag::O_DIRECTORY | OFlag::O_CLOEXEC, Mode::empty())?;
161+
let new_dirfd = open(new_parent, OFlag::O_DIRECTORY | OFlag::O_CLOEXEC, Mode::empty())?;
162+
153163
// Attempt hard link
154-
let link_result = linkat(None, path, None, &target, LinkatFlags::NoSymlinkFollow);
164+
let link_result = linkat(old_dirfd, path, new_dirfd, &target, AtFlags::AT_SYMLINK_NOFOLLOW);
155165

156166
// Copy instead
157167
if link_result.is_err() {
@@ -544,4 +554,6 @@ pub enum Error {
544554
Io(#[from] io::Error),
545555
#[error("git")]
546556
Git(#[from] git::GitError),
557+
#[error("nix")]
558+
Nix(#[from] nix::errno::Errno),
547559
}

crates/container/src/lib.rs

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
//
33
// SPDX-License-Identifier: MPL-2.0
44

5-
use std::io;
6-
use std::os::fd::AsRawFd;
5+
use std::io::{self};
6+
use std::os::fd::OwnedFd;
77
use std::path::{Path, PathBuf};
88
use std::process::Command;
99
use std::ptr::addr_of_mut;
@@ -24,7 +24,7 @@ use nix::sys::signal::{SaFlags, SigAction, SigHandler, Signal, kill, sigaction};
2424
use nix::sys::signalfd::SigSet;
2525
use nix::sys::stat::{Mode, umask};
2626
use nix::sys::wait::{WaitStatus, waitpid};
27-
use nix::unistd::{Pid, Uid, close, pipe, pivot_root, read, sethostname, tcsetpgrp, write};
27+
use nix::unistd::{Pid, Uid, pipe, pivot_root, read, sethostname, tcsetpgrp, write};
2828
use snafu::{ResultExt, Snafu};
2929

3030
use self::idmap::idmap;
@@ -132,6 +132,7 @@ impl Container {
132132

133133
// Pipe to synchronize parent & child
134134
let sync = pipe().context(NixSnafu)?;
135+
let (read_fd, write_fd) = sync;
135136

136137
let mut flags =
137138
CloneFlags::CLONE_NEWNS | CloneFlags::CLONE_NEWPID | CloneFlags::CLONE_NEWIPC | CloneFlags::CLONE_NEWUTS;
@@ -144,24 +145,26 @@ impl Container {
144145
flags |= CloneFlags::CLONE_NEWNET;
145146
}
146147

147-
let clone_cb = Box::new(|| match enter(&self, sync, &mut f) {
148-
Ok(_) => 0,
149-
// Write error back to parent process
150-
Err(error) => {
151-
let error = format_error(error);
152-
let mut pos = 0;
148+
let clone_cb = Box::new(|| {
149+
let write_fd = write_fd.try_clone().unwrap();
153150

154-
while pos < error.len() {
155-
let Ok(len) = write(sync.1, &error.as_bytes()[pos..]) else {
156-
break;
157-
};
151+
match enter(&self, &read_fd, &mut f) {
152+
Ok(_) => 0,
153+
Err(error) => {
154+
let error = format_error(error);
155+
let mut pos = 0;
158156

159-
pos += len;
160-
}
157+
while pos < error.len() {
158+
let Ok(len) = write(&write_fd, &error.as_bytes()[pos..]) else {
159+
break;
160+
};
161+
pos += len;
162+
}
161163

162-
let _ = close(sync.1);
164+
let _ = drop(write_fd);
163165

164-
1
166+
1
167+
}
165168
}
166169
});
167170
let pid = unsafe { clone(clone_cb, &mut *addr_of_mut!(STACK), flags, Some(SIGCHLD)) }.context(NixSnafu)?;
@@ -172,9 +175,9 @@ impl Container {
172175
}
173176

174177
// Allow child to continue
175-
write(sync.1, &[Message::Continue as u8]).context(NixSnafu)?;
178+
write(&write_fd, &[Message::Continue as u8]).context(NixSnafu)?;
176179
// Write no longer needed
177-
close(sync.1).context(NixSnafu)?;
180+
drop(write_fd);
178181

179182
if self.ignore_host_sigint {
180183
ignore_sigint().context(NixSnafu)?;
@@ -193,7 +196,7 @@ impl Container {
193196
let mut buffer = [0u8; 1024];
194197

195198
loop {
196-
let len = read(sync.0, &mut buffer).context(NixSnafu)?;
199+
let len = read(&read_fd, &mut buffer).context(NixSnafu)?;
197200

198201
if len == 0 {
199202
break;
@@ -215,7 +218,7 @@ impl Container {
215218
}
216219

217220
/// Reenter the container
218-
fn enter<E>(container: &Container, sync: (i32, i32), mut f: impl FnMut() -> Result<(), E>) -> Result<(), ContainerError>
221+
fn enter<E>(container: &Container, sync: &OwnedFd, mut f: impl FnMut() -> Result<(), E>) -> Result<(), ContainerError>
219222
where
220223
E: std::error::Error + Send + Sync + 'static,
221224
{
@@ -224,12 +227,9 @@ where
224227

225228
// Wait for continue message
226229
let mut message = [0u8; 1];
227-
read(sync.0, &mut message).context(ReadContinueMsgSnafu)?;
230+
read(sync, &mut message).context(ReadContinueMsgSnafu)?;
228231
assert_eq!(message[0], Message::Continue as u8);
229232

230-
// Close unused read end
231-
close(sync.0).context(CloseReadFdSnafu)?;
232-
233233
setup(container)?;
234234

235235
f().boxed().context(RunSnafu)
@@ -347,7 +347,7 @@ fn bind_mount(source: &Path, target: &Path, read_only: bool) -> Result<(), Conta
347347
unsafe {
348348
let inner = || {
349349
// Bind mount to fd
350-
let fd = open_tree(AT_FDCWD, source, OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC).map_err(Errno::from_i32)?;
350+
let fd = open_tree(AT_FDCWD, source, OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC).map_err(Errno::from_raw)?;
351351

352352
// Set rd flag if applicable
353353
if read_only {
@@ -365,11 +365,11 @@ fn bind_mount(source: &Path, target: &Path, read_only: bool) -> Result<(), Conta
365365
&attr as *const mount_attr_t as usize,
366366
size_of::<mount_attr_t>(),
367367
)
368-
.map_err(Errno::from_i32)?;
368+
.map_err(Errno::from_raw)?;
369369
}
370370

371371
// Move detached mount to target
372-
move_mount(fd, Path::new(""), AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH).map_err(Errno::from_i32)?;
372+
move_mount(fd, Path::new(""), AT_FDCWD, target, MOVE_MOUNT_F_EMPTY_PATH).map_err(Errno::from_raw)?;
373373

374374
Ok(())
375375
};
@@ -427,7 +427,7 @@ pub fn set_term_fg(pgid: Pid) -> Result<(), nix::Error> {
427427
)?
428428
};
429429
// Set term fg to pid
430-
let res = tcsetpgrp(io::stdin().as_raw_fd(), pgid);
430+
let res = tcsetpgrp(io::stdin(), pgid);
431431
// Set up old handler
432432
unsafe { sigaction(Signal::SIGTTOU, &prev_handler)? };
433433

@@ -492,6 +492,8 @@ pub enum Error {
492492
// FIXME: Replace with more fine-grained variants
493493
#[snafu(display("nix"))]
494494
Nix { source: nix::Error },
495+
#[snafu(display("io"))]
496+
Io { source: io::Error },
495497
}
496498

497499
#[derive(Debug, Snafu)]
@@ -508,8 +510,6 @@ enum ContainerError {
508510
SetPDeathSig { source: nix::Error },
509511
#[snafu(display("wait for continue message"))]
510512
ReadContinueMsg { source: nix::Error },
511-
#[snafu(display("close read end of pipe"))]
512-
CloseReadFd { source: nix::Error },
513513
#[snafu(display("sethostname"))]
514514
SetHostname { source: nix::Error },
515515
#[snafu(display("pivot_root"))]

moss/src/client/mod.rs

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
use std::{
1313
borrow::Borrow,
1414
fmt, io,
15-
os::{fd::RawFd, unix::fs::symlink},
15+
os::{fd::OwnedFd, unix::fs::symlink},
1616
path::{Path, PathBuf},
1717
time::{Duration, Instant},
1818
};
@@ -23,7 +23,7 @@ use futures_util::{StreamExt, TryStreamExt, stream};
2323
use itertools::Itertools;
2424
use nix::{
2525
errno::Errno,
26-
fcntl::{self, OFlag},
26+
fcntl::{self, AtFlags, OFlag},
2727
libc::{AT_FDCWD, RENAME_EXCHANGE, SYS_renameat2, syscall},
2828
sys::stat::{Mode, fchmodat, mkdirat},
2929
unistd::{close, linkat, mkdir, symlinkat},
@@ -979,7 +979,7 @@ pub fn blit_root(installation: &Installation, tree: &vfs::Tree<PendingFile>, bli
979979
.into_par_iter()
980980
.map(|child| {
981981
let _guard = current_span.enter();
982-
blit_element(root_dir, cache_fd, child, &progress)
982+
blit_element(&root_dir, &cache_fd, child, &progress)
983983
})
984984
.try_reduce(BlitStats::default, |a, b| Ok(a.merge(b)))?,
985985
);
@@ -1010,8 +1010,8 @@ pub fn blit_root(installation: &Installation, tree: &vfs::Tree<PendingFile>, bli
10101010
/// Care is taken to retain the directory file descriptor to avoid costly path
10111011
/// resolution at runtime.
10121012
fn blit_element(
1013-
parent: RawFd,
1014-
cache: RawFd,
1013+
parent: &OwnedFd,
1014+
cache: &OwnedFd,
10151015
element: Element<'_, PendingFile>,
10161016
progress: &ProgressBar,
10171017
) -> Result<BlitStats, Error> {
@@ -1047,7 +1047,7 @@ fn blit_element(
10471047
.into_par_iter()
10481048
.map(|child| {
10491049
let _guard = current_span.enter();
1050-
blit_element(newdir, cache, child, progress)
1050+
blit_element(&newdir, cache, child, progress)
10511051
})
10521052
.try_reduce(BlitStats::default, |a, b| Ok(a.merge(b)))?,
10531053
);
@@ -1073,8 +1073,8 @@ fn blit_element(
10731073
/// * `subpath` - the base name of the new inode
10741074
/// * `item` - New inode being recorded
10751075
fn blit_element_item(
1076-
parent: RawFd,
1077-
cache: RawFd,
1076+
parent: &OwnedFd,
1077+
cache: &OwnedFd,
10781078
subpath: &str,
10791079
item: &PendingFile,
10801080
stats: &mut BlitStats,
@@ -1105,17 +1105,11 @@ fn blit_element_item(
11051105
}
11061106
// Regular file
11071107
_ => {
1108-
linkat(
1109-
Some(cache),
1110-
fp.to_str().unwrap(),
1111-
Some(parent),
1112-
subpath,
1113-
nix::unistd::LinkatFlags::NoSymlinkFollow,
1114-
)?;
1108+
linkat(cache, fp.to_str().unwrap(), parent, subpath, AtFlags::empty())?;
11151109

11161110
// Fix permissions
11171111
fchmodat(
1118-
Some(parent),
1112+
parent,
11191113
subpath,
11201114
Mode::from_bits_truncate(item.layout.mode),
11211115
nix::sys::stat::FchmodatFlags::NoFollowSymlink,
@@ -1126,7 +1120,7 @@ fn blit_element_item(
11261120
stats.num_files += 1;
11271121
}
11281122
StonePayloadLayoutFile::Symlink(source, _) => {
1129-
symlinkat(source.as_str(), Some(parent), subpath)?;
1123+
symlinkat(source.as_str(), parent, subpath)?;
11301124
stats.num_symlinks += 1;
11311125
}
11321126
StonePayloadLayoutFile::Directory(_) => {

0 commit comments

Comments
 (0)