Skip to content

Commit

Permalink
Root::mkdir_all: switch mkdir loop to use basic openat
Browse files Browse the repository at this point in the history
There is no reason to use the resolver to look a path component under a
directory we have a handle to already. The O_NOFOLLOW behaviour was also
somewhat hidden behind the way the resolver API works.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
  • Loading branch information
cyphar committed Dec 8, 2024
1 parent 2cdc1cc commit 2557cba
Showing 1 changed file with 17 additions and 6 deletions.
23 changes: 17 additions & 6 deletions src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,12 @@ impl RootRef<'_> {

// For the remaining components, create a each component one-by-one.
for part in remaining_parts {
if part.as_bytes().contains(&b'/') {
Err(ErrorImpl::SafetyViolation {
description: "remaining component for mkdir contains '/'".into(),
})?;
}

// NOTE: mkdirat(2) does not follow trailing symlinks (even if it is
// a dangling symlink with only a trailing component missing), so we
// can safely create the final component without worrying about
Expand All @@ -1009,11 +1015,16 @@ impl RootRef<'_> {
// Get a handle to the directory we just created. Unfortunately we
// can't do an atomic create+open (a-la O_CREAT) with mkdirat(), so
// a separate O_NOFOLLOW is the best we can do.
let next = self
.resolver
.resolve(&current, &part, true)
.and_then(|handle| handle.reopen(OpenFlags::O_DIRECTORY))
.wrap("failed to open newly-created directory with O_DIRECTORY")?;
let next = syscalls::openat(
&current,
&part,
OpenFlags::O_NOFOLLOW | OpenFlags::O_DIRECTORY,
0,
)
.map_err(|err| ErrorImpl::RawOsError {
operation: "open newly created directory".into(),
source: err,
})?;

// Unfortunately, we cannot create a directory and open it
// atomically (a-la O_CREAT). This means an attacker could swap our
Expand All @@ -1035,7 +1046,7 @@ impl RootRef<'_> {
// doesn't seem to provide any practical benefit.

// Keep walking.
current = next;
current = next.into();
}

Ok(Handle::from_fd(current))
Expand Down

0 comments on commit 2557cba

Please sign in to comment.