| #!/usr/bin/env bash |
| # SPDX-License-Identifier: LGPL-2.1-or-later |
| set -eux |
| set -o pipefail |
| |
| systemd-analyze log-level debug |
| |
| runas() { |
| declare userid=$1 |
| shift |
| # shellcheck disable=SC2016 |
| su "$userid" -s /bin/sh -c 'XDG_RUNTIME_DIR=/run/user/$UID exec "$@"' -- sh "$@" |
| } |
| |
| runas testuser systemd-run --wait --user --unit=test-private-users \ |
| -p PrivateUsers=yes -P echo hello |
| |
| runas testuser systemctl --user log-level debug |
| |
| runas testuser systemd-run --wait --user --unit=test-private-tmp-innerfile \ |
| -p PrivateUsers=yes -p PrivateTmp=yes \ |
| -P touch /tmp/innerfile.txt |
| # File should not exist outside the job's tmp directory. |
| test ! -e /tmp/innerfile.txt |
| |
| touch /tmp/outerfile.txt |
| # File should not appear in unit's private tmp. |
| runas testuser systemd-run --wait --user --unit=test-private-tmp-outerfile \ |
| -p PrivateUsers=yes -p PrivateTmp=yes \ |
| -P test ! -e /tmp/outerfile.txt |
| |
| # Confirm that creating a file in home works |
| runas testuser systemd-run --wait --user --unit=test-unprotected-home \ |
| -P touch /home/testuser/works.txt |
| test -e /home/testuser/works.txt |
| |
| # Confirm that creating a file in home is blocked under read-only |
| runas testuser systemd-run --wait --user --unit=test-protect-home-read-only \ |
| -p PrivateUsers=yes -p ProtectHome=read-only \ |
| -P bash -c ' |
| test -e /home/testuser/works.txt || exit 10 |
| touch /home/testuser/blocked.txt && exit 11 |
| ' \ |
| && { echo 'unexpected success'; exit 1; } |
| test ! -e /home/testuser/blocked.txt |
| |
| # Check that tmpfs hides the whole directory |
| runas testuser systemd-run --wait --user --unit=test-protect-home-tmpfs \ |
| -p PrivateUsers=yes -p ProtectHome=tmpfs \ |
| -P test ! -e /home/testuser |
| |
| # Confirm that home, /root, and /run/user are inaccessible under "yes" |
| # shellcheck disable=SC2016 |
| runas testuser systemd-run --wait --user --unit=test-protect-home-yes \ |
| -p PrivateUsers=yes -p ProtectHome=yes \ |
| -P bash -c ' |
| test "$(stat -c %a /home)" = "0" |
| test "$(stat -c %a /root)" = "0" |
| test "$(stat -c %a /run/user)" = "0" |
| ' |
| |
| # Confirm we cannot change groups because we only have one mapping in the user |
| # namespace (no CAP_SETGID in the parent namespace to write the additional |
| # mapping of the user supplied group and thus cannot change groups to an |
| # unmapped group ID) |
| runas testuser systemd-run --wait --user --unit=test-group-fail \ |
| -p PrivateUsers=yes -p Group=daemon \ |
| -P true \ |
| && { echo 'unexpected success'; exit 1; } |
| |
| # Check that with a new user namespace we can bind mount |
| # files and use a different root directory |
| runas testuser systemd-run --wait --user --unit=test-bind-mount \ |
| -p PrivateUsers=yes -p BindPaths=/dev/null:/etc/os-release \ |
| test ! -s /etc/os-release |
| |
| runas testuser systemd-run --wait --user --unit=test-read-write \ |
| -p PrivateUsers=yes -p ReadOnlyPaths=/ \ |
| -p ReadWritePaths="/var /run /tmp" \ |
| -p NoExecPaths=/ -p ExecPaths=/usr \ |
| test ! -w /etc/os-release |
| |
| runas testuser systemd-run --wait --user --unit=test-caps \ |
| -p PrivateUsers=yes -p AmbientCapabilities=CAP_SYS_ADMIN \ |
| -p CapabilityBoundingSet=CAP_SYS_ADMIN \ |
| test -s /etc/os-release |
| |
| runas testuser systemd-run --wait --user --unit=test-devices \ |
| -p PrivateUsers=yes -p PrivateDevices=yes -p PrivateIPC=yes \ |
| sh -c "ls -1 /dev/ | wc -l | grep -q -F 18" |
| |
| # Same check as test/test-execute/exec-privatenetwork-yes.service |
| runas testuser systemd-run --wait --user --unit=test-network \ |
| -p PrivateUsers=yes -p PrivateNetwork=yes \ |
| /bin/sh -x -c '! ip link | grep -E "^[0-9]+: " | grep -Ev ": (lo|(erspan|gre|gretap|ip_vti|ip6_vti|ip6gre|ip6tnl|sit|tunl)0@.*):"' |
| |
| runas testuser systemd-run --wait --user --unit=test-hostname \ |
| -p PrivateUsers=yes -p ProtectHostname=yes \ |
| hostnamectl hostname foo \ |
| && { echo 'unexpected success'; exit 1; } |
| |
| runas testuser systemd-run --wait --user --unit=test-clock \ |
| -p PrivateUsers=yes -p ProtectClock=yes \ |
| timedatectl set-time "2012-10-30 18:17:16" \ |
| && { echo 'unexpected success'; exit 1; } |
| |
| runas testuser systemd-run --wait --user --unit=test-kernel-tunable \ |
| -p PrivateUsers=yes -p ProtectKernelTunables=yes \ |
| sh -c "echo 0 > /proc/sys/user/max_user_namespaces" \ |
| && { echo 'unexpected success'; exit 1; } |
| |
| runas testuser systemd-run --wait --user --unit=test-kernel-mod \ |
| -p PrivateUsers=yes -p ProtectKernelModules=yes \ |
| sh -c "modprobe -r overlay && modprobe overlay" \ |
| && { echo 'unexpected success'; exit 1; } |
| |
| if sysctl kernel.dmesg_restrict=0; then |
| runas testuser systemd-run --wait --user --unit=test-kernel-log \ |
| -p PrivateUsers=yes -p ProtectKernelLogs=yes -p LogNamespace=yes \ |
| dmesg \ |
| && { echo 'unexpected success'; exit 1; } |
| fi |
| |
| unsquashfs -no-xattrs -d /tmp/img /usr/share/minimal_0.raw |
| runas testuser systemd-run --wait --user --unit=test-root-dir \ |
| -p PrivateUsers=yes -p RootDirectory=/tmp/img \ |
| grep MARKER=1 /etc/os-release |
| |
| mkdir /tmp/img_bind |
| mount --bind /tmp/img /tmp/img_bind |
| runas testuser systemd-run --wait --user --unit=test-root-dir-bind \ |
| -p PrivateUsers=yes -p RootDirectory=/tmp/img_bind -p MountFlags=private \ |
| grep MARKER=1 /etc/os-release |
| umount /tmp/img_bind |
| |
| # Unprivileged overlayfs was added to Linux 5.11, so try to detect it first |
| mkdir -p /tmp/a /tmp/b /tmp/c |
| if unshare --mount --user --map-root-user mount -t overlay overlay /tmp/c -o lowerdir=/tmp/a:/tmp/b; then |
| unsquashfs -no-xattrs -d /tmp/app2 /usr/share/app1.raw |
| runas testuser systemd-run --wait --user --unit=test-extension-dir \ |
| -p PrivateUsers=yes -p ExtensionDirectories=/tmp/app2 \ |
| -p TemporaryFileSystem=/run -p RootDirectory=/tmp/img \ |
| -p MountAPIVFS=yes \ |
| grep PORTABLE_PREFIXES=app1 /usr/lib/extension-release.d/extension-release.app2 |
| fi |
| |
| systemd-analyze log-level info |
| |
| echo OK >/testok |
| |
| exit 0 |