Repository navigation
cow: serve O_PATH and other openat opens of branch entries honestly - #334
Merged
Merged
Conversation
Handlers that open on a child's behalf do so with openat2, which rejects two things openat silently drops: flags beside O_PATH other than O_DIRECTORY, O_NOFOLLOW and O_CLOEXEC (glibc always adds the kernel's O_LARGEFILE), and a mode without O_CREAT or O_TMPFILE. The serving open failed with EINVAL, and COW fell back to the kernel, which cannot see the upper layer, so an O_PATH open of a directory created during the run failed with EACCES (issue #325). Decode open and openat into the open_how the kernel itself builds for them. openat2 callers keep their flags verbatim, so they still get the kernel's EINVAL for the same combinations. Signed-off-by: Cong Wang <cwang@multikernel.io>
congwang-mk
force-pushed
the
cow-openat-flags
branch
from
October 30, 2026 04:23
bed788e to
1bf56c4
Compare
When the serving open, the copy-up, or the open plan failed, handle_cow_open returned Continue. The kernel cannot see the upper layer, so it reported EACCES or ENOENT for entries that exist in the branch, and a write open whose copy-up failed went to the lower file itself, landing outside the branch. Return the failure's errno. A failed fd injection is answered with EACCES to fail closed, which told the child an O_PATH open of an upper-only entry was denied when the kernel's ADDFD had refused the O_PATH source with EBADF. Report that case as EOPNOTSUPP; kernels whose ADDFD accepts O_PATH succeed without any probe (issue #325). Signed-off-by: Cong Wang <cwang@multikernel.io>
congwang-mk
force-pushed
the
cow-openat-flags
branch
from
October 30, 2026 04:29
1bf56c4 to
7f58077
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #325.
Two fixes for opens of entries that exist only in the COW upper layer.
Translate open/openat flags before serving them with openat2. Handlers serve opens on the child's behalf with
openat2, which rejects whatopenatsilently drops: flags besideO_PATHother thanO_DIRECTORY,O_NOFOLLOWandO_CLOEXEC(glibc adds the kernel'sO_LARGEFILE), and a mode withoutO_CREAT/O_TMPFILE.decode_open_argsnow builds theopen_howthe kernel itself builds foropen/openat;openat2callers keep their flags verbatim.Answer failed opens instead of handing them to the kernel.
handle_cow_openreturnedContinuewhen the serving open, the copy-up, or the open plan failed. The kernel cannot see the upper layer, so it reportedEACCES/ENOENTfor entries that exist, and a write open whose copy-up failed reached the lower file directly, outside the branch. These now return the failure's errno.A failed fd injection still fails closed, but when ADDFD refuses an
O_PATHsource withEBADFthe child now getsEOPNOTSUPPinstead of a denial. That refusal comes fromfget()inseccomp_notify_addfd(); the kernel fix ("seccomp: allow addfd to transfer O_PATH descriptors", switching it tofget_raw()) is queued in Kees Cook's tree. With it, the same code path hands the child a workingO_PATHfd, with no version check or probe.On a kernel without that fix, the #325 workload gets an honest
EOPNOTSUPPbut still cannot open the directory withO_PATH, so the issue stays open until the kernel fix is available.Tests
openat_how_matches_what_openat2_accepts,inject_failure_of_an_o_path_source_is_eopnotsupptest_seccomp_cow_openat_ignores_mode_without_creat(failed withENOENTbefore),test_seccomp_cow_o_path_open_of_created_dir(failed withEACCESbefore; accepts a fd orEOPNOTSUPP)sandlock-coreintegration suite passes locally (583).🤖 Generated with Claude Code