[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