Re: [apparmor] AppArmor APIs
Thanks John, So far I've been successful from the info you have provided. I've compiled a policy into a binary blob and got it loaded into a buffer and successfully loaded this into the kernel. Colin On 15/12/15 00:32, John Johansen wrote: > On 12/14/2015 07:44 AM, Colin Ian King wrote: >> Hi there, >> >> I'm looking at writing some stress tests for AppArmor, so I'd like to >> construct some simple rules and insert/remove them. I looked for some >> API documentation, but all I can find is: >> >> http://wiki.apparmor.net/index.php/AppArmorAPIs >> >> Are there any API docs, guides or worked examples for libaaparse and >> libapparmor? >> > > Hey Colin, > sorry the interfaces aren't better documented. It is one of those perpetual > todo items. There is a quick view of the basic apis bellow and I'll work on > getting you some better docs > > The libapparmor api, is fairly well documented in the man pages (though it > seems the cross refs to find them could stand to be updated) > > man aa_change_hat > aa_change_hatv > aa_change_hat_vargs > > man aa_change_profile > aa_change_onexec > > man aa_getprocattr_raw >aa_getprocattr >aa_gettaskcon >aa_getcon >aa_getpeercon_raw >aa_getpeercon > > man aa_splitcon > > man aa_features > aa_features_new > aa_features_new_from_string > aa_features_new_from_kernel > aa_features_ref > aa_features_unref > aa_features_write_to_file > aa_features_is_equal > aa_features_supports > > man aa_is_enabled > aa_find_mountpoint > > man aa_kernel_interface > aa_kernel_interface_new > aa_kernel_interface_ref > aa_kernel_interface_unref > aa_kernel_interface_load_policy > aa_kernel_interface_load_policy_from_file > aa_kernel_interface_load_policy_from_fd > aa_kernel_interface_replace_policy > aa_kernel_interface_replace_policy_from_file > aa_kernel_interface_replace_policy_from_fd > aa_kernel_interface_remove_policy > aa_kernel_interface_write_policy > > man aa_policy_cache > aa_policy_cache_new > aa_policy_cache_ref > aa_policy_cache_unref > aa_policy_cache_remove > aa_policy_cache_replace_all > > man aa_query_label > aa_query_file_path > aa_query_file_path_len > aa_query_link_path_len > aa_query_link_path > > > > the logparsing doesn't seem to be documented at all :( > The 2 exported functions are > aa_log_record *parse_record(char *str) > void free_record(aa_log_record *record) > > with aa_log_record being defined in include/aalogparse.h > there are a fair number of log parsing tests in > libraries/libapparmor/testsuite/ > > there are a set of private functions that a pseudo exported but being private > apis may change at any time > _aa_is_blacklisted; > _aa_autofree; > _aa_autoclose; > _aa_autofclose; > _aa_dirat_for_each; > > > > the apparmor_parser flags are fairly well documented in > man apparmor_parser > > > > the lowlevel interfaces are not well documented at all > reading of a sockets label is done via > getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, ); > > read of a tasks label is done via > /proc//attr/current > > read of a scheduled change at exec via > /proc//attr/exec > > read of parent while in a hat > /proc//attr/prev > > setting self label (another tasks label can not be directly set) is done by > writing to > /proc//attr/current > > setting of self label at exec (again another tasks is not allow) is done > via writing to > /proc//attr/exec > > the /proc//attr/ fscreate keycreate sockcreate files are currently > not used > > the sock and proc/attr interface are limited to pagesize reads and writes > atm > > > > the apparmor filesystem used for loading and introspecting policy is usually > mounted at >/sys/kernel/security/apparmor. > > Well its not really the apparmor filesystem anymore as it is a sub of the > securityfs > filesystem. Under this there is > ls apparmor/ > .access features .load .null policy profiles .remove .replace > > .access - is a file that allows querying permissions. I'll work on getting > you some docs > on its format > > profiles - flattened, virtualized view of what policy is visible to the > inquiring task. > I'll work on some better docs for you > > features - dir of features supported by the kernel (should be read only) > > policy - dir of policy currently visible (actually currently this is always > from root > policy ns, but ideally it should get virtualized (except doing that > properly > with the way the vfs is setup is impossible, so there will be > something half > assed for 16.04). > > This represents an expanded view of what is available in the > profiles
Re: [apparmor] AppArmor APIs
-BEGIN PGP SIGNED MESSAGE- Hash: SHA256 On 15/12/15 18:45, Steve Beattie wrote: > Hey Colin, > > On Tue, Dec 15, 2015 at 05:29:43PM +, Colin Ian King wrote: >> So far I've been successful from the info you have provided. I've >> compiled a policy into a binary blob and got it loaded into a buffer and >> successfully loaded this into the kernel. > > That's great! > > I'm curious which elements of apparmor you're trying to stress with > what you're adding to stress-ng. The general process outline goes like > this: > > policy -> apparmor_parser -> kernel policy load interface -> policy enforcement > > The first phase, of turning a textual policy into a binary blob, > occurs entirely in user space, and is likely of little interest to you . > > The second phase, where a binary policy blob is loaded into the kernel > and stored in kernel data structures is certainly a valuable place to > look for problems[1], though it is at this point in time considered a > mostly trusted interface (you must have CAP_MAC_ADMIN to make use of > it). However, future plans include this becoming not true, and there > currently exist tools that auto-generate policy based on templates, > so it's still a sensitive interface. It seems that this is the area > you're focusing on? Currently, I'm just piling a load of different stressors onto the kernel interfaces using the aa_kernel* userspace API, I've only just started today, so it is very early "work in progress", c.f: http://kernel.ubuntu.com/git/cking/stress-ng.git/tree/stress-apparmor.c? id=1fdb0ca847db3840ab47daae04384608db0149bf I'm currently hacking some code to force EPROTO failures by twidding the data being passed to the kernel, and I'll be focusing on the raw compiled profile blob for the moment. > > It also seems to me that stressing the enforcement side of things > is valuable, as well as the related interfaces around policy > domain transitions (changing policy or not on exec(), change_hat(), > change_profile()). We also have relatively recently added interfaces > (which I think John referred to earlier) around querying confinement > status and querying permissions directly. Exercising and stressing > these direct interfaces would be great; stressing access mediation > would be indirect via regular syscalls (e.g. open()). OK, that's a good place to focus on. > > There are some known existing performance limitations in some of the > interfaces; for example, change_hat() on a policy with 5 digits of > hats is slow, due to the in-kernel data structures used. > > Thanks again for your work on this, both in general for stress-ng > and for specifically adding apparmor to it! > > [1] For anyone looking for an interesting security relevant project > to take on, extending one of the (syscall) fuzzing tools out > there to exercise the policy loading interface and other apparmor > kernel<->userspace interface layers would be a great thing to do. > -BEGIN PGP SIGNATURE- Version: GnuPG v2 iQIcBAEBCAAGBQJWcGGnAAoJEGjCh9/GqAImZSQP/0zqHXnuHRU/8EMrjESTOfrq 99fSX2xfqjpiNE12FlHuXJiQKmxqToIHOf4/r+meHO9JGD26ssy3+ve+SvLRoAwF fFrsE7mp0MRNNM49NJEH1YOnkba2qdR0PpoMhXeCd4DL2sQCrw9uvmIag0WGdtrL d8zSDBm5sNiBSlngrtlKXhhyQqdHVuAMfPMfCbh1QJLXmaWU6J/RAMlZNcCUyQHo 5n+yg/7V5eP10evFlpGzEgpoZWyEZGWew4y3OqRIKDCa1WE/IHKSKzWNO+nU4fMr jIRP3oNPCJvdub26WSpBGIvzUj8FBCukQsX0RsmNlAOC3EZL0yhqsCSjNXHs7i1t 3X/ofz2bR2n6rkeYMcjCdTo2fsYXMoJ3NrGzAgBMM5sIWOt9SlOjz2NuVAdbrz/z FAllRQKAV7gnsLtYlWpWOwWmf1ae3o1aa8C7/x1RzOmpIj5s5fn/Ighw6VSmf3ub iJlSaCqHBmWAa8OQCGPKkfpSIAn/MpVApt6Au7W7xKQSzrVr3nqlKwMRHICChyPt QrxOqAySYSCyGWEZO0ipcVVorjUp1JSizq+90t0lrrhZZ0NBXLgIMjv2IYRVftsF bp8sxwbXjMMBBb54PYyf4R0/Xcvbzoe4lvNf7WA38O8FIjtWgbJNI1Rjm8Ky4pOp t8pIhN9EhZL2UfWVDqea =reFM -END PGP SIGNATURE- -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
Re: [apparmor] AppArmor APIs
Hey Colin, On Tue, Dec 15, 2015 at 05:29:43PM +, Colin Ian King wrote: > So far I've been successful from the info you have provided. I've > compiled a policy into a binary blob and got it loaded into a buffer and > successfully loaded this into the kernel. That's great! I'm curious which elements of apparmor you're trying to stress with what you're adding to stress-ng. The general process outline goes like this: policy -> apparmor_parser -> kernel policy load interface -> policy enforcement The first phase, of turning a textual policy into a binary blob, occurs entirely in user space, and is likely of little interest to you. The second phase, where a binary policy blob is loaded into the kernel and stored in kernel data structures is certainly a valuable place to look for problems[1], though it is at this point in time considered a mostly trusted interface (you must have CAP_MAC_ADMIN to make use of it). However, future plans include this becoming not true, and there currently exist tools that auto-generate policy based on templates, so it's still a sensitive interface. It seems that this is the area you're focusing on? It also seems to me that stressing the enforcement side of things is valuable, as well as the related interfaces around policy domain transitions (changing policy or not on exec(), change_hat(), change_profile()). We also have relatively recently added interfaces (which I think John referred to earlier) around querying confinement status and querying permissions directly. Exercising and stressing these direct interfaces would be great; stressing access mediation would be indirect via regular syscalls (e.g. open()). There are some known existing performance limitations in some of the interfaces; for example, change_hat() on a policy with 5 digits of hats is slow, due to the in-kernel data structures used. Thanks again for your work on this, both in general for stress-ng and for specifically adding apparmor to it! [1] For anyone looking for an interesting security relevant project to take on, extending one of the (syscall) fuzzing tools out there to exercise the policy loading interface and other apparmor kernel<->userspace interface layers would be a great thing to do. -- Steve Beattiehttp://NxNW.org/~steve/ signature.asc Description: Digital signature -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
[apparmor] [PATCH 2/6] utils: Initial implementation of aa-exec in C
Create a simple aa-exec implementation, written in C, matching the --help, --debug, --verbose, and --profile options present in the current Perl implementation. The build system is updated to honor the USE_SYSTEM make variable which allows aa-exec to be linked against the system libapparmor rather than the libapparmor built in-tree. For now, the C based implementation is built as the aa-exec-c binary until it is feature equivalent with the Perl version. Signed-off-by: Tyler Hicks--- utils/Makefile | 42 ++- utils/aa_exec.c | 165 2 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 utils/aa_exec.c diff --git a/utils/Makefile b/utils/Makefile index 4762262..711626b 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -43,7 +43,46 @@ PYPREFIX=/usr PYFLAKES=pyflakes po/${NAME}.pot: ${TOOLS} ${PYMODULES} - $(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${TOOLS} ${PYMODULES}" + $(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${TOOLS} ${PYMODULES} aa-exec.c" + +ifdef USE_SYSTEM + LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \ + pkg-config --silence-errors --libs libapparmor ; \ + elif ldconfig -p | grep -q libapparmor\.so$$ ; then \ + echo -lapparmor ; \ + fi ) + ifeq ($(strip $(LIBAPPARMOR)),) + ERROR_MESSAGE = $(error ${nl}\ +${nl}\ +Unable to find libapparmor installed on this system; either${nl}\ +install libapparmor devel packages, set the LIBAPPARMOR variable${nl}\ +manually, or build against in-tree libapparmor.${nl}\ +${nl}) + endif # LIBAPPARMOR not set + LDLIBS += $(LIBAPPARMOR) +else # !USE_SYSTEM + # use in-tree versions + LIBAPPARMOR_SRC := ../libraries/libapparmor/ + LIBAPPARMOR_INCLUDE = $(LIBAPPARMOR_SRC)/include + LIBAPPARMOR_PATH := $(LIBAPPARMOR_SRC)/src/.libs/ + ifeq ($(realpath $(LIBAPPARMOR_PATH)/libapparmor.a),) + ERROR_MESSAGE = $(error ${nl}\ +${nl}\ +$(LIBAPPARMOR_PATH)/libapparmor.a is missing; either build against${nl}\ +the in-tree libapparmor by building it first and then trying again${nl}\ +(see the top-level README for help) or build against the system${nl}\ +libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\ +${nl}) + endif + + CFLAGS += -L$(LIBAPPARMOR_PATH) -I$(LIBAPPARMOR_INCLUDE) + LDLIBS += -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread +endif # USE_SYSTEM + +CFLAGS += -g -O0 -Wall -Wstrict-prototypes + +aa-exec-c: aa_exec.c + ${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS} .PHONY: install install: ${MANPAGES} ${HTMLMANPAGES} @@ -71,6 +110,7 @@ clean: pod_clean rm -rf staging/ build/ rm -f apparmor/*.pyc apparmor/rule/*.pyc rm -rf apparmor/__pycache__/ apparmor/rule/__pycache__/ + rm -f aa-exec-c # ${CAPABILITIES} is defined in common/Make.rules .PHONY: check_severity_db diff --git a/utils/aa_exec.c b/utils/aa_exec.c new file mode 100644 index 000..12f54d1 --- /dev/null +++ b/utils/aa_exec.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2015 + * Canonical, Ltd. (All rights reserved) + * + * 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 Novell, Inc. or Canonical + * Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static const char *opt_profile = NULL; +static bool opt_debug = false; +static bool opt_verbose = false; + +static void usage(const char *name, bool error) +{ + FILE *stream = stdout; + int status = EXIT_SUCCESS; + + if (error) { + stream = stderr; + status = EXIT_FAILURE; + } + + fprintf(stream, + "USAGE: %s [OPTIONS] \n" + "\n" + "Confine with the specified PROFILE.\n" + "\n" + "OPTIONS:\n" + " -p PROFILE, --profile=PROFILEPROFILE to confine with\n" + " -d, --debug show messages with debugging information\n" + " -v, --verbose
[apparmor] [PATCH 0/6] Rewrite aa-exec in C
This patch set creates regression tests for aa-exec and rewrites aa-exec in C rather than Perl. The main reason behind the rewrite is that aa-exec is becoming a widely used utility that has its place on even the most minimal of Linux images and Perl is falling out of favor in some of those environments. The rewrite is feature complete with one exception. I did not implement the --file option of aa-exec. I feel like it encourages programs to be run as root since aa-exec must be run as root in order for the specified profile to be loaded and there's no privilege dropping option. Instead of complicating aa-exec with a privilege dropping option, I decided to leave it out of the new aa-exec. I'm open to tacking on another patch to reintroduce --file if anyone feels strongly about it. Tyler -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
[apparmor] [PATCH 1/6] tests: Add regression tests for aa-exec
Add regression tests for the --profile, --namespace, and --immediate options of aa-exec. A new variable is added to uservars.inc to point to the in-tree or system aa-exec depending on the presence of the USE_SYSTEM=1 make variable at build time. Signed-off-by: Tyler Hicks--- tests/regression/apparmor/Makefile| 34 +-- tests/regression/apparmor/aa_exec.sh | 81 +++ tests/regression/apparmor/aa_exec_wrapper.sh | 28 + tests/regression/apparmor/uservars.inc.source | 3 + tests/regression/apparmor/uservars.inc.system | 3 + 5 files changed, 144 insertions(+), 5 deletions(-) create mode 100755 tests/regression/apparmor/aa_exec.sh create mode 100755 tests/regression/apparmor/aa_exec_wrapper.sh diff --git a/tests/regression/apparmor/Makefile b/tests/regression/apparmor/Makefile index c0aad62..d0e4b35 100644 --- a/tests/regression/apparmor/Makefile +++ b/tests/regression/apparmor/Makefile @@ -18,7 +18,7 @@ ifdef USE_SYSTEM echo -lapparmor ; \ fi ) ifeq ($(strip $(LIBAPPARMOR)),) -ERROR_MESSAGE = $(error ${nl}\ +LIBAPPARMOR_ERROR_MESSAGE = $(error ${nl}\ ${nl}\ Unable to find libapparmor installed on this system; either${nl}\ install libapparmor devel packages, set the LIBAPPARMOR variable${nl}\ @@ -27,13 +27,23 @@ manually, or build against in-tree libapparmor.${nl}\ endif # LIBAPPARMOR not set LDLIBS += $(LIBAPPARMOR) + AA_EXEC = $(shell which aa-exec) + ifeq ($(AA_EXEC),) +AA_EXEC_ERROR_MESSAGE = $(error ${nl}\ +${nl}\ +Unable to find aa-exec installed on this system; either install the${nl}\ +apparmor package, set the AA_EXEC variable manually, or use the in-tree${nl}\ +aa-exec.${nl}\ +${nl}) + endif # AA_EXEC not set + else # !USE_SYSTEM # use in-tree versions LIBAPPARMOR_SRC := ../../../libraries/libapparmor/ LIBAPPARMOR_INCLUDE = $(LIBAPPARMOR_SRC)/include LIBAPPARMOR_PATH := $(LIBAPPARMOR_SRC)/src/.libs/ ifeq ($(realpath $(LIBAPPARMOR_PATH)/libapparmor.a),) -ERROR_MESSAGE = $(error ${nl}\ +LIBAPPARMOR_ERROR_MESSAGE = $(error ${nl}\ ${nl}\ $(LIBAPPARMOR_PATH)/libapparmor.a is missing; either build against${nl}\ the in-tree libapparmor by building it first and then trying again${nl}\ @@ -42,6 +52,17 @@ libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\ ${nl}) endif + UTILS_SRC := ../../../utils + AA_EXEC = $(UTILS_SRC)/aa-exec + ifeq ($(realpath $(AA_EXEC)),) +AA_EXEC_ERROR_MESSAGE = $(error ${nl}\ +${nl}\ +$(AA_EXEC) is missing; either build the $(UTILS_SRC) directory${nl}\ +and then try again (see the top-level README for help) or use the${nl}\ +system aa-exec by adding USE_SYSTEM=1 to your make command.${nl}\ +${nl}) + endif + CFLAGS += -L$(LIBAPPARMOR_PATH) -I$(LIBAPPARMOR_INCLUDE) LDLIBS += -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread endif # USE_SYSTEM @@ -152,7 +173,8 @@ endif EXEC=$(SRC:%.c=%) -TESTS=access \ +TESTS=aa_exec \ + access \ introspect \ capabilities \ changeprofile \ @@ -217,9 +239,11 @@ RISKY_TESTS= .PHONY: libapparmor_check .SILENT: libapparmor_check -libapparmor_check: ; $(ERROR_MESSAGE) +libapparmor_check: ; $(LIBAPPARMOR_ERROR_MESSAGE) + +aa_exec_check: ; $(AA_EXEC_ERROR_MESSAGE) -all: libapparmor_check $(EXEC) changehat.h uservars.inc +all: libapparmor_check aa_exec_check $(EXEC) changehat.h uservars.inc uservars.inc: uservars.inc.source uservars.inc.system ifdef USE_SYSTEM diff --git a/tests/regression/apparmor/aa_exec.sh b/tests/regression/apparmor/aa_exec.sh new file mode 100755 index 000..daaefee --- /dev/null +++ b/tests/regression/apparmor/aa_exec.sh @@ -0,0 +1,81 @@ +#! /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_exec +#=DESCRIPTION +# This test verifies that the aa_exec command is indeed transitioning +# profiles as intended. +#=END + +#set -x + +pwd=`dirname $0` +pwd=`cd $pwd ; /bin/pwd` + +bin=$pwd + +. $bin/prologue.inc + +ns=aa_exec_ns + +genprofile_aa_exec() +{ + mode="" + if [ $# -eq 2 ]; then + if [ $2 -ne 0 ]; then + mode="(complain) " + fi + fi +
[apparmor] [PATCH 6/6] utils: Remove --file option from aa-exec(8) man page
The new C based aa-exec does not implement the --file option. Signed-off-by: Tyler Hicks--- utils/aa-exec.pod | 4 1 file changed, 4 deletions(-) diff --git a/utils/aa-exec.pod b/utils/aa-exec.pod index 58dedb2..14f0429 100644 --- a/utils/aa-exec.pod +++ b/utils/aa-exec.pod @@ -57,10 +57,6 @@ use the current profile name (likely unconfined). use profiles in NAMESPACE. This will result in confinement transitioning to using the new profile namespace. -=item -f FILE, --file=FILE - -a file or directory containing profiles to load before confining the program. - =item -i, --immediate transition to PROFILE before doing executing I . This -- 2.5.0 -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
[apparmor] [PATCH 3/6] utils: Add --immediate option to C based aa-exec
Call aa_change_profile(), instead of aa_change_onexec(), when --immediate is passed in. Signed-off-by: Tyler Hicks--- utils/aa_exec.c | 18 -- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/utils/aa_exec.c b/utils/aa_exec.c index 12f54d1..972c20e 100644 --- a/utils/aa_exec.c +++ b/utils/aa_exec.c @@ -27,6 +27,7 @@ static const char *opt_profile = NULL; static bool opt_debug = false; +static bool opt_immediate = false; static bool opt_verbose = false; static void usage(const char *name, bool error) @@ -47,6 +48,7 @@ static void usage(const char *name, bool error) "OPTIONS:\n" " -p PROFILE, --profile=PROFILEPROFILE to confine with\n" " -d, --debug show messages with debugging information\n" + " -i, --immediate change profile immediately instead of at exec\n" " -v, --verboseshow messages with stats\n" " -h, --help display this help\n" "\n", name); @@ -108,10 +110,11 @@ static char **parse_args(int argc, char **argv) {"debug", no_argument, 0, 'd'}, {"help", no_argument, 0, 'h'}, {"profile", required_argument, 0, 'p'}, + {"immediate", no_argument, 0, 'i'}, {"verbose", no_argument, 0, 'v'}, }; - while ((opt = getopt_long(argc, argv, "+dhp:v", long_opts, NULL)) != -1) { + while ((opt = getopt_long(argc, argv, "+dhp:iv", long_opts, NULL)) != -1) { switch (opt) { case 'd': opt_debug = true; @@ -122,6 +125,9 @@ static char **parse_args(int argc, char **argv) case 'p': opt_profile = optarg; break; + case 'i': + opt_immediate = true; + break; case 'v': opt_verbose = true; break; @@ -143,7 +149,14 @@ int main(int argc, char **argv) argv = parse_args(argc, argv); - if (opt_profile) { + if (!opt_profile) + goto exec; + + if (opt_immediate) { + verbose("aa_change_profile(\"%s\")", opt_profile); + rc = aa_change_profile(opt_profile); + debug("%d = aa_change_profile(\"%s\")", rc, opt_profile); + } else { verbose("aa_change_onexec(\"%s\")", opt_profile); rc = aa_change_onexec(opt_profile); debug("%d = aa_change_onexec(\"%s\")", rc, opt_profile); @@ -159,6 +172,7 @@ int main(int argc, char **argv) } } +exec: verbose_print_argv(argv); execvp(argv[0], argv); error("Failed to execute \"%s\": %m", argv[0]); -- 2.5.0 -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
[apparmor] [PATCH 5/6] utils: Replace Perl aa-exec with C aa-exec
Remove the Perl aa-exec implementation and build aa_exec.c as aa-exec. Note that the new C aa-exec does not implement the --file option which was present in the Perl aa-exec. It encouraged running programs as root, since root privileges were required to load the specified profile. All other features of the Perl aa-exec are present in the C aa-exec. Signed-off-by: Tyler Hicks--- utils/Makefile | 11 +++--- utils/aa-exec | 122 - 2 files changed, 6 insertions(+), 127 deletions(-) delete mode 100755 utils/aa-exec diff --git a/utils/Makefile b/utils/Makefile index 711626b..3511d23 100644 --- a/utils/Makefile +++ b/utils/Makefile @@ -20,7 +20,8 @@ COMMONDIR=../common/ include $(COMMONDIR)/Make.rules -PERLTOOLS = aa-exec aa-notify +SRCS = aa-exec.c +PERLTOOLS = aa-notify PYTOOLS = aa-easyprof aa-genprof aa-logprof aa-cleanprof aa-mergeprof \ aa-autodep aa-audit aa-complain aa-enforce aa-disable \ aa-status aa-unconfined @@ -30,7 +31,7 @@ PYMODULES = $(wildcard apparmor/*.py apparmor/rule/*.py) MANPAGES = ${TOOLS:=.8} logprof.conf.5 -all: ${MANPAGES} ${HTMLMANPAGES} +all: ${MANPAGES} ${HTMLMANPAGES} aa-exec $(MAKE) -C po all $(MAKE) -C vim all @@ -43,7 +44,7 @@ PYPREFIX=/usr PYFLAKES=pyflakes po/${NAME}.pot: ${TOOLS} ${PYMODULES} - $(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${TOOLS} ${PYMODULES} aa-exec.c" + $(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${TOOLS} ${PYMODULES} ${SRCS}" ifdef USE_SYSTEM LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \ @@ -81,7 +82,7 @@ endif # USE_SYSTEM CFLAGS += -g -O0 -Wall -Wstrict-prototypes -aa-exec-c: aa_exec.c +aa-exec: aa_exec.c ${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS} .PHONY: install @@ -110,7 +111,7 @@ clean: pod_clean rm -rf staging/ build/ rm -f apparmor/*.pyc apparmor/rule/*.pyc rm -rf apparmor/__pycache__/ apparmor/rule/__pycache__/ - rm -f aa-exec-c + rm -f aa-exec # ${CAPABILITIES} is defined in common/Make.rules .PHONY: check_severity_db diff --git a/utils/aa-exec b/utils/aa-exec deleted file mode 100755 index 23bd3ac..000 --- a/utils/aa-exec +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/perl -# -- -# -#Copyright (C) 2011-2013 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. -# -# -- - -use strict; -use warnings; -use Errno; - -require LibAppArmor; -require POSIX; - -my $opt_d = ''; -my $opt_h = ''; -my $opt_p = ''; -my $opt_n = ''; -my $opt_i = ''; -my $opt_v = ''; -my $opt_f = ''; - -sub _warn { -my $msg = $_[0]; -print STDERR "aa-exec: WARN: $msg\n"; -} -sub _error { -my $msg = $_[0]; -print STDERR "aa-exec: ERROR: $msg\n"; -exit 1 -} - -sub _debug { -$opt_d or return; -my $msg = $_[0]; -print STDERR "aa-exec: DEBUG: $msg\n"; -} - -sub _verbose { -$opt_v or return; -my $msg = $_[0]; -print STDERR "$msg\n"; -} - -sub usage() { -my $s = <<'EOF'; -USAGE: aa-exec [OPTIONS] - -Confine with the specified PROFILE. - -OPTIONS: - -p PROFILE, --profile=PROFILEPROFILE to confine with - -n NAMESPACE, --namespace=NAMESPACE NAMESPACE to confine in - -f FILE, --file FILE profile file to load - -i, --immediate change profile immediately instead of at exec - -v, --verboseshow messages with stats - -h, --help display this help - -EOF -print $s; -} - -use Getopt::Long; - -GetOptions( -'debug|d'=> \$opt_d, -'help|h' => \$opt_h, -'profile|p=s'=> \$opt_p, -'namespace|n=s' => \$opt_n, -'file|f=s' => \$opt_f, -'immediate|i'=> \$opt_i, -'verbose|v' => \$opt_v, -); - -if ($opt_h) { -usage(); -exit(0); -} - -if ($opt_n || $opt_p) { - my $test; - my $prof; - - if ($opt_n) { - $prof = ":$opt_n:"; - } - - $prof .= $opt_p; - - if ($opt_f) { - system("apparmor_parser", "-r", "$opt_f") == 0 - or _error("\'aborting could not load $opt_f\'"); - } - - if ($opt_i) { - _verbose("aa_change_profile(\"$prof\")"); - $test = LibAppArmor::aa_change_profile($prof); - _debug("$test = aa_change_profile(\"$prof\"); $!"); - } else { - _verbose("aa_change_onexec(\"$prof\")"); - $test = LibAppArmor::aa_change_onexec($prof); - _debug("$test = aa_change_onexec(\"$prof\"); $!"); - } - - if ($test != 0) { - if ($!{ENOENT} || $!{EACCESS}) { - my $pre = ($opt_p) ? "profile" : "namespace"; - _error("$pre \'$prof\' does not exist\n"); - } elsif ($!{EINVAL}) { -
Re: [apparmor] [PATCH 0/6] Rewrite aa-exec in C
On 12/15/2015 12:55 PM, Tyler Hicks wrote: > This patch set creates regression tests for aa-exec and rewrites aa-exec in C > rather than Perl. The main reason behind the rewrite is that aa-exec is > becoming a widely used utility that has its place on even the most minimal of > Linux images and Perl is falling out of favor in some of those environments. > > The rewrite is feature complete with one exception. I did not implement the > --file option of aa-exec. I feel like it encourages programs to be run as root > since aa-exec must be run as root in order for the specified profile to be > loaded and there's no privilege dropping option. Instead of complicating > aa-exec with a privilege dropping option, I decided to leave it out of the new > aa-exec. I'm open to tacking on another patch to reintroduce --file if anyone > feels strongly about it. > heck no, that was a convenience thing for hacking on apparmor not something we really want to support -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
Re: [apparmor] [PATCH] utils: Print aa-easyprof error to stderr upon manifest parsing error
On 2015-12-15 17:37:35, Tyler Hicks wrote: > On 2015-12-02 22:00:32, Christian Boltz wrote: > > Hello, > > > > Am Dienstag, 1. Dezember 2015 schrieb Christian Boltz: > > > Am Montag, 30. November 2015 schrieb Tyler Hicks: > > > > A common usage of aa-easyprof is to pipe its stdout to a file > > > > representing an AppArmor profile. Errors must go to stderr. > > > > > > > > https://launchpad.net/bugs/1521400 > > > > > > > > Signed-off-by: Tyler Hicks> > > > --- > > > > > > > > utils/aa-easyprof | 5 - > > > > 1 file changed, 4 insertions(+), 1 deletion(-) > > > > > > > > diff --git a/utils/aa-easyprof b/utils/aa-easyprof > > > > index 93861ae..8e9db71 100755 > > > > --- a/utils/aa-easyprof > > > > +++ b/utils/aa-easyprof > > > > > > > > @@ -53,7 +53,10 @@ if __name__ == "__main__": > > > > error("Could not read '%s': %s (%d)\n" % (opt.manifest, > > > > > > > > os.strerror(e.errno), e.errno)) -profiles = > > > > apparmor.easyprof.parse_manifest(manifest, opt) +try: > > > > +profiles = apparmor.easyprof.parse_manifest(manifest, > > > > opt) > > > > +except AppArmorException as e: > > > > +error(e.value) > > > > > > > > else: # fake up a tuple list when processing command line args > > > > > > > > profiles.append( (binary, opt) ) > > > > > > NAK. > > > > > > aa-easyprof is using apparmor.fail for exception handling, so it > > > doesn't make sense to fix this only for aa-easyprof. We should fix > > > this in apparmor.fail so that everybody benefits ;-) > > I was simply making this call site apparmor.easyprof.* call sites which > catch AppArmorExceptions and print the error to stderr. Bah. I meant, "I was simply making this apparmor.easyprof.* call site match the other apparmor.easyprof.* call sites which catch AppArmorExceptions and print the error to stderr." Tyler signature.asc Description: Digital signature -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
Re: [apparmor] aa-enabled
On Tue, Dec 15, 2015 at 06:41:48PM -0600, Tyler Hicks wrote: > > + if (!quiet) { > > + switch(err) { > > + case ENOSYS: > > + printf(_("No - not available on this system.\n")); > > + break; > > + case ECANCELED: > > + printf(_("No - disabled at boot.\n")); > > + break; > > + case ENOENT: > > + printf(_("Maybe - policy interface not available.\n")); > > + break; > > + case EPERM: > > + case EACCES: > > + printf(_("Maybe - insufficient permissions to determine > > availability.\n")); > > + break; > > + default: > > + printf(_("Error - '%s'\n"), strerror(err)); > > + } > > + } > > + > > + return err; > > Do we really want to return an errno value here? Why not just > EXIT_FAILURE? Sigh, I looked right at this, made suggestions, and missed the point entirely -- we have to exit with different exit codes because the exit code from aa-status(8) is documented with these descriptions. But we can't just return with EPERM, we actually need to map all these to 1--4. Thanks signature.asc Description: Digital signature -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
Re: [apparmor] [PATCH 5/6] utils: Replace Perl aa-exec with C aa-exec
On 12/15/2015 12:56 PM, Tyler Hicks wrote: > Remove the Perl aa-exec implementation and build aa_exec.c as aa-exec. > > Note that the new C aa-exec does not implement the --file option which > was present in the Perl aa-exec. It encouraged running programs as root, > since root privileges were required to load the specified profile. > > All other features of the Perl aa-exec are present in the C aa-exec. > > Signed-off-by: Tyler Hicksso this hits the question (again) of where we want these binary tools packaged. So for aa-enabled I dropped it in ... binutils, and we are also going to have an aa-sha1 tool landing in there as well. I am not opposed to dropping the C based tools in utils but it seemed that people where leaning towards a separate dir and a separate package > --- > utils/Makefile | 11 +++--- > utils/aa-exec | 122 > - > 2 files changed, 6 insertions(+), 127 deletions(-) > delete mode 100755 utils/aa-exec > > diff --git a/utils/Makefile b/utils/Makefile > index 711626b..3511d23 100644 > --- a/utils/Makefile > +++ b/utils/Makefile > @@ -20,7 +20,8 @@ COMMONDIR=../common/ > > include $(COMMONDIR)/Make.rules > > -PERLTOOLS = aa-exec aa-notify > +SRCS = aa-exec.c > +PERLTOOLS = aa-notify > PYTOOLS = aa-easyprof aa-genprof aa-logprof aa-cleanprof aa-mergeprof \ >aa-autodep aa-audit aa-complain aa-enforce aa-disable \ > aa-status aa-unconfined > @@ -30,7 +31,7 @@ PYMODULES = $(wildcard apparmor/*.py apparmor/rule/*.py) > > MANPAGES = ${TOOLS:=.8} logprof.conf.5 > > -all: ${MANPAGES} ${HTMLMANPAGES} > +all: ${MANPAGES} ${HTMLMANPAGES} aa-exec > $(MAKE) -C po all > $(MAKE) -C vim all > > @@ -43,7 +44,7 @@ PYPREFIX=/usr > PYFLAKES=pyflakes > > po/${NAME}.pot: ${TOOLS} ${PYMODULES} > - $(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${TOOLS} ${PYMODULES} > aa-exec.c" > + $(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${TOOLS} ${PYMODULES} > ${SRCS}" > > ifdef USE_SYSTEM >LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \ > @@ -81,7 +82,7 @@ endif # USE_SYSTEM > > CFLAGS += -g -O0 -Wall -Wstrict-prototypes > > -aa-exec-c: aa_exec.c > +aa-exec: aa_exec.c > ${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS} > > .PHONY: install > @@ -110,7 +111,7 @@ clean: pod_clean > rm -rf staging/ build/ > rm -f apparmor/*.pyc apparmor/rule/*.pyc > rm -rf apparmor/__pycache__/ apparmor/rule/__pycache__/ > - rm -f aa-exec-c > + rm -f aa-exec > > # ${CAPABILITIES} is defined in common/Make.rules > .PHONY: check_severity_db > diff --git a/utils/aa-exec b/utils/aa-exec > deleted file mode 100755 > index 23bd3ac..000 > --- a/utils/aa-exec > +++ /dev/null > @@ -1,122 +0,0 @@ > -#!/usr/bin/perl > -# -- > -# > -#Copyright (C) 2011-2013 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. > -# > -# -- > - > -use strict; > -use warnings; > -use Errno; > - > -require LibAppArmor; > -require POSIX; > - > -my $opt_d = ''; > -my $opt_h = ''; > -my $opt_p = ''; > -my $opt_n = ''; > -my $opt_i = ''; > -my $opt_v = ''; > -my $opt_f = ''; > - > -sub _warn { > -my $msg = $_[0]; > -print STDERR "aa-exec: WARN: $msg\n"; > -} > -sub _error { > -my $msg = $_[0]; > -print STDERR "aa-exec: ERROR: $msg\n"; > -exit 1 > -} > - > -sub _debug { > -$opt_d or return; > -my $msg = $_[0]; > -print STDERR "aa-exec: DEBUG: $msg\n"; > -} > - > -sub _verbose { > -$opt_v or return; > -my $msg = $_[0]; > -print STDERR "$msg\n"; > -} > - > -sub usage() { > -my $s = <<'EOF'; > -USAGE: aa-exec [OPTIONS] > - > -Confine with the specified PROFILE. > - > -OPTIONS: > - -p PROFILE, --profile=PROFILE PROFILE to confine with > - -n NAMESPACE, --namespace=NAMESPACENAMESPACE to confine in > - -f FILE, --file FILE profile file to load > - -i, --immediatechange profile immediately instead of at exec > - -v, --verbose show messages with stats > - -h, --help display this help > - > -EOF > -print $s; > -} > - > -use Getopt::Long; > - > -GetOptions( > -'debug|d'=> \$opt_d, > -'help|h' => \$opt_h, > -'profile|p=s'=> \$opt_p, > -'namespace|n=s' => \$opt_n, > -'file|f=s' => \$opt_f, > -'immediate|i'=> \$opt_i, > -'verbose|v' => \$opt_v, > -); > - > -if ($opt_h) { > -usage(); > -exit(0); > -} > - > -if ($opt_n || $opt_p) { > - my $test; > - my $prof; > - > - if ($opt_n) { > - $prof = ":$opt_n:"; > - } > - > - $prof .= $opt_p; > - > - if
Re: [apparmor] [PATCH 6/6] utils: Remove --file option from aa-exec(8) man page
On 12/15/2015 12:56 PM, Tyler Hicks wrote: > The new C based aa-exec does not implement the --file option. > > Signed-off-by: Tyler HicksAcked-by: John Johansen > --- > utils/aa-exec.pod | 4 > 1 file changed, 4 deletions(-) > > diff --git a/utils/aa-exec.pod b/utils/aa-exec.pod > index 58dedb2..14f0429 100644 > --- a/utils/aa-exec.pod > +++ b/utils/aa-exec.pod > @@ -57,10 +57,6 @@ use the current profile name (likely unconfined). > use profiles in NAMESPACE. This will result in confinement transitioning > to using the new profile namespace. > > -=item -f FILE, --file=FILE > - > -a file or directory containing profiles to load before confining the program. > - > =item -i, --immediate > > transition to PROFILE before doing executing I . This > -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
[apparmor] [PATCH] utils: Use apparmor.fail for AppArmorException handling in aa-easyprof
Don't catch AppArmorExceptions in aa-easyprof any longer and rely on apparmor.fail to print the exception to stderr. Signed-off-by: Tyler Hicks--- utils/aa-easyprof | 12 ++-- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/utils/aa-easyprof b/utils/aa-easyprof index 93861ae..de7236c 100755 --- a/utils/aa-easyprof +++ b/utils/aa-easyprof @@ -61,12 +61,7 @@ if __name__ == "__main__": for (binary, options) in profiles: if len(profiles) > 1: count += 1 -try: -easyp = apparmor.easyprof.AppArmorEasyProfile(binary, options) -except AppArmorException as e: -error(e.value) -except Exception: -raise +easyp = apparmor.easyprof.AppArmorEasyProfile(binary, options) if options.list_templates: apparmor.easyprof.print_basefilenames(easyp.get_templates()) @@ -118,7 +113,4 @@ if __name__ == "__main__": sys.stdout.write('%s\n' % easyp.gen_manifest(params)) else: params['no_verify'] = options.no_verify -try: -easyp.output_policy(params, count, opt.output_directory) -except AppArmorException as e: -error(e) +easyp.output_policy(params, count, opt.output_directory) -- 2.5.0 -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
Re: [apparmor] aa-enabled
John asked that I take a look at this patch in order to see if my proposed aa-exec rewrite in C should use the binutils/ dir proposed by this patch. On 2015-11-28 10:38:34, John Johansen wrote: > v3 > > change conflicting/unknown option warning message slightly > output error string on failure > add binutils dir > add manpage > add makefile > add pot file > > --- > > === modified file 'Makefile' > --- Makefile 2015-01-24 00:01:14 + > +++ Makefile 2015-11-28 17:33:33 + > @@ -11,6 +11,7 @@ > DIRS=parser \ > profiles \ > utils \ > + binutils \ > libraries/libapparmor \ > changehat/mod_apparmor \ > changehat/pam_apparmor \ > > === added directory 'binutils' > === added file 'binutils/Makefile' > --- binutils/Makefile 1970-01-01 00:00:00 + > +++ binutils/Makefile 2015-11-28 18:18:25 + > @@ -0,0 +1,200 @@ > +# -- > +#Copyright (c) 2015 > +#Canonical Ltd. (All rights reserved) > +# > +#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. > +# -- > +NAME=aa-binutils > +all: > +COMMONDIR=../common/ > + > +include $(COMMONDIR)/Make.rules > + > +DESTDIR=/ > +CONFDIR=/etc/apparmor > +INSTALL_CONFDIR=${DESTDIR}${CONFDIR} > +LOCALEDIR=/usr/share/locale > +MANPAGES=aa-enabled.8 > + > +WARNINGS = -Wall > +EXTRA_WARNINGS = -Wsign-compare -Wmissing-field-initializers > -Wformat-security -Wunused-parameter > +CPP_WARNINGS = > +ifndef CFLAGS > +CFLAGS = -g -O2 -pipe > + > +ifdef DEBUG > +CFLAGS += -pg -D DEBUG > +endif > +ifdef COVERAGE > +CFLAGS = -g -pg -fprofile-arcs -ftest-coverage > +endif > +endif #CFLAGS > + > +EXTRA_CFLAGS = ${EXTRA_CXXFLAGS} ${CPP_WARNINGS} > + > +#INCLUDEDIR = /usr/src/linux/include > +INCLUDEDIR = > + > +ifdef INCLUDEDIR > + CFLAGS += -I$(INCLUDEDIR) > +endif > + > +# Internationalization support. Define a package and a LOCALEDIR > +EXTRA_CFLAGS+=-DPACKAGE=\"${NAME}\" -DLOCALEDIR=\"${LOCALEDIR}\" > + > +# Compile-time configuration of the location of the config file > +EXTRA_CFLAGS+=-DSUBDOMAIN_CONFDIR=\"${CONFDIR}\" > + > +SRCS = aa-enabled.c It is nitpicky but the style throughout the code base is that source files use underscores as separators and the resulting binaries use hyphens. > +HDRS = > +TOOLS = aa-enabled > + > +AALIB = -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread > + > +ifdef USE_SYSTEM > + # Using the system libapparmor so Makefile dependencies can't be used > + LIBAPPARMOR_A = > + INCLUDE_APPARMOR = > + APPARMOR_H = > +else > + LIBAPPARMOR_SRC = ../libraries/libapparmor/ > + LOCAL_LIBAPPARMOR_INCLUDE = $(LIBAPPARMOR_SRC)/include > + LOCAL_LIBAPPARMOR_LDPATH = $(LIBAPPARMOR_SRC)/src/.libs > + > + LIBAPPARMOR_A = $(LOCAL_LIBAPPARMOR_LDPATH)/libapparmor.a > + INCLUDE_APPARMOR = -I$(LOCAL_LIBAPPARMOR_INCLUDE) > + APPARMOR_H = $(LOCAL_LIBAPPARMOR_INCLUDE)/sys/apparmor.h > +endif > +EXTRA_CFLAGS += $(INCLUDE_APPARMOR) > + > +ifdef V > + VERBOSE = 1 > +endif > +ifndef VERBOSE > + VERBOSE = 0 > +endif > +ifeq ($(VERBOSE),1) > + BUILD_OUTPUT = > + Q = > +else > + BUILD_OUTPUT = > /dev/null 2>&1 > + Q = @ > +endif > +export Q VERBOSE BUILD_OUTPUT > + > +po/%.pot: %.c > + $(MAKE) -C po $(@F) NAME=$* SOURCES=$*.c > + > +# targets arranged this way so that people who don't want full docs can > +# pick specific targets they want. > +arch:$(TOOLS) > + > +manpages:$(MANPAGES) > + > +docs:manpages > + > +indep: docs > + $(Q)$(MAKE) -C po all > + > +all: arch indep > + > +.PHONY: coverage > +coverage: > + $(MAKE) clean aa-enabled COVERAGE=1 > + > +ifndef USE_SYSTEM > +$(LIBAPPARMOR_A): > + @if [ ! -f $@ ]; then \ > + echo "error: $@ is missing. Pick one of these possible > solutions:" 1>&2; \ > + echo " 1) Build against the in-tree libapparmor by building it > first and then trying again. See the top-level README for help." 1>&2; \ > + echo " 2) Build against the system libapparmor by adding > USE_SYSTEM=1 to your make command." 1>&2;\ > + return 1; \ > + fi > +endif > + > +aa-enabled: aa-enabled.c $(LIBAPPARMOR_A) > + $(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB) > + > +.SILENT: check > +.PHONY: check > +check: check_pod_files tests > + > +.SILENT: tests > +tests: aa-enabled $(TESTS) > + echo "no tests atm" > + > +.PHONY: install-rhel4 > +install-rhel4: install-redhat > + > +.PHONY: install-redhat > +install-redhat: > + > +.PHONY: install-suse >