Skip to content

Commit e32bf8c

Browse files
committed
Handle openat2 returning EPERM.
Systemd's seccomp sandbox has `openat2` returning `EPERM` to indicate that it's not supported. Treat `EPERM` as indicating that `openat2` is temporarily unavailable and use the non-`openat2` fallback path, rather than propagating the `EPERM` error.
1 parent 3bfe8f4 commit e32bf8c

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

cap-primitives/src/posish/linux/fs/open_impl.rs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,24 @@ pub(crate) fn open_beneath(
8585
Err(err) => match err.raw_os_error() {
8686
Some(libc::EAGAIN) => continue,
8787
Some(libc::EXDEV) => return Err(errors::escape_attempt()),
88+
89+
// `EPERM` is used by some `seccomp` sandboxes to indicate
90+
// that `openat2` is unimplemented:
91+
// <https://github.com/systemd/systemd/blob/e2357b1c8a87b610066b8b2a59517bcfb20b832e/src/shared/seccomp-util.c#L2066>
92+
//
93+
// However, `EPERM` may also indicate a failed `O_NOATIME`
94+
// or a file seal prevented the operation, and it's complex
95+
// to detect those cases, so exit the loop and use the
96+
// fallback.
97+
Some(libc::EPERM) => break,
98+
99+
// `ENOSYS` means `openat2` is permanently unavailable;
100+
// mark it so and exit the loop.
88101
Some(libc::ENOSYS) => {
89-
// `openat2` is permanently unavailable; mark it so and
90-
// exit the loop.
91102
INVALID.store(true, Relaxed);
92103
break;
93104
}
105+
94106
_ => return Err(err),
95107
},
96108
}

0 commit comments

Comments
 (0)