The AT_SECURE value in the kernel's per-process auxiliary vector is what signals to libc that the process' environment should be scrubbed. This new set of regression tests checks the AT_SECURE value after performing the various types of exec transitions that AppArmor supports (file rules with different exec access modes and change_profile rules).
Different versions of the kernel handle AT_SECURE differently with respect to change_profile rules. This change in behavior was introduced in the AppArmor profile stacking kernel support and the tests are conditionalized to account for this change. Signed-off-by: Tyler Hicks <[email protected]> --- tests/regression/apparmor/Makefile | 5 ++ tests/regression/apparmor/at_secure.c | 55 ++++++++++++ tests/regression/apparmor/at_secure.sh | 153 +++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 tests/regression/apparmor/at_secure.c create mode 100755 tests/regression/apparmor/at_secure.sh diff --git a/tests/regression/apparmor/Makefile b/tests/regression/apparmor/Makefile index f194396..8d75c69 100644 --- a/tests/regression/apparmor/Makefile +++ b/tests/regression/apparmor/Makefile @@ -70,6 +70,7 @@ endif # USE_SYSTEM CFLAGS += -g -O0 -Wall -Wstrict-prototypes SRC=access.c \ + at_secure.c \ introspect.c \ changeprofile.c \ onexec.c \ @@ -187,6 +188,7 @@ EXEC=$(SRC:%.c=%) TESTS=aa_exec \ access \ + at_secure \ introspect \ capabilities \ changeprofile \ @@ -265,6 +267,9 @@ else # !USE_SYSTEM cp uservars.inc.source uservars.inc endif # USE_SYSTEM +at_secure: at_secure.c transition + ${CC} ${CFLAGS} ${LDFLAGS} $< -o $@ ${LDLIBS} + changehat_pthread: changehat_pthread.c changehat.h ${CC} ${CFLAGS} ${LDFLAGS} $< -o $@ ${LDLIBS} -pthread diff --git a/tests/regression/apparmor/at_secure.c b/tests/regression/apparmor/at_secure.c new file mode 100644 index 0000000..bfb80b8 --- /dev/null +++ b/tests/regression/apparmor/at_secure.c @@ -0,0 +1,55 @@ +/** + * Copyright (C) 2016 Canonical, Ltd. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, contact Canonical Ltd. + */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/auxv.h> + +int check_at_secure(unsigned long expected) +{ + unsigned long at_secure; + + errno = 0; + at_secure = getauxval(AT_SECURE); + if (at_secure == 0 && errno != 0) { + perror("FAIL - getauxval"); + return 1; + } + + if (at_secure != expected) { + fprintf(stderr, + "FAIL - AT_SECURE value (%lu) did not match the expected value (%lu)\n", + at_secure, expected); + return 1; + } + + printf("PASS\n"); + return 0; +} + +int main(int argc, char **argv) +{ + unsigned long expected; + + if (argc != 2) { + fprintf(stderr, "usage: %s EXPECTED_AT_SECURE\n", argv[0]); + return 1; + } + + expected = strtoul(argv[1], NULL, 10); + return check_at_secure(expected); +} diff --git a/tests/regression/apparmor/at_secure.sh b/tests/regression/apparmor/at_secure.sh new file mode 100755 index 0000000..7c507e7 --- /dev/null +++ b/tests/regression/apparmor/at_secure.sh @@ -0,0 +1,153 @@ +#! /bin/bash +# Copyright (C) 2016 Canonical, Ltd. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation, version 2 of the +# License. + +#=NAME at_secure +#=DESCRIPTION +# Verifies the AT_SECURE flag in the auxillary vector after an exec transition +#=END + +pwd=`dirname $0` +pwd=`cd $pwd ; /bin/pwd` + +bin=$pwd + +. $bin/prologue.inc + +settest transition +at_secure=$pwd/at_secure +test_prof=at_secure +stacking_supported="$(kernel_features domain/stack || true)" + +onexec_default=1 +if [ "$stacking_supported" != "true" ]; then + # Pre-stacking kernels default to insecure exec transitions with + # change_profile rules that have an exec condition but don't have an + # "(un)safe" modifier. + onexec_default=0 +fi + +# Verify AT_SECURE after unconfined -> unconfined transition +runchecktest "AT_SECURE (unconfined -> unconfined - change_onexec)" \ + pass -O unconfined -- $at_secure 0 +runchecktest "AT_SECURE (unconfined -> unconfined - change_onexec) [NEGATIVE]" \ + fail -O unconfined -- $at_secure 1 + +# Verify AT_SECURE after unconfined -> confined transition +genprofile image=$test_prof addimage:$at_secure +runchecktest "AT_SECURE (unconfined -> confined - change_onexec)" \ + pass -O $test_prof -- $at_secure 0 +runchecktest "AT_SECURE (unconfined -> confined - change_onexec) [NEGATIVE]" \ + fail -O $test_prof -- $at_secure 1 + +genprofile image=$at_secure +runchecktest "AT_SECURE (unconfined -> confined - binary attachment)" \ + pass -- $at_secure 0 +runchecktest "AT_SECURE (unconfined -> confined - binary attachment) [NEGATIVE]" \ + fail -- $at_secure 1 + +# Verify AT_SECURE after confined -> unconfined transition +genprofile "change_profile:unconfined" +runchecktest "AT_SECURE (confined -> unconfined - change_onexec)" \ + pass -O unconfined -- $at_secure $onexec_default + +genprofile $at_secure:ux +runchecktest "AT_SECURE (confined -> unconfined - ux)" \ + pass -- $at_secure 0 + +genprofile $at_secure:Ux +runchecktest "AT_SECURE (confined -> unconfined - Ux)" \ + pass -- $at_secure 1 + +genprofile $at_secure:pux +runchecktest "AT_SECURE (confined -> unconfined - pux fallback)" \ + pass -- $at_secure 0 + +genprofile $at_secure:PUx +runchecktest "AT_SECURE (confined -> unconfined - PUx fallback)" \ + pass -- $at_secure 1 + +genprofile $at_secure:cux +runchecktest "AT_SECURE (confined -> unconfined - cux fallback)" \ + pass -- $at_secure 0 + +genprofile $at_secure:CUx +runchecktest "AT_SECURE (confined -> unconfined - CUx fallback)" \ + pass -- $at_secure 1 + +# Verify AT_SECURE after confined -> confined transition +genprofile "change_profile:$test_prof" -- image=$test_prof addimage:$at_secure +runchecktest "AT_SECURE (confined -> confined - change_onexec)" \ + pass -O $test_prof -- $at_secure $onexec_default + +genprofile $at_secure:px -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - px)" \ + pass -- $at_secure 0 + +genprofile $at_secure:Px -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - Px)" \ + pass -- $at_secure 1 + +genprofile $at_secure:pux -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - pux)" \ + pass -- $at_secure 0 + +genprofile $at_secure:PUx -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - PUx)" \ + pass -- $at_secure 1 + +genprofile $at_secure:ix -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - ix)" \ + pass -- $at_secure 0 + +genprofile $at_secure:pix -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - pix)" \ + pass -- $at_secure 0 + +genprofile $at_secure:Pix -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - Pix)" \ + pass -- $at_secure 1 + +genprofile $at_secure:cix -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - cix fallback)" \ + pass -- $at_secure 0 + +genprofile $at_secure:Cix -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - Cix fallback)" \ + pass -- $at_secure 0 + +# TODO: Adjust mkprofile.pl to allow child profiles so that cx and Cx can be +# tested as well as the non-fallback cix and Cix cases + +if [ "$stacking_supported" != "true" ]; then + echo "Warning: kernel doesn't support stacking. Skipping tests..." +else + removeprofile + + # Verify AT_SECURE after unconfined -> &unconfined stacking transition + runchecktest "AT_SECURE (unconfined -> &unconfined - stack_onexec)" \ + pass -o unconfined -- $at_secure 0 + runchecktest "AT_SECURE (unconfined -> &unconfined - stack_onexec) [NEGATIVE]" \ + fail -o unconfined -- $at_secure 1 + + # Verify AT_SECURE after unconfined -> &confined stacking transition + genprofile image=$test_prof addimage:$at_secure + runchecktest "AT_SECURE (unconfined -> &confined - stack_onexec)" \ + pass -o $test_prof -- $at_secure 0 + runchecktest "AT_SECURE (unconfined -> &confined - stack_onexec) [NEGATIVE]" \ + fail -o $test_prof -- $at_secure 1 + + # Verify AT_SECURE after confined -> &unconfined stacking transition + genprofile "change_profile:&unconfined" + runchecktest "AT_SECURE (confined -> &unconfined - stack_onexec)" \ + pass -o unconfined -- $at_secure $onexec_default + + # Verify AT_SECURE after confined -> &confined stacking transition + genprofile "change_profile:&$test_prof" -- image=$test_prof addimage:$at_secure + runchecktest "AT_SECURE (confined -> &confined - stack_onexec)" \ + pass -o $test_prof -- $at_secure $onexec_default +fi -- 2.7.4 -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
