On 05/25/2016 01:59 PM, Tyler Hicks wrote: > 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]>
wouldn't hurt to add extra negative cases as below, with or without Acked-by: John Johansen <[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) [NEGATIVE]" \ + fail -- $at_secure 1 > +genprofile $at_secure:Ux > +runchecktest "AT_SECURE (confined -> unconfined - Ux)" \ > + pass -- $at_secure 1 > + +genprofile $at_secure:Ux +runchecktest "AT_SECURE (confined -> unconfined - Ux) [NEGATIVE]" \ + fail -- $at_secure 0 > +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) [NEGATIVE]" \ + fail -- $at_secure 1 > +genprofile $at_secure:PUx > +runchecktest "AT_SECURE (confined -> unconfined - PUx fallback)" \ > + pass -- $at_secure 1 +genprofile $at_secure:PUx +runchecktest "AT_SECURE (confined -> unconfined - PUx fallback) [NEGATIVE]" \ + fail -- $at_secure 0 + > +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) [NEGATIVE]" \ + fail -- $at_secure 1 + > +genprofile $at_secure:CUx > +runchecktest "AT_SECURE (confined -> unconfined - CUx fallback)" \ > + pass -- $at_secure 1 > + +genprofile $at_secure:CUx +runchecktest "AT_SECURE (confined -> unconfined - CUx fallback) [NEGATIVE]" \ + fail -- $at_secure 0 > +# 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) [NEGATIVE]" \ + fail -- $at_secure 1 > + > +genprofile $at_secure:Px -- image=$at_secure > +runchecktest "AT_SECURE (confined -> confined - Px)" \ > + pass -- $at_secure 1 > + +genprofile $at_secure:Px -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - Px) [NEGATIVE]" \ + fail -- $at_secure 0 > +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) [NEGATIVE]" \ + fail -- $at_secure 1 > +genprofile $at_secure:PUx -- image=$at_secure > +runchecktest "AT_SECURE (confined -> confined - PUx)" \ > + pass -- $at_secure 1 > + +genprofile $at_secure:PUx -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - PUx) [NEGATIVE]" \ + fail -- $at_secure 0 > +genprofile $at_secure:ix -- image=$at_secure > +runchecktest "AT_SECURE (confined -> confined - ix)" \ > + pass -- $at_secure 0 > + +genprofile $at_secure:ix -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - ix) [NEGATIVE]" \ + fail -- $at_secure 1 > +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) [NEGATIVE]" \ + fail -- $at_secure 1 > +genprofile $at_secure:Pix -- image=$at_secure > +runchecktest "AT_SECURE (confined -> confined - Pix)" \ > + pass -- $at_secure 1 > + +genprofile $at_secure:Pix -- image=$at_secure +runchecktest "AT_SECURE (confined -> confined - Pix) [NEGATIVE]" \ + fail -- $at_secure 0 > +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) [NEGATIVE]" \ > + fail -- $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) [NEGATIVE]" \ + fail -- $at_secure 1 > + > +# 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 > -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
