mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-30 13:58:22 +00:00
Merge from apparmor trunk; fixed up conflict due to imported indonesian
.po file.
This commit is contained in:
15
.bzrignore
15
.bzrignore
@@ -46,7 +46,10 @@ libraries/libapparmor/ylwrap
|
|||||||
libraries/libapparmor/doc/Makefile
|
libraries/libapparmor/doc/Makefile
|
||||||
libraries/libapparmor/doc/Makefile.in
|
libraries/libapparmor/doc/Makefile.in
|
||||||
libraries/libapparmor/doc/*.2
|
libraries/libapparmor/doc/*.2
|
||||||
|
libraries/libapparmor/doc/aa_*.3
|
||||||
|
libraries/libapparmor/include/Makefile
|
||||||
libraries/libapparmor/include/Makefile.in
|
libraries/libapparmor/include/Makefile.in
|
||||||
|
libraries/libapparmor/include/sys/Makefile
|
||||||
libraries/libapparmor/include/sys/Makefile.in
|
libraries/libapparmor/include/sys/Makefile.in
|
||||||
libraries/libapparmor/src/.deps
|
libraries/libapparmor/src/.deps
|
||||||
libraries/libapparmor/src/.libs
|
libraries/libapparmor/src/.libs
|
||||||
@@ -54,10 +57,16 @@ libraries/libapparmor/src/Makefile
|
|||||||
libraries/libapparmor/src/Makefile.in
|
libraries/libapparmor/src/Makefile.in
|
||||||
libraries/libapparmor/src/af_protos.h
|
libraries/libapparmor/src/af_protos.h
|
||||||
libraries/libapparmor/src/change_hat.lo
|
libraries/libapparmor/src/change_hat.lo
|
||||||
|
libraries/libapparmor/src/features.lo
|
||||||
libraries/libapparmor/src/grammar.lo
|
libraries/libapparmor/src/grammar.lo
|
||||||
|
libraries/libapparmor/src/kernel.lo
|
||||||
|
libraries/libapparmor/src/kernel_interface.lo
|
||||||
libraries/libapparmor/src/libaalogparse.lo
|
libraries/libapparmor/src/libaalogparse.lo
|
||||||
libraries/libapparmor/src/libimmunix_warning.lo
|
libraries/libapparmor/src/libimmunix_warning.lo
|
||||||
|
libraries/libapparmor/src/policy_cache.lo
|
||||||
|
libraries/libapparmor/src/private.lo
|
||||||
libraries/libapparmor/src/scanner.lo
|
libraries/libapparmor/src/scanner.lo
|
||||||
|
libraries/libapparmor/src/libapparmor.pc
|
||||||
libraries/libapparmor/src/libapparmor.la
|
libraries/libapparmor/src/libapparmor.la
|
||||||
libraries/libapparmor/src/libimmunix.la
|
libraries/libapparmor/src/libimmunix.la
|
||||||
libraries/libapparmor/src/grammar.c
|
libraries/libapparmor/src/grammar.c
|
||||||
@@ -74,12 +83,18 @@ libraries/libapparmor/swig/perl/Makefile.PL
|
|||||||
libraries/libapparmor/swig/perl/Makefile.in
|
libraries/libapparmor/swig/perl/Makefile.in
|
||||||
libraries/libapparmor/swig/perl/Makefile.perl
|
libraries/libapparmor/swig/perl/Makefile.perl
|
||||||
libraries/libapparmor/swig/perl/Makefile.perle
|
libraries/libapparmor/swig/perl/Makefile.perle
|
||||||
|
libraries/libapparmor/swig/perl/MYMETA.json
|
||||||
|
libraries/libapparmor/swig/perl/MYMETA.yml
|
||||||
libraries/libapparmor/swig/perl/blib
|
libraries/libapparmor/swig/perl/blib
|
||||||
libraries/libapparmor/swig/perl/libapparmor_wrap.c
|
libraries/libapparmor/swig/perl/libapparmor_wrap.c
|
||||||
libraries/libapparmor/swig/perl/pm_to_blib
|
libraries/libapparmor/swig/perl/pm_to_blib
|
||||||
|
libraries/libapparmor/swig/python/__init__.py
|
||||||
|
libraries/libapparmor/swig/python/build/
|
||||||
|
libraries/libapparmor/swig/python/libapparmor_wrap.c
|
||||||
libraries/libapparmor/swig/python/Makefile
|
libraries/libapparmor/swig/python/Makefile
|
||||||
libraries/libapparmor/swig/python/Makefile.in
|
libraries/libapparmor/swig/python/Makefile.in
|
||||||
libraries/libapparmor/swig/python/setup.py
|
libraries/libapparmor/swig/python/setup.py
|
||||||
|
libraries/libapparmor/swig/python/test/Makefile
|
||||||
libraries/libapparmor/swig/python/test/Makefile.in
|
libraries/libapparmor/swig/python/test/Makefile.in
|
||||||
libraries/libapparmor/swig/ruby/Makefile
|
libraries/libapparmor/swig/ruby/Makefile
|
||||||
libraries/libapparmor/swig/ruby/Makefile.in
|
libraries/libapparmor/swig/ruby/Makefile.in
|
||||||
|
1
Makefile
1
Makefile
@@ -11,6 +11,7 @@ include ${COMMONDIR}/Make.rules
|
|||||||
DIRS=parser \
|
DIRS=parser \
|
||||||
profiles \
|
profiles \
|
||||||
utils \
|
utils \
|
||||||
|
binutils \
|
||||||
libraries/libapparmor \
|
libraries/libapparmor \
|
||||||
changehat/mod_apparmor \
|
changehat/mod_apparmor \
|
||||||
changehat/pam_apparmor \
|
changehat/pam_apparmor \
|
||||||
|
10
README
10
README
@@ -27,6 +27,7 @@ Source Layout
|
|||||||
|
|
||||||
AppArmor consists of several different parts:
|
AppArmor consists of several different parts:
|
||||||
|
|
||||||
|
binutils/ source for basic utilities written in compiled languages
|
||||||
changehat/ source for using changehat with Apache, PAM and Tomcat
|
changehat/ source for using changehat with Apache, PAM and Tomcat
|
||||||
common/ common makefile rules
|
common/ common makefile rules
|
||||||
desktop/ empty
|
desktop/ empty
|
||||||
@@ -71,6 +72,13 @@ $ make install
|
|||||||
generate Ruby bindings to libapparmor.]
|
generate Ruby bindings to libapparmor.]
|
||||||
|
|
||||||
|
|
||||||
|
Binary Utilities:
|
||||||
|
$ cd binutils
|
||||||
|
$ make
|
||||||
|
$ make check
|
||||||
|
$ make install
|
||||||
|
|
||||||
|
|
||||||
Utilities:
|
Utilities:
|
||||||
$ cd utils
|
$ cd utils
|
||||||
$ make
|
$ make
|
||||||
@@ -104,7 +112,7 @@ $ make check # depends on the parser having been built first
|
|||||||
$ make install
|
$ make install
|
||||||
|
|
||||||
|
|
||||||
[Note that for the parser and the utils, if you only with to build/use
|
[Note that for the parser, binutils, and utils, if you only wish to build/use
|
||||||
some of the locale languages, you can override the default by passing
|
some of the locale languages, you can override the default by passing
|
||||||
the LANGS arguments to make; e.g. make all install "LANGS=en_US fr".]
|
the LANGS arguments to make; e.g. make all install "LANGS=en_US fr".]
|
||||||
|
|
||||||
|
157
binutils/Makefile
Normal file
157
binutils/Makefile
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# 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=/
|
||||||
|
BINDIR=${DESTDIR}/usr/bin
|
||||||
|
LOCALEDIR=/usr/share/locale
|
||||||
|
MANPAGES=aa-enabled.8 aa-exec.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}\"
|
||||||
|
|
||||||
|
SRCS = aa_enabled.c
|
||||||
|
HDRS =
|
||||||
|
TOOLS = aa-enabled aa-exec
|
||||||
|
|
||||||
|
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 =
|
||||||
|
LIBAPPARMOR_LDFLAGS =
|
||||||
|
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
|
||||||
|
LIBAPPARMOR_LDFLAGS = -L$(LOCAL_LIBAPPARMOR_LDPATH)
|
||||||
|
endif
|
||||||
|
EXTRA_CFLAGS += $(INCLUDE_APPARMOR)
|
||||||
|
LDFLAGS += $(LIBAPPARMOR_LDFLAGS)
|
||||||
|
|
||||||
|
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 $(TOOLS) 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)
|
||||||
|
|
||||||
|
aa-exec: aa_exec.c $(LIBAPPARMOR_A)
|
||||||
|
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
||||||
|
|
||||||
|
.SILENT: check
|
||||||
|
.PHONY: check
|
||||||
|
check: check_pod_files tests
|
||||||
|
|
||||||
|
.SILENT: tests
|
||||||
|
tests: $(TOOLS) $(TESTS)
|
||||||
|
echo "no tests atm"
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
install: install-indep install-arch
|
||||||
|
|
||||||
|
.PHONY: install-arch
|
||||||
|
install-arch: arch
|
||||||
|
install -m 755 -d ${BINDIR}
|
||||||
|
install -m 755 ${TOOLS} ${BINDIR}
|
||||||
|
|
||||||
|
.PHONY: install-indep
|
||||||
|
install-indep:
|
||||||
|
$(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
|
||||||
|
$(MAKE) install_manpages DESTDIR=${DESTDIR}
|
||||||
|
|
||||||
|
ifndef VERBOSE
|
||||||
|
.SILENT: clean
|
||||||
|
endif
|
||||||
|
.PHONY: clean
|
||||||
|
clean: pod_clean
|
||||||
|
rm -f core core.* *.o *.s *.a *~ *.gcda *.gcno
|
||||||
|
rm -f gmon.out
|
||||||
|
rm -f $(TOOLS) $(TESTS)
|
||||||
|
$(MAKE) -s -C po clean
|
||||||
|
|
94
binutils/aa-enabled.pod
Normal file
94
binutils/aa-enabled.pod
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
# This publication is intellectual property of Canonical Ltd. Its contents
|
||||||
|
# can be duplicated, either in part or in whole, provided that a copyright
|
||||||
|
# label is visibly located on each copy.
|
||||||
|
#
|
||||||
|
# All information found in this book has been compiled with utmost
|
||||||
|
# attention to detail. However, this does not guarantee complete accuracy.
|
||||||
|
# Neither Canonical Ltd, the authors, nor the translators shall be held
|
||||||
|
# liable for possible errors or the consequences thereof.
|
||||||
|
#
|
||||||
|
# Many of the software and hardware descriptions cited in this book
|
||||||
|
# are registered trademarks. All trade names are subject to copyright
|
||||||
|
# restrictions and may be registered trade marks. Canonical Ltd
|
||||||
|
# essentially adheres to the manufacturer's spelling.
|
||||||
|
#
|
||||||
|
# Names of products and trademarks appearing in this book (with or without
|
||||||
|
# specific notation) are likewise subject to trademark and trade protection
|
||||||
|
# laws and may thus fall under copyright restrictions.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
=pod
|
||||||
|
|
||||||
|
=head1 NAME
|
||||||
|
|
||||||
|
aa-enabled - test whether AppArmor is enabled
|
||||||
|
|
||||||
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
|
B<aa-enabled> [options]
|
||||||
|
|
||||||
|
=head1 DESCRIPTION
|
||||||
|
|
||||||
|
B<aa-enabled> is used to determine if AppArmor is enabled.
|
||||||
|
|
||||||
|
=head1 OPTIONS
|
||||||
|
|
||||||
|
B<aa-enabled> accepts the following arguments:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item -h, --help
|
||||||
|
|
||||||
|
Display a brief usage guide.
|
||||||
|
|
||||||
|
=item -q, --quiet
|
||||||
|
|
||||||
|
Do not output anything to stdout. This option is intended to be used by
|
||||||
|
scripts that simply want to use the exit code to determine if AppArmor is
|
||||||
|
enabled.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 EXIT STATUS
|
||||||
|
|
||||||
|
Upon exiting, B<aa-enabled> will set its exit status to the following values:
|
||||||
|
|
||||||
|
=over 4
|
||||||
|
|
||||||
|
=item 0:
|
||||||
|
|
||||||
|
if AppArmor is enabled.
|
||||||
|
|
||||||
|
=item 1:
|
||||||
|
|
||||||
|
if AppArmor is not enabled/loaded.
|
||||||
|
|
||||||
|
=item 2:
|
||||||
|
|
||||||
|
intentionally not used as an B<aa-enabled> exit status.
|
||||||
|
|
||||||
|
=item 3:
|
||||||
|
|
||||||
|
if the AppArmor control files aren't available under /sys/kernel/security/.
|
||||||
|
|
||||||
|
=item 4:
|
||||||
|
|
||||||
|
if B<aa-enabled> doesn't have enough privileges to read the apparmor control files.
|
||||||
|
|
||||||
|
=item 64:
|
||||||
|
|
||||||
|
if any unexpected error or condition is encountered.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
=head1 BUGS
|
||||||
|
|
||||||
|
If you find any bugs, please report them at
|
||||||
|
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||||
|
|
||||||
|
=head1 SEE ALSO
|
||||||
|
|
||||||
|
apparmor(7), apparmor.d(5), aa_is_enabled(2), and L<http://wiki.apparmor.net>.
|
||||||
|
|
||||||
|
=cut
|
@@ -57,10 +57,6 @@ use the current profile name (likely unconfined).
|
|||||||
use profiles in NAMESPACE. This will result in confinement transitioning
|
use profiles in NAMESPACE. This will result in confinement transitioning
|
||||||
to using the new profile namespace.
|
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
|
=item -i, --immediate
|
||||||
|
|
||||||
transition to PROFILE before doing executing I<E<lt>commandE<gt>>. This
|
transition to PROFILE before doing executing I<E<lt>commandE<gt>>. This
|
92
binutils/aa_enabled.c
Normal file
92
binutils/aa_enabled.c
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <locale.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#define _(s) gettext(s)
|
||||||
|
|
||||||
|
#include <sys/apparmor.h>
|
||||||
|
|
||||||
|
void print_help(const char *command)
|
||||||
|
{
|
||||||
|
printf(_("%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"),
|
||||||
|
command);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Exit statuses and meanings are documented in the aa-enabled.pod file */
|
||||||
|
static void exit_with_error(int saved_errno, int quiet)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
switch(saved_errno) {
|
||||||
|
case ENOSYS:
|
||||||
|
if (!quiet)
|
||||||
|
printf(_("No - not available on this system.\n"));
|
||||||
|
exit(1);
|
||||||
|
case ECANCELED:
|
||||||
|
if (!quiet)
|
||||||
|
printf(_("No - disabled at boot.\n"));
|
||||||
|
exit(1);
|
||||||
|
case ENOENT:
|
||||||
|
if (!quiet)
|
||||||
|
printf(_("Maybe - policy interface not available.\n"));
|
||||||
|
exit(3);
|
||||||
|
case EPERM:
|
||||||
|
case EACCES:
|
||||||
|
if (!quiet)
|
||||||
|
printf(_("Maybe - insufficient permissions to determine availability.\n"));
|
||||||
|
exit(4);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!quiet)
|
||||||
|
printf(_("Error - %s\n"), strerror(saved_errno));
|
||||||
|
exit(64);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int enabled;
|
||||||
|
int quiet = 0;
|
||||||
|
|
||||||
|
setlocale(LC_MESSAGES, "");
|
||||||
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||||
|
textdomain(PACKAGE);
|
||||||
|
|
||||||
|
if (argc > 2) {
|
||||||
|
printf(_("unknown or incompatible options\n"));
|
||||||
|
print_help(argv[0]);
|
||||||
|
} else if (argc == 2) {
|
||||||
|
if (strcmp(argv[1], "--quiet") == 0 ||
|
||||||
|
strcmp(argv[1], "-q") == 0) {
|
||||||
|
quiet = 1;
|
||||||
|
} else if (strcmp(argv[1], "--help") == 0 ||
|
||||||
|
strcmp(argv[1], "-h") == 0) {
|
||||||
|
print_help(argv[0]);
|
||||||
|
} else {
|
||||||
|
printf(_("unknown option '%s'\n"), argv[1]);
|
||||||
|
print_help(argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled = aa_is_enabled();
|
||||||
|
if (!enabled)
|
||||||
|
exit_with_error(errno, quiet);
|
||||||
|
|
||||||
|
if (!quiet)
|
||||||
|
printf(_("Yes\n"));
|
||||||
|
exit(0);
|
||||||
|
}
|
218
binutils/aa_exec.c
Normal file
218
binutils/aa_exec.c
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
/*
|
||||||
|
* 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 <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <libintl.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/apparmor.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#define _(s) gettext(s)
|
||||||
|
|
||||||
|
static const char *opt_profile = NULL;
|
||||||
|
static const char *opt_namespace = NULL;
|
||||||
|
static bool opt_debug = false;
|
||||||
|
static bool opt_immediate = 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] <prog> <args>\n"
|
||||||
|
"\n"
|
||||||
|
"Confine <prog> with the specified PROFILE.\n"
|
||||||
|
"\n"
|
||||||
|
"OPTIONS:\n"
|
||||||
|
" -p PROFILE, --profile=PROFILE PROFILE to confine <prog> with\n"
|
||||||
|
" -n NAMESPACE, --namespace=NAMESPACE NAMESPACE to confine <prog> in\n"
|
||||||
|
" -d, --debug show messages with debugging information\n"
|
||||||
|
" -i, --immediate change profile immediately instead of at exec\n"
|
||||||
|
" -v, --verbose show messages with stats\n"
|
||||||
|
" -h, --help display this help\n"
|
||||||
|
"\n"), name);
|
||||||
|
exit(status);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define error(fmt, args...) _error(_("aa-exec: ERROR: " fmt "\n"), ## args)
|
||||||
|
static void _error(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
vfprintf(stderr, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define debug(fmt, args...) _debug(_("aa-exec: DEBUG: " fmt "\n"), ## args)
|
||||||
|
static void _debug(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (!opt_debug)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
vfprintf(stderr, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define verbose(fmt, args...) _verbose(_(fmt "\n"), ## args)
|
||||||
|
static void _verbose(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
if (!opt_verbose)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
vfprintf(stderr, fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void verbose_print_argv(char **argv)
|
||||||
|
{
|
||||||
|
if (!opt_verbose)
|
||||||
|
return;
|
||||||
|
|
||||||
|
fprintf(stderr, _("exec"));
|
||||||
|
for (; *argv; argv++)
|
||||||
|
fprintf(stderr, " %s", *argv);
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static char **parse_args(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int opt;
|
||||||
|
struct option long_opts[] = {
|
||||||
|
{"debug", no_argument, 0, 'd'},
|
||||||
|
{"help", no_argument, 0, 'h'},
|
||||||
|
{"profile", required_argument, 0, 'p'},
|
||||||
|
{"namespace", required_argument, 0, 'n'},
|
||||||
|
{"immediate", no_argument, 0, 'i'},
|
||||||
|
{"verbose", no_argument, 0, 'v'},
|
||||||
|
};
|
||||||
|
|
||||||
|
while ((opt = getopt_long(argc, argv, "+dhp:n:iv", long_opts, NULL)) != -1) {
|
||||||
|
switch (opt) {
|
||||||
|
case 'd':
|
||||||
|
opt_debug = true;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
usage(argv[0], false);
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
opt_profile = optarg;
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
opt_namespace = optarg;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
opt_immediate = true;
|
||||||
|
break;
|
||||||
|
case 'v':
|
||||||
|
opt_verbose = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0], true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc)
|
||||||
|
usage(argv[0], true);
|
||||||
|
|
||||||
|
return argv + optind;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void build_name(char *name, size_t name_len,
|
||||||
|
const char *namespace, const char *profile)
|
||||||
|
{
|
||||||
|
size_t required_len = 1; /* reserve 1 byte for NUL-terminator */
|
||||||
|
|
||||||
|
if (namespace)
|
||||||
|
required_len += 1 + strlen(namespace) + 3; /* :<NAMESPACE>:// */
|
||||||
|
|
||||||
|
if (profile)
|
||||||
|
required_len += strlen(profile);
|
||||||
|
|
||||||
|
if (required_len > name_len)
|
||||||
|
error("name too long (%zu > %zu)", required_len, name_len);
|
||||||
|
|
||||||
|
name[0] = '\0';
|
||||||
|
|
||||||
|
if (namespace) {
|
||||||
|
strcat(name, ":");
|
||||||
|
strcat(name, namespace);
|
||||||
|
strcat(name, "://");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profile)
|
||||||
|
strcat(name, profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char name[PATH_MAX];
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
argv = parse_args(argc, argv);
|
||||||
|
|
||||||
|
if (opt_namespace || opt_profile)
|
||||||
|
build_name(name, sizeof(name), opt_namespace, opt_profile);
|
||||||
|
else
|
||||||
|
goto exec;
|
||||||
|
|
||||||
|
if (opt_immediate) {
|
||||||
|
verbose("aa_change_profile(\"%s\")", name);
|
||||||
|
rc = aa_change_profile(name);
|
||||||
|
debug("%d = aa_change_profile(\"%s\")", rc, name);
|
||||||
|
} else {
|
||||||
|
verbose("aa_change_onexec(\"%s\")", name);
|
||||||
|
rc = aa_change_onexec(name);
|
||||||
|
debug("%d = aa_change_onexec(\"%s\")", rc, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc) {
|
||||||
|
if (errno == ENOENT || errno == EACCES) {
|
||||||
|
error("%s '%s' does not exist\n",
|
||||||
|
opt_profile ? "profile" : "namespace", name);
|
||||||
|
} else if (errno == EINVAL) {
|
||||||
|
error("AppArmor interface not available");
|
||||||
|
} else {
|
||||||
|
error("%m");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exec:
|
||||||
|
verbose_print_argv(argv);
|
||||||
|
execvp(argv[0], argv);
|
||||||
|
error("Failed to execute \"%s\": %m", argv[0]);
|
||||||
|
}
|
19
binutils/po/Makefile
Normal file
19
binutils/po/Makefile
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# ----------------------------------------------------------------------
|
||||||
|
# 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.
|
||||||
|
# ----------------------------------------------------------------------
|
||||||
|
all:
|
||||||
|
|
||||||
|
# As translations get added, they will automatically be included, unless
|
||||||
|
# the lang is explicitly added to DISABLED_LANGS; e.g. DISABLED_LANGS=en es
|
||||||
|
|
||||||
|
DISABLED_LANGS=
|
||||||
|
|
||||||
|
COMMONDIR=../../common
|
||||||
|
include $(COMMONDIR)/Make-po.rules
|
||||||
|
|
||||||
|
XGETTEXT_ARGS+=--language=C --keyword=_ $(shell if [ -f ${NAME}.pot ] ; then echo -n -j ; fi)
|
||||||
|
|
66
binutils/po/aa-enabled.pot
Normal file
66
binutils/po/aa-enabled.pot
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
# Copyright (C) 2015 Canonical Ltd
|
||||||
|
# This file is distributed under the same license as the AppArmor package.
|
||||||
|
# John Johansen <john.johansen@canonical.com>, 2015.
|
||||||
|
#
|
||||||
|
#, fuzzy
|
||||||
|
msgid ""
|
||||||
|
msgstr ""
|
||||||
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
|
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
|
||||||
|
"POT-Creation-Date: 2015-11-28 10:23-0800\n"
|
||||||
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
|
"Language: \n"
|
||||||
|
"MIME-Version: 1.0\n"
|
||||||
|
"Content-Type: text/plain; charset=CHARSET\n"
|
||||||
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:26
|
||||||
|
#, c-format
|
||||||
|
msgid ""
|
||||||
|
"%s: [options]\n"
|
||||||
|
" options:\n"
|
||||||
|
" -q | --quiet Don't print out any messages\n"
|
||||||
|
" -h | --help Print help\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:45
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown or incompatible options\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:55
|
||||||
|
#, c-format
|
||||||
|
msgid "unknown option '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:64
|
||||||
|
#, c-format
|
||||||
|
msgid "Yes\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:71
|
||||||
|
#, c-format
|
||||||
|
msgid "No - not available on this system.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:74
|
||||||
|
#, c-format
|
||||||
|
msgid "No - disabled at boot.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:77
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - policy interface not available.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:81
|
||||||
|
#, c-format
|
||||||
|
msgid "Maybe - insufficient permissions to determine availability.\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: ../aa_enabled.c:84
|
||||||
|
#, c-format
|
||||||
|
msgid "Error - '%s'\n"
|
||||||
|
msgstr ""
|
@@ -16,6 +16,7 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2016-01-21 05:11+0000\n"
|
"X-Launchpad-Export-Date: 2016-01-21 05:11+0000\n"
|
||||||
"X-Generator: Launchpad (build 17886)\n"
|
"X-Generator: Launchpad (build 17886)\n"
|
||||||
|
"Language: id\n"
|
||||||
|
|
||||||
#: ../aa_enabled.c:26
|
#: ../aa_enabled.c:26
|
||||||
#, c-format
|
#, c-format
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Copyright (c) 1999-2008 NOVELL (All rights reserved)
|
# Copyright (c) 1999-2008 NOVELL (All rights reserved)
|
||||||
# Copyright 2009-2010 Canonical Ltd.
|
# Copyright 2009-2015 Canonical Ltd.
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of version 2 of the GNU General Public
|
# modify it under the terms of version 2 of the GNU General Public
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
# exist
|
# exist
|
||||||
LOCALEDIR=/usr/share/locale
|
LOCALEDIR=/usr/share/locale
|
||||||
|
|
||||||
XGETTEXT_ARGS=--copyright-holder="NOVELL, Inc." --msgid-bugs-address=apparmor@lists.ubuntu.com -d ${NAME}
|
XGETTEXT_ARGS=--copyright-holder="Canonical Ltd" --msgid-bugs-address=apparmor@lists.ubuntu.com -d ${NAME}
|
||||||
|
|
||||||
# When making the .pot file, it's expected that the parent Makefile will
|
# When making the .pot file, it's expected that the parent Makefile will
|
||||||
# pass in the list of sources in the SOURCES variable
|
# pass in the list of sources in the SOURCES variable
|
||||||
|
@@ -82,7 +82,7 @@ pod_clean:
|
|||||||
# =====================
|
# =====================
|
||||||
|
|
||||||
# emits defined capabilities in a simple list, e.g. "CAP_NAME CAP_NAME2"
|
# emits defined capabilities in a simple list, e.g. "CAP_NAME CAP_NAME2"
|
||||||
CAPABILITIES=$(shell echo "\#include <linux/capability.h>" | cpp -dM | LC_ALL=C sed -n -e '/CAP_EMPTY_SET/d' -e 's/^\#define[ \t]\+CAP_\([A-Z0-9_]\+\)[ \t]\+\([0-9xa-f]\+\)\(.*\)$$/CAP_\1/p' | sort)
|
CAPABILITIES=$(shell echo "\#include <linux/capability.h>" | cpp -dM | LC_ALL=C sed -n -e '/CAP_EMPTY_SET/d' -e 's/^\#define[ \t]\+CAP_\([A-Z0-9_]\+\)[ \t]\+\([0-9xa-f]\+\)\(.*\)$$/CAP_\1/p' | LC_ALL=C sort)
|
||||||
|
|
||||||
.PHONY: list_capabilities
|
.PHONY: list_capabilities
|
||||||
list_capabilities: /usr/include/linux/capability.h
|
list_capabilities: /usr/include/linux/capability.h
|
||||||
|
@@ -1 +1 @@
|
|||||||
2.9.90
|
2.10.90
|
||||||
|
Binary file not shown.
@@ -24,27 +24,23 @@
|
|||||||
|
|
||||||
aa_query_label - query access permission associated with a label
|
aa_query_label - query access permission associated with a label
|
||||||
|
|
||||||
|
aa_query_file_path, aa_query_file_path_len - query access permissions of a file path
|
||||||
|
|
||||||
|
aa_query_link_path, aa_query_link_path_len - query access permissions of a link path
|
||||||
|
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||||
|
|
||||||
B<int aa_query_label((uint32_t mask, char *query, size_t size,
|
B<int aa_query_label(uint32_t mask, char *query, size_t size, int *allowed, int *audited);>
|
||||||
int *allowed, int *audited);>
|
|
||||||
|
|
||||||
B<int aa_query_file_path((uint32_t mask, const char *label, size_t label_len,
|
B<int aa_query_file_path(uint32_t mask, const char *label, size_t label_len, const char *path, int *allowed, int *audited);>
|
||||||
const char *path, int *allowed, int *audited);>
|
|
||||||
|
|
||||||
B<int aa_query_file_path_len((uint32_t mask, const char *label,
|
B<int aa_query_file_path_len(uint32_t mask, const char *label, size_t label_len, const char *path, size_t path_len, int *allowed, int *audited);>
|
||||||
size_t label_len, const char *path, size_t path_len,
|
|
||||||
int *allowed, int *audited);>
|
|
||||||
|
|
||||||
B<int aa_query_link_path_len(const char *label, size_t label_len,
|
B<int aa_query_link_path(const char *label, const char *target, const char *link, int *allowed, int *audited);>
|
||||||
const char *target, size_t target_len,
|
|
||||||
const char *link, size_t link_len,
|
|
||||||
int *allowed, int *audited);>
|
|
||||||
|
|
||||||
B<int aa_query_link_path(const char *label, const char *target,
|
B<int aa_query_link_path_len(const char *label, size_t label_len, const char *target, size_t target_len, const char *link, size_t link_len, int *allowed, int *audited);>
|
||||||
const char *link, int *allowed, int *audited);>
|
|
||||||
|
|
||||||
|
|
||||||
Link with B<-lapparmor> when compiling.
|
Link with B<-lapparmor> when compiling.
|
||||||
|
@@ -26,9 +26,9 @@ INCLUDES = $(all_includes)
|
|||||||
# For more information, see:
|
# For more information, see:
|
||||||
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
|
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
|
||||||
#
|
#
|
||||||
AA_LIB_CURRENT = 3
|
AA_LIB_CURRENT = 4
|
||||||
AA_LIB_REVISION = 1
|
AA_LIB_REVISION = 0
|
||||||
AA_LIB_AGE = 2
|
AA_LIB_AGE = 3
|
||||||
|
|
||||||
SUFFIXES = .pc.in .pc
|
SUFFIXES = .pc.in .pc
|
||||||
|
|
||||||
|
@@ -166,6 +166,11 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
|||||||
%token TOK_SYSLOG_KERNEL
|
%token TOK_SYSLOG_KERNEL
|
||||||
%token TOK_SYSLOG_USER
|
%token TOK_SYSLOG_USER
|
||||||
|
|
||||||
|
%destructor { free($$); } TOK_QUOTED_STRING TOK_ID TOK_MODE TOK_DMESG_STAMP
|
||||||
|
%destructor { free($$); } TOK_AUDIT_DIGITS TOK_DATE_MONTH TOK_DATE TOK_TIME
|
||||||
|
%destructor { free($$); } TOK_HEXSTRING TOK_TYPE_OTHER TOK_MSG_REST
|
||||||
|
%destructor { free($$); } TOK_IP_ADDR
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
|
||||||
log_message: audit_type
|
log_message: audit_type
|
||||||
@@ -201,7 +206,7 @@ other_audit: TOK_TYPE_OTHER audit_msg TOK_MSG_REST
|
|||||||
;
|
;
|
||||||
|
|
||||||
dmesg_type: TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
|
dmesg_type: TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id key_list
|
||||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; }
|
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($1); }
|
||||||
;
|
;
|
||||||
|
|
||||||
syslog_type:
|
syslog_type:
|
||||||
|
@@ -34,19 +34,25 @@ int main(void)
|
|||||||
retstr = hex_to_string("2F746D702F646F6573206E6F74206578697374");
|
retstr = hex_to_string("2F746D702F646F6573206E6F74206578697374");
|
||||||
MY_TEST(retstr, "basic allocation");
|
MY_TEST(retstr, "basic allocation");
|
||||||
MY_TEST(strcmp(retstr, "/tmp/does not exist") == 0, "basic dehex 1");
|
MY_TEST(strcmp(retstr, "/tmp/does not exist") == 0, "basic dehex 1");
|
||||||
|
free(retstr);
|
||||||
|
|
||||||
retstr = hex_to_string("61");
|
retstr = hex_to_string("61");
|
||||||
MY_TEST(strcmp(retstr, "a") == 0, "basic dehex 2");
|
MY_TEST(strcmp(retstr, "a") == 0, "basic dehex 2");
|
||||||
|
free(retstr);
|
||||||
|
|
||||||
retstr = hex_to_string("");
|
retstr = hex_to_string("");
|
||||||
MY_TEST(strcmp(retstr, "") == 0, "empty string");
|
MY_TEST(strcmp(retstr, "") == 0, "empty string");
|
||||||
|
free(retstr);
|
||||||
|
|
||||||
/* ipproto_to_string() tests */
|
/* ipproto_to_string() tests */
|
||||||
retstr = ipproto_to_string((unsigned) 99999);
|
retstr = ipproto_to_string((unsigned) 99999);
|
||||||
MY_TEST(strcmp(retstr, "unknown(99999)") == 0, "invalid protocol test");
|
MY_TEST(strcmp(retstr, "unknown(99999)") == 0, "invalid protocol test");
|
||||||
|
free(retstr);
|
||||||
|
|
||||||
retstr = ipproto_to_string((unsigned) 6);
|
retstr = ipproto_to_string((unsigned) 6);
|
||||||
MY_TEST(strcmp(retstr, "tcp") == 0, "protocol=tcp");
|
MY_TEST(strcmp(retstr, "tcp") == 0, "protocol=tcp");
|
||||||
|
free(retstr);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,5 +15,10 @@ test_multi_multi_LDADD = -L../src/.libs -lapparmor
|
|||||||
|
|
||||||
clean-local:
|
clean-local:
|
||||||
rm -rf tmp.err.* tmp.out.* site.exp site.bak test_multi/out
|
rm -rf tmp.err.* tmp.out.* site.exp site.bak test_multi/out
|
||||||
|
rm -f libaalogparse.log libaalogparse.sum
|
||||||
|
|
||||||
|
check-local:
|
||||||
|
if ! test -f libaalogparse.log ; then echo '*** libaalogparse.log not found - is dejagnu installed? ***'; exit 1; fi
|
||||||
|
if grep ERROR libaalogparse.log ; then exit 1 ; fi
|
||||||
|
|
||||||
EXTRA_DIST = test_multi/*.in test_multi/*.out test_multi/*.err
|
EXTRA_DIST = test_multi/*.in test_multi/*.out test_multi/*.err
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
type=AVC msg=audit(1449442292.901:961): apparmor="ALLOWED" operation="change_hat" profile="/usr/sbin/httpd{,2}-prefork" pid=8527 comm="httpd-prefork" target="/usr/sbin/httpd{,2}-prefork//HANDLING_UNTRUSTED_INPUT"
|
@@ -0,0 +1,11 @@
|
|||||||
|
START
|
||||||
|
File: testcase_changehat_01.in
|
||||||
|
Event type: AA_RECORD_ALLOWED
|
||||||
|
Audit ID: 1449442292.901:961
|
||||||
|
Operation: change_hat
|
||||||
|
Profile: /usr/sbin/httpd{,2}-prefork
|
||||||
|
Command: httpd-prefork
|
||||||
|
Name2: /usr/sbin/httpd{,2}-prefork//HANDLING_UNTRUSTED_INPUT
|
||||||
|
PID: 8527
|
||||||
|
Epoch: 1449442292
|
||||||
|
Audit subid: 961
|
@@ -0,0 +1 @@
|
|||||||
|
Jul 25 15:02:00 redacted kernel: [ 296.524447] audit: type=1400 audit(1437850920.403:64): apparmor="ALLOWED" operation="open" profile="/usr/sbin/vsftpd" name="/home/bane/foo" pid=1811 comm="vsftpd" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
|
@@ -0,0 +1,15 @@
|
|||||||
|
START
|
||||||
|
File: testcase_syslog_read.in
|
||||||
|
Event type: AA_RECORD_ALLOWED
|
||||||
|
Audit ID: 1437850920.403:64
|
||||||
|
Operation: open
|
||||||
|
Mask: r
|
||||||
|
Denied Mask: r
|
||||||
|
fsuid: 1000
|
||||||
|
ouid: 1000
|
||||||
|
Profile: /usr/sbin/vsftpd
|
||||||
|
Name: /home/bane/foo
|
||||||
|
Command: vsftpd
|
||||||
|
PID: 1811
|
||||||
|
Epoch: 1437850920
|
||||||
|
Audit subid: 64
|
@@ -103,7 +103,7 @@ capabilities(7))
|
|||||||
|
|
||||||
B<NETWORK RULE> = [ I<QUALIFIERS> ] 'network' [ I<DOMAIN> ] [ I<TYPE> | I<PROTOCOL> ]
|
B<NETWORK RULE> = [ I<QUALIFIERS> ] 'network' [ I<DOMAIN> ] [ I<TYPE> | I<PROTOCOL> ]
|
||||||
|
|
||||||
B<DOMAIN> = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'bluetooth' | 'netlink' | 'unix' | 'rds' | 'llc' | 'can' | 'tipc' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' ) ','
|
B<DOMAIN> = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'bluetooth' | 'netlink' | 'unix' | 'rds' | 'llc' | 'can' | 'tipc' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'mpls' | 'ib' ) ','
|
||||||
|
|
||||||
B<TYPE> = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' | 'packet' )
|
B<TYPE> = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' | 'packet' )
|
||||||
|
|
||||||
@@ -161,7 +161,7 @@ B<SIGNAL SET> = 'set' '=' '(' I<SIGNAL LIST> ')'
|
|||||||
|
|
||||||
B<SIGNAL LIST> = Comma or space separated list of I<SIGNALS>
|
B<SIGNAL LIST> = Comma or space separated list of I<SIGNALS>
|
||||||
|
|
||||||
B<SIGNALS> = ( 'hup' | 'int' | 'quit' | 'ill' | 'trap' | 'abrt' | 'bus' | 'fpe' | 'kill' | 'usr1' | 'segv' | 'usr2' | 'pipe' | 'alrm' | 'term' | 'stkflt' | 'chld' | 'cont' | 'stop' | 'stp' | 'ttin' | 'ttou' | 'urg' | 'xcpu' | 'xfsz' | 'vtalrm' | 'prof' | 'winch' | 'io' | 'pwr' | 'sys' | 'emt' | 'exists' )
|
B<SIGNALS> = ( 'hup' | 'int' | 'quit' | 'ill' | 'trap' | 'abrt' | 'bus' | 'fpe' | 'kill' | 'usr1' | 'segv' | 'usr2' | 'pipe' | 'alrm' | 'term' | 'stkflt' | 'chld' | 'cont' | 'stop' | 'stp' | 'ttin' | 'ttou' | 'urg' | 'xcpu' | 'xfsz' | 'vtalrm' | 'prof' | 'winch' | 'io' | 'pwr' | 'sys' | 'emt' | 'exists' | 'rtmin+0' ... 'rtmin+32' )
|
||||||
|
|
||||||
B<SIGNAL PEER> = 'peer' '=' I<AARE>
|
B<SIGNAL PEER> = 'peer' '=' I<AARE>
|
||||||
|
|
||||||
@@ -231,11 +231,13 @@ B<RLIMIT RULE> = 'set' 'rlimit' [I<RLIMIT> 'E<lt>=' I<RLIMIT VALUE> ]
|
|||||||
|
|
||||||
B<RLIMIT> = ( 'cpu' | 'fsize' | 'data' | 'stack' | 'core' | 'rss' | 'nofile' | 'ofile' | 'as' | 'nproc' | 'memlock' | 'locks' | 'sigpending' | 'msgqueue' | 'nice' | 'rtprio' | 'rttime' )
|
B<RLIMIT> = ( 'cpu' | 'fsize' | 'data' | 'stack' | 'core' | 'rss' | 'nofile' | 'ofile' | 'as' | 'nproc' | 'memlock' | 'locks' | 'sigpending' | 'msgqueue' | 'nice' | 'rtprio' | 'rttime' )
|
||||||
|
|
||||||
B<RLIMIT VALUE> = ( I<RLIMIT SIZE> | I<RLIMIT NUMBER> | I<RLIMIT NICE> )
|
B<RLIMIT VALUE> = ( I<RLIMIT SIZE> | I<RLIMIT NUMBER> | I<RLIMIT TIME> | I<RLIMIT NICE> )
|
||||||
|
|
||||||
B<RLIMIT SIZE> = I<NUMBER> ( 'K' | 'M' | 'G' ) Only applies to RLIMIT of 'fsize', 'data', 'stack', 'core', 'rss', 'as', 'memlock', 'msgqueue'.
|
B<RLIMIT SIZE> = I<NUMBER> ( 'K' | 'M' | 'G' ) Only applies to RLIMIT of 'fsize', 'data', 'stack', 'core', 'rss', 'as', 'memlock', 'msgqueue'.
|
||||||
|
|
||||||
B<RLIMIT NUMBER> = number from 0 to max rlimit value. Only applies ot RLIMIT of 'nofile', 'locks', 'sigpending', 'nproc', 'rtprio', 'cpu'
|
B<RLIMIT NUMBER> = number from 0 to max rlimit value. Only applies ot RLIMIT of 'ofile', 'nofile', 'locks', 'sigpending', 'nproc', 'rtprio'
|
||||||
|
|
||||||
|
B<RLIMIT TIME> = I<NUMBER> ( 'us' | 'microsecond' | 'microseconds' | 'ms' | 'millisecond' | 'milliseconds' | 's' | 'sec' | 'second' | 'seconds' | 'min' | 'minute' | 'minutes' | 'h' | 'hour' | 'hours' | 'd' | 'day' | 'days' | 'week' | 'weeks' ) Only applies to RLIMIT of 'cpu', 'rttime'. RLIMIT 'cpu' only allows units >= 'seconds'.
|
||||||
|
|
||||||
B<RLIMIT NICE> = a number between -20 and 19. Only applies to RLIMIT of 'nice'
|
B<RLIMIT NICE> = a number between -20 and 19. Only applies to RLIMIT of 'nice'
|
||||||
|
|
||||||
@@ -962,6 +964,9 @@ Example AppArmor signal rules:
|
|||||||
# Allow us to signal ourselves using the built-in @{profile_name} variable
|
# Allow us to signal ourselves using the built-in @{profile_name} variable
|
||||||
signal peer=@{profile_name},
|
signal peer=@{profile_name},
|
||||||
|
|
||||||
|
# Allow two real-time signals
|
||||||
|
signal set=(rtmin+0 rtmin+32),
|
||||||
|
|
||||||
=head2 DBus rules
|
=head2 DBus rules
|
||||||
|
|
||||||
AppArmor supports DBus mediation. The mediation is performed in conjunction
|
AppArmor supports DBus mediation. The mediation is performed in conjunction
|
||||||
@@ -1227,8 +1232,10 @@ provided AppArmor policy:
|
|||||||
@{HOMEDIRS}
|
@{HOMEDIRS}
|
||||||
@{multiarch}
|
@{multiarch}
|
||||||
@{pid}
|
@{pid}
|
||||||
|
@{pids}
|
||||||
@{PROC}
|
@{PROC}
|
||||||
@{securityfs}
|
@{securityfs}
|
||||||
|
@{apparmorfs}
|
||||||
@{sys}
|
@{sys}
|
||||||
@{tid}
|
@{tid}
|
||||||
@{XDG_DESKTOP_DIR}
|
@{XDG_DESKTOP_DIR}
|
||||||
|
@@ -278,9 +278,32 @@ the matching stats flag.
|
|||||||
|
|
||||||
Use --help=dump to see a full list of which dump flags are supported
|
Use --help=dump to see a full list of which dump flags are supported
|
||||||
|
|
||||||
|
=item -j n, --jobs=n
|
||||||
|
|
||||||
|
Set the number of jobs used to compile the specified policy. Where n can
|
||||||
|
be
|
||||||
|
|
||||||
|
# - a specific number of jobs
|
||||||
|
auto - the # of cpus in the in the system
|
||||||
|
x# - # * number of cpus
|
||||||
|
|
||||||
|
Eg.
|
||||||
|
-j8 OR --jobs=8 allows for 8 parallel jobs
|
||||||
|
-jauto OR --jobs=auto sets the jobs to the # of cpus
|
||||||
|
-jx4 OR --jobs=x4 sets the jobs to # of cpus * 4
|
||||||
|
-jx1 is equivalent to -jauto
|
||||||
|
|
||||||
|
The default value is the number of cpus in the system.
|
||||||
|
|
||||||
|
=item --max-jobs n
|
||||||
|
|
||||||
|
Set a hard cap on the value that can be specified by the --jobs flag.
|
||||||
|
It takes the same set of options available to the --jobs option, and
|
||||||
|
defaults to 8*cpus
|
||||||
|
|
||||||
=item -O n, --optimize=n
|
=item -O n, --optimize=n
|
||||||
|
|
||||||
Set the optimization flags used by policy compilation. A sinlge optimization
|
Set the optimization flags used by policy compilation. A single optimization
|
||||||
flag can be toggled per -O option, but the optimize flag can be passed
|
flag can be toggled per -O option, but the optimize flag can be passed
|
||||||
multiple times. Turning off some phases of the optimization can make
|
multiple times. Turning off some phases of the optimization can make
|
||||||
it so that policy can't complete compilation due to size constraints
|
it so that policy can't complete compilation due to size constraints
|
||||||
|
@@ -96,13 +96,13 @@ ostream &operator<<(ostream &os, Node &node);
|
|||||||
/* An abstract node in the syntax tree. */
|
/* An abstract node in the syntax tree. */
|
||||||
class Node {
|
class Node {
|
||||||
public:
|
public:
|
||||||
Node(): nullable(false) { child[0] = child[1] = 0; }
|
Node(): nullable(false), label(0) { child[0] = child[1] = 0; }
|
||||||
Node(Node *left): nullable(false)
|
Node(Node *left): nullable(false), label(0)
|
||||||
{
|
{
|
||||||
child[0] = left;
|
child[0] = left;
|
||||||
child[1] = 0;
|
child[1] = 0;
|
||||||
}
|
}
|
||||||
Node(Node *left, Node *right): nullable(false)
|
Node(Node *left, Node *right): nullable(false), label(0)
|
||||||
{
|
{
|
||||||
child[0] = left;
|
child[0] = left;
|
||||||
child[1] = right;
|
child[1] = right;
|
||||||
|
@@ -103,7 +103,7 @@
|
|||||||
#define MS_CMDS (MS_MOVE | MS_REMOUNT | MS_BIND | MS_RBIND | \
|
#define MS_CMDS (MS_MOVE | MS_REMOUNT | MS_BIND | MS_RBIND | \
|
||||||
MS_UNBINDABLE | MS_RUNBINDABLE | MS_PRIVATE | MS_RPRIVATE | \
|
MS_UNBINDABLE | MS_RUNBINDABLE | MS_PRIVATE | MS_RPRIVATE | \
|
||||||
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED)
|
MS_SLAVE | MS_RSLAVE | MS_SHARED | MS_RSHARED)
|
||||||
#define MS_REMOUNT_FLAGS (MS_ALL_FLAGS & ~(MS_CMDS & ~MS_REMOUNT))
|
#define MS_REMOUNT_FLAGS (MS_ALL_FLAGS & ~(MS_CMDS & ~MS_REMOUNT & ~MS_BIND & ~MS_RBIND))
|
||||||
|
|
||||||
#define MNT_SRC_OPT 1
|
#define MNT_SRC_OPT 1
|
||||||
#define MNT_DST_OPT 2
|
#define MNT_DST_OPT 2
|
||||||
|
@@ -402,6 +402,9 @@ extern void free_cod_entries(struct cod_entry *list);
|
|||||||
extern void __debug_capabilities(uint64_t capset, const char *name);
|
extern void __debug_capabilities(uint64_t capset, const char *name);
|
||||||
void debug_cod_entries(struct cod_entry *list);
|
void debug_cod_entries(struct cod_entry *list);
|
||||||
|
|
||||||
|
#define SECONDS_P_MS (1000LL * 1000LL)
|
||||||
|
long long convert_time_units(long long value, long long base, const char *units);
|
||||||
|
|
||||||
|
|
||||||
/* parser_symtab.c */
|
/* parser_symtab.c */
|
||||||
struct set_value {
|
struct set_value {
|
||||||
|
@@ -57,7 +57,7 @@
|
|||||||
* numbers where supported.
|
* numbers where supported.
|
||||||
*/
|
*/
|
||||||
uint32_t policy_version = 2;
|
uint32_t policy_version = 2;
|
||||||
uint32_t parser_abi_version = 1;
|
uint32_t parser_abi_version = 2;
|
||||||
uint32_t kernel_abi_version = 5;
|
uint32_t kernel_abi_version = 5;
|
||||||
|
|
||||||
int force_complain = 0;
|
int force_complain = 0;
|
||||||
|
@@ -447,7 +447,7 @@ LT_EQUAL <=
|
|||||||
}
|
}
|
||||||
|
|
||||||
<RLIMIT_MODE>{
|
<RLIMIT_MODE>{
|
||||||
-?{NUMBER}[[:alpha:]]* {
|
-?{NUMBER} {
|
||||||
yylval.var_val = strdup(yytext);
|
yylval.var_val = strdup(yytext);
|
||||||
RETURN_TOKEN(TOK_VALUE);
|
RETURN_TOKEN(TOK_VALUE);
|
||||||
}
|
}
|
||||||
@@ -523,6 +523,13 @@ LT_EQUAL <=
|
|||||||
yy_push_state(INCLUDE);
|
yy_push_state(INCLUDE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include/{WS} {
|
||||||
|
/* Don't use PUSH() macro here as we don't want #include echoed out.
|
||||||
|
* It needs to be handled specially
|
||||||
|
*/
|
||||||
|
yy_push_state(INCLUDE);
|
||||||
|
}
|
||||||
|
|
||||||
#.*\r?\n { /* normal comment */
|
#.*\r?\n { /* normal comment */
|
||||||
DUMP_AND_DEBUG("comment(%d): %s\n", current_lineno, yytext);
|
DUMP_AND_DEBUG("comment(%d): %s\n", current_lineno, yytext);
|
||||||
current_lineno++;
|
current_lineno++;
|
||||||
|
@@ -36,8 +36,11 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <sys/apparmor.h>
|
#include <sys/apparmor.h>
|
||||||
|
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "features.h"
|
#include "features.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
@@ -76,6 +79,18 @@ int abort_on_error = 0; /* stop processing profiles if error */
|
|||||||
int skip_bad_cache_rebuild = 0;
|
int skip_bad_cache_rebuild = 0;
|
||||||
int mru_skip_cache = 1;
|
int mru_skip_cache = 1;
|
||||||
int debug_cache = 0;
|
int debug_cache = 0;
|
||||||
|
|
||||||
|
/* for jobs_max and jobs
|
||||||
|
* LONG_MAX : no limit
|
||||||
|
* 0 : auto = detect system processing cores
|
||||||
|
* n : use that number of processes/threads to compile policy
|
||||||
|
*/
|
||||||
|
#define JOBS_AUTO 0
|
||||||
|
long jobs_max = -8; /* 8 * cpus */
|
||||||
|
long jobs = JOBS_AUTO; /* default: number of processor cores */
|
||||||
|
long njobs = 0;
|
||||||
|
bool debug_jobs = false;
|
||||||
|
|
||||||
struct timespec cache_tstamp, mru_policy_tstamp;
|
struct timespec cache_tstamp, mru_policy_tstamp;
|
||||||
|
|
||||||
static char *apparmorfs = NULL;
|
static char *apparmorfs = NULL;
|
||||||
@@ -84,7 +99,7 @@ static char *cacheloc = NULL;
|
|||||||
static aa_features *features = NULL;
|
static aa_features *features = NULL;
|
||||||
|
|
||||||
/* Make sure to update BOTH the short and long_options */
|
/* Make sure to update BOTH the short and long_options */
|
||||||
static const char *short_options = "adf:h::rRVvI:b:BCD:NSm:M:qQn:XKTWkL:O:po:";
|
static const char *short_options = "ad::f:h::rRVvI:b:BCD:NSm:M:qQn:XKTWkL:O:po:j:";
|
||||||
struct option long_options[] = {
|
struct option long_options[] = {
|
||||||
{"add", 0, 0, 'a'},
|
{"add", 0, 0, 'a'},
|
||||||
{"binary", 0, 0, 'B'},
|
{"binary", 0, 0, 'B'},
|
||||||
@@ -116,7 +131,7 @@ struct option long_options[] = {
|
|||||||
{"purge-cache", 0, 0, 130}, /* no short option */
|
{"purge-cache", 0, 0, 130}, /* no short option */
|
||||||
{"create-cache-dir", 0, 0, 131}, /* no short option */
|
{"create-cache-dir", 0, 0, 131}, /* no short option */
|
||||||
{"cache-loc", 1, 0, 'L'},
|
{"cache-loc", 1, 0, 'L'},
|
||||||
{"debug", 0, 0, 'd'},
|
{"debug", 2, 0, 'd'},
|
||||||
{"dump", 1, 0, 'D'},
|
{"dump", 1, 0, 'D'},
|
||||||
{"Dump", 1, 0, 'D'},
|
{"Dump", 1, 0, 'D'},
|
||||||
{"optimize", 1, 0, 'O'},
|
{"optimize", 1, 0, 'O'},
|
||||||
@@ -126,6 +141,8 @@ struct option long_options[] = {
|
|||||||
{"skip-bad-cache-rebuild", 0, 0, 133}, /* no short option */
|
{"skip-bad-cache-rebuild", 0, 0, 133}, /* no short option */
|
||||||
{"warn", 1, 0, 134}, /* no short option */
|
{"warn", 1, 0, 134}, /* no short option */
|
||||||
{"debug-cache", 0, 0, 135}, /* no short option */
|
{"debug-cache", 0, 0, 135}, /* no short option */
|
||||||
|
{"jobs", 1, 0, 'j'},
|
||||||
|
{"max-jobs", 1, 0, 136}, /* no short option */
|
||||||
{NULL, 0, 0, 0},
|
{NULL, 0, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -170,11 +187,13 @@ static void display_usage(const char *command)
|
|||||||
"-v, --verbose Show profile names as they load\n"
|
"-v, --verbose Show profile names as they load\n"
|
||||||
"-Q, --skip-kernel-load Do everything except loading into kernel\n"
|
"-Q, --skip-kernel-load Do everything except loading into kernel\n"
|
||||||
"-V, --version Display version info and exit\n"
|
"-V, --version Display version info and exit\n"
|
||||||
"-d, --debug Debug apparmor definitions\n"
|
"-d [n], --debug Debug apparmor definitions OR [n]\n"
|
||||||
"-p, --preprocess Dump preprocessed profile\n"
|
"-p, --preprocess Dump preprocessed profile\n"
|
||||||
"-D [n], --dump Dump internal info for debugging\n"
|
"-D [n], --dump Dump internal info for debugging\n"
|
||||||
"-O [n], --Optimize Control dfa optimizations\n"
|
"-O [n], --Optimize Control dfa optimizations\n"
|
||||||
"-h [cmd], --help[=cmd] Display this text or info about cmd\n"
|
"-h [cmd], --help[=cmd] Display this text or info about cmd\n"
|
||||||
|
"-j n, --jobs n Set the number of compile threads\n"
|
||||||
|
"--max-jobs n Hard cap on --jobs. Default 8*cpus\n"
|
||||||
"--abort-on-error Abort processing of profiles on first error\n"
|
"--abort-on-error Abort processing of profiles on first error\n"
|
||||||
"--skip-bad-cache-rebuild Do not try rebuilding the cache if it is rejected by the kernel\n"
|
"--skip-bad-cache-rebuild Do not try rebuilding the cache if it is rejected by the kernel\n"
|
||||||
"--warn n Enable warnings (see --help=warn)\n"
|
"--warn n Enable warnings (see --help=warn)\n"
|
||||||
@@ -268,6 +287,32 @@ static int getopt_long_file(FILE *f, const struct option *longopts,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static long process_jobs_arg(const char *arg, const char *val) {
|
||||||
|
char *end;
|
||||||
|
long n;
|
||||||
|
|
||||||
|
if (!val || strcmp(val, "auto") == 0)
|
||||||
|
n = JOBS_AUTO;
|
||||||
|
else if (strcmp(val, "max") == 0)
|
||||||
|
n = LONG_MAX;
|
||||||
|
else {
|
||||||
|
bool multiple = false;
|
||||||
|
if (*val == 'x') {
|
||||||
|
multiple = true;
|
||||||
|
val++;
|
||||||
|
}
|
||||||
|
n = strtol(val, &end, 0);
|
||||||
|
if (!(*val && val != end && *end == '\0')) {
|
||||||
|
PERROR("%s: Invalid option %s=%s%s\n", progname, arg, multiple ? "x" : "", val);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (multiple)
|
||||||
|
n = -n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
/* process a single argment from getopt_long
|
/* process a single argment from getopt_long
|
||||||
* Returns: 1 if an action arg, else 0
|
* Returns: 1 if an action arg, else 0
|
||||||
*/
|
*/
|
||||||
@@ -286,8 +331,17 @@ static int process_arg(int c, char *optarg)
|
|||||||
option = OPTION_ADD;
|
option = OPTION_ADD;
|
||||||
break;
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
|
if (!optarg) {
|
||||||
debug++;
|
debug++;
|
||||||
skip_read_cache = 1;
|
skip_read_cache = 1;
|
||||||
|
} else if (strcmp(optarg, "jobs") == 0 ||
|
||||||
|
strcmp(optarg, "j") == 0) {
|
||||||
|
debug_jobs = true;
|
||||||
|
} else {
|
||||||
|
PERROR("%s: Invalid --debug option '%s'\n",
|
||||||
|
progname, optarg);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
if (!optarg) {
|
if (!optarg) {
|
||||||
@@ -470,6 +524,12 @@ static int process_arg(int c, char *optarg)
|
|||||||
case 135:
|
case 135:
|
||||||
debug_cache = 1;
|
debug_cache = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'j':
|
||||||
|
jobs = process_jobs_arg("-j", optarg);
|
||||||
|
break;
|
||||||
|
case 136:
|
||||||
|
jobs_max = process_jobs_arg("max-jobs", optarg);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
display_usage(progname);
|
display_usage(progname);
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -803,6 +863,118 @@ out:
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Do not call directly, this is a helper for work_sync, which can handle
|
||||||
|
* single worker cases and cases were the work queue is optimized away
|
||||||
|
*
|
||||||
|
* call only if there are work children to wait on
|
||||||
|
*/
|
||||||
|
#define work_sync_one(RESULT) \
|
||||||
|
do { \
|
||||||
|
int status; \
|
||||||
|
wait(&status); \
|
||||||
|
if (WIFEXITED(status)) \
|
||||||
|
RESULT(WEXITSTATUS(status)); \
|
||||||
|
else \
|
||||||
|
RESULT(ECHILD); \
|
||||||
|
/* TODO: do we need to handle traced */ \
|
||||||
|
njobs--; \
|
||||||
|
if (debug_jobs) \
|
||||||
|
fprintf(stderr, " JOBS SYNC ONE: result %d, jobs left %ld\n", status, njobs); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define work_sync(RESULT) \
|
||||||
|
do { \
|
||||||
|
if (debug_jobs) \
|
||||||
|
fprintf(stderr, "JOBS SYNC: jobs left %ld\n", njobs); \
|
||||||
|
while (njobs) \
|
||||||
|
work_sync_one(RESULT); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define work_spawn(WORK, RESULT) \
|
||||||
|
do { \
|
||||||
|
/* what to do to avoid fork() overhead when single threaded \
|
||||||
|
if (jobs == 1) { \
|
||||||
|
// no parallel work so avoid fork() overhead \
|
||||||
|
RESULT(WORK); \
|
||||||
|
break; \
|
||||||
|
}*/ \
|
||||||
|
if (njobs == jobs) { \
|
||||||
|
/* wait for a child */ \
|
||||||
|
if (debug_jobs) \
|
||||||
|
fprintf(stderr, " JOBS SPAWN: waiting (jobs %ld == max %ld) ...\n", njobs, jobs); \
|
||||||
|
work_sync_one(RESULT); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
pid_t child = fork(); \
|
||||||
|
if (child == 0) { \
|
||||||
|
/* child - exit work unit with returned value */ \
|
||||||
|
exit(WORK); \
|
||||||
|
} else if (child > 0) { \
|
||||||
|
/* parent */ \
|
||||||
|
njobs++; \
|
||||||
|
if (debug_jobs) \
|
||||||
|
fprintf(stderr, " JOBS SPAWN: created %ld ...\n", njobs); \
|
||||||
|
} else { \
|
||||||
|
/* error */ \
|
||||||
|
if (debug_jobs) \
|
||||||
|
fprintf(stderr, " JOBS SPAWN: failed error: %d) ...\n", errno); \
|
||||||
|
RESULT(errno); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
/* sadly C forces us to do this with exit, long_jump or returning error
|
||||||
|
* from work_spawn and work_sync. We could throw a C++ exception, is it
|
||||||
|
* worth doing it to avoid the exit here.
|
||||||
|
*
|
||||||
|
* atm not all resources maybe cleanedup at exit
|
||||||
|
*/
|
||||||
|
int last_error = 0;
|
||||||
|
void handle_work_result(int retval)
|
||||||
|
{
|
||||||
|
if (retval) {
|
||||||
|
last_error = retval;
|
||||||
|
if (abort_on_error) {
|
||||||
|
/* already in abort mode we don't need subsequent
|
||||||
|
* syncs to do this too
|
||||||
|
*/
|
||||||
|
abort_on_error = 0;
|
||||||
|
work_sync(handle_work_result);
|
||||||
|
exit(last_error);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static long compute_jobs(long n, long j)
|
||||||
|
{
|
||||||
|
if (j == JOBS_AUTO)
|
||||||
|
j = n;
|
||||||
|
else if (j < 0)
|
||||||
|
j = n * j * -1;
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_parallel_compile(void)
|
||||||
|
{
|
||||||
|
/* jobs and paralell_max set by default, config or args */
|
||||||
|
long n = sysconf(_SC_NPROCESSORS_ONLN);
|
||||||
|
if (n == -1)
|
||||||
|
/* unable to determine number of processors, default to 1 */
|
||||||
|
n = 1;
|
||||||
|
jobs = compute_jobs(n, jobs);
|
||||||
|
jobs_max = compute_jobs(n, jobs_max);
|
||||||
|
|
||||||
|
if (jobs > jobs_max) {
|
||||||
|
pwarn("%s: Warning capping number of jobs to %ld * # of cpus == '%ld'",
|
||||||
|
progname, jobs_max, jobs);
|
||||||
|
jobs = jobs_max;
|
||||||
|
}
|
||||||
|
njobs = 0;
|
||||||
|
if (debug_jobs)
|
||||||
|
fprintf(stderr, "jobs: %ld\n", jobs);
|
||||||
|
}
|
||||||
|
|
||||||
struct dir_cb_data {
|
struct dir_cb_data {
|
||||||
aa_kernel_interface *kernel_interface;
|
aa_kernel_interface *kernel_interface;
|
||||||
const char *dirname; /* name of the parent dir */
|
const char *dirname; /* name of the parent dir */
|
||||||
@@ -820,8 +992,9 @@ static int profile_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
|||||||
autofree char *path = NULL;
|
autofree char *path = NULL;
|
||||||
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0)
|
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0)
|
||||||
PERROR(_("Out of memory"));
|
PERROR(_("Out of memory"));
|
||||||
rc = process_profile(option, cb_data->kernel_interface, path,
|
work_spawn(process_profile(option, cb_data->kernel_interface,
|
||||||
cb_data->cachedir);
|
path, cb_data->cachedir),
|
||||||
|
handle_work_result);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -837,7 +1010,9 @@ static int binary_dir_cb(int dirfd unused, const char *name, struct stat *st,
|
|||||||
autofree char *path = NULL;
|
autofree char *path = NULL;
|
||||||
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0)
|
if (asprintf(&path, "%s/%s", cb_data->dirname, name) < 0)
|
||||||
PERROR(_("Out of memory"));
|
PERROR(_("Out of memory"));
|
||||||
rc = process_binary(option, cb_data->kernel_interface, path);
|
work_spawn(process_binary(option, cb_data->kernel_interface,
|
||||||
|
path),
|
||||||
|
handle_work_result);
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -860,8 +1035,8 @@ static void setup_flags(void)
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
aa_kernel_interface *kernel_interface = NULL;
|
aa_kernel_interface *kernel_interface = NULL;
|
||||||
aa_policy_cache *policy_cache;
|
aa_policy_cache *policy_cache = NULL;
|
||||||
int retval, last_error;
|
int retval;
|
||||||
int i;
|
int i;
|
||||||
int optind;
|
int optind;
|
||||||
|
|
||||||
@@ -873,6 +1048,8 @@ int main(int argc, char *argv[])
|
|||||||
process_config_file("/etc/apparmor/parser.conf");
|
process_config_file("/etc/apparmor/parser.conf");
|
||||||
optind = process_args(argc, argv);
|
optind = process_args(argc, argv);
|
||||||
|
|
||||||
|
setup_parallel_compile();
|
||||||
|
|
||||||
setlocale(LC_MESSAGES, "");
|
setlocale(LC_MESSAGES, "");
|
||||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||||
textdomain(PACKAGE);
|
textdomain(PACKAGE);
|
||||||
@@ -964,8 +1141,10 @@ int main(int argc, char *argv[])
|
|||||||
void *data);
|
void *data);
|
||||||
struct dir_cb_data cb_data;
|
struct dir_cb_data cb_data;
|
||||||
|
|
||||||
|
memset(&cb_data, 0, sizeof(struct dir_cb_data));
|
||||||
cb_data.dirname = profilename;
|
cb_data.dirname = profilename;
|
||||||
cb_data.cachedir = cacheloc;
|
cb_data.cachedir = cacheloc;
|
||||||
|
cb_data.kernel_interface = kernel_interface;
|
||||||
cb = binary_input ? binary_dir_cb : profile_dir_cb;
|
cb = binary_input ? binary_dir_cb : profile_dir_cb;
|
||||||
if ((retval = dirat_for_each(AT_FDCWD, profilename,
|
if ((retval = dirat_for_each(AT_FDCWD, profilename,
|
||||||
&cb_data, cb))) {
|
&cb_data, cb))) {
|
||||||
@@ -973,25 +1152,23 @@ int main(int argc, char *argv[])
|
|||||||
profilename);
|
profilename);
|
||||||
}
|
}
|
||||||
} else if (binary_input) {
|
} else if (binary_input) {
|
||||||
retval = process_binary(option, kernel_interface,
|
work_spawn(process_binary(option, kernel_interface,
|
||||||
profilename);
|
profilename),
|
||||||
|
handle_work_result);
|
||||||
} else {
|
} else {
|
||||||
retval = process_profile(option, kernel_interface,
|
work_spawn(process_profile(option, kernel_interface,
|
||||||
profilename, cacheloc);
|
profilename, cacheloc),
|
||||||
|
handle_work_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (profilename) free(profilename);
|
if (profilename) free(profilename);
|
||||||
profilename = NULL;
|
profilename = NULL;
|
||||||
|
|
||||||
if (retval) {
|
|
||||||
last_error = retval;
|
|
||||||
if (abort_on_error)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
work_sync(handle_work_result);
|
||||||
|
|
||||||
if (ofile)
|
if (ofile)
|
||||||
fclose(ofile);
|
fclose(ofile);
|
||||||
|
aa_policy_cache_unref(policy_cache);
|
||||||
|
|
||||||
return last_error;
|
return last_error;
|
||||||
}
|
}
|
||||||
|
@@ -724,7 +724,7 @@ static const char *capnames[] = {
|
|||||||
"audit_write",
|
"audit_write",
|
||||||
"audit_control",
|
"audit_control",
|
||||||
"setfcap",
|
"setfcap",
|
||||||
"mac_override"
|
"mac_override",
|
||||||
"syslog",
|
"syslog",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -867,6 +867,54 @@ void print_cond_entry(struct cond_entry *ent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct time_units {
|
||||||
|
const char *str;
|
||||||
|
long long value;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct time_units time_units[] = {
|
||||||
|
{ "us", 1LL },
|
||||||
|
{ "microsecond", 1LL },
|
||||||
|
{ "microseconds", 1LL },
|
||||||
|
{ "ms", 1000LL },
|
||||||
|
{ "millisecond", 1000LL },
|
||||||
|
{ "milliseconds", 1000LL },
|
||||||
|
{ "s", 1000LL * 1000LL },
|
||||||
|
{ "sec", SECONDS_P_MS },
|
||||||
|
{ "second", SECONDS_P_MS },
|
||||||
|
{ "seconds", SECONDS_P_MS },
|
||||||
|
{ "min" , 60LL * SECONDS_P_MS },
|
||||||
|
{ "minute", 60LL * SECONDS_P_MS },
|
||||||
|
{ "minutes", 60LL * SECONDS_P_MS },
|
||||||
|
{ "h", 60LL * 60LL * SECONDS_P_MS },
|
||||||
|
{ "hour", 60LL * 60LL * SECONDS_P_MS },
|
||||||
|
{ "hours", 60LL * 60LL * SECONDS_P_MS },
|
||||||
|
{ "d", 24LL * 60LL * 60LL * SECONDS_P_MS },
|
||||||
|
{ "day", 24LL * 60LL * 60LL * SECONDS_P_MS },
|
||||||
|
{ "days", 24LL * 60LL * 60LL * SECONDS_P_MS },
|
||||||
|
{ "week", 7LL * 24LL * 60LL * 60LL * SECONDS_P_MS },
|
||||||
|
{ "weeks", 7LL * 24LL * 60LL * 60LL * SECONDS_P_MS },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
long long convert_time_units(long long value, long long base, const char *units)
|
||||||
|
{
|
||||||
|
struct time_units *ent;
|
||||||
|
if (!units)
|
||||||
|
/* default to base if no units */
|
||||||
|
return value;
|
||||||
|
|
||||||
|
for (ent = time_units; ent->str; ent++) {
|
||||||
|
if (strcmp(ent->str, units) == 0) {
|
||||||
|
if (value * ent->value < base)
|
||||||
|
return -1LL;
|
||||||
|
return value * ent->value / base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -2LL;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef UNIT_TEST
|
#ifdef UNIT_TEST
|
||||||
|
|
||||||
#include "unit_test.h"
|
#include "unit_test.h"
|
||||||
@@ -1085,6 +1133,50 @@ int test_processquoted(void)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define TIME_TEST(V, B, U, R) \
|
||||||
|
MY_TEST(convert_time_units((V), (B), U) == (R), \
|
||||||
|
"convert " #V " with base of " #B ", " #U " units")
|
||||||
|
|
||||||
|
int test_convert_time_units()
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
TIME_TEST(1LL, 1LL, NULL, 1LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, NULL, 12345LL);
|
||||||
|
TIME_TEST(10LL, 10LL, NULL, 10LL);
|
||||||
|
TIME_TEST(123450LL, 10LL, NULL, 123450LL);
|
||||||
|
|
||||||
|
TIME_TEST(12345LL, 1LL, "us", 12345LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "microsecond", 12345LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "microseconds", 12345LL);
|
||||||
|
|
||||||
|
TIME_TEST(12345LL, 1LL, "ms", 12345LL*1000LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "millisecond", 12345LL*1000LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "milliseconds", 12345LL*1000LL);
|
||||||
|
|
||||||
|
TIME_TEST(12345LL, 1LL, "s", 12345LL*1000LL*1000LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "sec", 12345LL*1000LL*1000LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "second", 12345LL*1000LL*1000LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "seconds", 12345LL*1000LL*1000LL);
|
||||||
|
|
||||||
|
TIME_TEST(12345LL, 1LL, "min", 12345LL*1000LL*1000LL*60LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "minute", 12345LL*1000LL*1000LL*60LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "minutes", 12345LL*1000LL*1000LL*60LL);
|
||||||
|
|
||||||
|
TIME_TEST(12345LL, 1LL, "h", 12345LL*1000LL*1000LL*60LL*60LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "hour", 12345LL*1000LL*1000LL*60LL*60LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "hours", 12345LL*1000LL*1000LL*60LL*60LL);
|
||||||
|
|
||||||
|
TIME_TEST(12345LL, 1LL, "d", 12345LL*1000LL*1000LL*60LL*60LL*24LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "day", 12345LL*1000LL*1000LL*60LL*60LL*24LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "days", 12345LL*1000LL*1000LL*60LL*60LL*24LL);
|
||||||
|
|
||||||
|
TIME_TEST(12345LL, 1LL, "week", 12345LL*1000LL*1000LL*60LL*60LL*24LL*7LL);
|
||||||
|
TIME_TEST(12345LL, 1LL, "weeks", 12345LL*1000LL*1000LL*60LL*60LL*24LL*7LL);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@@ -1102,6 +1194,10 @@ int main(void)
|
|||||||
if (retval != 0)
|
if (retval != 0)
|
||||||
rc = retval;
|
rc = retval;
|
||||||
|
|
||||||
|
retval = test_convert_time_units();
|
||||||
|
if (retval != 0)
|
||||||
|
rc = retval;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
#endif /* UNIT_TEST */
|
#endif /* UNIT_TEST */
|
||||||
|
@@ -275,12 +275,51 @@ static int process_variables_in_rules(Profile &prof)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int process_variables_in_name(Profile &prof)
|
||||||
|
{
|
||||||
|
/* this needs to be done before alias expansion, ie. altnames are
|
||||||
|
* setup
|
||||||
|
*/
|
||||||
|
int error = expand_entry_variables(&prof.name);
|
||||||
|
if (!error && prof.attachment)
|
||||||
|
error = expand_entry_variables(&prof.attachment);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string escape_re(std::string str)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < str.length(); i++) {
|
||||||
|
if (str[i] == '\\') {
|
||||||
|
/* skip \ and follow char. Skipping \ and first
|
||||||
|
* char is enough for multichar escape sequence
|
||||||
|
*/
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strchr("{}[]*?", str[i]) != NULL) {
|
||||||
|
str.insert(i++, "\\");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
int process_profile_variables(Profile *prof)
|
int process_profile_variables(Profile *prof)
|
||||||
{
|
{
|
||||||
int error = 0, rc;
|
int error = 0, rc;
|
||||||
|
|
||||||
error = new_set_var(PROFILE_NAME_VARIABLE, prof->get_name(true).c_str());
|
/* needs to be before PROFILE_NAME_VARIABLE so that variable will
|
||||||
|
* have the correct name
|
||||||
|
*/
|
||||||
|
error = process_variables_in_name(*prof);
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
/* escape profile name elements that could be interpreted
|
||||||
|
* as regular expressions.
|
||||||
|
*/
|
||||||
|
error = new_set_var(PROFILE_NAME_VARIABLE, escape_re(prof->get_name(false)).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (!error)
|
if (!error)
|
||||||
error = process_variables_in_entries(prof->entries);
|
error = process_variables_in_entries(prof->entries);
|
||||||
|
@@ -78,7 +78,6 @@ mnt_rule *do_mnt_rule(struct cond_entry *src_conds, char *src,
|
|||||||
int mode);
|
int mode);
|
||||||
mnt_rule *do_pivot_rule(struct cond_entry *old, char *root,
|
mnt_rule *do_pivot_rule(struct cond_entry *old, char *root,
|
||||||
char *transition);
|
char *transition);
|
||||||
|
|
||||||
void add_local_entry(Profile *prof);
|
void add_local_entry(Profile *prof);
|
||||||
|
|
||||||
%}
|
%}
|
||||||
@@ -252,6 +251,7 @@ void add_local_entry(Profile *prof);
|
|||||||
%type <val_list> valuelist
|
%type <val_list> valuelist
|
||||||
%type <boolean> expr
|
%type <boolean> expr
|
||||||
%type <id> id_or_var
|
%type <id> id_or_var
|
||||||
|
%type <id> opt_id_or_var
|
||||||
%type <boolean> opt_subset_flag
|
%type <boolean> opt_subset_flag
|
||||||
%type <boolean> opt_audit_flag
|
%type <boolean> opt_audit_flag
|
||||||
%type <boolean> opt_owner_flag
|
%type <boolean> opt_owner_flag
|
||||||
@@ -307,7 +307,10 @@ opt_ns: { /* nothing */ $$ = NULL; }
|
|||||||
opt_id: { /* nothing */ $$ = NULL; }
|
opt_id: { /* nothing */ $$ = NULL; }
|
||||||
| TOK_ID { $$ = $1; }
|
| TOK_ID { $$ = $1; }
|
||||||
|
|
||||||
profile_base: TOK_ID opt_id flags TOK_OPEN rules TOK_CLOSE
|
opt_id_or_var: { /* nothing */ $$ = NULL; }
|
||||||
|
| id_or_var { $$ = $1; }
|
||||||
|
|
||||||
|
profile_base: TOK_ID opt_id_or_var flags TOK_OPEN rules TOK_CLOSE
|
||||||
{
|
{
|
||||||
Profile *prof = $5;
|
Profile *prof = $5;
|
||||||
|
|
||||||
@@ -315,13 +318,17 @@ profile_base: TOK_ID opt_id flags TOK_OPEN rules TOK_CLOSE
|
|||||||
yyerror(_("Memory allocation error."));
|
yyerror(_("Memory allocation error."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Honor the --namespace-string command line option */
|
||||||
|
if (profile_ns) {
|
||||||
|
prof->ns = strdup(profile_ns);
|
||||||
|
if (!prof->ns)
|
||||||
|
yyerror(_("Memory allocation error."));
|
||||||
|
}
|
||||||
|
|
||||||
prof->name = $1;
|
prof->name = $1;
|
||||||
prof->attachment = $2;
|
prof->attachment = $2;
|
||||||
if ($2 && $2[0] != '/')
|
if ($2 && !($2[0] == '/' || strncmp($2, "@{", 2) == 0))
|
||||||
/* we don't support variables as part of the profile
|
yyerror(_("Profile attachment must begin with a '/' or variable."));
|
||||||
* name or attachment atm
|
|
||||||
*/
|
|
||||||
yyerror(_("Profile attachment must begin with a '/'."));
|
|
||||||
prof->flags = $3;
|
prof->flags = $3;
|
||||||
if (force_complain && kernel_abi_version == 5)
|
if (force_complain && kernel_abi_version == 5)
|
||||||
/* newer abis encode force complain as part of the
|
/* newer abis encode force complain as part of the
|
||||||
@@ -351,12 +358,17 @@ profile: opt_profile_flag opt_ns profile_base
|
|||||||
if ($3->name[0] != '/' && !($1 || $2))
|
if ($3->name[0] != '/' && !($1 || $2))
|
||||||
yyerror(_("Profile names must begin with a '/', namespace or keyword 'profile' or 'hat'."));
|
yyerror(_("Profile names must begin with a '/', namespace or keyword 'profile' or 'hat'."));
|
||||||
|
|
||||||
if ($2 && profile_ns) {
|
if (prof->ns) {
|
||||||
pwarn("%s: -n %s overriding policy specified namespace :%s:\n", progname, profile_ns, $2);
|
/**
|
||||||
|
* Print warning if the profile specified a namespace
|
||||||
|
* different than the one specified with the
|
||||||
|
* --namespace-string command line option
|
||||||
|
*/
|
||||||
|
if ($2 && strcmp(prof->ns, $2)) {
|
||||||
|
pwarn("%s: -n %s overriding policy specified namespace :%s:\n",
|
||||||
|
progname, prof->ns, $2);
|
||||||
|
}
|
||||||
free($2);
|
free($2);
|
||||||
prof->ns = strdup(profile_ns);
|
|
||||||
if (!prof->ns)
|
|
||||||
yyerror(_("Memory allocation error."));
|
|
||||||
} else
|
} else
|
||||||
prof->ns = $2;
|
prof->ns = $2;
|
||||||
if ($1 == 2)
|
if ($1 == 2)
|
||||||
@@ -853,7 +865,7 @@ rules: rules cond_rule
|
|||||||
$$ = merge_policy($1, $2);
|
$$ = merge_policy($1, $2);
|
||||||
}
|
}
|
||||||
|
|
||||||
rules: rules TOK_SET TOK_RLIMIT TOK_ID TOK_LE TOK_VALUE TOK_END_OF_RULE
|
rules: rules TOK_SET TOK_RLIMIT TOK_ID TOK_LE TOK_VALUE opt_id TOK_END_OF_RULE
|
||||||
{
|
{
|
||||||
rlim_t value = RLIM_INFINITY;
|
rlim_t value = RLIM_INFINITY;
|
||||||
long long tmp;
|
long long tmp;
|
||||||
@@ -866,11 +878,6 @@ rules: rules TOK_SET TOK_RLIMIT TOK_ID TOK_LE TOK_VALUE TOK_END_OF_RULE
|
|||||||
if (strcmp($6, "infinity") == 0) {
|
if (strcmp($6, "infinity") == 0) {
|
||||||
value = RLIM_INFINITY;
|
value = RLIM_INFINITY;
|
||||||
} else {
|
} else {
|
||||||
const char *seconds = "seconds";
|
|
||||||
const char *milliseconds = "ms";
|
|
||||||
const char *minutes = "minutes";
|
|
||||||
const char *hours = "hours";
|
|
||||||
const char *days = "days";
|
|
||||||
const char *kb = "KB";
|
const char *kb = "KB";
|
||||||
const char *mb = "MB";
|
const char *mb = "MB";
|
||||||
const char *gb = "GB";
|
const char *gb = "GB";
|
||||||
@@ -880,34 +887,25 @@ rules: rules TOK_SET TOK_RLIMIT TOK_ID TOK_LE TOK_VALUE TOK_END_OF_RULE
|
|||||||
case RLIMIT_CPU:
|
case RLIMIT_CPU:
|
||||||
if (!end || $6 == end || tmp < 0)
|
if (!end || $6 == end || tmp < 0)
|
||||||
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
|
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
|
||||||
if (*end == '\0' ||
|
tmp = convert_time_units(tmp, SECONDS_P_MS, $7);
|
||||||
strstr(seconds, end) == seconds) {
|
if (tmp == -1LL)
|
||||||
value = tmp;
|
yyerror("RLIMIT '%s %s' < minimum value of 1s\n", $4, $6);
|
||||||
} else if (strstr(minutes, end) == minutes) {
|
else if (tmp < 0LL)
|
||||||
value = tmp * 60;
|
|
||||||
} else if (strstr(hours, end) == hours) {
|
|
||||||
value = tmp * 60 * 60;
|
|
||||||
} else if (strstr(days, end) == days) {
|
|
||||||
value = tmp * 60 * 60 * 24;
|
|
||||||
} else {
|
|
||||||
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
|
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
|
||||||
}
|
if (!$7)
|
||||||
|
pwarn(_("RLIMIT 'cpu' no units specified using default units of seconds\n"));
|
||||||
|
value = tmp;
|
||||||
break;
|
break;
|
||||||
case RLIMIT_RTTIME:
|
case RLIMIT_RTTIME:
|
||||||
/* RTTIME is measured in microseconds */
|
/* RTTIME is measured in microseconds */
|
||||||
if (!end || $6 == end || tmp < 0)
|
if (!end || $6 == end || tmp < 0)
|
||||||
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
|
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7 ? $7 : "");
|
||||||
if (*end == '\0') {
|
tmp = convert_time_units(tmp, 1LL, $7);
|
||||||
|
if (tmp < 0LL)
|
||||||
|
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7 ? $7 : "");
|
||||||
|
if (!$7)
|
||||||
|
pwarn(_("RLIMIT 'rttime' no units specified using default units of microseconds\n"));
|
||||||
value = tmp;
|
value = tmp;
|
||||||
} else if (strstr(milliseconds, end) == milliseconds) {
|
|
||||||
value = tmp * 1000;
|
|
||||||
} else if (strstr(seconds, end) == seconds) {
|
|
||||||
value = tmp * 1000 * 1000;
|
|
||||||
} else if (strstr(minutes, end) == minutes) {
|
|
||||||
value = tmp * 1000 * 1000 * 60;
|
|
||||||
} else {
|
|
||||||
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case RLIMIT_NOFILE:
|
case RLIMIT_NOFILE:
|
||||||
case RLIMIT_NPROC:
|
case RLIMIT_NPROC:
|
||||||
@@ -915,15 +913,15 @@ rules: rules TOK_SET TOK_RLIMIT TOK_ID TOK_LE TOK_VALUE TOK_END_OF_RULE
|
|||||||
case RLIMIT_SIGPENDING:
|
case RLIMIT_SIGPENDING:
|
||||||
#ifdef RLIMIT_RTPRIO
|
#ifdef RLIMIT_RTPRIO
|
||||||
case RLIMIT_RTPRIO:
|
case RLIMIT_RTPRIO:
|
||||||
if (!end || $6 == end || *end != '\0' || tmp < 0)
|
if (!end || $6 == end || $7 || tmp < 0)
|
||||||
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
|
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7 ? $7 : "");
|
||||||
value = tmp;
|
value = tmp;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
#ifdef RLIMIT_NICE
|
#ifdef RLIMIT_NICE
|
||||||
case RLIMIT_NICE:
|
case RLIMIT_NICE:
|
||||||
if (!end || $6 == end || *end != '\0')
|
if (!end || $6 == end || $7)
|
||||||
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
|
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7 ? $7 : "");
|
||||||
if (tmp < -20 || tmp > 19)
|
if (tmp < -20 || tmp > 19)
|
||||||
yyerror("RLIMIT '%s' out of range (-20 .. 19) %d\n", $4, tmp);
|
yyerror("RLIMIT '%s' out of range (-20 .. 19) %d\n", $4, tmp);
|
||||||
value = tmp + 20;
|
value = tmp + 20;
|
||||||
@@ -938,15 +936,17 @@ rules: rules TOK_SET TOK_RLIMIT TOK_ID TOK_LE TOK_VALUE TOK_END_OF_RULE
|
|||||||
case RLIMIT_MEMLOCK:
|
case RLIMIT_MEMLOCK:
|
||||||
case RLIMIT_MSGQUEUE:
|
case RLIMIT_MSGQUEUE:
|
||||||
if ($6 == end || tmp < 0)
|
if ($6 == end || tmp < 0)
|
||||||
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
|
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7 ? $7 : "");
|
||||||
if (strstr(kb, end) == kb) {
|
if (!$7) {
|
||||||
|
; /* use default of bytes */
|
||||||
|
} else if (strstr(kb, $7) == kb) {
|
||||||
tmp *= 1024;
|
tmp *= 1024;
|
||||||
} else if (strstr(mb, end) == mb) {
|
} else if (strstr(mb, $7) == mb) {
|
||||||
tmp *= 1024*1024;
|
tmp *= 1024*1024;
|
||||||
} else if (strstr(gb, end) == gb) {
|
} else if (strstr(gb, $7) == gb) {
|
||||||
tmp *= 1024*1024*1024;
|
tmp *= 1024*1024*1024;
|
||||||
} else if (*end != '\0') {
|
} else {
|
||||||
yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
|
yyerror("RLIMIT '%s' invalid value %s %s\n", $4, $6, $7);
|
||||||
}
|
}
|
||||||
value = tmp;
|
value = tmp;
|
||||||
break;
|
break;
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -25,8 +26,6 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
|
||||||
#include <utime.h>
|
|
||||||
|
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
@@ -166,12 +165,21 @@ void install_cache(const char *cachetmpname, const char *cachename)
|
|||||||
/* Only install the generate cache file if it parsed correctly
|
/* Only install the generate cache file if it parsed correctly
|
||||||
and did not have write/close errors */
|
and did not have write/close errors */
|
||||||
if (cachetmpname) {
|
if (cachetmpname) {
|
||||||
struct timeval t;
|
struct timespec times[2];
|
||||||
|
|
||||||
/* set the mtime of the cache file to the most newest mtime
|
/* set the mtime of the cache file to the most newest mtime
|
||||||
* of policy files used to generate it
|
* of policy files used to generate it
|
||||||
*/
|
*/
|
||||||
TIMESPEC_TO_TIMEVAL(&t, &mru_policy_tstamp);
|
times[0].tv_sec = 0;
|
||||||
utimes(cachetmpname, &t);
|
times[0].tv_nsec = UTIME_OMIT;
|
||||||
|
times[1] = mru_policy_tstamp;
|
||||||
|
if (utimensat(AT_FDCWD, cachetmpname, times, 0) < 0) {
|
||||||
|
PERROR("%s: Failed to set the mtime of cache file '%s': %m\n",
|
||||||
|
progname, cachename);
|
||||||
|
unlink(cachetmpname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (rename(cachetmpname, cachename) < 0) {
|
if (rename(cachetmpname, cachename) < 0) {
|
||||||
pwarn("Warning failed to write cache: %s\n", cachename);
|
pwarn("Warning failed to write cache: %s\n", cachename);
|
||||||
unlink(cachetmpname);
|
unlink(cachetmpname);
|
||||||
|
@@ -94,12 +94,13 @@ aa_log_skipped_msg() {
|
|||||||
echo -e "$rc_skipped"
|
echo -e "$rc_skipped"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_set_status() {
|
||||||
|
return $1
|
||||||
|
}
|
||||||
|
|
||||||
aa_log_end_msg() {
|
aa_log_end_msg() {
|
||||||
v="-v"
|
_set_status $1
|
||||||
if [ "$1" != '0' ]; then
|
rc_status -v
|
||||||
rc="-v$1"
|
|
||||||
fi
|
|
||||||
rc_status $v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
|
@@ -1,8 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# ------------------------------------------------------------------
|
# ------------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Copyright (C) 2013 Canonical Ltd.
|
# Copyright (C) 2013-2015 Canonical Ltd.
|
||||||
# Author: Steve Beattie <steve@nxnw.org>
|
# Authors: Steve Beattie <steve@nxnw.org>
|
||||||
|
# Tyler Hicks <tyhicks@canonical.com>
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or
|
# This program is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of version 2 of the GNU General Public
|
# modify it under the terms of version 2 of the GNU General Public
|
||||||
@@ -12,11 +13,11 @@
|
|||||||
|
|
||||||
# TODO
|
# TODO
|
||||||
# - check cache not used if parser in $PATH is newer
|
# - check cache not used if parser in $PATH is newer
|
||||||
# - check cache used/not used if includes are newer/older
|
|
||||||
# - check cache used for force-complain, disable symlink, etc.
|
# - check cache used for force-complain, disable symlink, etc.
|
||||||
|
|
||||||
from argparse import ArgumentParser
|
from argparse import ArgumentParser
|
||||||
import os
|
import os
|
||||||
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
import time
|
import time
|
||||||
import tempfile
|
import tempfile
|
||||||
@@ -24,19 +25,24 @@ import unittest
|
|||||||
|
|
||||||
import testlib
|
import testlib
|
||||||
|
|
||||||
|
ABSTRACTION_CONTENTS = '''
|
||||||
|
# Simple example abstraction
|
||||||
|
capability setuid,
|
||||||
|
'''
|
||||||
|
ABSTRACTION = 'suid-abstraction'
|
||||||
|
|
||||||
PROFILE_CONTENTS = '''
|
PROFILE_CONTENTS = '''
|
||||||
# Simple example profile for caching tests
|
# Simple example profile for caching tests
|
||||||
|
|
||||||
/bin/pingy {
|
/bin/pingy {
|
||||||
|
#include <%s>
|
||||||
capability net_raw,
|
capability net_raw,
|
||||||
capability setuid,
|
|
||||||
network inet raw,
|
network inet raw,
|
||||||
|
|
||||||
/bin/ping mixr,
|
/bin/ping mixr,
|
||||||
/etc/modules.conf r,
|
/etc/modules.conf r,
|
||||||
}
|
}
|
||||||
'''
|
''' % (ABSTRACTION)
|
||||||
PROFILE = 'sbin.pingy'
|
PROFILE = 'sbin.pingy'
|
||||||
config = None
|
config = None
|
||||||
|
|
||||||
@@ -51,11 +57,6 @@ class AAParserCachingCommon(testlib.AATestTemplate):
|
|||||||
# REPORT ALL THE OUTPUT
|
# REPORT ALL THE OUTPUT
|
||||||
self.maxDiff = None
|
self.maxDiff = None
|
||||||
|
|
||||||
# skip all the things if apparmor securityfs isn't mounted
|
|
||||||
if not os.path.exists("/sys/kernel/security/apparmor"):
|
|
||||||
raise unittest.SkipTest("WARNING: /sys/kernel/security/apparmor does not exist. "
|
|
||||||
"Skipping tests")
|
|
||||||
|
|
||||||
self.tmp_dir = tempfile.mkdtemp(prefix='aa-caching-')
|
self.tmp_dir = tempfile.mkdtemp(prefix='aa-caching-')
|
||||||
os.chmod(self.tmp_dir, 0o755)
|
os.chmod(self.tmp_dir, 0o755)
|
||||||
|
|
||||||
@@ -63,7 +64,11 @@ class AAParserCachingCommon(testlib.AATestTemplate):
|
|||||||
self.cache_dir = os.path.join(self.tmp_dir, 'cache')
|
self.cache_dir = os.path.join(self.tmp_dir, 'cache')
|
||||||
os.mkdir(self.cache_dir)
|
os.mkdir(self.cache_dir)
|
||||||
|
|
||||||
# write our sample profile out
|
# default path of the output cache file
|
||||||
|
self.cache_file = os.path.join(self.cache_dir, PROFILE)
|
||||||
|
|
||||||
|
# write our sample abstraction and profile out
|
||||||
|
self.abstraction = testlib.write_file(self.tmp_dir, ABSTRACTION, ABSTRACTION_CONTENTS)
|
||||||
self.profile = testlib.write_file(self.tmp_dir, PROFILE, PROFILE_CONTENTS)
|
self.profile = testlib.write_file(self.tmp_dir, PROFILE, PROFILE_CONTENTS)
|
||||||
|
|
||||||
if config.debug:
|
if config.debug:
|
||||||
@@ -72,6 +77,9 @@ class AAParserCachingCommon(testlib.AATestTemplate):
|
|||||||
|
|
||||||
self.cmd_prefix = [config.parser, '--base', self.tmp_dir, '--skip-kernel-load']
|
self.cmd_prefix = [config.parser, '--base', self.tmp_dir, '--skip-kernel-load']
|
||||||
|
|
||||||
|
if not self.is_apparmorfs_mounted():
|
||||||
|
self.cmd_prefix += ['-M', './features_files/features.all']
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
'''teardown for each test'''
|
'''teardown for each test'''
|
||||||
|
|
||||||
@@ -89,7 +97,17 @@ class AAParserCachingCommon(testlib.AATestTemplate):
|
|||||||
self.assertFalse(os.path.exists(path),
|
self.assertFalse(os.path.exists(path),
|
||||||
'test created file %s, when it was not expected to do so' % path)
|
'test created file %s, when it was not expected to do so' % path)
|
||||||
|
|
||||||
|
def is_apparmorfs_mounted(self):
|
||||||
|
return os.path.exists("/sys/kernel/security/apparmor")
|
||||||
|
|
||||||
|
def require_apparmorfs(self):
|
||||||
|
# skip the test if apparmor securityfs isn't mounted
|
||||||
|
if not self.is_apparmorfs_mounted():
|
||||||
|
raise unittest.SkipTest("WARNING: /sys/kernel/security/apparmor does not exist. Skipping test.")
|
||||||
|
|
||||||
def compare_features_file(self, features_path, expected=True):
|
def compare_features_file(self, features_path, expected=True):
|
||||||
|
# tests that need this function should call require_apparmorfs() early
|
||||||
|
|
||||||
# compare features contents
|
# compare features contents
|
||||||
expected_output = testlib.read_features_dir('/sys/kernel/security/apparmor/features')
|
expected_output = testlib.read_features_dir('/sys/kernel/security/apparmor/features')
|
||||||
with open(features_path) as f:
|
with open(features_path) as f:
|
||||||
@@ -143,6 +161,8 @@ class AAParserBasicCachingTests(AAParserCachingCommon):
|
|||||||
def test_features_match_when_caching(self):
|
def test_features_match_when_caching(self):
|
||||||
'''test features file is written when caching'''
|
'''test features file is written when caching'''
|
||||||
|
|
||||||
|
self.require_apparmorfs()
|
||||||
|
|
||||||
cmd = list(self.cmd_prefix)
|
cmd = list(self.cmd_prefix)
|
||||||
cmd.extend(['-q', '--write-cache', '-r', self.profile])
|
cmd.extend(['-q', '--write-cache', '-r', self.profile])
|
||||||
self.run_cmd_check(cmd)
|
self.run_cmd_check(cmd)
|
||||||
@@ -203,21 +223,34 @@ class AAParserCachingTests(AAParserCachingCommon):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(AAParserCachingTests, self).setUp()
|
super(AAParserCachingTests, self).setUp()
|
||||||
|
|
||||||
# need separation of length timeout between generating profile
|
|
||||||
# and generating cache entry, as the parser distinguishes
|
|
||||||
# between ctime, not mtime.
|
|
||||||
if not 'timeout' in dir(config):
|
|
||||||
r = testlib.filesystem_time_resolution()
|
r = testlib.filesystem_time_resolution()
|
||||||
config.timeout = r[1]
|
self.mtime_res = r[1]
|
||||||
|
|
||||||
time.sleep(config.timeout)
|
|
||||||
|
|
||||||
def _generate_cache_file(self):
|
def _generate_cache_file(self):
|
||||||
|
|
||||||
cmd = list(self.cmd_prefix)
|
cmd = list(self.cmd_prefix)
|
||||||
cmd.extend(['-q', '--write-cache', '-r', self.profile])
|
cmd.extend(['-q', '--write-cache', '-r', self.profile])
|
||||||
self.run_cmd_check(cmd)
|
self.run_cmd_check(cmd)
|
||||||
self.assert_path_exists(os.path.join(self.cache_dir, PROFILE))
|
self.assert_path_exists(self.cache_file)
|
||||||
|
|
||||||
|
def _assertTimeStampEquals(self, time1, time2):
|
||||||
|
'''Compare two timestamps to ensure equality'''
|
||||||
|
|
||||||
|
# python 3.2 and earlier don't support writing timestamps with
|
||||||
|
# nanosecond resolution, only microsecond. When comparing
|
||||||
|
# timestamps in such an environment, loosen the equality bounds
|
||||||
|
# to compensate
|
||||||
|
# Reference: https://bugs.python.org/issue12904
|
||||||
|
(major, minor, _) = platform.python_version_tuple()
|
||||||
|
if (int(major) < 3) or ((int(major) == 3) and (int(minor) <= 2)):
|
||||||
|
self.assertAlmostEquals(time1, time2, places=5)
|
||||||
|
else:
|
||||||
|
self.assertEquals(time1, time2)
|
||||||
|
|
||||||
|
def _set_mtime(self, path, mtime):
|
||||||
|
atime = os.stat(path).st_atime
|
||||||
|
os.utime(path, (atime, mtime))
|
||||||
|
self._assertTimeStampEquals(os.stat(path).st_mtime, mtime)
|
||||||
|
|
||||||
def test_cache_loaded_when_exists(self):
|
def test_cache_loaded_when_exists(self):
|
||||||
'''test cache is loaded when it exists, is newer than profile, and features match'''
|
'''test cache is loaded when it exists, is newer than profile, and features match'''
|
||||||
@@ -260,6 +293,8 @@ class AAParserCachingTests(AAParserCachingCommon):
|
|||||||
def test_cache_writing_does_not_overwrite_features_when_features_differ(self):
|
def test_cache_writing_does_not_overwrite_features_when_features_differ(self):
|
||||||
'''test cache writing does not overwrite the features files when it differs and --skip-bad-cache is given'''
|
'''test cache writing does not overwrite the features files when it differs and --skip-bad-cache is given'''
|
||||||
|
|
||||||
|
self.require_apparmorfs()
|
||||||
|
|
||||||
features_file = testlib.write_file(self.cache_dir, '.features', 'monkey\n')
|
features_file = testlib.write_file(self.cache_dir, '.features', 'monkey\n')
|
||||||
|
|
||||||
cmd = list(self.cmd_prefix)
|
cmd = list(self.cmd_prefix)
|
||||||
@@ -277,11 +312,13 @@ class AAParserCachingTests(AAParserCachingCommon):
|
|||||||
cmd = list(self.cmd_prefix)
|
cmd = list(self.cmd_prefix)
|
||||||
cmd.extend(['-v', '--write-cache', '--skip-bad-cache', '-r', self.profile])
|
cmd.extend(['-v', '--write-cache', '--skip-bad-cache', '-r', self.profile])
|
||||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||||
self.assert_path_exists(os.path.join(self.cache_dir, PROFILE), expected=False)
|
self.assert_path_exists(self.cache_file, expected=False)
|
||||||
|
|
||||||
def test_cache_writing_updates_features(self):
|
def test_cache_writing_updates_features(self):
|
||||||
'''test cache writing updates features'''
|
'''test cache writing updates features'''
|
||||||
|
|
||||||
|
self.require_apparmorfs()
|
||||||
|
|
||||||
features_file = testlib.write_file(self.cache_dir, '.features', 'monkey\n')
|
features_file = testlib.write_file(self.cache_dir, '.features', 'monkey\n')
|
||||||
|
|
||||||
cmd = list(self.cmd_prefix)
|
cmd = list(self.cmd_prefix)
|
||||||
@@ -294,18 +331,18 @@ class AAParserCachingTests(AAParserCachingCommon):
|
|||||||
'''test cache writing updates cache file'''
|
'''test cache writing updates cache file'''
|
||||||
|
|
||||||
cache_file = testlib.write_file(self.cache_dir, PROFILE, 'monkey\n')
|
cache_file = testlib.write_file(self.cache_dir, PROFILE, 'monkey\n')
|
||||||
orig_size = os.stat(cache_file).st_size
|
orig_stat = os.stat(cache_file)
|
||||||
|
|
||||||
cmd = list(self.cmd_prefix)
|
cmd = list(self.cmd_prefix)
|
||||||
cmd.extend(['-v', '--write-cache', '-r', self.profile])
|
cmd.extend(['-v', '--write-cache', '-r', self.profile])
|
||||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||||
self.assert_path_exists(cache_file)
|
self.assert_path_exists(cache_file)
|
||||||
with open(cache_file, 'rb') as f:
|
stat = os.stat(cache_file)
|
||||||
new_size = os.fstat(f.fileno()).st_size
|
|
||||||
# We check sizes here rather than whether the string monkey is
|
# We check sizes here rather than whether the string monkey is
|
||||||
# in cache_contents because of the difficulty coercing cache
|
# in cache_contents because of the difficulty coercing cache
|
||||||
# file bytes into strings in python3
|
# file bytes into strings in python3
|
||||||
self.assertNotEquals(orig_size, new_size, 'Expected cache file to be updated, size is not changed.')
|
self.assertNotEquals(orig_stat.st_size, stat.st_size, 'Expected cache file to be updated, size is not changed.')
|
||||||
|
self.assertEquals(os.stat(self.profile).st_mtime, stat.st_mtime)
|
||||||
|
|
||||||
def test_cache_writing_clears_all_files(self):
|
def test_cache_writing_clears_all_files(self):
|
||||||
'''test cache writing clears all cache files'''
|
'''test cache writing clears all cache files'''
|
||||||
@@ -317,27 +354,110 @@ class AAParserCachingTests(AAParserCachingCommon):
|
|||||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||||
self.assert_path_exists(check_file, expected=False)
|
self.assert_path_exists(check_file, expected=False)
|
||||||
|
|
||||||
|
def test_profile_mtime_preserved(self):
|
||||||
|
'''test profile mtime is preserved when it is newest'''
|
||||||
|
expected = 1
|
||||||
|
self._set_mtime(self.abstraction, 0)
|
||||||
|
self._set_mtime(self.profile, expected)
|
||||||
|
self._generate_cache_file()
|
||||||
|
self.assertEquals(expected, os.stat(self.cache_file).st_mtime)
|
||||||
|
|
||||||
|
def test_abstraction_mtime_preserved(self):
|
||||||
|
'''test abstraction mtime is preserved when it is newest'''
|
||||||
|
expected = 1000
|
||||||
|
self._set_mtime(self.profile, 0)
|
||||||
|
self._set_mtime(self.abstraction, expected)
|
||||||
|
self._generate_cache_file()
|
||||||
|
self.assertEquals(expected, os.stat(self.cache_file).st_mtime)
|
||||||
|
|
||||||
|
def test_equal_mtimes_preserved(self):
|
||||||
|
'''test equal profile and abstraction mtimes are preserved'''
|
||||||
|
expected = 10000 + self.mtime_res
|
||||||
|
self._set_mtime(self.profile, expected)
|
||||||
|
self._set_mtime(self.abstraction, expected)
|
||||||
|
self._generate_cache_file()
|
||||||
|
self.assertEquals(expected, os.stat(self.cache_file).st_mtime)
|
||||||
|
|
||||||
def test_profile_newer_skips_cache(self):
|
def test_profile_newer_skips_cache(self):
|
||||||
'''test cache is skipped if profile is newer'''
|
'''test cache is skipped if profile is newer'''
|
||||||
|
|
||||||
self._generate_cache_file()
|
self._generate_cache_file()
|
||||||
time.sleep(config.timeout)
|
profile_mtime = os.stat(self.cache_file).st_mtime + self.mtime_res
|
||||||
testlib.touch(self.profile)
|
self._set_mtime(self.profile, profile_mtime)
|
||||||
|
|
||||||
|
orig_stat = os.stat(self.cache_file)
|
||||||
|
|
||||||
cmd = list(self.cmd_prefix)
|
cmd = list(self.cmd_prefix)
|
||||||
cmd.extend(['-v', '-r', self.profile])
|
cmd.extend(['-v', '-r', self.profile])
|
||||||
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||||
|
|
||||||
|
stat = os.stat(self.cache_file)
|
||||||
|
self.assertEquals(orig_stat.st_size, stat.st_size)
|
||||||
|
self.assertEquals(orig_stat.st_ino, stat.st_ino)
|
||||||
|
self.assertEquals(orig_stat.st_mtime, stat.st_mtime)
|
||||||
|
|
||||||
|
def test_abstraction_newer_skips_cache(self):
|
||||||
|
'''test cache is skipped if abstraction is newer'''
|
||||||
|
|
||||||
|
self._generate_cache_file()
|
||||||
|
abstraction_mtime = os.stat(self.cache_file).st_mtime + self.mtime_res
|
||||||
|
self._set_mtime(self.abstraction, abstraction_mtime)
|
||||||
|
|
||||||
|
orig_stat = os.stat(self.cache_file)
|
||||||
|
|
||||||
|
cmd = list(self.cmd_prefix)
|
||||||
|
cmd.extend(['-v', '-r', self.profile])
|
||||||
|
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||||
|
|
||||||
|
stat = os.stat(self.cache_file)
|
||||||
|
self.assertEquals(orig_stat.st_size, stat.st_size)
|
||||||
|
self.assertEquals(orig_stat.st_ino, stat.st_ino)
|
||||||
|
self.assertEquals(orig_stat.st_mtime, stat.st_mtime)
|
||||||
|
|
||||||
|
def test_profile_newer_rewrites_cache(self):
|
||||||
|
'''test cache is rewritten if profile is newer'''
|
||||||
|
|
||||||
|
self._generate_cache_file()
|
||||||
|
profile_mtime = os.stat(self.cache_file).st_mtime + self.mtime_res
|
||||||
|
self._set_mtime(self.profile, profile_mtime)
|
||||||
|
|
||||||
|
orig_stat = os.stat(self.cache_file)
|
||||||
|
|
||||||
|
cmd = list(self.cmd_prefix)
|
||||||
|
cmd.extend(['-v', '-r', '-W', self.profile])
|
||||||
|
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||||
|
|
||||||
|
stat = os.stat(self.cache_file)
|
||||||
|
self.assertNotEquals(orig_stat.st_ino, stat.st_ino)
|
||||||
|
self._assertTimeStampEquals(profile_mtime, stat.st_mtime)
|
||||||
|
|
||||||
|
def test_abstraction_newer_rewrites_cache(self):
|
||||||
|
'''test cache is rewritten if abstraction is newer'''
|
||||||
|
|
||||||
|
self._generate_cache_file()
|
||||||
|
abstraction_mtime = os.stat(self.cache_file).st_mtime + self.mtime_res
|
||||||
|
self._set_mtime(self.abstraction, abstraction_mtime)
|
||||||
|
|
||||||
|
orig_stat = os.stat(self.cache_file)
|
||||||
|
|
||||||
|
cmd = list(self.cmd_prefix)
|
||||||
|
cmd.extend(['-v', '-r', '-W', self.profile])
|
||||||
|
self.run_cmd_check(cmd, expected_string='Replacement succeeded for')
|
||||||
|
|
||||||
|
stat = os.stat(self.cache_file)
|
||||||
|
self.assertNotEquals(orig_stat.st_ino, stat.st_ino)
|
||||||
|
self._assertTimeStampEquals(abstraction_mtime, stat.st_mtime)
|
||||||
|
|
||||||
def test_parser_newer_uses_cache(self):
|
def test_parser_newer_uses_cache(self):
|
||||||
'''test cache is not skipped if parser is newer'''
|
'''test cache is not skipped if parser is newer'''
|
||||||
|
|
||||||
self._generate_cache_file()
|
self._generate_cache_file()
|
||||||
time.sleep(config.timeout)
|
|
||||||
|
|
||||||
# copy parser
|
# copy parser
|
||||||
os.mkdir(os.path.join(self.tmp_dir, 'parser'))
|
os.mkdir(os.path.join(self.tmp_dir, 'parser'))
|
||||||
new_parser = os.path.join(self.tmp_dir, 'parser', 'apparmor_parser')
|
new_parser = os.path.join(self.tmp_dir, 'parser', 'apparmor_parser')
|
||||||
shutil.copy(config.parser, new_parser)
|
shutil.copy(config.parser, new_parser)
|
||||||
|
self._set_mtime(new_parser, os.stat(self.cache_file).st_mtime + self.mtime_res)
|
||||||
|
|
||||||
cmd = list(self.cmd_prefix)
|
cmd = list(self.cmd_prefix)
|
||||||
cmd[0] = new_parser
|
cmd[0] = new_parser
|
||||||
@@ -379,6 +499,7 @@ class AAParserAltCacheTests(AAParserCachingTests):
|
|||||||
|
|
||||||
self.orig_cache_dir = self.cache_dir
|
self.orig_cache_dir = self.cache_dir
|
||||||
self.cache_dir = alt_cache_dir
|
self.cache_dir = alt_cache_dir
|
||||||
|
self.cache_file = os.path.join(self.cache_dir, PROFILE)
|
||||||
self.cmd_prefix.extend(['--cache-loc', alt_cache_dir])
|
self.cmd_prefix.extend(['--cache-loc', alt_cache_dir])
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
@@ -464,6 +464,77 @@ verify_binary_equality "change_profile == change_profile -> **" \
|
|||||||
"/t { change_profile /**, }" \
|
"/t { change_profile /**, }" \
|
||||||
"/t { change_profile /** -> **, }"
|
"/t { change_profile /** -> **, }"
|
||||||
|
|
||||||
|
verify_binary_equality "profile name is hname in rule" \
|
||||||
|
":ns:/hname { signal peer=/hname, }" \
|
||||||
|
":ns:/hname { signal peer=@{profile_name}, }"
|
||||||
|
|
||||||
|
verify_binary_inequality "profile name is NOT fq name in rule" \
|
||||||
|
":ns:/hname { signal peer=:ns:/hname, }" \
|
||||||
|
":ns:/hname { signal peer=@{profile_name}, }"
|
||||||
|
|
||||||
|
verify_binary_equality "profile name is hname in sub pofile rule" \
|
||||||
|
":ns:/hname { profile child { signal peer=/hname//child, } }" \
|
||||||
|
":ns:/hname { profile child { signal peer=@{profile_name}, } }"
|
||||||
|
|
||||||
|
verify_binary_inequality "profile name is NOT fq name in sub profile rule" \
|
||||||
|
":ns:/hname { profile child { signal peer=:ns:/hname//child, } }" \
|
||||||
|
":ns:/hname { profile child { signal peer=@{profile_name}, } }"
|
||||||
|
|
||||||
|
verify_binary_equality "profile name is hname in hat rule" \
|
||||||
|
":ns:/hname { ^child { signal peer=/hname//child, } }" \
|
||||||
|
":ns:/hname { ^child { signal peer=@{profile_name}, } }"
|
||||||
|
|
||||||
|
verify_binary_inequality "profile name is NOT fq name in hat rule" \
|
||||||
|
":ns:/hname { ^child { signal peer=:ns:/hname//child, } }" \
|
||||||
|
":ns:/hname { ^child { signal peer=@{profile_name}, } }"
|
||||||
|
|
||||||
|
verify_binary_equality "@{profile_name} is literal in peer" \
|
||||||
|
"/{a,b} { signal peer=/\{a,b\}, }" \
|
||||||
|
"/{a,b} { signal peer=@{profile_name}, }"
|
||||||
|
|
||||||
|
verify_binary_equality "@{profile_name} is literal in peer with pattern" \
|
||||||
|
"/{a,b} { signal peer={/\{a,b\},c}, }" \
|
||||||
|
"/{a,b} { signal peer={@{profile_name},c}, }"
|
||||||
|
|
||||||
|
verify_binary_inequality "@{profile_name} is not pattern in peer" \
|
||||||
|
"/{a,b} { signal peer=/{a,b}, }" \
|
||||||
|
"/{a,b} { signal peer=@{profile_name}, }"
|
||||||
|
|
||||||
|
verify_binary_equality "@{profile_name} is literal in peer with esc sequence" \
|
||||||
|
"/\\\\a { signal peer=/\\\\a, }" \
|
||||||
|
"/\\\\a { signal peer=@{profile_name}, }"
|
||||||
|
|
||||||
|
verify_binary_equality "@{profile_name} is literal in peer with esc alt sequence" \
|
||||||
|
"/\\{a,b\\},c { signal peer=/\\{a,b\\},c, }" \
|
||||||
|
"/\\{a,b\\},c { signal peer=@{profile_name}, }"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# verify rlimit data conversions
|
||||||
|
verify_binary_equality "set rlimit rttime <= 12 weeks" \
|
||||||
|
"/t { set rlimit rttime <= 12 weeks, }" \
|
||||||
|
"/t { set rlimit rttime <= $((12 * 7)) days, }" \
|
||||||
|
"/t { set rlimit rttime <= $((12 * 7 * 24)) hours, }" \
|
||||||
|
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60)) minutes, }" \
|
||||||
|
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60)) seconds, }" \
|
||||||
|
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000)) ms, }" \
|
||||||
|
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)) us, }" \
|
||||||
|
"/t { set rlimit rttime <= $((12 * 7 * 24 * 60 * 60 * 1000 * 1000)), }"
|
||||||
|
|
||||||
|
verify_binary_equality "set rlimit cpu <= 42 weeks" \
|
||||||
|
"/t { set rlimit cpu <= 42 weeks, }" \
|
||||||
|
"/t { set rlimit cpu <= $((42 * 7)) days, }" \
|
||||||
|
"/t { set rlimit cpu <= $((42 * 7 * 24)) hours, }" \
|
||||||
|
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60)) minutes, }" \
|
||||||
|
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)) seconds, }" \
|
||||||
|
"/t { set rlimit cpu <= $((42 * 7 * 24 * 60 * 60)), }"
|
||||||
|
|
||||||
|
verify_binary_equality "set rlimit memlock <= 2GB" \
|
||||||
|
"/t { set rlimit memlock <= 2GB, }" \
|
||||||
|
"/t { set rlimit memlock <= $((2 * 1024)) MB, }" \
|
||||||
|
"/t { set rlimit memlock <= $((2 * 1024 * 1024)) KB, }" \
|
||||||
|
"/t { set rlimit memlock <= $((2 * 1024 * 1024 * 1024)) , }" \
|
||||||
|
|
||||||
if [ $fails -ne 0 -o $errors -ne 0 ]
|
if [ $fails -ne 0 -o $errors -ne 0 ]
|
||||||
then
|
then
|
||||||
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1
|
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1
|
||||||
|
7
parser/tst/simple_tests/bare_include_tests/bad_1.sd
Normal file
7
parser/tst/simple_tests/bare_include_tests/bad_1.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION includes testing - non-existent include should fail
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/does/not/exist {
|
||||||
|
include <does-not-exist/does-not-exist>
|
||||||
|
}
|
7
parser/tst/simple_tests/bare_include_tests/bad_2.sd
Normal file
7
parser/tst/simple_tests/bare_include_tests/bad_2.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION includes testing - mis-parsing include should fail
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/does/not/exist {
|
||||||
|
include does-not-exist/does-not-exist
|
||||||
|
}
|
8
parser/tst/simple_tests/bare_include_tests/bad_3.sd
Normal file
8
parser/tst/simple_tests/bare_include_tests/bad_3.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION includes testing - non-existent include should fail
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/does/not/exist {
|
||||||
|
include <does-not-exist/does-not-exist>
|
||||||
|
include <includes/base>
|
||||||
|
}
|
8
parser/tst/simple_tests/bare_include_tests/bad_4.sd
Normal file
8
parser/tst/simple_tests/bare_include_tests/bad_4.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION includes testing - non-existent include should fail
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/does/not/exist {
|
||||||
|
include <includes/base>
|
||||||
|
include <does-not-exist/does-not-exist>
|
||||||
|
}
|
@@ -0,0 +1 @@
|
|||||||
|
THIS WILL NOT PARSE!
|
@@ -0,0 +1 @@
|
|||||||
|
THIS WILL NOT PARSE!
|
@@ -0,0 +1 @@
|
|||||||
|
THIS WILL NOT PARSE!
|
@@ -0,0 +1 @@
|
|||||||
|
THIS WILL NOT PARSE!
|
@@ -0,0 +1 @@
|
|||||||
|
THIS WILL NOT PARSE!
|
@@ -0,0 +1 @@
|
|||||||
|
THIS WILL NOT PARSE!
|
@@ -0,0 +1 @@
|
|||||||
|
THIS WILL NOT PARSE!
|
@@ -0,0 +1,6 @@
|
|||||||
|
#=DESCRIPTION Valid include
|
||||||
|
#
|
||||||
|
# if parsed stand-alone,
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO} = /foo /bar
|
@@ -0,0 +1,10 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION includes testing - verify that ignored suffixes are ignored
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
|
||||||
|
include <include_tests/ignored_suffix>
|
||||||
|
|
||||||
|
/does/not/exist {
|
||||||
|
@{FOO} r,
|
||||||
|
}
|
@@ -0,0 +1,10 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION includes testing - verify that only suffixes are ignored
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
|
||||||
|
include <include_tests/ignored_suffix_2>
|
||||||
|
|
||||||
|
/does/not/exist {
|
||||||
|
@{FOO} r,
|
||||||
|
}
|
@@ -0,0 +1,6 @@
|
|||||||
|
#=DESCRIPTION Valid include
|
||||||
|
#
|
||||||
|
# if parsed stand-alone,
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO} = /foo /bar
|
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION A helper for includes_okay.sd
|
||||||
|
#
|
||||||
|
# if parsed standalone,
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
include <includes/fonts>
|
||||||
|
|
||||||
|
/tmp/** r,
|
9
parser/tst/simple_tests/bare_include_tests/ok_1.sd
Normal file
9
parser/tst/simple_tests/bare_include_tests/ok_1.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION includes testing - basic include of global and local include
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
/does/not/exist {
|
||||||
|
#include <includes/base>
|
||||||
|
#include <include_tests/includes_okay_helper.include>
|
||||||
|
#include <includes/base>
|
||||||
|
}
|
8
parser/tst/simple_tests/bare_include_tests/ok_2.sd
Normal file
8
parser/tst/simple_tests/bare_include_tests/ok_2.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION includes testing - test some "odd" locations of includes
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
/does/not/exist {
|
||||||
|
/does/not/exist mr, #include <includes/base> /bin/true Px,
|
||||||
|
include <include_tests/includes_okay_helper.include> #include <includes/base>
|
||||||
|
}
|
9
parser/tst/simple_tests/bare_include_tests/ok_3.sd
Normal file
9
parser/tst/simple_tests/bare_include_tests/ok_3.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION includes testing - basic include of a directory
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
/does/not/exist {
|
||||||
|
include <includes/base>
|
||||||
|
include <includes/>
|
||||||
|
include <includes/base>
|
||||||
|
}
|
7
parser/tst/simple_tests/bare_include_tests/recursive.sd
Normal file
7
parser/tst/simple_tests/bare_include_tests/recursive.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION includes testing - recursive include should fail
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/does/not/exist {
|
||||||
|
include <include_tests/recursive.sd>
|
||||||
|
}
|
7
parser/tst/simple_tests/capability/bad_outside1.sd
Normal file
7
parser/tst/simple_tests/capability/bad_outside1.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION capability rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
|
||||||
|
capability,
|
||||||
|
|
7
parser/tst/simple_tests/change_profile/bad_outside_1.sd
Normal file
7
parser/tst/simple_tests/change_profile/bad_outside_1.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION change_profile rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
|
||||||
|
change_profile -> /bin/foo,
|
||||||
|
|
5
parser/tst/simple_tests/dbus/bad_outside_1.sd
Normal file
5
parser/tst/simple_tests/dbus/bad_outside_1.sd
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION dbus rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
|
||||||
|
dbus name=(SomeService),
|
7
parser/tst/simple_tests/dbus/ok_bind_2.sd
Normal file
7
parser/tst/simple_tests/dbus/ok_bind_2.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION simple dbus implicit bind acceptance test with deny keyword
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
profile a_profile {
|
||||||
|
deny dbus name=(SomeService),
|
||||||
|
}
|
7
parser/tst/simple_tests/file/bad_bare_file_outside.sd
Normal file
7
parser/tst/simple_tests/file/bad_bare_file_outside.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION bare file rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
|
||||||
|
file,
|
||||||
|
|
7
parser/tst/simple_tests/file/bad_link_outside.sd
Normal file
7
parser/tst/simple_tests/file/bad_link_outside.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION link rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
|
||||||
|
deny link /alpha/beta -> /tmp/**,
|
||||||
|
|
7
parser/tst/simple_tests/file/ok_bare_1.sd
Normal file
7
parser/tst/simple_tests/file/ok_bare_1.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description bare file rule
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
deny file,
|
||||||
|
}
|
6
parser/tst/simple_tests/mount/bad_outside_1.sd
Normal file
6
parser/tst/simple_tests/mount/bad_outside_1.sd
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#
|
||||||
|
#=Description mount rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
|
||||||
|
mount,
|
7
parser/tst/simple_tests/network/bad_network_outside_1.sd
Normal file
7
parser/tst/simple_tests/network/bad_network_outside_1.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION network rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
|
||||||
|
network,
|
||||||
|
|
7
parser/tst/simple_tests/ptrace/bad_outside_01.sd
Normal file
7
parser/tst/simple_tests/ptrace/bad_outside_01.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description ptrace all rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
|
||||||
|
ptrace,
|
||||||
|
|
7
parser/tst/simple_tests/rlimits/bad_rlimit_01.sd
Normal file
7
parser/tst/simple_tests/rlimits/bad_rlimit_01.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION realtime time rlimit test with ambiguous unit 'm' which could mean 'ms' or 'minutes'
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
|
||||||
|
profile rlimit {
|
||||||
|
set rlimit rttime <= 60m,
|
||||||
|
}
|
5
parser/tst/simple_tests/rlimits/bad_rlimit_outside_01.sd
Normal file
5
parser/tst/simple_tests/rlimits/bad_rlimit_outside_01.sd
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION simple cpu rlimit rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
|
||||||
|
set rlimit cpu <= 1024,
|
@@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
#=DESCRIPTION simple cpu rlimit test
|
#=DESCRIPTION simple cpu rlimit test, cpu allows default units
|
||||||
#=EXRESULT PASS
|
#=EXRESULT PASS
|
||||||
|
|
||||||
profile rlimit {
|
profile rlimit {
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
#=DESCRIPTION simple cpu rlimit test
|
#=DESCRIPTION simple rttime rlimit allows default units
|
||||||
#=EXRESULT PASS
|
#=EXRESULT PASS
|
||||||
|
|
||||||
profile rlimit {
|
profile rlimit {
|
||||||
set rlimit cpu <= 12,
|
set rlimit rttime <= 12,
|
||||||
}
|
}
|
||||||
|
7
parser/tst/simple_tests/signal/bad_outside_01.sd
Normal file
7
parser/tst/simple_tests/signal/bad_outside_01.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#
|
||||||
|
#=Description signal rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
|
||||||
|
signal,
|
||||||
|
|
5
parser/tst/simple_tests/unix/bad_outside_1.sd
Normal file
5
parser/tst/simple_tests/unix/bad_outside_1.sd
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION unix accept rule outside of a profile
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
|
||||||
|
unix accept,
|
8
parser/tst/simple_tests/vars/vars_profile_name_01.sd
Normal file
8
parser/tst/simple_tests/vars/vars_profile_name_01.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#=DESCRIPTION reference variables in rules that also have alternations
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
|
||||||
|
/does/not/exist@{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
8
parser/tst/simple_tests/vars/vars_profile_name_02.sd
Normal file
8
parser/tst/simple_tests/vars/vars_profile_name_02.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#=DESCRIPTION reference variables in rules that also have alternations
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar baz
|
||||||
|
|
||||||
|
/does/not/exist@{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
8
parser/tst/simple_tests/vars/vars_profile_name_03.sd
Normal file
8
parser/tst/simple_tests/vars/vars_profile_name_03.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#=DESCRIPTION profiles declared with the profile keyword can begin with var
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
|
||||||
|
profile @{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
8
parser/tst/simple_tests/vars/vars_profile_name_04.sd
Normal file
8
parser/tst/simple_tests/vars/vars_profile_name_04.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#=DESCRIPTION profiles declared with the profile keyword can begin with var
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar baz
|
||||||
|
|
||||||
|
profile @{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
8
parser/tst/simple_tests/vars/vars_profile_name_05.sd
Normal file
8
parser/tst/simple_tests/vars/vars_profile_name_05.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#=DESCRIPTION reference variables in rules that also have alternations
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
|
||||||
|
profile /does/not /exist{@{FOO},} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
8
parser/tst/simple_tests/vars/vars_profile_name_06.sd
Normal file
8
parser/tst/simple_tests/vars/vars_profile_name_06.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#=DESCRIPTION reference variables in rules that also have alternations
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar baz
|
||||||
|
|
||||||
|
profile /does/not /exist@{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
10
parser/tst/simple_tests/vars/vars_profile_name_07.sd
Normal file
10
parser/tst/simple_tests/vars/vars_profile_name_07.sd
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#=DESCRIPTION profiles declared with the profile keyword can begin with var
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#=TODO
|
||||||
|
# This test needs check on @{FOO} attachment having leading / post var expansion
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
|
||||||
|
profile /does/not/exist @{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
10
parser/tst/simple_tests/vars/vars_profile_name_08.sd
Normal file
10
parser/tst/simple_tests/vars/vars_profile_name_08.sd
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#=DESCRIPTION profiles declared with the profile keyword can begin with var
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#=TODO
|
||||||
|
# This test needs check on @{FOO} attachment having leading / post var expansion
|
||||||
|
|
||||||
|
@{FOO}=bar baz
|
||||||
|
|
||||||
|
profile /does/not/exist @{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
9
parser/tst/simple_tests/vars/vars_profile_name_09.sd
Normal file
9
parser/tst/simple_tests/vars/vars_profile_name_09.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#=DESCRIPTION reference variables in name and attachment
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
@{BAR}=baz
|
||||||
|
|
||||||
|
profile /does/not@{BAR} /exist@{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
9
parser/tst/simple_tests/vars/vars_profile_name_10.sd
Normal file
9
parser/tst/simple_tests/vars/vars_profile_name_10.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#=DESCRIPTION reference variables in rules that also have alternations
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar baz
|
||||||
|
@{BAR}=baz
|
||||||
|
|
||||||
|
profile /does/not@{BAR} /exist@{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
9
parser/tst/simple_tests/vars/vars_profile_name_11.sd
Normal file
9
parser/tst/simple_tests/vars/vars_profile_name_11.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#=DESCRIPTION profiles declared with the profile keyword have var and var attachment
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=/bar /baz
|
||||||
|
@{BAR}=baz foo
|
||||||
|
|
||||||
|
profile /does/not/exist@{BAR} @{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
11
parser/tst/simple_tests/vars/vars_profile_name_12.sd
Normal file
11
parser/tst/simple_tests/vars/vars_profile_name_12.sd
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#=DESCRIPTION profiles declared with the profile keyword can expand var and have var attachment
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#=TODO
|
||||||
|
# This test needs check on @{FOO} attachment having leading / post var expansion
|
||||||
|
|
||||||
|
@{FOO}=bar baz
|
||||||
|
@{BAR}=baz foo
|
||||||
|
|
||||||
|
profile /does/not/exist@{BAR} @{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
11
parser/tst/simple_tests/vars/vars_profile_name_13.sd
Normal file
11
parser/tst/simple_tests/vars/vars_profile_name_13.sd
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#=DESCRIPTION reference variables that are the profile name and attachment
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#=TODO
|
||||||
|
# This test needs check on @{FOO} attachment having leading / post var expansion
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
@{BAR}=baz
|
||||||
|
|
||||||
|
profile @{BAR} @{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
11
parser/tst/simple_tests/vars/vars_profile_name_14.sd
Normal file
11
parser/tst/simple_tests/vars/vars_profile_name_14.sd
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#=DESCRIPTION reference variables in rules that also have alternations
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#=TODO
|
||||||
|
# This test needs check on @{FOO} attachment having leading / post var expansion
|
||||||
|
|
||||||
|
@{FOO}=/bar /baz
|
||||||
|
@{BAR}=baz
|
||||||
|
|
||||||
|
profile @{BAR} @{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
11
parser/tst/simple_tests/vars/vars_profile_name_15.sd
Normal file
11
parser/tst/simple_tests/vars/vars_profile_name_15.sd
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#=DESCRIPTION profiles declared with the profile keyword can begin with var
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#=TODO
|
||||||
|
# This test needs check on @{FOO} attachment having leading / post var expansion
|
||||||
|
|
||||||
|
@{FOO}=bar baz
|
||||||
|
@{BAR}=baz foo
|
||||||
|
|
||||||
|
profile @{BAR} @{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
9
parser/tst/simple_tests/vars/vars_profile_name_16.sd
Normal file
9
parser/tst/simple_tests/vars/vars_profile_name_16.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#=DESCRIPTION var in sub profile name
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
|
||||||
|
profile /does/not/exist {
|
||||||
|
profile foo@{FOO} {
|
||||||
|
}
|
||||||
|
}
|
9
parser/tst/simple_tests/vars/vars_profile_name_17.sd
Normal file
9
parser/tst/simple_tests/vars/vars_profile_name_17.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#=DESCRIPTION var in sub profile name
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
|
||||||
|
profile /does/not/exist {
|
||||||
|
profile @{FOO} {
|
||||||
|
}
|
||||||
|
}
|
9
parser/tst/simple_tests/vars/vars_profile_name_18.sd
Normal file
9
parser/tst/simple_tests/vars/vars_profile_name_18.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#=DESCRIPTION var in hat name
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
|
||||||
|
profile /does/not/exist {
|
||||||
|
^foo@{FOO} {
|
||||||
|
}
|
||||||
|
}
|
9
parser/tst/simple_tests/vars/vars_profile_name_19.sd
Normal file
9
parser/tst/simple_tests/vars/vars_profile_name_19.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#=DESCRIPTION var in sub profile name
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
|
||||||
|
profile /does/not/exist {
|
||||||
|
profile @{FOO} {
|
||||||
|
}
|
||||||
|
}
|
9
parser/tst/simple_tests/vars/vars_profile_name_20.sd
Normal file
9
parser/tst/simple_tests/vars/vars_profile_name_20.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#=DESCRIPTION var in sub profile name
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
|
||||||
|
profile /does/not/exist {
|
||||||
|
profile foo@{FOO} {
|
||||||
|
}
|
||||||
|
}
|
9
parser/tst/simple_tests/vars/vars_profile_name_21.sd
Normal file
9
parser/tst/simple_tests/vars/vars_profile_name_21.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#=DESCRIPTION var in hat name
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{FOO}=bar
|
||||||
|
|
||||||
|
profile /does/not/exist {
|
||||||
|
^@{FOO} {
|
||||||
|
}
|
||||||
|
}
|
10
parser/tst/simple_tests/vars/vars_profile_name_22.sd
Normal file
10
parser/tst/simple_tests/vars/vars_profile_name_22.sd
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#=DESCRIPTION all attachment expansions must start with /
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#=TODO
|
||||||
|
# This test needs check on @{FOO} attachment having leading / post var expansion
|
||||||
|
|
||||||
|
@{FOO}=/bar baz
|
||||||
|
|
||||||
|
profile /does/not/exist @{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
7
parser/tst/simple_tests/vars/vars_profile_name_23.sd
Normal file
7
parser/tst/simple_tests/vars/vars_profile_name_23.sd
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
#=DESCRIPTION reference variables in profile name is undefined
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
|
||||||
|
|
||||||
|
/does/not/exist@{FOO} {
|
||||||
|
/does/not/exist r,
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user