Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions crates/lib/src/podstorage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,24 @@ pub(crate) fn bind_storage_roots(
// But...how did we avoid that circular dependency by using the process cwd?
//
// I tried making the mounts recursively private, but that didn't help.
// (We do make them private below, but for a different reason.)
let oldwd = rustix::fs::open(
".",
OFlags::DIRECTORY | OFlags::CLOEXEC | OFlags::RDONLY,
Mode::empty(),
)?;
rustix::process::fchdir(&storage_root)?;
rustix::thread::unshare_unsafe(rustix::thread::UnshareFlags::NEWNS)?;
// The new namespace inherits the caller's propagation. If that is shared
// (e.g. `install to-existing-root --source-imgref` run directly on a systemd
// host, which skips our usual unshare), the bind below would propagate back
// and stay mounted on the host's /run/bootc/storage after we exit.
// https://github.com/bootc-dev/bootc/issues/2455
rustix::mount::mount_change(
c"/",
rustix::mount::MountPropagationFlags::PRIVATE

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is fine, but probably going forward we should actually prefer SLAVE so we do pick up mounts from the host into our mountns. But it's unlikely to matter because the process here is short-lived.

| rustix::mount::MountPropagationFlags::REC,
)?;
rustix::mount::mount_bind(".", STORAGE_ALIAS_DIR)?;
rustix::process::fchdir(&oldwd)?;
Ok(())
Expand Down
8 changes: 8 additions & 0 deletions tmt/plans/integration.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -392,4 +392,12 @@ execute:
enabled: true
extra-try_bind_storage: true
extra-skip_if_ostree: true

/plan-63-install-shared-propagation:
summary: Install from a shared mount namespace without leaking the storage bind mount
discover:
how: fmf
test:
- /tmt/tests/tests/test-63-install-shared-propagation
extra-fixme_skip_if_composefs: true
# END GENERATED PLANS
41 changes: 41 additions & 0 deletions tmt/tests/booted/test-install-shared-propagation.nu
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# number: 63
# tmt:
# summary: Install from a shared mount namespace without leaking the storage bind mount
# duration: 30m
# extra:
# # bootloader=none is not supported for composefs (see test-install-no-boot-dir.nu)
# fixme_skip_if_composefs: true

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem strictly necessary?

#
# Regression test for https://github.com/bootc-dev/bootc/issues/2455
#
# Installing with --source-imgref skips bootc's own mount namespace unshare,
# so on a host where / is shared (the systemd default) the bind mount made
# for podman onto /run/bootc/storage used to propagate back and stay mounted.
# run_install already uses MountFlags=slave, which hides that, so make /
# shared again inside that namespace before installing.

use std assert
use tap.nu

def main [] {
tap begin "install to-filesystem with shared mount propagation"

bootc image copy-to-storage
let target_image = "containers-storage:localhost/bootc"

mkdir /var/mnt
truncate -s 10G disk.img
mkfs.ext4 disk.img
mount -o loop disk.img /var/mnt

setenforce 0

tap run_install $"mount --make-rshared /
bootc install to-filesystem --disable-selinux --bootloader=none --source-imgref ($target_image) /var/mnt
if findmnt /run/bootc/storage; then echo 'error: /run/bootc/storage mount leaked'; exit 1; fi"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be glommed onto an existing test, but ok for now.


umount /var/mnt
rm -f disk.img

tap ok
}
5 changes: 5 additions & 0 deletions tmt/tests/tests.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,8 @@ check:
- when: boot_type == aboot
enabled: true
test: python3 booted/test-aboot-update-rollback.py

/test-63-install-shared-propagation:
summary: Install from a shared mount namespace without leaking the storage bind mount
duration: 30m
test: nu booted/test-install-shared-propagation.nu
Loading