tests: Add regression tests for the aa_policy_cache API

The aa_features and aa_kernel_interface APIs get a little bit of
testing, as well.

Signed-off-by: Tyler Hicks <tyhicks@canonical.com>
Acked-by: Steve Beattie <steve@nxnw.org>
This commit is contained in:
Tyler Hicks 2015-03-26 10:19:46 -05:00
parent fc8d3d4edc
commit 6da919d400
3 changed files with 395 additions and 0 deletions

View file

@ -135,6 +135,21 @@ Install libdbus-1-dev or equivalent package to build and run these tests${nl}\
************************************************************************${nl})
endif
ifdef USE_SYSTEM
ifneq (,$(shell pkg-config --atleast-version 2.10 libapparmor && echo TRUE))
SRC+=aa_policy_cache.c
AA_POLICY_CACHE_TEST=aa_policy_cache
else
$(warning ${nl}\
************************************************************************${nl}\
Skipping aa_policy_cache tests: requires libapparmor 2.10 or newer ...${nl}\
************************************************************************${nl})
endif
else
SRC+=aa_policy_cache.c
AA_POLICY_CACHE_TEST=aa_policy_cache
endif
EXEC=$(SRC:%.c=%)
TESTS=access \
@ -195,6 +210,8 @@ ifneq (,$(shell pkg-config --exists dbus-1 && echo TRUE))
TESTS+=dbus_eavesdrop dbus_message dbus_service dbus_unrequested_reply
endif
TESTS+=$(AA_POLICY_CACHE_TEST)
# Tests that can crash the kernel should be placed here
RISKY_TESTS=

View file

