[apparmor] [PATCH 03/11] tests: Regression tests to verify AT_SECURE across exec transitions
Tyler Hicks
tyhicks at canonical.com
Wed May 25 20:59:35 UTC 2016
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>
---
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
More information about the AppArmor
mailing list