mirror of
https://github.com/xcat2/xcat-dep.git
synced 2026-09-12 04:26:25 +00:00
fix(xcat-dep): run mock builds in an rslave mount namespace to protect the host cgroup
mock mounts /sys/fs/cgroup into every build chroot. On the systemd build hosts every mount carries `shared` propagation, so the chroot cgroup joins the same peer group as the host's own /sys/fs/cgroup. When mock tears a chroot down -- its post-build --scrub, or an aborted build's cleanup -- the cgroup unmount PROPAGATES back through the shared peer group and unmounts the HOST's /sys/fs/cgroup. Every subsequent mock (and even new login sessions) then fails with 'Failed to determine whether the unified cgroups hierarchy is used: No medium found', wedging the whole build host until an operator remounts cgroup2. ppc64le is hit hardest because it leaks corpse chroot mounts on abort, but x86_64 shares the identical shared-cgroup exposure and is one bad abort away from the same failure. Re-exec mockbuild-all.pl inside a private mount namespace made rslave (unshare --mount --propagation slave): the namespace still sees host mounts one-way, but nothing mock mounts or unmounts can propagate out to the host, so a chroot teardown can no longer unmount the host cgroup. The namespace also auto-reaps every mount mock leaks when the process exits, so an aborted build no longer strands corpse mounts under /var/lib/mock. Best-effort and guarded: only re-execs as root with unshare present, and MOCKBUILD_ALL_MOUNTNS prevents a re-exec loop. Signed-off-by: Daniel Hilst <392820+dhilst@users.noreply.github.com>
This commit is contained in:
@@ -18,6 +18,36 @@ use MockBuildUtils qw(sh_quote print_step version_matches required_pkgs
|
||||
rpm_version rpm_release rpm_sigmd5 restamp_release_line
|
||||
cross_copy_genesis finalize_xcat_dep bump_dep_release_suffix);
|
||||
|
||||
# --- Mount-namespace isolation: guard the host cgroup against mock teardown propagation ----------
|
||||
# mock mounts /sys/fs/cgroup into every build chroot. On these systemd build hosts every mount is
|
||||
# `shared`, so the chroot's cgroup joins the HOST's cgroup peer group. When mock tears a chroot down
|
||||
# -- its post-build --scrub, or an aborted build's cleanup -- the unmount PROPAGATES back through the
|
||||
# shared peer group and unmounts the HOST's /sys/fs/cgroup, after which every later mock (and even new
|
||||
# login sessions) dies with "Failed to determine whether the unified cgroups hierarchy is used: No
|
||||
# medium found". This bit ppc hardest (it leaks corpse chroot mounts on abort) but x86 shares the same
|
||||
# shared-cgroup exposure. Re-exec inside a private mount namespace made rslave
|
||||
# (`unshare --mount --propagation slave`): the namespace still sees host mounts (slave = one-way), but
|
||||
# nothing mock mounts/unmounts can propagate OUT to the host. As a bonus the namespace tears down every
|
||||
# mount mock leaks when we exit, so an aborted build can no longer leave corpse mounts under
|
||||
# /var/lib/mock. Best-effort: only as root (needs CAP_SYS_ADMIN) and only if `unshare` exists;
|
||||
# otherwise warn loudly and continue unisolated. MOCKBUILD_ALL_MOUNTNS guards against a re-exec loop.
|
||||
unless ($ENV{MOCKBUILD_ALL_MOUNTNS}) {
|
||||
if ($> != 0) {
|
||||
warn "WARN: not root -- skipping mount-namespace isolation (host-cgroup propagation guard); "
|
||||
. "run as root in CI so mock chroot teardown cannot unmount the host /sys/fs/cgroup\n";
|
||||
} elsif (system('sh', '-c', 'command -v unshare >/dev/null 2>&1') != 0) {
|
||||
warn "WARN: 'unshare' not found -- skipping mount-namespace isolation; mock chroot teardown "
|
||||
. "may unmount the host /sys/fs/cgroup on a shared-propagation host\n";
|
||||
} else {
|
||||
$ENV{MOCKBUILD_ALL_MOUNTNS} = 1;
|
||||
my @reexec = ('unshare', '--mount', '--propagation', 'slave', '--', $^X, $0, @ARGV);
|
||||
exec { $reexec[0] } @reexec;
|
||||
# exec only returns on failure -- fall through and run unisolated rather than abort the build.
|
||||
warn "WARN: exec unshare failed ($!) -- continuing without mount-namespace isolation\n";
|
||||
delete $ENV{MOCKBUILD_ALL_MOUNTNS};
|
||||
}
|
||||
}
|
||||
|
||||
my $script_dir = abs_path(dirname(__FILE__));
|
||||
my $repo_root = abs_path($script_dir);
|
||||
my $xcat_src = "$repo_root/../xcat-core";
|
||||
|
||||
Reference in New Issue
Block a user