This test will soon be made to do more than just stack a new profile.
It will be extended to allow for changing to a new profile and,
therefore, be renamed.

Signed-off-by: Tyler Hicks <[email protected]>
---
 tests/regression/apparmor/Makefile        |   4 +-
 tests/regression/apparmor/exec_stack.sh   |   2 +-
 tests/regression/apparmor/stacking.c      | 337 ------------------------------
 tests/regression/apparmor/stackonexec.sh  |   2 +-
 tests/regression/apparmor/stackprofile.sh |   2 +-
 tests/regression/apparmor/transition.c    | 337 ++++++++++++++++++++++++++++++
 6 files changed, 342 insertions(+), 342 deletions(-)
 delete mode 100644 tests/regression/apparmor/stacking.c
 create mode 100644 tests/regression/apparmor/transition.c

diff --git a/tests/regression/apparmor/Makefile 
b/tests/regression/apparmor/Makefile
index ca9a294..87f756a 100644
--- a/tests/regression/apparmor/Makefile
+++ b/tests/regression/apparmor/Makefile
@@ -168,7 +168,7 @@ ifdef USE_SYSTEM
   endif
 
   ifneq (,$(shell pkg-config --atleast-version 2.10.95 libapparmor && echo 
TRUE))
-    SRC+=stacking.c
+    SRC+=transition.c
     CONDITIONAL_TESTS+=exec_stack stackonexec stackprofile
   else
     $(warning ${nl}\
@@ -177,7 +177,7 @@ ifdef USE_SYSTEM
     
************************************************************************${nl})
   endif
 else
-  SRC+=aa_policy_cache.c stacking.c
+  SRC+=aa_policy_cache.c transition.c
   CONDITIONAL_TESTS+=exec_stack aa_policy_cache stackonexec stackprofile
 endif
 
diff --git a/tests/regression/apparmor/exec_stack.sh 
b/tests/regression/apparmor/exec_stack.sh
index ef12015..2423dea 100755
--- a/tests/regression/apparmor/exec_stack.sh
+++ b/tests/regression/apparmor/exec_stack.sh
@@ -20,7 +20,7 @@ bin=$pwd
 . $bin/prologue.inc
 
 requires_kernel_features domain/stack
-settest stacking
+settest transition
 
 file=$tmpdir/file
 otherfile=$tmpdir/file2
