linux: treats empty path to safe_openat as root#1753
Conversation
Reviewer's GuideThis PR adds explicit handling for empty path arguments in safe_openat (treating them as root), refactors the create-and-open fallback logic for consistency, streamlines rootfsfd management across mounting routines, and includes new tests for mounting to root (bind and tmpfs) and for RDT value length validation. Sequence Diagram for Root Filesystem Descriptor Update on Root MountsequenceDiagram
participant DM as do_mount
participant PD as libcrun_private_data
participant OS as OperatingSystem
Note over DM: Called within do_mounts when processing a mount entry
DM->>DM: Mount target is empty string (e.g., destination: "/")
DM->>OS: dup(fd_of_new_root_mount_source)
OS-->>DM: tmp_fd (new rootfs fd)
DM->>OS: close(PD.rootfsfd) (old rootfs fd)
DM->>PD: Update rootfsfd = tmp_fd
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey @giuseppe - I've reviewed your changes - here's some feedback:
- In test_mounts.py, test_mount_to_root defines mount_opt but never applies it to the config or asserts any outcome—please add the mount to conf['mounts'] (or equivalent) and verify the expected behavior.
- In crun_safe_create_and_open_ref_at, the final safe_openat call’s return value and error context aren’t checked before returning—capture and propagate its error result so failures aren’t swallowed.
Here's what I looked at during the review
- 🟢 General issues: all looks good
- 🟢 Security: all looks good
- 🟡 Testing: 1 issue found
- 🟢 Complexity: all looks good
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| conf = base_config() | ||
| conf['process']['args'] = ['/init', 'true'] | ||
| add_all_namespaces(conf) | ||
| mount_opt = {"destination": "/", "type": "tmpfs", "source": "tmpfs", "options": ["tmpcopyup"]} |
There was a problem hiding this comment.
issue (testing): The mount_opt variable is defined but not added to the configuration passed to run_and_get_output.
Add conf['mounts'] = [mount_opt] before calling run_and_get_output so the test actually mounts to /.
|
TMT tests failed. @containers/packit-build please check. |
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
b04d295 to
6a4ee79
Compare
if `do_open` is used with an empty path, the reopen the `dirpath`. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This change ensures that the file descriptor for the rootfs is always sourced directly from the container's private data. This avoids potential stale file descriptor issues that could happen if a local variable were used and the descriptor in the private data was updated elsewhere. Should not introduce any behavior change. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
If an empty path is used, reopens directly the rootfs so that it can grab a reference to the topmost mount, not the previously open file descriptor. Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
When a mount operation replaces the container's root filesystem ("/"),
the existing `rootfsfd` becomes stale. This file descriptor would
still point to the old, now overmounted root, potentially causing
subsequent filesystem operations within the container setup to fail
or target the incorrect filesystem.
Closes: containers#1752
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
6a4ee79 to
64a2e0e
Compare
There was a problem hiding this comment.
Hey @giuseppe - I've reviewed your changes and they look great!
Here's what I looked at during the review
- 🟡 General issues: 1 issue found
- 🟢 Security: all looks good
- 🟡 Testing: 2 issues found
- 🟢 Complexity: all looks good
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| if (UNLIKELY (ret < 0)) | ||
| return crun_make_error (err, errno, "open `%s`", rootfs); | ||
|
|
||
| get_private_data (container)->rootfsfd = ret; |
There was a problem hiding this comment.
issue (bug_risk): Potential file descriptor leak on early return
Open the fd into a temporary variable (e.g. via cleanup_close) and assign it to private_data only after all operations succeed, or close/reset it on every error path.
| return 0 | ||
| return -1 | ||
|
|
||
| def test_mount_bind_to_rootfs(): |
There was a problem hiding this comment.
issue (testing): Add assertions to verify the bind mount to root.
Create a unique file in tmpdir before invoking the container, then inside the container (e.g. via /init or its args) assert that this file appears at / to confirm the bind mount.
| _, _ = run_and_get_output(conf, hide_stderr=True) | ||
| return 0 | ||
|
|
||
| def test_mount_tmpfs_to_rootfs(): |
There was a problem hiding this comment.
issue (testing): Add assertions to verify the tmpfs mount to root and tmpcopyup.
Assert that /init is present and executable inside the container to confirm tmpcopyup worked after mounting root as tmpfs.
|
@kolyshkin PTAL |
|
@flouthoc PTAL |
When an empty string is provided as the
pathargument tosafe_openat, it is now explicitly treated as "/".Closes: #1752
Summary by Sourcery
Treat empty paths as root in safe_openat and streamline rootfsfd handling across mounting and device creation code, ensure proper cleanup of the rootfs file descriptor, add helper for validating fd targets, and expand tests for root-level bind and tmpfs mounts and rdt value length checks.
Bug Fixes:
Enhancements:
Tests:
Chores: