mirror of
https://github.com/containers/podman
synced 2024-10-20 17:23:30 +00:00
33179c281e
- stop: test --all and --ignore (#9051) - build: test /run/secrets (#8679, but see below) - sensitive mount points: deal with 'stat' failures - selinux: confirm useful diagnostics on unknown labels (#8946) The 'build' test is intended as a fix for #8679, in which 'podman build' does not mount secrets from mounts.conf. Unfortunately, as of this writing, 'podman build' does not pass the --default-mounts-file option to buildah, so there's no reasonable way to test this path. Still, we can at least confirm /run/secrets on 'podman run'. The /sys thing is related to #8949: RHEL8, rootless, cgroups v1. It's just a workaround to get gating tests to pass on RHEL. Signed-off-by: Ed Santiago <santiago@redhat.com>
180 lines
6.2 KiB
Bash
180 lines
6.2 KiB
Bash
#!/usr/bin/env bats -*- bats -*-
|
|
#
|
|
# Tests #2730 - regular users are not able to read/write container storage
|
|
# Tests #6957 - /sys/dev (et al) are masked from unprivileged containers
|
|
#
|
|
|
|
load helpers
|
|
|
|
@test "podman container storage is not accessible by unprivileged users" {
|
|
skip_if_rootless "test meaningless without suid"
|
|
skip_if_remote
|
|
|
|
run_podman run --name c_uidmap --uidmap 0:10000:10000 $IMAGE true
|
|
run_podman run --name c_uidmap_v --uidmap 0:10000:10000 -v foo:/foo $IMAGE true
|
|
|
|
run_podman run --name c_mount $IMAGE \
|
|
sh -c "echo hi > /myfile;mkdir -p /mydir/mysubdir; chmod 777 /myfile /mydir /mydir/mysubdir"
|
|
|
|
run_podman mount c_mount
|
|
mount_path=$output
|
|
|
|
# Do all the work from within a test script. Since we'll be invoking it
|
|
# as a user, the parent directory must be world-readable.
|
|
test_script=$PODMAN_TMPDIR/fail-if-writable
|
|
cat >$test_script <<"EOF"
|
|
#!/usr/bin/env bash
|
|
|
|
path="$1"
|
|
|
|
die() {
|
|
echo "#/vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" >&2
|
|
echo "#| FAIL: $*" >&2
|
|
echo "#\\^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^" >&2
|
|
|
|
# Show permissions of directories from here on up
|
|
while expr "$path" : "/var/lib/containers" >/dev/null; do
|
|
echo "#| $(ls -ld $path)"
|
|
path=$(dirname $path)
|
|
done
|
|
|
|
exit 1
|
|
}
|
|
|
|
parent=$(dirname "$path")
|
|
if chmod +w $parent; then
|
|
die "Able to chmod $parent"
|
|
fi
|
|
if chmod +w "$path"; then
|
|
die "Able to chmod $path"
|
|
fi
|
|
|
|
if [ -d "$path" ]; then
|
|
if ls "$path" >/dev/null; then
|
|
die "Able to run 'ls $path' without error"
|
|
fi
|
|
if echo hi >"$path"/test; then
|
|
die "Able to write to file under $path"
|
|
fi
|
|
else
|
|
# Plain file
|
|
if cat "$path" >/dev/null; then
|
|
die "Able to read $path"
|
|
fi
|
|
if echo hi >"$path"; then
|
|
die "Able to write to $path"
|
|
fi
|
|
fi
|
|
|
|
exit 0
|
|
EOF
|
|
chmod 755 $PODMAN_TMPDIR $test_script
|
|
|
|
# get podman image and container storage directories
|
|
run_podman info --format '{{.Store.GraphRoot}}'
|
|
is "$output" "/var/lib/containers/storage" "GraphRoot in expected place"
|
|
GRAPH_ROOT="$output"
|
|
run_podman info --format '{{.Store.RunRoot}}'
|
|
is "$output" ".*/run/containers/storage" "RunRoot in expected place"
|
|
RUN_ROOT="$output"
|
|
|
|
# The main test: find all world-writable files or directories underneath
|
|
# container storage, run the test script as a nonroot user, and try to
|
|
# access each path.
|
|
find $GRAPH_ROOT $RUN_ROOT \! -type l -perm -o+w -print | while read i; do
|
|
dprint " o+w: $i"
|
|
|
|
# use chroot because su fails if uid/gid don't exist or have no shell
|
|
# For development: test all this by removing the "--userspec x:x"
|
|
chroot --userspec 1000:1000 / $test_script "$i"
|
|
done
|
|
|
|
# Done. Clean up.
|
|
rm -f $test_script
|
|
|
|
run_podman umount c_mount
|
|
run_podman rm c_mount
|
|
|
|
run_podman rm c_uidmap c_uidmap_v
|
|
}
|
|
|
|
|
|
# #6957 - mask out /proc/acpi, /sys/dev, and other sensitive system files
|
|
@test "sensitive mount points are masked without --privileged" {
|
|
# Weird error, maybe a flake?
|
|
# can only attach to created or running containers: container state improper
|
|
# https://github.com/containers/podman/pull/7111#issuecomment-666858715
|
|
skip_if_remote "FIXME: Weird flake"
|
|
|
|
# FIXME: this should match the list in pkg/specgen/generate/config_linux.go
|
|
local -a mps=(
|
|
/proc/acpi
|
|
/proc/kcore
|
|
/proc/keys
|
|
/proc/latency_stats
|
|
/proc/timer_list
|
|
/proc/timer_stats
|
|
/proc/sched_debug
|
|
/proc/scsi
|
|
/sys/firmware
|
|
/sys/fs/selinux
|
|
/sys/dev/block
|
|
)
|
|
|
|
# Some of the above may not exist on our host. Find only the ones that do.
|
|
local -a subset=()
|
|
for mp in ${mps[@]}; do
|
|
if [ -e $mp ]; then
|
|
subset+=($mp)
|
|
fi
|
|
done
|
|
|
|
# Run 'stat' on all the files, plus /dev/null. Get path, file type,
|
|
# number of links, major, and minor (see below for why). Do it all
|
|
# in one go, to avoid multiple podman-runs
|
|
run_podman '?' run --rm $IMAGE stat -c'%n:%F:%h:%T:%t' /dev/null ${subset[@]}
|
|
if [[ $status -gt 1 ]]; then
|
|
die "Unexpected exit status $status: expected 0 or 1"
|
|
fi
|
|
|
|
local devnull=
|
|
for result in "${lines[@]}"; do
|
|
# e.g. /proc/acpi:character special file:1:3:1
|
|
local IFS=:
|
|
read path type nlinks major minor <<<"$result"
|
|
|
|
if [[ $path = "/dev/null" ]]; then
|
|
# /dev/null is our reference point: masked *files* (not directories)
|
|
# will be created as /dev/null clones.
|
|
# This depends on 'stat' returning results in argv order,
|
|
# so /dev/null is first, so we have a reference for others.
|
|
# If that ever breaks, this test will have to be done in two passes.
|
|
devnull="$major:$minor"
|
|
elif [[ $type = "character special file" ]]; then
|
|
# Container file is a character device: it must match /dev/null
|
|
is "$major:$minor" "$devnull" "$path: major/minor matches /dev/null"
|
|
elif [[ $type = "directory" ]]; then
|
|
# Directories: must be empty (only two links).
|
|
# FIXME: this is a horrible almost-worthless test! It does not
|
|
# actually check for files in the directory (expect: zero),
|
|
# merely for the nonexistence of any subdirectories! It relies
|
|
# on the observed (by Ed) fact that all the masked directories
|
|
# contain further subdirectories on the host. If there's ever
|
|
# a new masked directory that contains only files, this test
|
|
# will silently pass without any indication of error.
|
|
# If you can think of a better way to do this check,
|
|
# please feel free to fix it.
|
|
is "$nlinks" "2" "$path: directory link count"
|
|
elif [[ $result =~ stat:.*No.such.file.or.directory ]]; then
|
|
# No matter what the path is, this is OK. It has to do with #8949
|
|
# and RHEL8 and rootless and cgroups v1. Bottom line, what we care
|
|
# about is that the path not be available inside the container.
|
|
:
|
|
else
|
|
die "$path: Unknown file type '$type'"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# vim: filetype=sh
|