diff --git a/tests/regression/apparmor/stacking.c 
b/tests/regression/apparmor/stacking.c
deleted file mode 100644
index ac1afce..0000000
--- a/tests/regression/apparmor/stacking.c
+++ /dev/null
@@ -1,337 +0,0 @@
-/*
- * Copyright (C) 2014-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.
- */
-
-#define _GNU_SOURCE
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/apparmor.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "changehat.h" /* for do_open() */
-
-#define STACK_DELIM    "//&"
-#define STACK_DELIM_LEN        strlen(STACK_DELIM)
-
-#define NO_MODE                "(null)"
-
-static void file_io(const char *file)
-{
-       int rc = do_open(file);
-
-       if (rc != 0)
-               exit(rc);
-}
-
-struct single_label {
-       const char *label;
-       size_t len;
-};
-
-#define MAX_LABELS     32
-
-struct compound_label {
-       size_t num_labels;
-       struct single_label labels[MAX_LABELS];
-};
-
-/**
- * Initializes @sl by parsing @compound_label. Returns a pointer to the
- * location of the next label in the compound label string, which should be
- * passed in as @compound_label the next time that next_label() is called. NULL
- * is returned when there are no more labels in @compound_label.
- */
-static const char *next_label(struct single_label *sl,
-                             const char *compound_label)
-{
-       const char *delim;
-
-       if (!compound_label || compound_label[0] == '\0')
-               return NULL;
-
-       delim = strstr(compound_label, STACK_DELIM);
-       if (!delim) {
-               sl->label = compound_label;
-               sl->len = strlen(sl->label);
-               return sl->label + sl->len;
-       }
-
-       sl->label = compound_label;
-       sl->len = delim - sl->label;
-       return delim + STACK_DELIM_LEN;
-}
-
-/* Returns true if the compound label was constructed successfully */
-static bool compound_label_init(struct compound_label *cl,
-                               const char *compound_label)
-{
-       memset(cl, 0, sizeof(*cl));
-       while ((compound_label = next_label(&cl->labels[cl->num_labels],
-                                           compound_label))) {
-               cl->num_labels++;
-
-               if (cl->num_labels == MAX_LABELS)
-                       return false;
-       }
-
-       return true;
-}
-
-/* Returns true if the compound label contains the single label */
-static bool compound_label_contains(struct compound_label *cl,
-                                   struct single_label *sl)
-{
-       bool matched = false;
-       size_t i;
-
-       for (i = 0; !matched && i < cl->num_labels; i++) {
-               if (cl->labels[i].len != sl->len)
-                       continue;
-
-               if (strncmp(cl->labels[i].label, sl->label, sl->len))
-                       continue;
-
-               matched = true;
-       }
-
-       return matched;
-}
-
-/* Returns true if the two compound labels contain the same label sets */
-static bool compound_labels_equal(struct compound_label *cl1,
-                                 struct compound_label *cl2)
-{
-       size_t i;
-
-       if (cl1->num_labels != cl2->num_labels)
-               return false;
-
-       for (i = 0; i < cl1->num_labels; i++) {
-               if (!compound_label_contains(cl2, &cl1->labels[i]))
-                       return false;
-       }
-
-       return true;
-}
-
-/**
- * Verifies that the current confinement context matches the expected context.
- *
- * Either @expected_label or @expected_mode can be NULL if their values should
- * not be verified. If a NULL mode is expected, as what happens when an
- * unconfined process calls aa_getcon(2), then @expected_mode should be equal
- * to NO_MODE.
- */
-static void verify_confinement_context(const char *expected_label,
-                                      const char *expected_mode)
-{
-       char *label, *mode;
-       int expected_rc, rc;
-       bool null_expected_mode = expected_mode ?
-                                 strcmp(NO_MODE, expected_mode) == 0 : false;
-
-       rc = aa_getcon(&label, &mode);
-       if (rc < 0) {
-               int err = errno;
-               fprintf(stderr, "FAIL - aa_getcon: %m");
-               exit(err);
-       }
-
-       if (expected_label) {
-               struct compound_label cl, expected_cl;
-
-               if (!compound_label_init(&cl, label)) {
-                       fprintf(stderr, "FAIL - could not parse current 
compound label: %s\n",
-                               label);
-                       rc = EINVAL;
-                       goto err;
-               }
-
-               if (!compound_label_init(&expected_cl, expected_label)) {
-                       fprintf(stderr, "FAIL - could not parse expected 
compound label: %s\n",
-                               expected_label);
-                       rc = EINVAL;
-                       goto err;
-               }
-
-               if (!compound_labels_equal(&cl, &expected_cl)) {
-                       fprintf(stderr, "FAIL - label \"%s\" != expected_label 
\"%s\"\n",
-                               label, expected_label);
-                       rc = EINVAL;
-                       goto err;
-               }
-       }
-
-       if (expected_mode &&
-           ((!mode && !null_expected_mode) ||
-            (mode && strcmp(mode, expected_mode)))) {
-               fprintf(stderr, "FAIL - mode \"%s\" != expected_mode \"%s\"\n",
-                       mode, expected_mode);
-               rc = EINVAL;
-               goto err;
-       }
-
-       expected_rc = expected_label ? strlen(expected_label) : strlen(label);
-
-       /**
-        * Add the expected bytes following the returned label string:
-        *
-        *   ' ' + '(' + mode + ')'
-        */
-       if (expected_mode && !null_expected_mode)
-               expected_rc += 1 + 1 + strlen(expected_mode) + 1;
-       else if (mode)
-               expected_rc += 1 + 1 + strlen(mode) + 1;
-
-       expected_rc++; /* Trailing NUL terminator */
-
-       if (rc != expected_rc) {
-               fprintf(stderr, "FAIL - rc (%d) != expected_rc (%d)\n",
-                       rc, expected_rc);
-               rc = EINVAL;
-               goto err;
-       }
-
-       return;
-err:
-       free(label);
-       exit(EINVAL);
-}
-
-static void stack_onexec(const char *label)
-{
-       if (aa_stack_onexec(label) != 0) {
-               int err = errno;
-               perror("FAIL - aa_stack_onexec");
-               exit(err);
-       }
-}
-
-static void stack_profile(const char *label)
-{
-       if (aa_stack_profile(label) != 0) {
-               int err = errno;
-               perror("FAIL - aa_stack_profile");
-               exit(err);
-       }
-}
-
-static void exec(const char *prog, char **argv)
-{
-       int err;
-
-       execv(prog, argv);
-       err = errno;
-       perror("FAIL - execv");
-       exit(err);
-}
-
-static void usage(const char *prog)
-{
-       fprintf(stderr,
-               "%s: [-o <LABEL> | -p <LABEL>] [-l <LABEL>] [-m <MODE>] [-f 
<FILE>] [-- ... [-- ...]]\n"
-               "  -o <LABEL>\tCall aa_stack_onexec(LABEL)\n"
-               "  -p <LABEL>\tCall aa_stack_profile(LABEL)\n"
-               "  -l <LABEL>\tVerify that aa_getcon() returns LABEL\n"
-               "  -m <MODE>\tVerify that aa_getcon() returns MODE. Set to 
\"%s\" if a NULL mode is expected.\n"
-               "  -f <FILE>\tOpen FILE and attempt to write to and read from 
it\n\n"
-               "If \"--\" is encountered, execv() will be called using the 
following argument\n"
-               "as the program to execute and passing it all of the arguments 
following the\n"
-               "program name.\n", prog, NO_MODE);
-       exit(EINVAL);
-}
-
-struct options {
-       const char *file;
-       const char *expected_label;
-       const char *expected_mode;
-       const char *stack_onexec;
-       const char *stack_profile;
-       const char *exec;
-       char **exec_argv;
-};
-
-static void parse_opts(int argc, char **argv, struct options *opts)
-{
-       int o;
-
-       memset(opts, 0, sizeof(*opts));
-       while ((o = getopt(argc, argv, "f:l:m:o:p:")) != -1) {
-               switch (o) {
-               case 'f': /* file */
-                       opts->file = optarg;
-                       break;
-               case 'l': /* expected label */
-                       opts->expected_label = optarg;
-                       break;
-               case 'm': /* expected mode */
-                       opts->expected_mode = optarg;
-                       break;
-               case 'o': /* aa_stack_onexec */
-                       opts->stack_onexec = optarg;
-                       break;
-               case 'p': /* aa_stack_profile */
-                       opts->stack_profile = optarg;
-                       break;
-               default: /* '?' */
-                       usage(argv[0]);
-               }
-       }
-
-       /* Can only specify one or the other */
-       if (opts->stack_onexec && opts->stack_profile) {
-               usage(argv[0]);
-       }
-
-       if (optind < argc) {
-               /* Ensure that the previous option was "--" */
-               if (optind == 0 || strcmp("--", argv[optind - 1]))
-                       usage(argv[0]);
-
-               opts->exec = argv[optind];
-               opts->exec_argv = &argv[optind];
-       }
-}
-
-int main(int argc, char **argv)
-{
-       struct options opts;
-
-       parse_opts(argc, argv, &opts);
-
-       if (opts.stack_onexec)
-               stack_onexec(opts.stack_onexec);
-       else if (opts.stack_profile)
-               stack_profile(opts.stack_profile);
-
-       if (opts.file)
-               file_io(opts.file);
-
-       if (opts.expected_label || opts.expected_mode)
-               verify_confinement_context(opts.expected_label,
-                                          opts.expected_mode);
-
-       if (opts.exec)
-               exec(opts.exec, opts.exec_argv);
-
-       printf("PASS\n");
-       exit(0);
-}
-
diff --git a/tests/regression/apparmor/stackonexec.sh 
b/tests/regression/apparmor/stackonexec.sh
index 7bad824..565fbfc 100755
--- a/tests/regression/apparmor/stackonexec.sh
+++ b/tests/regression/apparmor/stackonexec.sh
@@ -20,7 +20,7 @@ bin=$pwd
 . $bin/prologue.inc
 
 requires_kernel_features domain/stack
