[apparmor] [PATCH 03/11] tests: Regression tests to verify AT_SECURE across exec transitions
John Johansen
john.johansen at canonical.com
Fri May 27 11:53:26 UTC 2016
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 <tyhicks at canonical.com>
wouldn't hurt to add extra negative cases as below, with or without
Acked-by: John Johansen <john.johansen at canonical.com>
> ---
> 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
>
More information about the AppArmor
mailing list