diff --git a/.image-garden.mk b/.image-garden.mk index e57fa9eb7..e46488143 100644 --- a/.image-garden.mk +++ b/.image-garden.mk @@ -33,6 +33,7 @@ packages: - python3-tk - python3-ttkthemes - swig +- toybox endef # Ubuntu shares cloud-init profile with Debian. diff --git a/profiles/apparmor.d/toybox b/profiles/apparmor.d/toybox index 7921fd874..e384606e3 100644 --- a/profiles/apparmor.d/toybox +++ b/profiles/apparmor.d/toybox @@ -4,7 +4,7 @@ abi , include -profile toybox /bin/toybox flags=(unconfined) { +profile toybox /usr/bin/toybox flags=(unconfined) { userns, # Site-specific additions and overrides. See local/README for details. diff --git a/spread.yaml b/spread.yaml index 0ed078054..3fbbebd21 100644 --- a/spread.yaml +++ b/spread.yaml @@ -123,6 +123,72 @@ debug-each: | uname -a suites: + tests/profiles/: + summary: Tests that exercise specific application profiles + # variables: + # PROFILE_NAME: name of the profile on disk + # PROGRAM_NAME: name of the program to execute + prepare-each: | + rm -f denials.txt + + # Disable rate-limiting so that we see all denials. + sysctl --values kernel.printk_ratelimit >old-ratelimit.txt + sysctl --write kernel.printk_ratelimit=0 + + # Stop auditd so that all denials end up in the ring buffer. + if [ "$(systemctl is-active auditd.service)" != inactive ]; then + systemctl stop auditd.service + touch did-stop-auditd.txt + fi + + # Clear the kernel ring buffer. + dmesg --clear + + # Compute profile name from the name of the task. + echo "PROFILE_NAME=${PROFILE_NAME:=$(basename "$SPREAD_TASK")}" + + "$SPREAD_PATH"/parser/apparmor_parser \ + --warn=all \ + --replace \ + --skip-cache \ + --base="$SPREAD_PATH"/profiles/apparmor.d \ + "$SPREAD_PATH"/profiles/apparmor.d/"$PROFILE_NAME" 2>parser.txt + if [ -s parser.txt ]; then + echo "Parser produced warnings:" + cat parser.txt + exit 1 + fi + + restore-each: | + # Compute profile name from the name of the task. + echo "PROFILE_NAME=${PROFILE_NAME:=$(basename "$SPREAD_TASK")}" + + "$SPREAD_PATH"/parser/apparmor_parser \ + --base="$SPREAD_PATH"/profiles/apparmor.d \ + --remove \ + "$SPREAD_PATH"/profiles/apparmor.d/"$PROFILE_NAME" + + # Restore auditd and old rate-limit. + if [ -f did-stop-auditd.txt ]; then + systemctl start auditd.service + rm -f did-stop-auditd.txt + fi + if [ -f old-ratelimit.txt ]; then + sysctl -w kernel.printk_ratelimit="$(cat old-ratelimit.txt)" + rm -f old-ratelimit.txt + fi + + # Check if running the test resulted in any logged denials. + if dmesg | grep DENIED > denials.txt; then + echo "Denials were emitted during the test" + cat denials.txt + exit 1 + fi + + debug-each: | + echo "PROGRAM_NAME=${PROGRAM_NAME:=$(basename "$SPREAD_TASK")}" + command -v "$PROGRAM_NAME" + utils/: summary: Unit tests for the Python utilities. prepare: | diff --git a/tests/profiles/toybox/task.yaml b/tests/profiles/toybox/task.yaml new file mode 100644 index 000000000..44e2f6ea1 --- /dev/null +++ b/tests/profiles/toybox/task.yaml @@ -0,0 +1,11 @@ +summary: smoke test for the toybox profile +systems: + # Toybox is not packaged on openSUSE + - -opensuse-* +execute: | + # Toybox works (this is a very basic test). + test "$(toybox id -u)" -eq 0 + # The profile may be used explicitly. + aa-exec -p toybox toybox cat /proc/self/attr/current | MATCH 'toybox \(unconfined\)' + # The profile is attached implicitly based on path name. + toybox cat /proc/self/attr/current | MATCH 'toybox \(unconfined\)'