-
Notifications
You must be signed in to change notification settings - Fork 305
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This tests the current behavior of making /sysroot a private mount so that submounts on /var do not propagate back to /sysroot. It also shows how submounts of /sysroot do not propagate into separate mount namespaces for the same reason.
- Loading branch information
1 parent
2b01c93
commit 877e870
Showing
1 changed file
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
#!/bin/bash | ||
# https://bugzilla.redhat.com/show_bug.cgi?id=1498281 | ||
set -xeuo pipefail | ||
|
||
. ${KOLA_EXT_DATA}/libinsttest.sh | ||
|
||
require_writable_sysroot | ||
|
||
has_mount() { | ||
local target=${1:?No target specified} | ||
local pid=${2:?No PID specified} | ||
local mounts="/proc/${pid}/mounts" | ||
|
||
# Unlike grep, awk doesn't exit based on whether it matched anything or not, | ||
# so that needs to be emulated. | ||
awk 'BEGIN {ret = 1}; $2 == "'"${target}"'" {print; ret = 0}; END {exit ret}' "${mounts}" | ||
} | ||
|
||
assert_has_mount() { | ||
local target=${1:?No target specified} | ||
local pid=${2:-$$} | ||
if ! has_mount "${target}" "${pid}"; then | ||
cat "/proc/${pid}/mounts" >&2 | ||
fatal "Mount '$target' not found in process $pid" | ||
fi | ||
} | ||
|
||
assert_not_has_mount() { | ||
local target=${1:?No target specified} | ||
local pid=${2:-$$} | ||
if has_mount "${target}" "${pid}"; then | ||
cat "/proc/${pid}/mounts" >&2 | ||
fatal "Mount '$target' found in process $pid" | ||
fi | ||
} | ||
|
||
test_mounts() { | ||
local stateroot=$(rpmostree_query_json '.deployments[0].osname') | ||
|
||
echo "Root namespace mountinfo:" | ||
cat "/proc/$$/mountinfo" | ||
|
||
echo "Sub namespace mountinfo:" | ||
cat "/proc/${ns_pid}/mountinfo" | ||
|
||
# Make sure the 2 PIDs are really in different mount namespaces. | ||
root_ns=$(readlink "/proc/$$/ns/mnt") | ||
sub_ns=$(readlink "/proc/${ns_pid}/ns/mnt") | ||
assert_not_streq "${root_ns}" "${sub_ns}" | ||
|
||
# Check the mounts exist in the root namespace and the /var/foo mount has not | ||
# propagated back to /sysroot. | ||
assert_has_mount /var/foo | ||
assert_has_mount /sysroot/bar | ||
assert_not_has_mount "/sysroot/ostree/deploy/${stateroot}/var/foo" | ||
|
||
# Repeat with the sub mount namespace. Since /sysroot is marked private, | ||
# /sysroot/bar will not be propagated into it. | ||
assert_has_mount /var/foo "${ns_pid}" | ||
assert_not_has_mount /sysroot/bar "${ns_pid}" | ||
assert_not_has_mount "/sysroot/ostree/deploy/${stateroot}/var/foo" "${ns_pid}" | ||
} | ||
|
||
case "${AUTOPKGTEST_REBOOT_MARK:-}" in | ||
"") | ||
mkdir -p /var/foo /sysroot/bar | ||
|
||
# Create a process in a separate mount namespace to see if the mounts | ||
# propagate into it correctly. | ||
unshare -m --propagation unchanged -- sleep infinity & | ||
ns_pid=$! | ||
|
||
mount -t tmpfs foo /var/foo | ||
mount -t tmpfs bar /sysroot/bar | ||
|
||
test_mounts | ||
|
||
# Now setup for the same test but with the mounts made early via fstab. | ||
cat >> /etc/fstab <<"EOF" | ||
foo /var/foo tmpfs defaults 0 0 | ||
bar /sysroot/bar tmpfs defaults 0 0 | ||
EOF | ||
|
||
# We want to start a process in a separate namespace after ostree-remount | ||
# has completed but before systemd starts the fstab generated mount units. | ||
cat > /etc/systemd/system/test-mounts.service <<"EOF" | ||
[Unit] | ||
DefaultDependencies=no | ||
After=ostree-remount.service | ||
Before=var-foo.mount sysroot-bar.mount | ||
RequiresMountsFor=/var /sysroot | ||
Conflicts=shutdown.target | ||
Before=shutdown.target | ||
[Service] | ||
Type=exec | ||
ExecStart=/usr/bin/sleep infinity | ||
ProtectSystem=strict | ||
[Install] | ||
WantedBy=local-fs.target | ||
EOF | ||
systemctl enable test-mounts.service | ||
|
||
/tmp/autopkgtest-reboot 2 | ||
;; | ||
2) | ||
# Check that the test service is running and get its PID. | ||
ns_state=$(systemctl show -P ActiveState test-mounts.service) | ||
assert_streq "${ns_state}" active | ||
ns_pid=$(systemctl show -P MainPID test-mounts.service) | ||
|
||
# Make sure that test-mounts.service started after ostree-remount.service | ||
# but before /var/foo and /sysroot/bar were mounted so that we can see if | ||
# the mounts were propagated into its mount namespace. | ||
remount_finished=$(journalctl -o json -g Finished -u ostree-remount.service | tail -n1 | jq -r .__MONOTONIC_TIMESTAMP) | ||
test_starting=$(journalctl -o json -g Starting -u test-mounts.service | tail -n1 | jq -r .__MONOTONIC_TIMESTAMP) | ||
test_started=$(journalctl -o json -g Started -u test-mounts.service | tail -n1 | jq -r .__MONOTONIC_TIMESTAMP) | ||
foo_mounting=$(journalctl -o json -g Mounting -u var-foo.mount | tail -n1 | jq -r .__MONOTONIC_TIMESTAMP) | ||
bar_mounting=$(journalctl -o json -g Mounting -u sysroot-bar.mount | tail -n1 | jq -r .__MONOTONIC_TIMESTAMP) | ||
test "${remount_finished}" -lt "${test_starting}" | ||
test "${test_started}" -lt "${foo_mounting}" | ||
test "${test_started}" -lt "${bar_mounting}" | ||
|
||
test_mounts | ||
;; | ||
*) fatal "Unexpected AUTOPKGTEST_REBOOT_MARK=${AUTOPKGTEST_REBOOT_MARK}" ;; | ||
esac |