-settest stacking
+settest transition
 
 file=$tmpdir/file
 otherfile=$tmpdir/file2
diff --git a/tests/regression/apparmor/stackprofile.sh 
b/tests/regression/apparmor/stackprofile.sh
index 7f248a1..efe8a7c 100755
--- a/tests/regression/apparmor/stackprofile.sh
+++ b/tests/regression/apparmor/stackprofile.sh
@@ -20,7 +20,7 @@ bin=$pwd
 . $bin/prologue.inc
 
 requires_kernel_features domain/stack
-settest stacking
+settest transition
 
 file=$tmpdir/file
 otherfile=$tmpdir/file2
diff --git a/tests/regression/apparmor/transition.c 
b/tests/regression/apparmor/transition.c
new file mode 100644
index 0000000..ac1afce
--- /dev/null
+++ b/tests/regression/apparmor/transition.c
@@ -0,0 +1,337 @@
+/*
+ * Copyright (C) 2014-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.
+ */
+
+#define _GNU_SOURCE
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/apparmor.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "changehat.h" /* for do_open() */
+
+#define STACK_DELIM    "//&"
+#define STACK_DELIM_LEN        strlen(STACK_DELIM)
+
+#define NO_MODE                "(null)"
+
+static void file_io(const char *file)
+{
+       int rc = do_open(file);
+
+       if (rc != 0)
+               exit(rc);
+}
+
+struct single_label {
+       const char *label;
+       size_t len;
+};
+
+#define MAX_LABELS     32
+
+struct compound_label {
+       size_t num_labels;
+       struct single_label labels[MAX_LABELS];
+};
+
+/**
+ * Initializes @sl by parsing @compound_label. Returns a pointer to the
+ * location of the next label in the compound label string, which should be
+ * passed in as @compound_label the next time that next_label() is called. NULL
+ * is returned when there are no more labels in @compound_label.
+ */
+static const char *next_label(struct single_label *sl,
+                             const char *compound_label)
+{
+       const char *delim;
+
+       if (!compound_label || compound_label[0] == '\0')
+               return NULL;
+
+       delim = strstr(compound_label, STACK_DELIM);
+       if (!delim) {
+               sl->label = compound_label;
+               sl->len = strlen(sl->label);
+               return sl->label + sl->len;
+       }
+
+       sl->label = compound_label;
+       sl->len = delim - sl->label;
+       return delim + STACK_DELIM_LEN;
+}
+
+/* Returns true if the compound label was constructed successfully */
+static bool compound_label_init(struct compound_label *cl,
+                               const char *compound_label)
+{
+       memset(cl, 0, sizeof(*cl));
+       while ((compound_label = next_label(&cl->labels[cl->num_labels],
+                                           compound_label))) {
+               cl->num_labels++;
+
+               if (cl->num_labels == MAX_LABELS)
+                       return false;
+       }
+
+       return true;
+}
+
+/* Returns true if the compound label contains the single label */
+static bool compound_label_contains(struct compound_label *cl,
+                                   struct single_label *sl)
+{
+       bool matched = false;
+       size_t i;
+
+       for (i = 0; !matched && i < cl->num_labels; i++) {
+               if (cl->labels[i].len != sl->len)
+                       continue;
+
+               if (strncmp(cl->labels[i].label, sl->label, sl->len))
+                       continue;
+
+               matched = true;
+       }
+
+       return matched;
+}
+
+/* Returns true if the two compound labels contain the same label sets */
+static bool compound_labels_equal(struct compound_label *cl1,
+                                 struct compound_label *cl2)
+{
+       size_t i;
+
+       if (cl1->num_labels != cl2->num_labels)
+               return false;
+
+       for (i = 0; i < cl1->num_labels; i++) {
+               if (!compound_label_contains(cl2, &cl1->labels[i]))
+                       return false;
+       }
+
+       return true;
+}
+
+/**
+ * Verifies that the current confinement context matches the expected context.
+ *
+ * Either @expected_label or @expected_mode can be NULL if their values should
+ * not be verified. If a NULL mode is expected, as what happens when an
+ * unconfined process calls aa_getcon(2), then @expected_mode should be equal
+ * to NO_MODE.
+ */
+static void verify_confinement_context(const char *expected_label,
+                                      const char *expected_mode)
+{
+       char *label, *mode;
+       int expected_rc, rc;
+       bool null_expected_mode = expected_mode ?
+                                 strcmp(NO_MODE, expected_mode) == 0 : false;
+
+       rc = aa_getcon(&label, &mode);
+       if (rc < 0) {
+               int err = errno;
+               fprintf(stderr, "FAIL - aa_getcon: %m");
+               exit(err);
+       }
+
+       if (expected_label) {
+               struct compound_label cl, expected_cl;
+
+               if (!compound_label_init(&cl, label)) {
+                       fprintf(stderr, "FAIL - could not parse current 
compound label: %s\n",
+                               label);
+                       rc = EINVAL;
+                       goto err;
+               }
+
+               if (!compound_label_init(&expected_cl, expected_label)) {
+                       fprintf(stderr, "FAIL - could not parse expected 
compound label: %s\n",
+                               expected_label);
+                       rc = EINVAL;
+                       goto err;
+               }
+
+               if (!compound_labels_equal(&cl, &expected_cl)) {
+                       fprintf(stderr, "FAIL - label \"%s\" != expected_label 
\"%s\"\n",
+                               label, expected_label);
+                       rc = EINVAL;
+                       goto err;
+               }
+       }
+
+       if (expected_mode &&
+           ((!mode && !null_expected_mode) ||
+            (mode && strcmp(mode, expected_mode)))) {
+               fprintf(stderr, "FAIL - mode \"%s\" != expected_mode \"%s\"\n",
+                       mode, expected_mode);
+               rc = EINVAL;
+               goto err;
+       }
+
+       expected_rc = expected_label ? strlen(expected_label) : strlen(label);
+
+       /**
+        * Add the expected bytes following the returned label string:
+        *
+        *   ' ' + '(' + mode + ')'
+        */
+       if (expected_mode && !null_expected_mode)
+               expected_rc += 1 + 1 + strlen(expected_mode) + 1;
+       else if (mode)
+               expected_rc += 1 + 1 + strlen(mode) + 1;
+
+       expected_rc++; /* Trailing NUL terminator */
+
+       if (rc != expected_rc) {
+               fprintf(stderr, "FAIL - rc (%d) != expected_rc (%d)\n",
+                       rc, expected_rc);
+               rc = EINVAL;
+               goto err;
+       }
+
+       return;
+err:
+       free(label);
+       exit(EINVAL);
+}
+
+static void stack_onexec(const char *label)
+{
+       if (aa_stack_onexec(label) != 0) {
+               int err = errno;
+               perror("FAIL - aa_stack_onexec");
+               exit(err);
+       }
+}
+
+static void stack_profile(const char *label)
+{
+       if (aa_stack_profile(label) != 0) {
+               int err = errno;
+               perror("FAIL - aa_stack_profile");
+               exit(err);
+       }
+}
+
+static void exec(const char *prog, char **argv)
+{
+       int err;
+
+       execv(prog, argv);
+       err = errno;
+       perror("FAIL - execv");
+       exit(err);
+}
+
+static void usage(const char *prog)
+{
+       fprintf(stderr,
+               "%s: [-o <LABEL> | -p <LABEL>] [-l <LABEL>] [-m <MODE>] [-f 
<FILE>] [-- ... [-- ...]]\n"
+               "  -o <LABEL>\tCall aa_stack_onexec(LABEL)\n"
+               "  -p <LABEL>\tCall aa_stack_profile(LABEL)\n"
+               "  -l <LABEL>\tVerify that aa_getcon() returns LABEL\n"
+               "  -m <MODE>\tVerify that aa_getcon() returns MODE. Set to 
\"%s\" if a NULL mode is expected.\n"
+               "  -f <FILE>\tOpen FILE and attempt to write to and read from 
it\n\n"
+               "If \"--\" is encountered, execv() will be called using the 
following argument\n"
+               "as the program to execute and passing it all of the arguments 
following the\n"
+               "program name.\n", prog, NO_MODE);
+       exit(EINVAL);
+}
+
+struct options {
+       const char *file;
+       const char *expected_label;
+       const char *expected_mode;
+       const char *stack_onexec;
+       const char *stack_profile;
+       const char *exec;
+       char **exec_argv;
+};
+
+static void parse_opts(int argc, char **argv, struct options *opts)
+{
+       int o;
+
+       memset(opts, 0, sizeof(*opts));
+       while ((o = getopt(argc, argv, "f:l:m:o:p:")) != -1) {
+               switch (o) {
+               case 'f': /* file */
+                       opts->file = optarg;
+                       break;
+               case 'l': /* expected label */
+                       opts->expected_label = optarg;
+                       break;
+               case 'm': /* expected mode */
+                       opts->expected_mode = optarg;
+                       break;
+               case 'o': /* aa_stack_onexec */
+                       opts->stack_onexec = optarg;
+                       break;
+               case 'p': /* aa_stack_profile */
+                       opts->stack_profile = optarg;
+                       break;
+               default: /* '?' */
+                       usage(argv[0]);
+               }
+       }
+
+       /* Can only specify one or the other */
+       if (opts->stack_onexec && opts->stack_profile) {
+               usage(argv[0]);
+       }
+
+       if (optind < argc) {
+               /* Ensure that the previous option was "--" */
+               if (optind == 0 || strcmp("--", argv[optind - 1]))
+                       usage(argv[0]);
+
+               opts->exec = argv[optind];
+               opts->exec_argv = &argv[optind];
+       }
+}
+
+int main(int argc, char **argv)
+{
+       struct options opts;
+
+       parse_opts(argc, argv, &opts);
+
+       if (opts.stack_onexec)
+               stack_onexec(opts.stack_onexec);
+       else if (opts.stack_profile)
+               stack_profile(opts.stack_profile);
+
+       if (opts.file)
+               file_io(opts.file);
+
+       if (opts.expected_label || opts.expected_mode)
+               verify_confinement_context(opts.expected_label,
+                                          opts.expected_mode);
+
+       if (opts.exec)
+               exec(opts.exec, opts.exec_argv);
+
+       printf("PASS\n");
+       exit(0);
+}
+
-- 
2.7.4


-- 
AppArmor mailing list
[email protected]
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to