@ -0,0 +1,229 @@
/*
* Copyright (C) 2015 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 <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/apparmor.h>
#define OPT_CREATE "create"
#define OPT_IS_VALID "is-valid"
#define OPT_NEW "new"
#define OPT_NEW_CREATE "new-create"
#define OPT_REMOVE "remove"
#define OPT_REMOVE_POLICY "remove-policy"
#define OPT_REPLACE_ALL "replace-all"
static void usage(const char *prog)
{
fprintf(stderr,
"FAIL - usage: %s %s <PATH>\n"
" %s %s <PATH>\n"
" %s %s <PATH>\n"
" %s %s <PATH>\n"
" %s %s <PATH>\n"
" %s %s <PROFILE_NAME>\n"
" %s %s <PATH>\n",
prog, OPT_CREATE, prog, OPT_IS_VALID, prog, OPT_NEW,
prog, OPT_NEW_CREATE, prog, OPT_REMOVE, prog, OPT_REMOVE_POLICY,
prog, OPT_REPLACE_ALL);
}
static int test_create(const char *path)
{
aa_features *features = NULL;
aa_policy_cache *policy_cache = NULL;
int rc = 1;
if (aa_features_new_from_kernel(&features)) {
perror("FAIL - aa_features_new_from_kernel");
goto out;
}
if (aa_policy_cache_new(&policy_cache, features, path, false)) {
perror("FAIL - aa_policy_cache_new");
goto out;
}
if (aa_policy_cache_create(policy_cache)) {
perror("FAIL - aa_policy_cache_create");
goto out;
}
rc = 0;
out:
aa_features_unref(features);
aa_policy_cache_unref(policy_cache);
return rc;
}
static int test_is_valid(const char *path)
{
aa_features *features = NULL;
aa_policy_cache *policy_cache = NULL;
int rc = 1;
if (aa_features_new_from_kernel(&features)) {
perror("FAIL - aa_features_new_from_kernel");
goto out;
}
if (aa_policy_cache_new(&policy_cache, features, path, false)) {
perror("FAIL - aa_policy_cache_new");
goto out;
}
if (!aa_policy_cache_is_valid(policy_cache)) {
errno = EINVAL;
perror("FAIL - aa_policy_cache_is_valid");
goto out;
}
rc = 0;
out:
aa_features_unref(features);
aa_policy_cache_unref(policy_cache);
return rc;
}
static int test_new(const char *path, bool create)
{
aa_features *features = NULL;
aa_policy_cache *policy_cache = NULL;
int rc = 1;
if (aa_features_new_from_kernel(&features)) {
perror("FAIL - aa_features_new_from_kernel");
goto out;
}
if (aa_policy_cache_new(&policy_cache, features, path, create)) {
perror("FAIL - aa_policy_cache_new");
goto out;
}
rc = 0;
out:
aa_features_unref(features);
aa_policy_cache_unref(policy_cache);
return rc;
}
static int test_remove(const char *path)
{
int rc = 1;
if (aa_policy_cache_remove(path)) {
perror("FAIL - aa_policy_cache_remove");
goto out;
}
rc = 0;
out:
return rc;
}
static int test_remove_policy(const char *name)
{
aa_features *features = NULL;
aa_kernel_interface *kernel_interface = NULL;
int rc = 1;
if (aa_features_new_from_kernel(&features)) {
perror("FAIL - aa_features_new_from_kernel");
goto out;
}
if (aa_kernel_interface_new(&kernel_interface, features, NULL)) {
perror("FAIL - aa_kernel_interface_new");
goto out;
}
if (aa_kernel_interface_remove_policy(kernel_interface, name)) {
perror("FAIL - aa_kernel_interface_remove_policy");
goto out;
}
rc = 0;
out:
aa_kernel_interface_unref(kernel_interface);
aa_features_unref(features);
return rc;
}
static int test_replace_all(const char *path)
{
aa_features *features = NULL;
aa_policy_cache *policy_cache = NULL;
int rc = 1;
if (aa_features_new_from_kernel(&features)) {
perror("FAIL - aa_features_new_from_kernel");
goto out;
}
if (aa_policy_cache_new(&policy_cache, features, path, false)) {
perror("FAIL - aa_policy_cache_new");
goto out;
}
if (aa_policy_cache_replace_all(policy_cache, NULL)) {
perror("FAIL - aa_policy_cache_replace_all");
goto out;
}
rc = 0;
out:
aa_features_unref(features);
aa_policy_cache_unref(policy_cache);
return rc;
}
int main(int argc, char **argv)
{
int rc = 1;
if (argc != 3) {
usage(argv[0]);
exit(1);
}
if (strcmp(argv[1], OPT_CREATE) == 0) {
rc = test_create(argv[2]);
} else if (strcmp(argv[1], OPT_IS_VALID) == 0) {
rc = test_is_valid(argv[2]);
} else if (strcmp(argv[1], OPT_NEW) == 0) {
rc = test_new(argv[2], false);
} else if (strcmp(argv[1], OPT_NEW_CREATE) == 0) {
rc = test_new(argv[2], true);
} else if (strcmp(argv[1], OPT_REMOVE) == 0) {
rc = test_remove(argv[2]);
} else if (strcmp(argv[1], OPT_REMOVE_POLICY) == 0) {
rc = test_remove_policy(argv[2]);
} else if (strcmp(argv[1], OPT_REPLACE_ALL) == 0) {
rc = test_replace_all(argv[2]);
} else {
usage(argv[0]);
}
if (!rc)
printf("PASS\n");
exit(rc);
}

View file

@ -0,0 +1,149 @@
#! /bin/bash
# Copyright (C) 2015 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 aa_policy_cache
#=DESCRIPTION
# This test verifies that the aa_policy_cache API works as expected.
#=END
pwd=`dirname $0`
pwd=`cd $pwd ; /bin/pwd`
bin=$pwd
. $bin/prologue.inc
cachedir=$tmpdir/cache
policies=$(echo aa_policy_cache_test_{0001..1024})
create_cachedir()
{
mkdir -p "$cachedir"
}
remove_cachedir()
{
if [ -n "$cachedir" ]
then
rm -rf "$cachedir"
fi
}
create_empty_cache()
{
$test new-create "$cachedir" > /dev/null
}
create_cache_files()
{
local cachefile
create_cachedir
for policy in $policies
do
cachefile="${cachedir}/${policy}"
echo "profile $policy { /f r, }" | ${subdomain} -qS > "$cachefile"
done
}
install_bad_features_file()
{
echo "file {\n}\n" > "${cachedir}/.features"
}
remove_features_file()
{
if [ -n "$cachedir" ]
then
rm -f "${cachedir}/.features"
fi
}
verify_policies_are_not_loaded()
{
for policy in $policies
do
if grep -q "^policy " /sys/kernel/security/apparmor/profiles
then
fatalerror "Policy \"${policy}\" must not be loaded"
return
fi
done
}
runchecktest_policies_are_loaded()
{
for policy in $policies
do
if ! grep -q "^$policy (enforce)" /sys/kernel/security/apparmor/profiles
then
echo "Error: Policy \"${policy}\" was not loaded"
testfailed
return
fi
done
}
runchecktest_remove_policies()
{
for policy in $policies
do
runchecktest "AA_POLICY_CACHE remove-policy ($policy)" pass remove-policy "$policy"
done
}
# IMPORTANT: These tests build on themselves so the first failing test can
# cause many failures
runchecktest "AA_POLICY_CACHE new (no cachedir)" fail new "$cachedir"
create_cachedir
runchecktest "AA_POLICY_CACHE new (no .features)" fail new "$cachedir"
remove_cachedir
runchecktest "AA_POLICY_CACHE new-create (no cachedir)" pass new-create "$cachedir"
runchecktest "AA_POLICY_CACHE new-create (existing cache)" pass new-create "$cachedir"
runchecktest "AA_POLICY_CACHE new (existing cache)" pass new "$cachedir"
runchecktest "AA_POLICY_CACHE is-valid (good .features)" pass is-valid "$cachedir"
install_bad_features_file
runchecktest "AA_POLICY_CACHE is-valid (bad .features)" fail is-valid "$cachedir"
remove_cachedir
runchecktest "AA_POLICY_CACHE is-valid (no cachedir)" fail is-valid "$cachedir"
create_cachedir
install_bad_features_file
runchecktest "AA_POLICY_CACHE create (bad .features)" pass create "$cachedir"
runchecktest "AA_POLICY_CACHE create (good .features)" pass create "$cachedir"
remove_features_file
runchecktest "AA_POLICY_CACHE create (no .features)" fail create "$cachedir"
remove_cachedir
runchecktest "AA_POLICY_CACHE create (no cachedir)" fail create "$cachedir"
# Make sure that no test policies are already loaded
verify_policies_are_not_loaded
runchecktest "AA_POLICY_CACHE replace-all (no cachedir)" fail replace-all "$cachedir"
create_cachedir
runchecktest "AA_POLICY_CACHE replace-all (no .features)" fail replace-all "$cachedir"
create_empty_cache
runchecktest "AA_POLICY_CACHE replace-all (empty cache)" pass replace-all "$cachedir"
create_cache_files
runchecktest "AA_POLICY_CACHE replace-all (full cache)" pass replace-all "$cachedir"
# Test that the previous policy load was successful
runchecktest_policies_are_loaded
runchecktest "AA_POLICY_CACHE remove-policy (DNE)" fail remove-policy "aa_policy_cache_test_DNE"
runchecktest_remove_policies
runchecktest "AA_POLICY_CACHE remove (full cache)" pass remove "$cachedir"
runchecktest "AA_POLICY_CACHE remove (no .features)" pass remove "$cachedir"
install_bad_features_file
runchecktest "AA_POLICY_CACHE remove (empty cache)" pass remove "$cachedir"
remove_cachedir
runchecktest "AA_POLICY_CACHE remove (DNE)" fail remove "$cachedir"