mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-02 23:35:37 +00:00
Compare commits
84 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
b37bd8a1aa | ||
|
ead71a306a | ||
|
aa45be1c10 | ||
|
c1c5192532 | ||
|
2b9260f27a | ||
|
4063647a5f | ||
|
b4048cf3de | ||
|
8a475341e8 | ||
|
5ca6986b43 | ||
|
4b58cf3bc4 | ||
|
a373b4ee93 | ||
|
8d5569f20b | ||
|
5390777e45 | ||
|
79240e7ddd | ||
|
494daee246 | ||
|
194cbfa94c | ||
|
9452e1e2af | ||
|
1556f782e3 | ||
|
7d1ff607fe | ||
|
242ece320a | ||
|
dc1d8e5253 | ||
|
0ac23ee34a | ||
|
5bc15cda41 | ||
|
9ebb1913bd | ||
|
720f6624e6 | ||
|
387de4458f | ||
|
38a69f5ebc | ||
|
7d84c61b6c | ||
|
f836ebd42b | ||
|
52b6aeb04c | ||
|
475a9bc691 | ||
|
0f7bf53afb | ||
|
8dcd54e365 | ||
|
097eb4258f | ||
|
9bc15eb6b8 | ||
|
9d6f7f53cb | ||
|
c1ae887576 | ||
|
0ec6ce96d2 | ||
|
8c19eb5521 | ||
|
21a41deabe | ||
|
576e8fe33b | ||
|
3c928c04e1 | ||
|
37b872b155 | ||
|
5ab8b7a483 | ||
|
b813f4ba53 | ||
|
05ab11fec4 | ||
|
2d7ba0871f | ||
|
c98b26069a | ||
|
70dc81c4fd | ||
|
1b68baf7a3 | ||
|
6af7faa2b7 | ||
|
a1529a16bd | ||
|
321a2c1dcb | ||
|
735ef5d32b | ||
|
9428498d90 | ||
|
3ea1e541c7 | ||
|
29b0634f34 | ||
|
586222c94e | ||
|
232b51504c | ||
|
df099620dd | ||
|
22d647ecb1 | ||
|
07b0886796 | ||
|
9da31bf281 | ||
|
c5ff27a91b | ||
|
cf4afcb860 | ||
|
75a186fa9f | ||
|
05bef291d7 | ||
|
76f71f7d84 | ||
|
34f2c1c6ea | ||
|
67dae2f1cf | ||
|
bbaaa00249 | ||
|
9ed8789918 | ||
|
f45628d749 | ||
|
602decfbfc | ||
|
9aa1efd744 | ||
|
c51a68eaaf | ||
|
49b739b184 | ||
|
53d071adf5 | ||
|
70cda06789 | ||
|
e8ffc1c4e8 | ||
|
09c93be47c | ||
|
ac8d886645 | ||
|
ec1dda24d0 | ||
|
e7e9053598 |
29
.bzrignore
29
.bzrignore
@@ -18,13 +18,13 @@ parser/*.8
|
||||
parser/*.7.html
|
||||
parser/*.5.html
|
||||
parser/*.8.html
|
||||
parser/common
|
||||
parser/apparmor_parser
|
||||
parser/libapparmor_re/regexp.cc
|
||||
parser/techdoc.aux
|
||||
parser/techdoc.log
|
||||
parser/techdoc.pdf
|
||||
parser/techdoc.toc
|
||||
profiles/apparmor.d/local/*.*
|
||||
libraries/libapparmor/Makefile
|
||||
libraries/libapparmor/Makefile.in
|
||||
libraries/libapparmor/aclocal.m4
|
||||
@@ -41,32 +41,20 @@ libraries/libapparmor/install-sh
|
||||
libraries/libapparmor/libtool
|
||||
libraries/libapparmor/ltmain.sh
|
||||
libraries/libapparmor/missing
|
||||
libraries/libapparmor/test-driver
|
||||
libraries/libapparmor/ylwrap
|
||||
libraries/libapparmor/doc/Makefile
|
||||
libraries/libapparmor/doc/Makefile.in
|
||||
libraries/libapparmor/doc/*.2
|
||||
libraries/libapparmor/doc/aa_*.3
|
||||
libraries/libapparmor/include/Makefile
|
||||
libraries/libapparmor/include/Makefile.in
|
||||
libraries/libapparmor/include/sys/Makefile
|
||||
libraries/libapparmor/include/sys/Makefile.in
|
||||
libraries/libapparmor/src/.deps
|
||||
libraries/libapparmor/src/.libs
|
||||
libraries/libapparmor/src/Makefile
|
||||
libraries/libapparmor/src/Makefile.in
|
||||
libraries/libapparmor/src/af_protos.h
|
||||
libraries/libapparmor/src/change_hat.lo
|
||||
libraries/libapparmor/src/features.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/libimmunix_warning.lo
|
||||
libraries/libapparmor/src/policy_cache.lo
|
||||
libraries/libapparmor/src/private.lo
|
||||
libraries/libapparmor/src/scanner.lo
|
||||
libraries/libapparmor/src/libapparmor.pc
|
||||
libraries/libapparmor/src/libapparmor.la
|
||||
libraries/libapparmor/src/libimmunix.la
|
||||
libraries/libapparmor/src/grammar.c
|
||||
@@ -82,20 +70,12 @@ libraries/libapparmor/swig/perl/Makefile
|
||||
libraries/libapparmor/swig/perl/Makefile.PL
|
||||
libraries/libapparmor/swig/perl/Makefile.in
|
||||
libraries/libapparmor/swig/perl/Makefile.perl
|
||||
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/libapparmor_wrap.c
|
||||
libraries/libapparmor/swig/perl/pm_to_blib
|
||||
libraries/libapparmor/swig/python/LibAppArmor.py
|
||||
libraries/libapparmor/swig/python/build/
|
||||
libraries/libapparmor/swig/python/libapparmor_wrap.c
|
||||
libraries/libapparmor/swig/python/Makefile
|
||||
libraries/libapparmor/swig/python/Makefile.in
|
||||
libraries/libapparmor/swig/python/setup.py
|
||||
libraries/libapparmor/swig/python/test/Makefile
|
||||
libraries/libapparmor/swig/python/test/Makefile.in
|
||||
libraries/libapparmor/swig/ruby/Makefile
|
||||
libraries/libapparmor/swig/ruby/Makefile.in
|
||||
libraries/libapparmor/testsuite/.deps
|
||||
@@ -114,6 +94,10 @@ libraries/libapparmor/testsuite/libaalogparse.test/Makefile
|
||||
libraries/libapparmor/testsuite/libaalogparse.test/Makefile.in
|
||||
libraries/libapparmor/testsuite/test_multi/out
|
||||
changehat/mod_apparmor/.libs
|
||||
changehat/mod_apparmor/common
|
||||
changehat/pam_apparmor/common
|
||||
changehat/tomcat_apparmor/common
|
||||
utils/common
|
||||
utils/*.8
|
||||
utils/*.8.html
|
||||
utils/*.5
|
||||
@@ -181,5 +165,4 @@ tests/regression/apparmor/unix_fd_server
|
||||
tests/regression/apparmor/unlink
|
||||
tests/regression/apparmor/xattrs
|
||||
tests/regression/apparmor/coredump
|
||||
**/__pycache__/
|
||||
*.orig
|
||||
./utils/apparmor/__pycache__
|
||||
|
10
Makefile
10
Makefile
@@ -1,12 +1,8 @@
|
||||
#
|
||||
#
|
||||
.PHONY: all
|
||||
all:
|
||||
@echo "*** See README for information how to build AppArmor ***"
|
||||
exit 1
|
||||
OVERRIDE_TARBALL=yes
|
||||
|
||||
COMMONDIR=common
|
||||
include ${COMMONDIR}/Make.rules
|
||||
include common/Make.rules
|
||||
|
||||
DIRS=parser \
|
||||
profiles \
|
||||
@@ -18,7 +14,7 @@ DIRS=parser \
|
||||
|
||||
#REPO_URL?=lp:apparmor
|
||||
# --per-file-timestamps is failing over SSH, https://bugs.launchpad.net/bzr/+bug/1257078
|
||||
REPO_URL?=https://code.launchpad.net/~apparmor-dev/apparmor/2.10
|
||||
REPO_URL?=https://code.launchpad.net/~apparmor-dev/apparmor/2.9
|
||||
# alternate possibilities to export from
|
||||
#REPO_URL=.
|
||||
#REPO_URL="bzr+ssh://bazaar.launchpad.net/~sbeattie/+junk/apparmor-dev/"
|
||||
|
@@ -17,7 +17,13 @@ NAME:=apache2-mod_apparmor
|
||||
all:
|
||||
COMMONDIR=../../common/
|
||||
|
||||
include $(COMMONDIR)/Make.rules
|
||||
include common/Make.rules
|
||||
|
||||
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
|
||||
ifeq ($(COMMONDIR_EXISTS), true)
|
||||
common/Make.rules: $(COMMONDIR)/Make.rules
|
||||
ln -sf $(COMMONDIR) .
|
||||
endif
|
||||
|
||||
TARGET:=mod_apparmor.so
|
||||
MANPAGES=mod_apparmor.8
|
||||
@@ -86,9 +92,9 @@ install: ${TARGET} ${MANPAGES}
|
||||
make install_manpages DESTDIR=${DESTDIR}
|
||||
|
||||
.PHONY: clean
|
||||
clean: pod_clean
|
||||
clean: _clean
|
||||
rm -rf .libs
|
||||
rm -f *.la *.lo *.so *.o *.slo
|
||||
rm -f *.la *.lo *.so *.o *.slo Make.rules
|
||||
|
||||
.PHONY: check
|
||||
check: check_pod_files
|
||||
|
@@ -137,7 +137,7 @@ aa_enter_hat(request_rec *r)
|
||||
ap_get_module_config(r->server->module_config, &apparmor_module);
|
||||
const char *aa_hat_array[6] = { NULL, NULL, NULL, NULL, NULL, NULL };
|
||||
int i = 0;
|
||||
char *aa_label, *aa_mode, *aa_hat;
|
||||
char *aa_con, *aa_mode, *aa_hat;
|
||||
const char *vhost_uri;
|
||||
|
||||
debug_dump_uri(r);
|
||||
@@ -201,14 +201,14 @@ aa_enter_hat(request_rec *r)
|
||||
/* Check to see if a defined AAHatName or AADefaultHatName would
|
||||
* apply, but wasn't the hat we landed up in; report a warning if
|
||||
* that's the case. */
|
||||
aa_ret = aa_getcon(&aa_label, &aa_mode);
|
||||
aa_ret = aa_getcon(&aa_con, &aa_mode);
|
||||
if (aa_ret < 0) {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_WARNING, errno, r, "aa_getcon call failed");
|
||||
} else {
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
|
||||
"AA checks: aa_getcon result is '%s', mode '%s'", aa_label, aa_mode);
|
||||
"AA checks: aa_getcon result is '%s', mode '%s'", aa_con, aa_mode);
|
||||
/* TODO: use libapparmor get hat_name fn here once it is implemented */
|
||||
aa_hat = strstr(aa_label, "//");
|
||||
aa_hat = strstr(aa_con, "//");
|
||||
if (aa_hat != NULL && strcmp(aa_mode, "enforce") == 0) {
|
||||
aa_hat += 2; /* skip "//" */
|
||||
ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, r,
|
||||
@@ -226,7 +226,7 @@ aa_enter_hat(request_rec *r)
|
||||
scfg->hat_name);
|
||||
}
|
||||
}
|
||||
free(aa_label);
|
||||
free(aa_con);
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
@@ -65,7 +65,7 @@ provides the AAHatName and AADefaultHatName Apache configuration options.
|
||||
|
||||
AAHatName allows you to specify a hat to be used for a given Apache
|
||||
E<lt>DirectoryE<gt>, E<lt>DirectoryMatchE<gt>, E<lt>LocationE<gt> or
|
||||
E<lt>LocationMatchE<gt> directive (see the Apache documentation for more
|
||||
E<lt>LocationMatchE<gt> directive (see the Apache documenation for more
|
||||
details). Note that mod_apparmor behavior can become confused if
|
||||
E<lt>Directory*E<gt> and E<lt>Location*E<gt> directives are intermingled
|
||||
and it is recommended to use one type of directive. If the hat specified by
|
||||
|
@@ -16,8 +16,15 @@
|
||||
NAME=pam_apparmor
|
||||
all:
|
||||
COMMONDIR=../../common/
|
||||
MAKE_RULES=common/Make.rules
|
||||
|
||||
include $(COMMONDIR)/Make.rules
|
||||
include ${MAKE_RULES}
|
||||
|
||||
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
|
||||
ifeq ($(COMMONDIR_EXISTS), true)
|
||||
common/Make.rules: $(COMMONDIR)/Make.rules
|
||||
ln -sf $(COMMONDIR) .
|
||||
endif
|
||||
|
||||
ifdef USE_SYSTEM
|
||||
LIBAPPARMOR = $(shell if pkg-config --exists libapparmor ; then \
|
||||
@@ -53,7 +60,7 @@ libapparmor by adding USE_SYSTEM=1 to your make command.${nl}\
|
||||
AA_LINK_FLAGS = -L$(LIBAPPARMOR_PATH)
|
||||
AA_LDLIBS = -lapparmor
|
||||
endif
|
||||
EXTRA_CFLAGS=$(CFLAGS) $(CPPFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
|
||||
EXTRA_CFLAGS=$(CFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
|
||||
LINK_FLAGS=-Xlinker -x $(AA_LINK_FLAGS)
|
||||
LIBS=-lpam $(AA_LDLIBS)
|
||||
OBJECTS=${NAME}.o get_options.o
|
||||
@@ -80,5 +87,7 @@ install: $(NAME).so
|
||||
install -m 555 $(NAME).so $(SECDIR)/
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
clean: ${MAKE_RULES}
|
||||
rm -f core core.* *.so *.o *.s *.a *~
|
||||
rm -f ${NAME}-*.tar.gz Make.rules
|
||||
|
||||
|
@@ -111,7 +111,6 @@ int pam_sm_open_session(pam_handle_t *pamh, int flags,
|
||||
sizeof(magic_token));
|
||||
if (retval < 0) {
|
||||
pam_syslog(pamh, LOG_ERR, "Can't read from /dev/urandom\n");
|
||||
close(fd);
|
||||
return PAM_PERM_DENIED;
|
||||
}
|
||||
} while ((magic_token == 0) || (retval != sizeof(magic_token)));
|
||||
|
@@ -17,7 +17,13 @@ NAME = tomcat_apparmor
|
||||
all:
|
||||
COMMONDIR=../../../common/
|
||||
|
||||
include $(COMMONDIR)/Make.rules
|
||||
include common/Make.rules
|
||||
|
||||
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
|
||||
ifeq ($(COMMONDIR_EXISTS), true)
|
||||
common/Make.rules: $(COMMONDIR)/Make.rules
|
||||
ln -sf $(COMMONDIR) .
|
||||
endif
|
||||
|
||||
LIB = lib
|
||||
CATALINA_HOME = /usr/share/tomcat5
|
||||
@@ -28,6 +34,7 @@ all:
|
||||
|
||||
clean:
|
||||
ant clean
|
||||
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
|
||||
|
||||
install:
|
||||
install: $(SPECFILE)
|
||||
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni
|
||||
|
@@ -17,7 +17,13 @@ NAME = tomcat_apparmor
|
||||
all:
|
||||
COMMONDIR=../../../common/
|
||||
|
||||
include $(COMMONDIR)/Make.rules
|
||||
include common/Make.rules
|
||||
|
||||
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
|
||||
ifeq ($(COMMONDIR_EXISTS), true)
|
||||
common/Make.rules: $(COMMONDIR)/Make.rules
|
||||
ln -sf $(COMMONDIR) .
|
||||
endif
|
||||
|
||||
LIB = lib
|
||||
CATALINA_HOME = /usr/share/tomcat55
|
||||
@@ -28,6 +34,7 @@ all:
|
||||
|
||||
clean:
|
||||
ant clean
|
||||
rm -f tomcat_apparmor.spec ${NAME}-*.tar.gz Make.rules
|
||||
|
||||
install:
|
||||
install: $(SPECFILE)
|
||||
ant -Dversion=$(VERSION) -Drelease=$(MAN_RELEASE) -Dcatalina_home=${CATALINA_HOME} -Dinstall_lib=${LIB} install_jar install_jni
|
||||
|
@@ -1,7 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) 2010-2015 Canonical, Ltd.
|
||||
# Copyright (C) 2010 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
|
||||
@@ -15,21 +15,17 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, contact Novell, Inc.
|
||||
# ------------------------------------------------------------------
|
||||
# Make.rules - common make targets and variables for building AppArmor
|
||||
# Make.rules - common make targets and variables for building the SHASS
|
||||
# product.
|
||||
#
|
||||
# NOTES:
|
||||
# Before including this file in your Makefile, you should
|
||||
# - define COMMONDIR (the location of the common/ directory)
|
||||
# - define the default rule (usually 'all:'). (Note: you can redefine
|
||||
# it later in your Makefile)
|
||||
|
||||
.PHONY: common_Make.rules_is_a_bad_target
|
||||
common_Make.rules_is_a_bad_target:
|
||||
@echo "*** default target in common/Make.rules hit - either you did something strange, or something is broken... ***"
|
||||
exit 1
|
||||
# - must define the package NAME before including this file.
|
||||
# - After checking in to cvs, you'll need to delele the hardlinked
|
||||
# Make.rules files that already exist in the individual application
|
||||
# directories
|
||||
|
||||
DISTRIBUTION=AppArmor
|
||||
VERSION=$(shell cat $(COMMONDIR)/Version)
|
||||
VERSION=$(shell cat common/Version)
|
||||
|
||||
# Convenience functions
|
||||
pathsearch = $(firstword $(wildcard $(addsuffix /$(1),$(subst :, ,$(PATH)))))
|
||||
@@ -45,8 +41,106 @@ define nl
|
||||
|
||||
endef
|
||||
|
||||
# OVERRIDABLE variables
|
||||
# Set these variables before including Make.rules to change its behavior
|
||||
# SPECFILE - for packages that have a non-standard specfile name
|
||||
# EXTERNAL_PACKAGE - for packages that have upstream versions that
|
||||
# we're locally modifying (e.g. imnxcerttool/gnutls).
|
||||
#
|
||||
# use 'make BUILDIR=/some/where/else/' to override the /usr/src/redhat
|
||||
# location -- it *should* pick out the right thing to do based on the
|
||||
# .rpmmacros file, but you can still use BUILDDIR to override that.
|
||||
TESTBUILDDIR=$(shell [ -f ${HOME}/.rpmmacros ] && awk '/^%_topdir/ {print $$2}' ${HOME}/.rpmmacros)
|
||||
ifndef BUILDDIR
|
||||
BUILDDIR=$(shell if [ -d "${TESTBUILDDIR}" ] ; then \
|
||||
echo ${TESTBUILDDIR} | sed "s^/$$^^" ; \
|
||||
elif [ -d "/usr/src/redhat" ] ; then \
|
||||
echo "/usr/src/redhat" ; \
|
||||
elif [ -d "/usr/src/packages" ] ; then \
|
||||
echo "/usr/src/packages" ; \
|
||||
else \
|
||||
echo "/tmp/${NAME}" ; \
|
||||
fi ;)
|
||||
endif
|
||||
ifndef DISTRO
|
||||
DISTRO=$(shell if [ -f /etc/slackware-version ] ; then \
|
||||
echo slackware ; \
|
||||
elif [ -f /etc/debian_version ] ; then \
|
||||
echo debian ;\
|
||||
elif which rpm > /dev/null ; then \
|
||||
if [ "$(rpm --eval '0%{?suse_version}')" != "0" ] ; then \
|
||||
echo suse ;\
|
||||
elif [ "$(rpm --eval '%{_host_vendor}')" = redhat ] ; then \
|
||||
echo rhel4 ;\
|
||||
elif [ "$(rpm --eval '0%{?fedora}')" != "0" ] ; then \
|
||||
echo rhel4 ;\
|
||||
else \
|
||||
echo unknown ;\
|
||||
fi ;\
|
||||
else \
|
||||
echo unknown ;\
|
||||
fi)
|
||||
endif
|
||||
RPMARG=--define "_topdir $(BUILDDIR:/=)" \
|
||||
--define "vendor NOVELL, Inc." \
|
||||
--define "distribution ${DISTRIBUTION}" \
|
||||
--define "debug_package %{nil}" \
|
||||
--define "immunix_version ${VERSION}" \
|
||||
$(shell [ -d ${BUILDDIR}/BUILDROOT ] && echo --define \"buildroot $(BUILDDIR:/=)/BUILDROOT\") \
|
||||
$(shell [ -n "${DISTRO}" ] && echo --define \"distro ${DISTRO}\")
|
||||
|
||||
REPO_VERSION_CMD=([ -x /usr/bin/bzr ] && /usr/bin/bzr version-info . 2> /dev/null || awk '{ print "revno: "$2 }' common/.stamp_rev) | awk '/^revno:/ { print $2 }'
|
||||
|
||||
ifdef EXTERNAL_PACKAGE
|
||||
RPMARG+=--define "_sourcedir $(shell pwd)"
|
||||
endif
|
||||
|
||||
ifndef SPECFILE
|
||||
SPECFILE = $(NAME).spec
|
||||
endif
|
||||
RELEASE_DIR = $(NAME)-$(VERSION)
|
||||
TAR = /bin/tar czvp -h --exclude .svn --exclude .bzr --exclude .bzrignore --exclude ${RELEASE_DIR}/${RELEASE_DIR} $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
|
||||
LDCONFIG = /sbin/ldconfig
|
||||
|
||||
RPMSUBDIRS=SOURCES SPECS BUILD BUILDROOT SRPMS RPMS/i386 RPMS/i586 \
|
||||
RPMS/i686 RPMS/athlon RPMS/noarch RPMS/x86_64
|
||||
BUILDRPMSUBDIRS=$(foreach subdir, $(RPMSUBDIRS), $(BUILDDIR:/=)/$(subdir))
|
||||
|
||||
ifdef EXTERNAL_PACKAGE
|
||||
.PHONY: rpm
|
||||
rpm: clean $(BUILDRPMSUBDIRS)
|
||||
rpmbuild -ba ${RPMARG} ${SPECFILE}
|
||||
|
||||
else
|
||||
.PHONY: rpm
|
||||
rpm: clean $(BUILDRPMSUBDIRS)
|
||||
__REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
|
||||
__TARBALL=$(NAME)-$(VERSION)-$${__REPO_VERSION}.tar.gz ; \
|
||||
make $${__TARBALL} ; \
|
||||
cp $${__TARBALL} $(BUILDDIR)/SOURCES/
|
||||
cp ${SPECFILE} $(BUILDDIR)/SPECS/
|
||||
rpmbuild -ba ${RPMARG} ${SPECFILE}
|
||||
|
||||
.PHONY: ${SPECFILE}
|
||||
${SPECFILE}: ${SPECFILE}.in
|
||||
__REPO_VERSION=`$(value REPO_VERSION_CMD)` ; \
|
||||
sed -e "s/@@immunix_version@@/${VERSION}/g" \
|
||||
-e "s/@@repo_version@@/$${__REPO_VERSION}/g" $< > $@
|
||||
|
||||
%.tar.gz: clean ${SPECFILE}
|
||||
-rm -rf $(RELEASE_DIR)
|
||||
mkdir $(RELEASE_DIR)
|
||||
$(TAR) --exclude $@ . | tar xz -C $(RELEASE_DIR)
|
||||
$(TAR) --exclude $@ -f $@ $(RELEASE_DIR)
|
||||
rm -rf $(RELEASE_DIR)
|
||||
|
||||
ifndef OVERRIDE_TARBALL
|
||||
.PHONY: tarball
|
||||
tarball: clean $(TARBALL)
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifndef PYTHON_VERSIONS
|
||||
PYTHON_VERSIONS = $(call map, pathsearch, python2 python3)
|
||||
endif
|
||||
@@ -61,18 +155,24 @@ pyalldo=set -e; $(foreach py, $(PYTHON_VERSIONS), $(py) $(1);)
|
||||
.PHONY: version
|
||||
.SILENT: version
|
||||
version:
|
||||
echo $(VERSION)
|
||||
rpm -q --define "_sourcedir ." ${RPMARG} --specfile ${SPECFILE}
|
||||
|
||||
.PHONY: repo_version
|
||||
.SILENT: repo_version
|
||||
repo_version:
|
||||
$(value REPO_VERSION_CMD)
|
||||
|
||||
.PHONY: pod_clean
|
||||
ifndef VERBOSE
|
||||
.SILENT: pod_clean
|
||||
endif
|
||||
pod_clean:
|
||||
|
||||
.PHONY: build_dir
|
||||
build_dir: $(BUILDRPMSUBDIRS)
|
||||
|
||||
$(BUILDRPMSUBDIRS):
|
||||
mkdir -p $(BUILDRPMSUBDIRS)
|
||||
|
||||
.PHONY: _clean
|
||||
.SILENT: _clean
|
||||
_clean:
|
||||
-[ -z "${NAME}" ] || rm -f ${NAME}-${VERSION}-*.tar.gz
|
||||
-rm -f ${MANPAGES} *.[0-9].gz ${HTMLMANPAGES} pod2htm*.tmp
|
||||
|
||||
# =====================
|
||||
@@ -82,7 +182,7 @@ pod_clean:
|
||||
# =====================
|
||||
|
||||
# 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' | LC_ALL=C 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' | sort)
|
||||
|
||||
.PHONY: list_capabilities
|
||||
list_capabilities: /usr/include/linux/capability.h
|
||||
@@ -98,7 +198,7 @@ list_capabilities: /usr/include/linux/capability.h
|
||||
# to mediate. We use PF_ here since that is what is required in
|
||||
# bits/socket.h, but we will rewrite these as AF_.
|
||||
|
||||
FILTER_FAMILIES=PF_UNIX
|
||||
FILTER_FAMILIES=PF_UNSPEC PF_UNIX
|
||||
|
||||
__FILTER=$(shell echo $(strip $(FILTER_FAMILIES)) | sed -e 's/ /\\\|/g')
|
||||
|
||||
|
@@ -1 +1 @@
|
||||
2.10.2
|
||||
2.9.2
|
||||
|
@@ -24,7 +24,13 @@ NAME = apparmor-utils
|
||||
all:
|
||||
COMMONDIR=../../common/
|
||||
|
||||
include $(COMMONDIR)/Make.rules
|
||||
include common/Make.rules
|
||||
|
||||
COMMONDIR_EXISTS=$(strip $(shell [ -d ${COMMONDIR} ] && echo true))
|
||||
ifeq ($(COMMONDIR_EXISTS), true)
|
||||
common/Make.rules: $(COMMONDIR)/Make.rules
|
||||
ln -sf $(COMMONDIR) .
|
||||
endif
|
||||
|
||||
MODDIR = Immunix
|
||||
PERLTOOLS = aa-genprof aa-logprof aa-autodep aa-audit aa-complain aa-enforce \
|
||||
@@ -50,8 +56,9 @@ install:
|
||||
ifndef VERBOSE
|
||||
.SILENT: clean
|
||||
endif
|
||||
clean: pod_clean
|
||||
clean: _clean
|
||||
rm -f core core.* *.o *.s *.a *~
|
||||
rm -f Make.rules
|
||||
rm -rf staging/ build/
|
||||
|
||||
.PHONY: check
|
||||
|
Binary file not shown.
@@ -4,4 +4,22 @@ SRCDIR = src
|
||||
|
||||
SUBDIRS = doc src include swig testsuite
|
||||
|
||||
REPO_VERSION=$(shell if [ -x /usr/bin/svn ] ; then \
|
||||
/usr/bin/svn info . 2> /dev/null | grep "^Last Changed Rev:" | sed "s/^Last Changed Rev: //" ; \
|
||||
fi)
|
||||
|
||||
REPO_URL=$(shell if [ -x /usr/bin/svn ] ; then \
|
||||
/usr/bin/svn info . 2> /dev/null | grep "^URL:" | sed "s/^URL: //" ; \
|
||||
fi)
|
||||
RELEASE_DIR = $(NAME)-$(VERSION)-${REPO_VERSION}
|
||||
|
||||
SVNTARBALL = $(NAME)-$(VERSION)-${REPO_VERSION}.tar.gz
|
||||
SVNTAR = /bin/tar czvp -h --exclude .svn --exclude CVS --exclude .cvsignore --exclude ${SVNTARBALL} --exclude ${RELEASE_DIR}/${RELEASE_DIR} $(shell test -f ${NAME}.exclude && echo "-X ${NAME}.exclude")
|
||||
|
||||
distball: clean
|
||||
rm -rf $(RELEASE_DIR)
|
||||
svn export -r $(REPO_VERSION) $(REPO_URL) $(RELEASE_DIR)
|
||||
$(SVNTAR) -f $(SVNTARBALL) $(RELEASE_DIR)
|
||||
rm -rf $(RELEASE_DIR)
|
||||
|
||||
EXTRA_DIST = AUTHORS ChangeLog COPYING.LGPL INSTALL NEWS README
|
||||
|
@@ -38,6 +38,6 @@ aclocal
|
||||
echo "Running autoconf"
|
||||
autoconf --force
|
||||
echo "Running libtoolize"
|
||||
libtoolize --automake -c --force
|
||||
libtoolize --automake -c
|
||||
echo "Running automake"
|
||||
automake -ac
|
||||
|
@@ -14,14 +14,6 @@ PKG_PROG_PKG_CONFIG
|
||||
|
||||
AC_PATH_PROG([SWIG], [swig])
|
||||
|
||||
AC_MSG_CHECKING([whether the libapparmor debug output should be enabled])
|
||||
AC_ARG_ENABLE([debug_output],
|
||||
[AS_HELP_STRING([--enable-debug-output], [generate the libapparmor debug output [[default=no]]])],
|
||||
[AC_MSG_RESULT([$enableval])],
|
||||
[enable_debug_output=no]
|
||||
[AC_MSG_RESULT([$enable_debug_output])])
|
||||
AS_IF([test "$enable_debug_output" = "yes"], [AC_DEFINE([ENABLE_DEBUG_OUTPUT], [1], [debug output])])
|
||||
|
||||
AC_MSG_CHECKING([whether the libapparmor man pages should be generated])
|
||||
AC_ARG_ENABLE(man_pages,
|
||||
[AS_HELP_STRING([--enable-man-pages], [generate the libapparmor man pages [[default=yes]]])],
|
||||
@@ -79,19 +71,14 @@ AM_CONDITIONAL(HAVE_PERL, test x$with_perl = xyes)
|
||||
AM_CONDITIONAL(HAVE_RUBY, test x$with_ruby = xyes)
|
||||
|
||||
AC_HEADER_STDC
|
||||
AC_CHECK_HEADERS(unistd.h stdint.h syslog.h)
|
||||
AC_CHECK_HEADERS(unistd.h stdint.h)
|
||||
|
||||
AC_CHECK_FUNCS([asprintf __secure_getenv secure_getenv])
|
||||
AC_CHECK_FUNCS(asprintf)
|
||||
|
||||
AM_PROG_CC_C_O
|
||||
AC_C_CONST
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
AC_PROG_CC_C99
|
||||
if test "$ac_cv_prog_cc_c99" = "no"; then
|
||||
AC_MSG_ERROR([C99 mode is required to build libapparmor])
|
||||
fi
|
||||
|
||||
AC_OUTPUT(
|
||||
Makefile
|
||||
doc/Makefile
|
||||
|
@@ -5,14 +5,14 @@ PODCHECKER = podchecker
|
||||
|
||||
if ENABLE_MAN_PAGES
|
||||
|
||||
man_MANS = aa_change_hat.2 aa_change_profile.2 aa_getcon.2 aa_find_mountpoint.2 aa_splitcon.3 aa_query_label.2 aa_features.3 aa_kernel_interface.3 aa_policy_cache.3
|
||||
man_MANS = aa_change_hat.2 aa_change_profile.2 aa_getcon.2 aa_find_mountpoint.2
|
||||
|
||||
PODS = $(subst .2,.pod,$(man_MANS)) $(subst .3,.pod,$(man_MANS))
|
||||
PODS = $(subst .2,.pod,$(man_MANS))
|
||||
|
||||
EXTRA_DIST = $(man_MANS) $(PODS)
|
||||
|
||||
## delete man pages at make clean
|
||||
CLEANFILES = $(man_MANS)
|
||||
## delete man pages at maintainer-clean
|
||||
BUILT_SOURCES = $(man_MANS)
|
||||
|
||||
%.2: %.pod
|
||||
$(PODCHECKER) -warnings -warnings $<
|
||||
@@ -23,13 +23,4 @@ CLEANFILES = $(man_MANS)
|
||||
--stderr \
|
||||
$< > $@
|
||||
|
||||
%.3: %.pod
|
||||
$(PODCHECKER) -warnings -warnings $<
|
||||
$(POD2MAN) \
|
||||
--section=3 \
|
||||
--release="AppArmor $(VERSION)" \
|
||||
--center="AppArmor" \
|
||||
--stderr \
|
||||
$< > $@
|
||||
|
||||
endif
|
||||
|
@@ -40,15 +40,16 @@ An AppArmor profile applies to an executable program; if a portion of
|
||||
the program needs different access permissions than other portions,
|
||||
the program can "change profile" to a different profile. To change into a
|
||||
new profile, it can use the aa_change_profile() function to do so. It passes
|
||||
in a pointer to the I<profile> to transition to. Confined programs wanting to
|
||||
use aa_change_profile() need to have rules permitting changing to the named
|
||||
profile. See apparmor.d(8) for details.
|
||||
in a pointer to the I<profile> to transition to. Transitioning to another
|
||||
profile via aa_change_profile() is permanent and the process is not
|
||||
permitted to transition back to the original profile. Confined programs
|
||||
wanting to use aa_change_profile() need to have rules permitting changing
|
||||
to the named profile. See apparmor.d(8) for details.
|
||||
|
||||
If a program wants to return out of the current profile to the
|
||||
original profile, it may use aa_change_hat(2). Otherwise, the two profiles must
|
||||
have rules permitting changing between the two profiles.
|
||||
original profile, it should use aa_change_hat(2) instead.
|
||||
|
||||
Open file descriptors may not be remediated after a call to aa_change_profile()
|
||||
Open file descriptors are not remediated after a call to aa_change_profile()
|
||||
so the calling program must close(2) open file descriptors to ensure they
|
||||
are not available after calling aa_change_profile(). As aa_change_profile()
|
||||
is typically used just before execve(2), you may want to use open(2) or
|
||||
@@ -83,8 +84,8 @@ Insufficient kernel memory was available.
|
||||
|
||||
=item B<EPERM>
|
||||
|
||||
The calling application is confined by apparmor and the no_new_privs bit is
|
||||
set.
|
||||
The calling application is not confined by apparmor, or the no_new_privs
|
||||
bit is set.
|
||||
|
||||
=item B<EACCES>
|
||||
|
||||
|
@@ -1,148 +0,0 @@
|
||||
# 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 adhere 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_features - an opaque object representing a set of AppArmor kernel features
|
||||
|
||||
aa_features_new - create a new aa_features object based on a path
|
||||
|
||||
aa_features_new_from_string - create a new aa_features object based on a string
|
||||
|
||||
aa_features_new_from_kernel - create a new aa_features object based on the current kernel
|
||||
|
||||
aa_features_ref - increments the ref count of an aa_features object
|
||||
|
||||
aa_features_unref - decrements the ref count and frees the aa_features object when 0
|
||||
|
||||
aa_features_write_to_file - write a string representation of an aa_features object to a file
|
||||
|
||||
aa_features_is_equal - equality test for two aa_features objects
|
||||
|
||||
aa_features_supports - provides aa_features object support status
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<typedef struct aa_features aa_features;>
|
||||
|
||||
B<int aa_features_new(aa_features **features, int dirfd, const char *path);>
|
||||
|
||||
B<int aa_features_new_from_string(aa_features **features, const char *string, size_t size);>
|
||||
|
||||
B<int aa_features_new_from_kernel(aa_features **features);>
|
||||
|
||||
B<aa_features *aa_features_ref(aa_features *features);>
|
||||
|
||||
B<void aa_features_unref(aa_features *features);>
|
||||
|
||||
B<int aa_features_write_to_file(aa_features *features, int dirfd, const char *path);>
|
||||
|
||||
B<bool aa_features_is_equal(aa_features *features1, aa_features *features2);>
|
||||
|
||||
B<bool aa_features_supports(aa_features *features, const char *str);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The I<aa_features> object contains information about the AppArmor features
|
||||
supported by a kernel. The feature support information is based upon the files
|
||||
AppArmor represents in securityfs, which is typically found at
|
||||
/sys/kernel/security/apparmor/features/. That information may be parsed and
|
||||
turned into a string or flat file in order to represent a set of features of a
|
||||
kernel that is not currently running.
|
||||
|
||||
The aa_features_new() function creates an I<aa_features> object based upon a
|
||||
directory file descriptor and path. The I<path> can point to a file or
|
||||
directory. See the openat(2) man page for examples of I<dirfd> and I<path>. The
|
||||
allocated I<features> object must be freed using aa_features_unref().
|
||||
|
||||
The aa_features_new_from_string() function is similar except that it accepts a
|
||||
NUL-terminated string representation of the AppArmor features as the I<string>
|
||||
argument. The length of the features string, not counting the NUL-terminator,
|
||||
must be specified as the I<size> argument. The allocated I<features> object
|
||||
must be freed using aa_features_unref().
|
||||
|
||||
The aa_features_new_from_kernel() function creates an I<aa_features> object
|
||||
from the current running kernel. The allocated I<features> object must be freed
|
||||
using aa_features_unref().
|
||||
|
||||
aa_features_ref() increments the reference count on the I<features> object.
|
||||
|
||||
aa_features_unref() decrements the reference count on the I<features> object
|
||||
and releases all corresponding resources when the reference count reaches zero.
|
||||
|
||||
The aa_features_write_to_file() function writes a string representation of the
|
||||
I<features> object to the file specified by the I<dirfd> and I<path>
|
||||
combination.
|
||||
|
||||
aa_features_is_equal() can be used to detect if the I<features1> and
|
||||
I<features2> objects are equal. The definition of equality is private to
|
||||
libapparmor and may be changed in ways that do not break backward
|
||||
compatibility.
|
||||
|
||||
The aa_features_supports() function can be used to query the I<features> object
|
||||
to determine if a feature is supported. The I<str> argument should be equal to
|
||||
the path, relative to the "apparmor/features/" directory of securityfs, of the
|
||||
feature to query. For example, to test if policy version 6 is supported, I<str>
|
||||
would be "policy/versions/v6".
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
The aa_features_new() family of functions return 0 on success and I<*features>
|
||||
will point to an I<aa_features> object that must be freed by
|
||||
aa_features_unref(). -1 is returned on error, with errno set appropriately, and
|
||||
I<*features> will be set to NULL.
|
||||
|
||||
aa_features_ref() returns the value of I<features>.
|
||||
|
||||
aa_features_write_to_file() returns 0 on success. -1 is returned on error, with
|
||||
errno set appropriately.
|
||||
|
||||
aa_features_is_equal() returns true if I<features1> and I<features2> are equal
|
||||
and false if they are not equal.
|
||||
|
||||
aa_features_supports() returns true if the feature represented by I<str> is
|
||||
supported and false if it is not supported.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
The errno value will be set according to the underlying error in the
|
||||
I<aa_features> family of functions that return -1 on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
All aa_features functions described above are present in libapparmor version
|
||||
2.10 and newer.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
openat(2) and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
@@ -34,38 +34,27 @@ B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len, char **mode);>
|
||||
|
||||
B<int aa_getprocattr(pid_t tid, const char *attr, char **label, char **mode);>
|
||||
B<int aa_getprocattr(pid_t tid, const char *attr, char **con, char **mode);>
|
||||
|
||||
B<int aa_gettaskcon(pid_t target, char **label, char **mode);>
|
||||
B<int aa_gettaskcon(pid_t target, char **con, char **mode);>
|
||||
|
||||
B<int aa_getcon(char **label, char **mode);>
|
||||
B<int aa_getcon(char **con, char **mode);>
|
||||
|
||||
B<int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);>
|
||||
|
||||
B<int aa_getpeercon(int fd, char **label, char **mode);>
|
||||
B<int aa_getpeercon(int fd, char **con, char **mode);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The aa_getcon function gets the current AppArmor confinement context for the
|
||||
current task. The confinement context consists of a label and a mode. The label
|
||||
is usually just the name of the AppArmor profile restricting the task, but it
|
||||
may include the profile namespace or in some cases a set of profile names
|
||||
(known as a stack of profiles). The mode is a string that describes how the
|
||||
kernel is enforcing the policy defined in the profile. Profiles loaded in
|
||||
"enforce" mode will result in enforcement of the policy defined in the profile
|
||||
as well as reporting policy violation attempts. Profiles in "complain" mode
|
||||
will not enforce policy but instead report policy violation attempts.
|
||||
|
||||
Some examples of possible returned *label strings are "unconfined", "/sbin/dhclient",
|
||||
and "Firefox". The string can consist of any non-NUL characters but it will be
|
||||
NUL-terminated. The *label string must be freed using free().
|
||||
|
||||
The possible *mode strings are "enforce" and "complain". Additionally, *mode may
|
||||
be NULL when *label is "unconfined". B<The *mode string must not be freed>. The
|
||||
*label and *mode strings come from a single buffer allocation and are separated
|
||||
by a NUL character.
|
||||
current task. The confinement context is usually just the name of the AppArmor
|
||||
profile restricting the task, but it may include the profile namespace or in
|
||||
some cases a set of profile names (known as a stack of profiles). The returned
|
||||
string *con should be freed using free(), but the returned string *mode should
|
||||
not be freed. The *con and *mode strings come from a single buffer allocation
|
||||
and are separated by a NUL character.
|
||||
|
||||
The aa_gettaskcon function is like the aa_getcon function except it will work
|
||||
for any arbitrary task in the system.
|
||||
@@ -131,7 +120,7 @@ L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2),
|
||||
aa_splitcon(3) and L<http://wiki.apparmor.net>.
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_change_profile(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
||||
|
@@ -1,162 +0,0 @@
|
||||
# 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 adhere 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_kernel_interface - an opaque object representing the AppArmor kernel interface for policy loading, replacing, and removing
|
||||
|
||||
aa_kernel_interface_new - create a new aa_kernel_interface object from an optional path
|
||||
|
||||
aa_kernel_interface_ref - increments the ref count of an aa_kernel_interface object
|
||||
|
||||
aa_kernel_interface_unref - decrements the ref count and frees the aa_kernel_interface object when 0
|
||||
|
||||
aa_kernel_interface_load_policy - load a policy from a buffer into the kernel
|
||||
|
||||
aa_kernel_interface_load_policy_from_file - load a policy from a file into the kernel
|
||||
|
||||
aa_kernel_interface_load_policy_from_fd - load a policy from a file descriptor into the kernel
|
||||
|
||||
aa_kernel_interface_replace_policy - replace a policy in the kernel with a policy from a buffer
|
||||
|
||||
aa_kernel_interface_replace_policy_from_file - replace a policy in the kernel with a policy from a file
|
||||
|
||||
aa_kernel_interface_replace_policy_from_fd - replace a policy in the kernel with a policy from a file descriptor
|
||||
|
||||
aa_kernel_interface_remove_policy - remove a policy from the kernel
|
||||
|
||||
aa_kernel_interface_write_policy - write a policy to a file descriptor
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<typedef struct aa_kernel_interface aa_kernel_interface;>
|
||||
|
||||
B<int aa_kernel_interface_new(aa_kernel_interface **kernel_interface, aa_features *kernel_features, const char *apparmorfs);>
|
||||
|
||||
B<aa_kernel_interface *aa_kernel_interface_ref(aa_kernel_interface *kernel_interface);>
|
||||
|
||||
B<void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface);>
|
||||
|
||||
B<int aa_kernel_interface_load_policy(aa_kernel_interface *kernel_interface, const char *buffer, size_t size);>
|
||||
|
||||
B<int aa_kernel_interface_load_policy_from_file(aa_kernel_interface *kernel_interface, int dirfd, const char *path);>
|
||||
|
||||
B<int aa_kernel_interface_load_policy_from_fd(aa_kernel_interface *kernel_interface, int fd);>
|
||||
|
||||
B<int aa_kernel_interface_replace_policy(aa_kernel_interface *kernel_interface, const char *buffer, size_t size);>
|
||||
|
||||
B<int aa_kernel_interface_replace_policy_from_file(aa_kernel_interface *kernel_interface, int dirfd, const char *path);>
|
||||
|
||||
B<int aa_kernel_interface_replace_policy_from_fd(aa_kernel_interface *kernel_interface, int fd);>
|
||||
|
||||
B<int aa_kernel_interface_remove_policy(aa_kernel_interface *kernel_interface, const char *fqname);>
|
||||
|
||||
B<int aa_kernel_interface_write_policy(int fd, const char *buffer, size_t size);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The I<aa_kernel_interface> object contains information about the AppArmor
|
||||
kernel interface for policy loading, replacing, and removing.
|
||||
|
||||
The aa_kernel_interface_new() function creates an I<aa_kernel_interface> object
|
||||
based on an optional I<aa_features> object and an optional path to the apparmor
|
||||
directory of securityfs, which is typically found at
|
||||
"/sys/kernel/security/apparmor/". If I<kernel_features> is NULL, then the
|
||||
features of the current kernel are used. When specifying a valid
|
||||
I<kernel_features> object, it must be compatible with the features of the
|
||||
currently running kernel. If I<apparmorfs> is NULL, then the default location
|
||||
is used. The allocated I<kernel_interface> object must be freed using
|
||||
aa_kernel_interface_unref().
|
||||
|
||||
aa_kernel_interface_ref() increments the reference count on the
|
||||
I<kernel_interface> object.
|
||||
|
||||
aa_kernel_interface_unref() decrements the reference count on the
|
||||
I<kernel_interface> object and releases all corresponding resources when the
|
||||
reference count reaches zero.
|
||||
|
||||
The aa_kernel_interface_load() family of functions load a policy into the
|
||||
kernel. The operation will fail if a policy of the same name is already loaded.
|
||||
Use the aa_kernel_interface_replace() family of functions if you wish to
|
||||
replace a previously loaded policy with a new policy of the same name. The
|
||||
aa_kernel_interface_replace() functions can also be used to load a policy that
|
||||
does not correspond to a previously loaded policy.
|
||||
|
||||
When loading or replacing from a buffer, the I<buffer> will contain binary
|
||||
data. The I<size> argument must specify the size of the I<buffer> argument.
|
||||
|
||||
When loading or replacing from a file, the I<dirfd> and I<path> combination are
|
||||
used to specify the location of the file. See the openat(2) man page for
|
||||
examples of I<dirfd> and I<path>.
|
||||
|
||||
It is also possible to load or replace from a file descriptor specified by the
|
||||
I<fd> argument. The file must be open for reading and the file offset must be
|
||||
set appropriately.
|
||||
|
||||
The aa_kernel_interface_remove_policy() function can be used to unload a
|
||||
previously loaded policy. The fully qualified policy name must be specified
|
||||
with the I<fqname> argument. The operation will fail if a policy matching
|
||||
I<fqname> is not found.
|
||||
|
||||
The aa_kernel_interface_write_policy() function allows for a policy, which is
|
||||
stored in I<buffer> and consists of I<size> bytes, to be written to a file
|
||||
descriptor. The I<fd> must be open for writing and the file offset must be set
|
||||
appropriately.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
The aa_kernel_interface_new() function returns 0 on success and
|
||||
I<*kernel_interface> will point to an I<aa_kernel_interface> object that must
|
||||
be freed by aa_kernel_interface_unref(). -1 is returned on error, with errno
|
||||
set appropriately, and I<*kernel_interface> will be set to NULL.
|
||||
|
||||
aa_kernel_features_ref() returns the value of I<kernel_features>.
|
||||
|
||||
The aa_kernel_interface_load() family of functions, the
|
||||
aa_kernel_interface_replace() family of functions,
|
||||
aa_kernel_interface_remove(), and aa_kernel_interface_write_policy()
|
||||
return 0 on success. -1 is returned on error, with errno set appropriately.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
The errno value will be set according to the underlying error in the
|
||||
I<aa_kernel_interface> family of functions that return -1 on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
All aa_kernel_interface functions described above are present in libapparmor
|
||||
version 2.10 and newer.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
aa_features(3), openat(2) and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
@@ -1,125 +0,0 @@
|
||||
# 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 adhere 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_policy_cache - an opaque object representing an AppArmor policy cache
|
||||
|
||||
aa_policy_cache_new - create a new aa_policy_cache object from a path
|
||||
|
||||
aa_policy_cache_ref - increments the ref count of an aa_policy_cache object
|
||||
|
||||
aa_policy_cache_unref - decrements the ref count and frees the aa_policy_cache object when 0
|
||||
|
||||
aa_policy_cache_remove - removes all policy cache files under a path
|
||||
|
||||
aa_policy_cache_replace_all - performs a kernel policy replacement of all cached policies
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<typedef struct aa_policy_cache aa_policy_cache;>
|
||||
|
||||
B<int aa_policy_cache_new(aa_policy_cache **policy_cache, aa_features *kernel_features, int dirfd, const char *path, uint16_t max_caches);>
|
||||
|
||||
B<aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);>
|
||||
|
||||
B<void aa_policy_cache_unref(aa_policy_cache *policy_cache);>
|
||||
|
||||
B<int aa_policy_cache_remove(int dirfd, const char *path);>
|
||||
|
||||
B<int aa_policy_cache_replace_all(aa_policy_cache *policy_cache, aa_kernel_interface *kernel_interface);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The I<aa_policy_cache> object contains information about a set of AppArmor
|
||||
policy cache files. The policy cache files are the binary representation of a
|
||||
human-readable AppArmor profile. The binary representation is the form that is
|
||||
loaded into the kernel.
|
||||
|
||||
The aa_policy_cache_new() function creates an I<aa_policy_cache> object based
|
||||
upon a directory file descriptor and path. The I<path> must point to a
|
||||
directory. See the openat(2) man page for examples of I<dirfd> and I<path>. If
|
||||
I<kernel_features> is NULL, then the features of the current kernel are used.
|
||||
When specifying a valid I<kernel_features> object, it must be the compatible
|
||||
with the features of the kernel of interest. The value of I<max_caches> should
|
||||
be equal to the number of caches that should be allowed before old caches are
|
||||
automatically reaped. The definition of what is considered to be an old cache
|
||||
is private to libapparmor. Specifying 0 means that no new caches should be
|
||||
created and only existing, valid caches may be used. Specifying UINT16_MAX
|
||||
means that a new cache may be created and that the reaping of old caches is
|
||||
disabled. The allocated I<aa_policy_cache> object must be freed using
|
||||
aa_policy_cache_unref().
|
||||
|
||||
aa_policy_cache_ref() increments the reference count on the I<policy_cache>
|
||||
object.
|
||||
|
||||
aa_policy_cache_unref() decrements the reference count on the I<policy_cache>
|
||||
object and releases all corresponding resources when the reference count
|
||||
reaches zero.
|
||||
|
||||
The aa_policy_cache_remove() function deletes all of the policy cache files
|
||||
based upon a directory file descriptor and path. The I<path> must point to a
|
||||
directory. See the openat(2) man page for examples of I<dirfd> and I<path>.
|
||||
|
||||
The aa_policy_cache_replace_all() function can be used to perform a policy
|
||||
replacement of all of the cache policies in the cache directory represented by
|
||||
the I<policy_cache> object. If I<kernel_interface> is NULL, then the current
|
||||
kernel interface is used. When specifying a valid I<kernel_interface> object,
|
||||
it must be the interface of the currently running kernel.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
The aa_policy_cache_new() function returns 0 on success and I<*policy_cache>
|
||||
will point to an I<aa_policy_cache> object that must be freed by
|
||||
aa_policy_cache_unref(). -1 is returned on error, with errno set appropriately,
|
||||
and I<*policy_cache> will be set to NULL.
|
||||
|
||||
aa_policy_cache_ref() returns the value of I<policy_cache>.
|
||||
|
||||
aa_policy_cache_remove() and aa_policy_cache_replace_all() return 0 on success.
|
||||
-1 is returned on error, with errno set appropriately.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
The errno value will be set according to the underlying error in the
|
||||
I<aa_policy_cache> family of functions that return -1 on error.
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
All aa_policy_cache functions described above are present in libapparmor
|
||||
version 2.10 and newer.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
aa_features(3), aa_kernel_interface(3), openat(2) and
|
||||
L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
@@ -1,137 +0,0 @@
|
||||
# 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 adhere 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_query_label - query access permission associated with a label
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<int aa_query_label((uint32_t mask, char *query, size_t size,
|
||||
int *allowed, int *audited);>
|
||||
|
||||
B<int aa_query_file_path((uint32_t mask, const char *label, size_t label_len,
|
||||
const char *path, int *allowed, int *audited);>
|
||||
|
||||
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);>
|
||||
|
||||
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);>
|
||||
|
||||
B<int aa_query_link_path(const char *label, const char *target,
|
||||
const char *link, int *allowed, int *audited);>
|
||||
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The aa_query_label function fetches the current permissions granted by the
|
||||
specified I<label> in the I<query> string.
|
||||
|
||||
The query is a raw binary formatted query, containing the label and
|
||||
permission query to make. The returned I<allowed> and I<audited> values are
|
||||
interpreted boolean values, simple stating whether the query is allowed and
|
||||
if it is audited.
|
||||
|
||||
The mask of the query string is a bit mask of permissions to query and is
|
||||
class type dependent (see AA_CLASS_xxx) entries in I<sys/apparmor.h>.
|
||||
|
||||
The format of the query string is also dependent on the B<AA_CLASS> and as
|
||||
such the the aa_query_xxx helper functions should usually be used instead
|
||||
of directly using I<aa_query_label>. If directly using the interface the
|
||||
I<query> string is required to have a header of B<AA_QUERY_CMD_LABEL_SIZE>
|
||||
that will be used by I<aa_query_label>.
|
||||
|
||||
The B<aa_query_file_path> and B<aa_query_file_path_len> functions are helper
|
||||
function that assemble a properly formatted file path query for the
|
||||
B<aa_query_label> function. The I<label> is a valid apparmor label as
|
||||
returned by I<aa_splitcon> with I<label_len> being the length of the I<label>.
|
||||
The I<path> is any valid filesystem path to query permissions for. For the
|
||||
B<aa_query_file_path_len> variant the I<path_len> parameter specifies the
|
||||
number of bytes in the I<path> to use as part of the query.
|
||||
|
||||
The B<aa_query_link_path> and B<aa_query_link_path_len> functions are helper
|
||||
functions that assemble a properly formatted link path query for the
|
||||
B<aa_query_label> function. The I<link_len> and I<target_len> parameters
|
||||
specify the number of bytes in the I<link> and I<target> to use as part of
|
||||
the query.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
On success 0 is returned, and the I<allowed> and I<audited> parameters
|
||||
contain a boolean value of 0 not allowed/audited or 1 allowed/audited. On
|
||||
error, -1 is returned, and errno(3) is set appropriately.
|
||||
|
||||
=head1 ERRORS
|
||||
|
||||
=over 4
|
||||
|
||||
=item B<EINVAL>
|
||||
|
||||
The requested I<mask> is empty.
|
||||
|
||||
The I<size> of the query is E<lt> the query B<AA_QUER?Y_CMD_LABEL_SIZE>
|
||||
|
||||
The apparmor kernel module is not loaded or the he kernel interface access
|
||||
interface is not available
|
||||
|
||||
=item B<ENOMEM>
|
||||
|
||||
Insufficient memory was available.
|
||||
|
||||
=item B<EACCES>
|
||||
|
||||
Access to the specified I<label> or query interface was denied.
|
||||
|
||||
=item B<ENOENT>
|
||||
|
||||
The specified I<label> does not exist or is not visible.
|
||||
|
||||
=item B<ERANGE>
|
||||
|
||||
The confinement data is too large to fit in the supplied buffer.
|
||||
|
||||
=back
|
||||
|
||||
=head1 NOTES
|
||||
|
||||
The label permissions returned are only valid for the time of the
|
||||
query and can change at any point in the future.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
apparmor(7), apparmor.d(5), apparmor_parser(8), aa_getcon(2), aa_splitcon(3)
|
||||
and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
@@ -1,72 +0,0 @@
|
||||
# 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 adhere 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_splitcon - split the confinement context into a label and mode
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
B<#include E<lt>sys/apparmor.hE<gt>>
|
||||
|
||||
B<char *aa_splitcon(char *con, char **mode);>
|
||||
|
||||
Link with B<-lapparmor> when compiling.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The aa_splitcon() function splits a confinement context into separate label
|
||||
and mode strings. The @con string is modified so that the label portion is NUL
|
||||
terminated. The enforcement mode is also NUL terminated and the parenthesis
|
||||
surrounding the mode are removed. If @mode is non-NULL, it will point to the
|
||||
first character in the enforcement mode string on success.
|
||||
|
||||
The Linux kernel's /proc/E<lt>PIDE<gt>/attr/current interface appends a
|
||||
trailing newline character to AppArmor contexts that are read from that file.
|
||||
If @con contains a single trailing newline character, it will be stripped by
|
||||
aa_splitcon() prior to all other processing.
|
||||
|
||||
=head1 RETURN VALUE
|
||||
|
||||
Returns a pointer to the first character in the label string. NULL is returned
|
||||
on error.
|
||||
|
||||
=head1 EXAMPLE
|
||||
|
||||
Context Label Mode
|
||||
----------------------------- ------------------ -------
|
||||
unconfined unconfined NULL
|
||||
unconfined\n unconfined NULL
|
||||
/bin/ping (enforce) /bin/ping enforce
|
||||
/bin/ping (enforce)\n /bin/ping enforce
|
||||
/usr/sbin/rsyslogd (complain) /usr/sbin/rsyslogd complain
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
None known. If you find any, please report them at
|
||||
L<https://bugs.launchpad.net/apparmor/+filebug>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
aa_getcon(2) and L<http://wiki.apparmor.net>.
|
||||
|
||||
=cut
|
@@ -1,3 +1,3 @@
|
||||
|
||||
apparmor_hdrdir = $(includedir)/sys
|
||||
apparmor_hdr_HEADERS = apparmor.h apparmor_private.h
|
||||
apparmor_hdr_HEADERS = apparmor.h
|
||||
|
@@ -18,7 +18,6 @@
|
||||
#ifndef _SYS_APPARMOR_H
|
||||
#define _SYS_APPARMOR_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -27,31 +26,10 @@ __BEGIN_DECLS
|
||||
/*
|
||||
* Class of public mediation types in the AppArmor policy db
|
||||
*/
|
||||
#define AA_CLASS_FILE 2
|
||||
|
||||
#define AA_CLASS_DBUS 32
|
||||
|
||||
|
||||
/* Permission flags for the AA_CLASS_FILE mediation class */
|
||||
#define AA_MAY_EXEC (1 << 0)
|
||||
#define AA_MAY_WRITE (1 << 1)
|
||||
#define AA_MAY_READ (1 << 2)
|
||||
#define AA_MAY_APPEND (1 << 3)
|
||||
#define AA_MAY_CREATE (1 << 4)
|
||||
#define AA_MAY_DELETE (1 << 5)
|
||||
#define AA_MAY_OPEN (1 << 6)
|
||||
#define AA_MAY_RENAME (1 << 7)
|
||||
#define AA_MAY_SETATTR (1 << 8)
|
||||
#define AA_MAY_GETATTR (1 << 9)
|
||||
#define AA_MAY_SETCRED (1 << 10)
|
||||
#define AA_MAY_GETCRED (1 << 11)
|
||||
#define AA_MAY_CHMOD (1 << 12)
|
||||
#define AA_MAY_CHOWN (1 << 13)
|
||||
#define AA_MAY_LOCK 0x8000
|
||||
#define AA_EXEC_MMAP 0x10000
|
||||
#define AA_MAY_LINK 0x40000
|
||||
#define AA_MAY_ONEXEC 0x20000000
|
||||
#define AA_MAY_CHANGE_PROFILE 0x40000000
|
||||
|
||||
/* Permission flags for the AA_CLASS_DBUS mediation class */
|
||||
#define AA_DBUS_SEND (1 << 1)
|
||||
#define AA_DBUS_RECEIVE (1 << 2)
|
||||
@@ -79,18 +57,16 @@ extern int aa_change_onexec(const char *profile);
|
||||
extern int aa_change_hatv(const char *subprofiles[], unsigned long token);
|
||||
extern int (aa_change_hat_vargs)(unsigned long token, int count, ...);
|
||||
|
||||
extern char *aa_splitcon(char *con, char **mode);
|
||||
/* Protypes for introspecting task confinement
|
||||
* Please see the aa_getcon(2) manpage for information
|
||||
*/
|
||||
extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
|
||||
char **mode);
|
||||
extern int aa_getprocattr(pid_t tid, const char *attr, char **label,
|
||||
char **mode);
|
||||
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
||||
extern int aa_getcon(char **label, char **mode);
|
||||
extern int aa_getprocattr(pid_t tid, const char *attr, char **con, char **mode);
|
||||
extern int aa_gettaskcon(pid_t target, char **con, char **mode);
|
||||
extern int aa_getcon(char **con, char **mode);
|
||||
extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
|
||||
extern int aa_getpeercon(int fd, char **label, char **mode);
|
||||
extern int aa_getpeercon(int fd, char **con, char **mode);
|
||||
|
||||
/* A NUL character is used to separate the query command prefix string from the
|
||||
* rest of the query string. The query command sizes intentionally include the
|
||||
@@ -101,17 +77,6 @@ extern int aa_getpeercon(int fd, char **label, char **mode);
|
||||
|
||||
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
||||
int *audit);
|
||||
extern 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);
|
||||
extern int aa_query_file_path(uint32_t mask, const char *label,
|
||||
const char *path, int *allowed, int *audited);
|
||||
extern 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);
|
||||
extern int aa_query_link_path(const char *label, const char *target,
|
||||
const char *link, int *allowed, int *audited);
|
||||
|
||||
#define __macroarg_counter(Y...) __macroarg_count1 ( , ##Y)
|
||||
#define __macroarg_count1(Y...) __macroarg_count2 (Y, 16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
|
||||
@@ -137,58 +102,6 @@ extern int aa_query_link_path(const char *label, const char *target,
|
||||
#define aa_change_hat_vargs(T, X...) \
|
||||
(aa_change_hat_vargs)(T, __macroarg_counter(X), X)
|
||||
|
||||
typedef struct aa_features aa_features;
|
||||
extern int aa_features_new(aa_features **features, int dirfd, const char *path);
|
||||
extern int aa_features_new_from_string(aa_features **features,
|
||||
const char *string, size_t size);
|
||||
extern int aa_features_new_from_kernel(aa_features **features);
|
||||
extern aa_features *aa_features_ref(aa_features *features);
|
||||
extern void aa_features_unref(aa_features *features);
|
||||
|
||||
extern int aa_features_write_to_file(aa_features *features,
|
||||
int dirfd, const char *path);
|
||||
extern bool aa_features_is_equal(aa_features *features1,
|
||||
aa_features *features2);
|
||||
extern bool aa_features_supports(aa_features *features, const char *str);
|
||||
|
||||
typedef struct aa_kernel_interface aa_kernel_interface;
|
||||
extern int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,
|
||||
aa_features *kernel_features,
|
||||
const char *apparmorfs);
|
||||
extern aa_kernel_interface *aa_kernel_interface_ref(aa_kernel_interface *kernel_interface);
|
||||
extern void aa_kernel_interface_unref(aa_kernel_interface *kernel_interface);
|
||||
|
||||
extern int aa_kernel_interface_load_policy(aa_kernel_interface *kernel_interface,
|
||||
const char *buffer, size_t size);
|
||||
extern int aa_kernel_interface_load_policy_from_file(aa_kernel_interface *kernel_interface,
|
||||
int dirfd,
|
||||
const char *path);
|
||||
extern int aa_kernel_interface_load_policy_from_fd(aa_kernel_interface *kernel_interface,
|
||||
int fd);
|
||||
extern int aa_kernel_interface_replace_policy(aa_kernel_interface *kernel_interface,
|
||||
const char *buffer, size_t size);
|
||||
extern int aa_kernel_interface_replace_policy_from_file(aa_kernel_interface *kernel_interface,
|
||||
int dirfd,
|
||||
const char *path);
|
||||
extern int aa_kernel_interface_replace_policy_from_fd(aa_kernel_interface *kernel_interface,
|
||||
int fd);
|
||||
extern int aa_kernel_interface_remove_policy(aa_kernel_interface *kernel_interface,
|
||||
const char *fqname);
|
||||
extern int aa_kernel_interface_write_policy(int fd, const char *buffer,
|
||||
size_t size);
|
||||
|
||||
typedef struct aa_policy_cache aa_policy_cache;
|
||||
extern int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
aa_features *kernel_features,
|
||||
int dirfd, const char *path,
|
||||
uint16_t max_caches);
|
||||
extern aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache);
|
||||
extern void aa_policy_cache_unref(aa_policy_cache *policy_cache);
|
||||
|
||||
extern int aa_policy_cache_remove(int dirfd, const char *path);
|
||||
extern int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
|
||||
aa_kernel_interface *kernel_interface);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* sys/apparmor.h */
|
||||
|
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 Canonical Ltd.
|
||||
*
|
||||
* The libapparmor library is licensed under the terms of the GNU
|
||||
* Lesser General Public License, version 2.1. Please see the file
|
||||
* COPYING.LGPL.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_APPARMOR_PRIVATE_H
|
||||
#define _SYS_APPARMOR_PRIVATE_H 1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
int _aa_is_blacklisted(const char *name);
|
||||
|
||||
void _aa_autofree(void *p);
|
||||
void _aa_autoclose(int *fd);
|
||||
void _aa_autofclose(FILE **f);
|
||||
|
||||
int _aa_asprintf(char **strp, const char *fmt, ...);
|
||||
|
||||
int _aa_dirat_for_each(int dirfd, const char *name, void *data,
|
||||
int (* cb)(int, const char *, struct stat *, void *));
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* sys/apparmor_private.h */
|
@@ -26,9 +26,9 @@ INCLUDES = $(all_includes)
|
||||
# For more information, see:
|
||||
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
|
||||
#
|
||||
AA_LIB_CURRENT = 4
|
||||
AA_LIB_REVISION = 0
|
||||
AA_LIB_AGE = 3
|
||||
AA_LIB_CURRENT = 3
|
||||
AA_LIB_REVISION = 1
|
||||
AA_LIB_AGE = 2
|
||||
|
||||
SUFFIXES = .pc.in .pc
|
||||
|
||||
@@ -46,9 +46,9 @@ af_protos.h: /usr/include/netinet/in.h
|
||||
LC_ALL=C sed -n -e "/IPPROTO_MAX/d" -e "s/^\#define[ \\t]\\+IPPROTO_\\([A-Z0-9_]\\+\\)\\(.*\\)$$/AA_GEN_PROTO_ENT(\\UIPPROTO_\\1, \"\\L\\1\")/p" $< > $@
|
||||
|
||||
lib_LTLIBRARIES = libapparmor.la
|
||||
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h
|
||||
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h
|
||||
|
||||
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c
|
||||
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel_interface.c scanner.c
|
||||
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -dynamic -pthread \
|
||||
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
|
||||
|
||||
@@ -63,15 +63,7 @@ CLEANFILES = libapparmor.pc
|
||||
|
||||
tst_aalogmisc_SOURCES = tst_aalogmisc.c
|
||||
tst_aalogmisc_LDADD = .libs/libapparmor.a
|
||||
|
||||
tst_features_SOURCES = tst_features.c
|
||||
tst_features_LDADD = .libs/libapparmor.a
|
||||
|
||||
tst_kernel_SOURCES = tst_kernel.c
|
||||
tst_kernel_LDADD = .libs/libapparmor.a
|
||||
tst_kernel_LDFLAGS = -pthread
|
||||
|
||||
check_PROGRAMS = tst_aalogmisc tst_features tst_kernel
|
||||
check_PROGRAMS = tst_aalogmisc
|
||||
TESTS = $(check_PROGRAMS)
|
||||
|
||||
EXTRA_DIST = grammar.y scanner.l libapparmor.map libapparmor.pc
|
||||
|
@@ -1,561 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014
|
||||
* 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 <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/apparmor.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#define FEATURES_FILE "/sys/kernel/security/apparmor/features"
|
||||
|
||||
#define STRING_SIZE 8192
|
||||
|
||||
struct aa_features {
|
||||
unsigned int ref_count;
|
||||
char string[STRING_SIZE];
|
||||
};
|
||||
|
||||
struct features_struct {
|
||||
char *buffer;
|
||||
int size;
|
||||
char *pos;
|
||||
};
|
||||
|
||||
struct component {
|
||||
const char *str;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
static int features_snprintf(struct features_struct *fst, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int i, remaining = fst->size - (fst->pos - fst->buffer);
|
||||
|
||||
if (remaining < 0) {
|
||||
errno = EINVAL;
|
||||
PERROR("Invalid features buffer offset\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
va_start(args, fmt);
|
||||
i = vsnprintf(fst->pos, remaining, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (i < 0) {
|
||||
errno = EIO;
|
||||
PERROR("Failed to write to features buffer\n");
|
||||
return -1;
|
||||
} else if (i >= remaining) {
|
||||
errno = ENOBUFS;
|
||||
PERROR("Feature buffer full.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fst->pos += i;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* load_features_file - opens and reads a file into @buffer and then NUL-terminates @buffer
|
||||
* @dirfd: a directory file descriptory or AT_FDCWD (see openat(2))
|
||||
* @path: name of the file
|
||||
* @buffer: the buffer to read the features file into (will be NUL-terminated on success)
|
||||
* @size: the size of @buffer
|
||||
*
|
||||
* Returns: The number of bytes copied into @buffer on success (not counting
|
||||
* the NUL-terminator), else -1 and errno is set. Note that @size must be
|
||||
* larger than the size of the file or -1 will be returned with errno set to
|
||||
* ENOBUFS indicating that @buffer was not large enough to contain all of the
|
||||
* file contents.
|
||||
*/
|
||||
static int load_features_file(int dirfd, const char *path,
|
||||
char *buffer, size_t size)
|
||||
{
|
||||
autoclose int file = -1;
|
||||
char *pos = buffer;
|
||||
ssize_t len;
|
||||
|
||||
file = openat(dirfd, path, O_RDONLY);
|
||||
if (file < 0) {
|
||||
PDEBUG("Could not open '%s'\n", path);
|
||||
return -1;
|
||||
}
|
||||
PDEBUG("Opened features \"%s\"\n", path);
|
||||
|
||||
if (!size) {
|
||||
errno = ENOBUFS;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Save room for a NUL-terminator at the end of @buffer */
|
||||
size--;
|
||||
|
||||
do {
|
||||
len = read(file, pos, size);
|
||||
if (len > 0) {
|
||||
size -= len;
|
||||
pos += len;
|
||||
}
|
||||
} while (len > 0 && size);
|
||||
|
||||
/**
|
||||
* Possible error conditions:
|
||||
* - len == -1: read failed and errno is already set so return -1
|
||||
* - len > 0: read() never returned 0 (EOF) meaning that @buffer was
|
||||
* too small to contain all of the file contents so set
|
||||
* errno to ENOBUFS and return -1
|
||||
*/
|
||||
if (len) {
|
||||
if (len > 0)
|
||||
errno = ENOBUFS;
|
||||
|
||||
PDEBUG("Error reading features file '%s': %m\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* NUL-terminate @buffer */
|
||||
*pos = 0;
|
||||
|
||||
return pos - buffer;
|
||||
}
|
||||
|
||||
static int features_dir_cb(int dirfd, const char *name, struct stat *st,
|
||||
void *data)
|
||||
{
|
||||
struct features_struct *fst = (struct features_struct *) data;
|
||||
|
||||
/* skip dot files and files with no name */
|
||||
if (*name == '.' || !strlen(name))
|
||||
return 0;
|
||||
|
||||
if (features_snprintf(fst, "%s {", name) == -1)
|
||||
return -1;
|
||||
|
||||
if (S_ISREG(st->st_mode)) {
|
||||
int len;
|
||||
int remaining = fst->size - (fst->pos - fst->buffer);
|
||||
|
||||
len = load_features_file(dirfd, name, fst->pos, remaining);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
fst->pos += len;
|
||||
} else if (S_ISDIR(st->st_mode)) {
|
||||
if (_aa_dirat_for_each(dirfd, name, fst, features_dir_cb))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (features_snprintf(fst, "}\n") == -1)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_features_dir(int dirfd, const char *path,
|
||||
char *buffer, int size)
|
||||
{
|
||||
struct features_struct fst = { buffer, size, buffer };
|
||||
|
||||
if (_aa_dirat_for_each(dirfd, path, &fst, features_dir_cb)) {
|
||||
PDEBUG("Failed evaluating %s\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool islbrace(int c)
|
||||
{
|
||||
return c == '{';
|
||||
}
|
||||
|
||||
static bool isrbrace(int c)
|
||||
{
|
||||
return c == '}';
|
||||
}
|
||||
|
||||
static bool isnul(int c)
|
||||
{
|
||||
return c == '\0';
|
||||
}
|
||||
|
||||
static bool isbrace(int c)
|
||||
{
|
||||
return islbrace(c) || isrbrace(c);
|
||||
}
|
||||
|
||||
static bool isbrace_or_nul(int c)
|
||||
{
|
||||
return isbrace(c) || isnul(c);
|
||||
}
|
||||
|
||||
static bool isbrace_space_or_nul(int c)
|
||||
{
|
||||
return isbrace(c) || isspace(c) || isnul(c);
|
||||
}
|
||||
|
||||
static size_t tokenize_path_components(const char *str,
|
||||
struct component *components,
|
||||
size_t max_components)
|
||||
{
|
||||
size_t i = 0;
|
||||
|
||||
memset(components, 0, sizeof(*components) * max_components);
|
||||
|
||||
if (!str)
|
||||
return 0;
|
||||
|
||||
while (*str && i < max_components) {
|
||||
const char *fwdslash = strchrnul(str, '/');
|
||||
|
||||
/* Save the token if it is not "/" */
|
||||
if (fwdslash != str) {
|
||||
components[i].str = str;
|
||||
components[i].len = fwdslash - str;
|
||||
i++;
|
||||
}
|
||||
|
||||
if (isnul(*fwdslash))
|
||||
break;
|
||||
|
||||
str = fwdslash + 1;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* walk_one - walk one component of a features string
|
||||
* @str: a pointer to the current position in a features string
|
||||
* @component: the component to walk
|
||||
* @is_top_level: true if component is a top-level component
|
||||
*
|
||||
* Imagine a features string such as:
|
||||
*
|
||||
* "feat1 { subfeat1.1 subfeat1.2 } feat2 { subfeat2.1 { subfeat2.1.1 } }"
|
||||
*
|
||||
* You want to know if "feat2/subfeat2.1/subfeat2.8" is valid. It will take 3
|
||||
* invocations of this function to determine if that string is valid. On the
|
||||
* first call, *@str will point to the beginning of the features string,
|
||||
* component->str will be "feat2", and is_top_level will be true since feat2 is
|
||||
* a top level feature. The function will return true and *@str will now point
|
||||
* at the the left brace after "feat2" in the features string. You can call
|
||||
* this function again with component->str being equal to "subfeat2.1" and it
|
||||
* will return true and *@str will now point at the left brace after
|
||||
* "subfeat2.1" in the features string. A third call to the function, with
|
||||
* component->str equal to "subfeat2.8", will return false and *@str will not
|
||||
* be changed.
|
||||
*
|
||||
* Returns true if the walk was successful and false otherwise. If the walk was
|
||||
* successful, *@str will point to the first encountered brace after the walk.
|
||||
* If the walk was unsuccessful, *@str is not updated.
|
||||
*/
|
||||
static bool walk_one(const char **str, const struct component *component,
|
||||
bool is_top_level)
|
||||
{
|
||||
const char *cur;
|
||||
uint32_t brace_count = 0;
|
||||
size_t i = 0;
|
||||
|
||||
/* NULL pointers and empty strings are not accepted */
|
||||
if (!str || !*str || !component || !component->str || !component->len)
|
||||
return false;
|
||||
|
||||
cur = *str;
|
||||
|
||||
/**
|
||||
* If @component is not top-level, the first character in the string to
|
||||
* search MUST be '{'
|
||||
*/
|
||||
if (!is_top_level) {
|
||||
if (!islbrace(*cur))
|
||||
return false;
|
||||
|
||||
cur++;
|
||||
}
|
||||
|
||||
/**
|
||||
* This loop tries to find the @component in *@str. When this loops
|
||||
* completes, cur will either point one character past the end of the
|
||||
* matched @component or to the NUL terminator of *@str.
|
||||
*/
|
||||
while(!isnul(*cur) && i < component->len) {
|
||||
if (!isascii(*cur)) {
|
||||
/* Only ASCII is expected */
|
||||
return false;
|
||||
} else if (islbrace(*cur)) {
|
||||
/* There's a limit to the number of left braces */
|
||||
if (brace_count == UINT32_MAX)
|
||||
return false;
|
||||
|
||||
brace_count++;
|
||||
} else if (isrbrace(*cur)) {
|
||||
/* Check for unexpected right braces */
|
||||
if (brace_count == 0)
|
||||
return false;
|
||||
|
||||
brace_count--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move to the next character in @component if we're not inside
|
||||
* of braces and we have a character match
|
||||
*/
|
||||
if (brace_count == 0 && *cur == component->str[i])
|
||||
i++;
|
||||
else
|
||||
i = 0;
|
||||
|
||||
cur++;
|
||||
}
|
||||
|
||||
/* Return false if a full match was not found */
|
||||
if (i != component->len) {
|
||||
return false;
|
||||
} else if (!isbrace_space_or_nul(*cur))
|
||||
return false;
|
||||
|
||||
/**
|
||||
* This loop eats up valid (ASCII) characters until a brace or NUL
|
||||
* character is found so that *@str is properly set to call back into
|
||||
* this function
|
||||
*/
|
||||
while (!isbrace_or_nul(*cur)) {
|
||||
if (!isascii(*cur))
|
||||
return false;
|
||||
|
||||
cur++;
|
||||
}
|
||||
|
||||
*str = cur;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_features_new - create a new aa_features object based on a path
|
||||
* @features: will point to the address of an allocated and initialized
|
||||
* aa_features object upon success
|
||||
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
|
||||
* @path: path to a features file or directory
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and *@features pointing to
|
||||
* NULL
|
||||
*/
|
||||
int aa_features_new(aa_features **features, int dirfd, const char *path)
|
||||
{
|
||||
struct stat stat_file;
|
||||
aa_features *f;
|
||||
int retval;
|
||||
|
||||
*features = NULL;
|
||||
|
||||
if (fstatat(dirfd, path, &stat_file, 0) == -1)
|
||||
return -1;
|
||||
|
||||
f = calloc(1, sizeof(*f));
|
||||
if (!f) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
aa_features_ref(f);
|
||||
|
||||
retval = S_ISDIR(stat_file.st_mode) ?
|
||||
load_features_dir(dirfd, path, f->string, STRING_SIZE) :
|
||||
load_features_file(dirfd, path, f->string, STRING_SIZE);
|
||||
if (retval == -1) {
|
||||
int save = errno;
|
||||
|
||||
aa_features_unref(f);
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*features = f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_features_new_from_string - create a new aa_features object based on a string
|
||||
* @features: will point to the address of an allocated and initialized
|
||||
* aa_features object upon success
|
||||
* @string: a NUL-terminated string representation of features
|
||||
* @size: the size of @string, not counting the NUL-terminator
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and *@features pointing to
|
||||
* NULL
|
||||
*/
|
||||
int aa_features_new_from_string(aa_features **features,
|
||||
const char *string, size_t size)
|
||||
{
|
||||
aa_features *f;
|
||||
|
||||
*features = NULL;
|
||||
|
||||
/* Require size to be less than STRING_SIZE so there's room for a NUL */
|
||||
if (size >= STRING_SIZE)
|
||||
return ENOBUFS;
|
||||
|
||||
f = calloc(1, sizeof(*f));
|
||||
if (!f) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
aa_features_ref(f);
|
||||
|
||||
memcpy(f->string, string, size);
|
||||
f->string[size] = '\0';
|
||||
*features = f;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_features_new_from_kernel - create a new aa_features object based on the current kernel
|
||||
* @features: will point to the address of an allocated and initialized
|
||||
* aa_features object upon success
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and *@features pointing to
|
||||
* NULL
|
||||
*/
|
||||
int aa_features_new_from_kernel(aa_features **features)
|
||||
{
|
||||
return aa_features_new(features, -1, FEATURES_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_features_ref - increments the ref count of an aa_features object
|
||||
* @features: the features
|
||||
*
|
||||
* Returns: the features
|
||||
*/
|
||||
aa_features *aa_features_ref(aa_features *features)
|
||||
{
|
||||
atomic_inc(&features->ref_count);
|
||||
return features;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_features_unref - decrements the ref count and frees the aa_features object when 0
|
||||
* @features: the features (can be NULL)
|
||||
*/
|
||||
void aa_features_unref(aa_features *features)
|
||||
{
|
||||
if (features && atomic_dec_and_test(&features->ref_count))
|
||||
free(features);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_features_write_to_file - write a string representation of an aa_features object to a file
|
||||
* @features: the features
|
||||
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
|
||||
* @path: the path to write to
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set
|
||||
*/
|
||||
int aa_features_write_to_file(aa_features *features,
|
||||
int dirfd, const char *path)
|
||||
{
|
||||
autoclose int fd = -1;
|
||||
size_t size;
|
||||
ssize_t retval;
|
||||
char *string;
|
||||
|
||||
fd = openat(dirfd, path,
|
||||
O_WRONLY | O_CREAT | O_TRUNC | O_SYNC | O_CLOEXEC,
|
||||
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
string = features->string;
|
||||
size = strlen(string);
|
||||
do {
|
||||
retval = write(fd, string, size);
|
||||
if (retval == -1)
|
||||
return -1;
|
||||
|
||||
size -= retval;
|
||||
string += retval;
|
||||
} while (size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_features_is_equal - equality test for two aa_features objects
|
||||
* @features1: the first features (can be NULL)
|
||||
* @features2: the second features (can be NULL)
|
||||
*
|
||||
* Returns: true if they're equal, false if they're not or either are NULL
|
||||
*/
|
||||
bool aa_features_is_equal(aa_features *features1, aa_features *features2)
|
||||
{
|
||||
return features1 && features2 &&
|
||||
strcmp(features1->string, features2->string) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_features_supports - provides aa_features object support status
|
||||
* @features: the features
|
||||
* @str: the string representation of a feature to check
|
||||
*
|
||||
* Example @str values are "dbus/mask/send", "caps/mask/audit_read", and
|
||||
* "policy/versions/v7".
|
||||
*
|
||||
* Returns: a bool specifying the support status of @str feature
|
||||
*/
|
||||
bool aa_features_supports(aa_features *features, const char *str)
|
||||
{
|
||||
const char *features_string = features->string;
|
||||
struct component components[32];
|
||||
size_t i, num_components;
|
||||
|
||||
/* Empty strings are not accepted. Neither are leading '/' chars. */
|
||||
if (!str || str[0] == '/')
|
||||
return false;
|
||||
|
||||
/**
|
||||
* Break @str into an array of components. For example,
|
||||
* "mount/mask/mount" would turn into { "mount", 5 } as the first
|
||||
* component, { "mask", 4 } as the second, and { "mount", 5 } as the
|
||||
* third
|
||||
*/
|
||||
num_components = tokenize_path_components(str, components,
|
||||
sizeof(components) / sizeof(*components));
|
||||
|
||||
/* At least one valid token is required */
|
||||
if (!num_components)
|
||||
return false;
|
||||
|
||||
/* Ensure that all components are valid and found */
|
||||
for (i = 0; i < num_components; i++) {
|
||||
if (!walk_one(&features_string, &components[i], i == 0))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@@ -166,15 +166,9 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
||||
%token TOK_SYSLOG_KERNEL
|
||||
%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
|
||||
| dmesg_type
|
||||
| syslog_type
|
||||
| audit_dispatch
|
||||
;
|
||||
@@ -205,10 +199,6 @@ 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
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($1); }
|
||||
;
|
||||
|
||||
syslog_type:
|
||||
syslog_date TOK_ID TOK_SYSLOG_KERNEL audit_id key_list
|
||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($2); }
|
||||
@@ -428,7 +418,7 @@ _parse_yacc(char *str)
|
||||
int parser_return;
|
||||
|
||||
ret_record = NULL;
|
||||
ret_record = malloc(sizeof(aa_log_record));
|
||||
ret_record = (aa_log_record *) malloc(sizeof(aa_log_record));
|
||||
|
||||
_init_log_record(ret_record);
|
||||
|
||||
|
@@ -1,982 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2003-2008 Novell, Inc. (All rights reserved)
|
||||
* Copyright 2009-2010 Canonical Ltd.
|
||||
*
|
||||
* The libapparmor library is licensed under the terms of the GNU
|
||||
* Lesser General Public License, version 2.1. Please see the file
|
||||
* COPYING.LGPL.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <mntent.h>
|
||||
#include <inttypes.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include <sys/apparmor.h>
|
||||
#include "private.h"
|
||||
|
||||
/* some non-Linux systems do not define a static value */
|
||||
#ifndef PATH_MAX
|
||||
# define PATH_MAX 4096
|
||||
#endif
|
||||
|
||||
#define symbol_version(real, name, version) \
|
||||
__asm__ (".symver " #real "," #name "@" #version)
|
||||
#define default_symbol_version(real, name, version) \
|
||||
__asm__ (".symver " #real "," #name "@@" #version)
|
||||
|
||||
#define UNCONFINED "unconfined"
|
||||
#define UNCONFINED_SIZE strlen(UNCONFINED)
|
||||
|
||||
/**
|
||||
* aa_find_mountpoint - find where the apparmor interface filesystem is mounted
|
||||
* @mnt: returns buffer with the mountpoint string
|
||||
*
|
||||
* Returns: 0 on success else -1 on error
|
||||
*
|
||||
* NOTE: this function only supports versions of apparmor using securityfs
|
||||
*/
|
||||
int aa_find_mountpoint(char **mnt)
|
||||
{
|
||||
struct stat statbuf;
|
||||
struct mntent *mntpt;
|
||||
FILE *mntfile;
|
||||
int rc = -1;
|
||||
|
||||
if (!mnt) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
mntfile = setmntent("/proc/mounts", "r");
|
||||
if (!mntfile)
|
||||
return -1;
|
||||
|
||||
while ((mntpt = getmntent(mntfile))) {
|
||||
char *proposed = NULL;
|
||||
if (strcmp(mntpt->mnt_type, "securityfs") != 0)
|
||||
continue;
|
||||
|
||||
if (asprintf(&proposed, "%s/apparmor", mntpt->mnt_dir) < 0)
|
||||
/* ENOMEM */
|
||||
break;
|
||||
|
||||
if (stat(proposed, &statbuf) == 0) {
|
||||
*mnt = proposed;
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
free(proposed);
|
||||
}
|
||||
endmntent(mntfile);
|
||||
if (rc == -1)
|
||||
errno = ENOENT;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_is_enabled - determine if apparmor is enabled
|
||||
*
|
||||
* Returns: 1 if enabled else reason it is not, or 0 on error
|
||||
*
|
||||
* ENOSYS - no indication apparmor is present in the system
|
||||
* ENOENT - enabled but interface could not be found
|
||||
* ECANCELED - disabled at boot
|
||||
* ENOMEM - out of memory
|
||||
*/
|
||||
int aa_is_enabled(void)
|
||||
{
|
||||
int serrno, fd, rc, size;
|
||||
char buffer[2];
|
||||
char *mnt;
|
||||
|
||||
/* if the interface mountpoint is available apparmor is enabled */
|
||||
rc = aa_find_mountpoint(&mnt);
|
||||
if (rc == 0) {
|
||||
free(mnt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* determine why the interface mountpoint isn't available */
|
||||
fd = open("/sys/module/apparmor/parameters/enabled", O_RDONLY);
|
||||
if (fd == -1) {
|
||||
if (errno == ENOENT)
|
||||
errno = ENOSYS;
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = read(fd, &buffer, 2);
|
||||
serrno = errno;
|
||||
close(fd);
|
||||
errno = serrno;
|
||||
|
||||
if (size > 0) {
|
||||
if (buffer[0] == 'Y')
|
||||
errno = ENOENT;
|
||||
else
|
||||
errno = ECANCELED;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline pid_t aa_gettid(void)
|
||||
{
|
||||
#ifdef SYS_gettid
|
||||
return syscall(SYS_gettid);
|
||||
#else
|
||||
return getpid();
|
||||
#endif
|
||||
}
|
||||
|
||||
static char *procattr_path(pid_t pid, const char *attr)
|
||||
{
|
||||
char *path = NULL;
|
||||
if (asprintf(&path, "/proc/%d/attr/%s", pid, attr) > 0)
|
||||
return path;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* parse_unconfined - check for the unconfined label
|
||||
* @con: the confinement context
|
||||
* @size: size of the confinement context (not including the NUL terminator)
|
||||
*
|
||||
* Returns: True if the con is the unconfined label or false otherwise
|
||||
*/
|
||||
static bool parse_unconfined(char *con, int size)
|
||||
{
|
||||
return size == UNCONFINED_SIZE &&
|
||||
strncmp(con, UNCONFINED, UNCONFINED_SIZE) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* splitcon - split the confinement context into a label and mode
|
||||
* @con: the confinement context
|
||||
* @size: size of the confinement context (not including the NUL terminator)
|
||||
* @strip_newline: true if a trailing newline character should be stripped
|
||||
* @mode: if non-NULL and a mode is present, will point to mode string in @con
|
||||
* on success
|
||||
*
|
||||
* Modifies the @con string to split it into separate label and mode strings.
|
||||
* If @strip_newline is true and @con contains a single trailing newline, it
|
||||
* will be stripped on success (it will not be stripped on error). The @mode
|
||||
* argument is optional. If @mode is NULL, @con will still be split between the
|
||||
* label and mode (if present) but @mode will not be set.
|
||||
*
|
||||
* Returns: a pointer to the label string or NULL on error
|
||||
*/
|
||||
static char *splitcon(char *con, int size, bool strip_newline, char **mode)
|
||||
{
|
||||
char *label = NULL;
|
||||
char *mode_str = NULL;
|
||||
char *newline = NULL;
|
||||
|
||||
if (size == 0)
|
||||
goto out;
|
||||
|
||||
if (strip_newline && con[size - 1] == '\n') {
|
||||
newline = &con[size - 1];
|
||||
size--;
|
||||
}
|
||||
|
||||
if (parse_unconfined(con, size)) {
|
||||
label = con;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (size > 3 && con[size - 1] == ')') {
|
||||
int pos = size - 2;
|
||||
|
||||
while (pos > 0 && !(con[pos] == ' ' && con[pos + 1] == '('))
|
||||
pos--;
|
||||
if (pos > 0) {
|
||||
con[pos] = 0; /* overwrite ' ' */
|
||||
con[size - 1] = 0; /* overwrite trailing ) */
|
||||
mode_str = &con[pos + 2]; /* skip '(' */
|
||||
label = con;
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (label && strip_newline && newline)
|
||||
*newline = 0; /* overwrite '\n', if requested, on success */
|
||||
if (mode)
|
||||
*mode = mode_str;
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_splitcon - split the confinement context into a label and mode
|
||||
* @con: the confinement context
|
||||
* @mode: if non-NULL and a mode is present, will point to mode string in @con
|
||||
* on success
|
||||
*
|
||||
* Modifies the @con string to split it into separate label and mode strings. A
|
||||
* single trailing newline character will be stripped from @con, if found. The
|
||||
* @mode argument is optional. If @mode is NULL, @con will still be split
|
||||
* between the label and mode (if present) but @mode will not be set.
|
||||
*
|
||||
* Returns: a pointer to the label string or NULL on error
|
||||
*/
|
||||
char *aa_splitcon(char *con, char **mode)
|
||||
{
|
||||
return splitcon(con, strlen(con), true, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_getprocattr_raw - get the contents of @attr for @tid into @buf
|
||||
* @tid: tid of task to query
|
||||
* @attr: which /proc/<tid>/attr/<attr> to query
|
||||
* @buf: buffer to store the result in
|
||||
* @len: size of the buffer
|
||||
* @mode: if non-NULL and a mode is present, will point to mode string in @buf
|
||||
*
|
||||
* Returns: size of data read or -1 on error, and sets errno
|
||||
*/
|
||||
int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
|
||||
char **mode)
|
||||
{
|
||||
int rc = -1;
|
||||
int fd, ret;
|
||||
char *tmp = NULL;
|
||||
int size = 0;
|
||||
|
||||
if (!buf || len <= 0) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp = procattr_path(tid, attr);
|
||||
if (!tmp)
|
||||
goto out;
|
||||
|
||||
fd = open(tmp, O_RDONLY);
|
||||
free(tmp);
|
||||
if (fd == -1) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
tmp = buf;
|
||||
do {
|
||||
ret = read(fd, tmp, len);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
tmp += ret;
|
||||
size += ret;
|
||||
len -= ret;
|
||||
if (len < 0) {
|
||||
errno = ERANGE;
|
||||
goto out2;
|
||||
}
|
||||
} while (ret > 0);
|
||||
|
||||
if (ret < 0) {
|
||||
int saved;
|
||||
if (ret != -1) {
|
||||
errno = EPROTO;
|
||||
}
|
||||
saved = errno;
|
||||
(void)close(fd);
|
||||
errno = saved;
|
||||
goto out;
|
||||
} else if (size > 0 && buf[size - 1] != 0) {
|
||||
/* check for null termination */
|
||||
if (buf[size - 1] != '\n') {
|
||||
if (len == 0) {
|
||||
errno = ERANGE;
|
||||
goto out2;
|
||||
} else {
|
||||
buf[size] = 0;
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
if (splitcon(buf, size, true, mode) != buf) {
|
||||
errno = EINVAL;
|
||||
goto out2;
|
||||
}
|
||||
}
|
||||
rc = size;
|
||||
|
||||
out2:
|
||||
(void)close(fd);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define INITIAL_GUESS_SIZE 128
|
||||
|
||||
/**
|
||||
* aa_getprocattr - get the contents of @attr for @tid into @label and @mode
|
||||
* @tid: tid of task to query
|
||||
* @attr: which /proc/<tid>/attr/<attr> to query
|
||||
* @label: allocated buffer the label is stored in
|
||||
* @mode: if non-NULL and a mode is present, will point to mode string in @label
|
||||
*
|
||||
* Returns: size of data read or -1 on error, and sets errno
|
||||
*
|
||||
* Guarantees that @label and @mode are null terminated. The length returned
|
||||
* is for all data including both @label and @mode, and maybe > than
|
||||
* strlen(@label) even if @mode is NULL
|
||||
*
|
||||
* Caller is responsible for freeing the buffer returned in @label. @mode is
|
||||
* always contained within @label's buffer and so NEVER do free(@mode)
|
||||
*/
|
||||
int aa_getprocattr(pid_t tid, const char *attr, char **label, char **mode)
|
||||
{
|
||||
int rc, size = INITIAL_GUESS_SIZE/2;
|
||||
char *buffer = NULL;
|
||||
|
||||
if (!label) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
char *tmp;
|
||||
|
||||
size <<= 1;
|
||||
tmp = realloc(buffer, size);
|
||||
if (!tmp) {
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
buffer = tmp;
|
||||
memset(buffer, 0, size);
|
||||
|
||||
rc = aa_getprocattr_raw(tid, attr, buffer, size, mode);
|
||||
} while (rc == -1 && errno == ERANGE);
|
||||
|
||||
if (rc == -1) {
|
||||
free(buffer);
|
||||
*label = NULL;
|
||||
if (mode)
|
||||
*mode = NULL;
|
||||
} else
|
||||
*label = buffer;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int setprocattr(pid_t tid, const char *attr, const char *buf, int len)
|
||||
{
|
||||
int rc = -1;
|
||||
int fd, ret;
|
||||
char *ctl = NULL;
|
||||
|
||||
if (!buf) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ctl = procattr_path(tid, attr);
|
||||
if (!ctl)
|
||||
goto out;
|
||||
|
||||
fd = open(ctl, O_WRONLY);
|
||||
if (fd == -1) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = write(fd, buf, len);
|
||||
if (ret != len) {
|
||||
int saved;
|
||||
if (ret != -1) {
|
||||
errno = EPROTO;
|
||||
}
|
||||
saved = errno;
|
||||
(void)close(fd);
|
||||
errno = saved;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = 0;
|
||||
(void)close(fd);
|
||||
|
||||
out:
|
||||
if (ctl) {
|
||||
free(ctl);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int aa_change_hat(const char *subprofile, unsigned long token)
|
||||
{
|
||||
int rc = -1;
|
||||
int len = 0;
|
||||
char *buf = NULL;
|
||||
const char *fmt = "changehat %016lx^%s";
|
||||
|
||||
/* both may not be null */
|
||||
if (!(token || subprofile)) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (subprofile && strnlen(subprofile, PATH_MAX + 1) > PATH_MAX) {
|
||||
errno = EPROTO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = asprintf(&buf, fmt, token, subprofile ? subprofile : "");
|
||||
if (len < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = setprocattr(aa_gettid(), "current", buf, len);
|
||||
out:
|
||||
if (buf) {
|
||||
/* clear local copy of magic token before freeing */
|
||||
memset(buf, '\0', len);
|
||||
free(buf);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* original change_hat interface */
|
||||
int __change_hat(char *subprofile, unsigned int token)
|
||||
{
|
||||
return aa_change_hat(subprofile, (unsigned long) token);
|
||||
}
|
||||
|
||||
int aa_change_profile(const char *profile)
|
||||
{
|
||||
char *buf = NULL;
|
||||
int len;
|
||||
int rc;
|
||||
|
||||
if (!profile) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = asprintf(&buf, "changeprofile %s", profile);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
rc = setprocattr(aa_gettid(), "current", buf, len);
|
||||
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int aa_change_onexec(const char *profile)
|
||||
{
|
||||
char *buf = NULL;
|
||||
int len;
|
||||
int rc;
|
||||
|
||||
if (!profile) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
len = asprintf(&buf, "exec %s", profile);
|
||||
if (len < 0)
|
||||
return -1;
|
||||
|
||||
rc = setprocattr(aa_gettid(), "exec", buf, len);
|
||||
|
||||
free(buf);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* create an alias for the old change_hat@IMMUNIX_1.0 symbol */
|
||||
extern typeof((__change_hat)) __old_change_hat __attribute__((alias ("__change_hat")));
|
||||
symbol_version(__old_change_hat, change_hat, IMMUNIX_1.0);
|
||||
default_symbol_version(__change_hat, change_hat, APPARMOR_1.0);
|
||||
|
||||
|
||||
int aa_change_hatv(const char *subprofiles[], unsigned long token)
|
||||
{
|
||||
int size, totallen = 0, hatcount = 0;
|
||||
int rc = -1;
|
||||
const char **hats;
|
||||
char *pos, *buf = NULL;
|
||||
const char *cmd = "changehat";
|
||||
|
||||
/* both may not be null */
|
||||
if (!token && !(subprofiles && *subprofiles)) {
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* validate hat lengths and while we are at it count how many and
|
||||
* mem required */
|
||||
if (subprofiles) {
|
||||
for (hats = subprofiles; *hats; hats++) {
|
||||
int len = strnlen(*hats, PATH_MAX + 1);
|
||||
if (len > PATH_MAX) {
|
||||
errno = EPROTO;
|
||||
goto out;
|
||||
}
|
||||
totallen += len + 1;
|
||||
hatcount++;
|
||||
}
|
||||
}
|
||||
|
||||
/* allocate size of cmd + space + token + ^ + vector of hats */
|
||||
size = strlen(cmd) + 18 + totallen + 1;
|
||||
buf = malloc(size);
|
||||
if (!buf) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* setup command string which is of the form
|
||||
* changehat <token>^hat1\0hat2\0hat3\0..\0
|
||||
*/
|
||||
sprintf(buf, "%s %016lx^", cmd, token);
|
||||
pos = buf + strlen(buf);
|
||||
if (subprofiles) {
|
||||
for (hats = subprofiles; *hats; hats++) {
|
||||
strcpy(pos, *hats);
|
||||
pos += strlen(*hats) + 1;
|
||||
}
|
||||
} else
|
||||
/* step pos past trailing \0 */
|
||||
pos++;
|
||||
|
||||
rc = setprocattr(aa_gettid(), "current", buf, pos - buf);
|
||||
|
||||
out:
|
||||
if (buf) {
|
||||
/* clear local copy of magic token before freeing */
|
||||
memset(buf, '\0', size);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* change_hat_vargs - change_hatv but passing the hats as fn arguments
|
||||
* @token: the magic token
|
||||
* @nhat: the number of hats being passed in the arguments
|
||||
* ...: a argument list of const char * being passed
|
||||
*
|
||||
* change_hat_vargs can be called directly but it is meant to be called
|
||||
* through its macro wrapper of the same name. Which automatically
|
||||
* fills in the nhats arguments based on the number of parameters
|
||||
* passed.
|
||||
* to call change_hat_vargs direction do
|
||||
* (change_hat_vargs)(token, nhats, hat1, hat2...)
|
||||
*/
|
||||
int (aa_change_hat_vargs)(unsigned long token, int nhats, ...)
|
||||
{
|
||||
va_list ap;
|
||||
const char *argv[nhats+1];
|
||||
int i;
|
||||
|
||||
va_start(ap, nhats);
|
||||
for (i = 0; i < nhats ; i++) {
|
||||
argv[i] = va_arg(ap, char *);
|
||||
}
|
||||
argv[nhats] = NULL;
|
||||
va_end(ap);
|
||||
return aa_change_hatv(argv, token);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_gettaskcon - get the confinement context for task @target in an allocated buffer
|
||||
* @target: task to query
|
||||
* @label: pointer to returned buffer with the label
|
||||
* @mode: if non-NULL and a mode is present, will point to mode string in @label
|
||||
*
|
||||
* Returns: length of confinement context or -1 on error and sets errno
|
||||
*
|
||||
* Guarantees that @label and @mode are null terminated. The length returned
|
||||
* is for all data including both @label and @mode, and maybe > than
|
||||
* strlen(@label) even if @mode is NULL
|
||||
*
|
||||
* Caller is responsible for freeing the buffer returned in @label. @mode is
|
||||
* always contained within @label's buffer and so NEVER do free(@mode)
|
||||
*/
|
||||
int aa_gettaskcon(pid_t target, char **label, char **mode)
|
||||
{
|
||||
return aa_getprocattr(target, "current", label, mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_getcon - get the confinement context for current task in an allocated buffer
|
||||
* @label: pointer to return buffer with the label if successful
|
||||
* @mode: if non-NULL and a mode is present, will point to mode string in @label
|
||||
*
|
||||
* Returns: length of confinement context or -1 on error and sets errno
|
||||
*
|
||||
* Guarantees that @label and @mode are null terminated. The length returned
|
||||
* is for all data including both @label and @mode, and may > than
|
||||
* strlen(@label) even if @mode is NULL
|
||||
*
|
||||
* Caller is responsible for freeing the buffer returned in @label. @mode is
|
||||
* always contained within @label's buffer and so NEVER do free(@mode)
|
||||
*/
|
||||
int aa_getcon(char **label, char **mode)
|
||||
{
|
||||
return aa_gettaskcon(aa_gettid(), label, mode);
|
||||
}
|
||||
|
||||
|
||||
#ifndef SO_PEERSEC
|
||||
#define SO_PEERSEC 31
|
||||
#endif
|
||||
|
||||
/**
|
||||
* aa_getpeercon_raw - get the confinement context of the socket's peer (other end)
|
||||
* @fd: socket to get peer confinement context for
|
||||
* @buf: buffer to store the result in
|
||||
* @len: initially contains size of the buffer, returns size of data read
|
||||
* @mode: if non-NULL and a mode is present, will point to mode string in @buf
|
||||
*
|
||||
* Returns: length of confinement context including null termination or -1 on
|
||||
* error if errno == ERANGE then @len will hold the size needed
|
||||
*/
|
||||
int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode)
|
||||
{
|
||||
socklen_t optlen = *len;
|
||||
int rc;
|
||||
|
||||
if (optlen <= 0 || buf == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rc = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, buf, &optlen);
|
||||
if (rc == -1 || optlen <= 0)
|
||||
goto out;
|
||||
|
||||
/* check for null termination */
|
||||
if (buf[optlen - 1] != 0) {
|
||||
if (optlen < *len) {
|
||||
buf[optlen] = 0;
|
||||
optlen++;
|
||||
} else {
|
||||
/* buf needs to be bigger by 1 */
|
||||
rc = -1;
|
||||
errno = ERANGE;
|
||||
optlen++;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (splitcon(buf, optlen - 1, false, mode) != buf) {
|
||||
rc = -1;
|
||||
errno = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = optlen;
|
||||
out:
|
||||
*len = optlen;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_getpeercon - get the confinement context of the socket's peer (other end)
|
||||
* @fd: socket to get peer confinement context for
|
||||
* @label: pointer to allocated buffer with the label
|
||||
* @mode: if non-NULL and a mode is present, will point to mode string in @label
|
||||
*
|
||||
* Returns: length of confinement context including null termination or -1 on error
|
||||
*
|
||||
* Guarantees that @label and @mode are null terminated. The length returned
|
||||
* is for all data including both @label and @mode, and maybe > than
|
||||
* strlen(@label) even if @mode is NULL
|
||||
*
|
||||
* Caller is responsible for freeing the buffer returned in @label. @mode is
|
||||
* always contained within @label's buffer and so NEVER do free(@mode)
|
||||
*/
|
||||
int aa_getpeercon(int fd, char **label, char **mode)
|
||||
{
|
||||
int rc, last_size, size = INITIAL_GUESS_SIZE;
|
||||
char *buffer = NULL;
|
||||
|
||||
if (!label) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
char *tmp;
|
||||
|
||||
last_size = size;
|
||||
tmp = realloc(buffer, size);
|
||||
if (!tmp) {
|
||||
free(buffer);
|
||||
return -1;
|
||||
}
|
||||
buffer = tmp;
|
||||
memset(buffer, 0, size);
|
||||
|
||||
rc = aa_getpeercon_raw(fd, buffer, &size, mode);
|
||||
/* size should contain actual size needed if errno == ERANGE */
|
||||
} while (rc == -1 && errno == ERANGE && size > last_size);
|
||||
|
||||
if (rc == -1) {
|
||||
free(buffer);
|
||||
*label = NULL;
|
||||
if (mode)
|
||||
*mode = NULL;
|
||||
size = -1;
|
||||
} else
|
||||
*label = buffer;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
static pthread_once_t aafs_access_control = PTHREAD_ONCE_INIT;
|
||||
static char *aafs_access = NULL;
|
||||
|
||||
static void aafs_access_init_once(void)
|
||||
{
|
||||
char *aafs;
|
||||
int ret;
|
||||
|
||||
ret = aa_find_mountpoint(&aafs);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
ret = asprintf(&aafs_access, "%s/.access", aafs);
|
||||
if (ret < 0)
|
||||
aafs_access = NULL;
|
||||
|
||||
free(aafs);
|
||||
}
|
||||
|
||||
/* "allow 0x00000000\ndeny 0x00000000\naudit 0x00000000\nquiet 0x00000000\n" */
|
||||
#define QUERY_LABEL_REPLY_LEN 67
|
||||
|
||||
/**
|
||||
* aa_query_label - query the access(es) of a label
|
||||
* @mask: permission bits to query
|
||||
* @query: binary query string, must be offset by AA_QUERY_CMD_LABEL_SIZE
|
||||
* @size: size of the query string must include AA_QUERY_CMD_LABEL_SIZE
|
||||
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
|
||||
* @audited: upon successful return, will be 1 if query should be audited and 0
|
||||
* if not
|
||||
*
|
||||
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
|
||||
* ENOENT, the subject label in the query string is unknown to the
|
||||
* kernel.
|
||||
*/
|
||||
int query_label(uint32_t mask, char *query, size_t size, int *allowed,
|
||||
int *audited)
|
||||
{
|
||||
char buf[QUERY_LABEL_REPLY_LEN];
|
||||
uint32_t allow, deny, audit, quiet;
|
||||
int fd, ret, saved;
|
||||
|
||||
if (!mask || size <= AA_QUERY_CMD_LABEL_SIZE) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = pthread_once(&aafs_access_control, aafs_access_init_once);
|
||||
if (ret) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
} else if (!aafs_access) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
fd = open(aafs_access, O_RDWR);
|
||||
if (fd == -1) {
|
||||
if (errno == ENOENT)
|
||||
errno = EPROTONOSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(query, AA_QUERY_CMD_LABEL, AA_QUERY_CMD_LABEL_SIZE);
|
||||
errno = 0;
|
||||
ret = write(fd, query, size);
|
||||
if (ret != size) {
|
||||
if (ret >= 0)
|
||||
errno = EPROTO;
|
||||
/* IMPORTANT: This is the only valid error path that can have
|
||||
* errno set to ENOENT. It indicates that the subject label
|
||||
* could not be found by the kernel.
|
||||
*/
|
||||
(void)close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = read(fd, buf, QUERY_LABEL_REPLY_LEN);
|
||||
saved = errno;
|
||||
(void)close(fd);
|
||||
errno = saved;
|
||||
if (ret != QUERY_LABEL_REPLY_LEN) {
|
||||
errno = EPROTO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = sscanf(buf, "allow 0x%8" SCNx32 "\n"
|
||||
"deny 0x%8" SCNx32 "\n"
|
||||
"audit 0x%8" SCNx32 "\n"
|
||||
"quiet 0x%8" SCNx32 "\n",
|
||||
&allow, &deny, &audit, &quiet);
|
||||
if (ret != 4) {
|
||||
errno = EPROTONOSUPPORT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*allowed = mask & ~(allow & ~deny) ? 0 : 1;
|
||||
if (!(*allowed))
|
||||
audit = 0xFFFFFFFF;
|
||||
*audited = mask & ~(audit & ~quiet) ? 0 : 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* export multiple aa_query_label symbols to compensate for downstream
|
||||
* releases with differing symbol versions. */
|
||||
extern typeof((query_label)) __aa_query_label __attribute__((alias ("query_label")));
|
||||
symbol_version(__aa_query_label, aa_query_label, APPARMOR_1.1);
|
||||
default_symbol_version(query_label, aa_query_label, APPARMOR_2.9);
|
||||
|
||||
|
||||
/**
|
||||
* aa_query_file_path_len - query access permissions for a file @path
|
||||
* @mask: permission bits to query
|
||||
* @label: apparmor label
|
||||
* @label_len: length of @label (does not include any terminating nul byte)
|
||||
* @path: file path to query permissions for
|
||||
* @path_len: length of @path (does not include any terminating nul byte)
|
||||
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
|
||||
* @audited: upon successful return, will be 1 if query should be audited and 0
|
||||
* if not
|
||||
*
|
||||
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
|
||||
* ENOENT, the subject label in the query string is unknown to the
|
||||
* kernel.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
autofree char *query = NULL;
|
||||
|
||||
/* + 1 for null separator */
|
||||
size_t size = AA_QUERY_CMD_LABEL_SIZE + label_len + 1 + path_len;
|
||||
query = malloc(size + 1);
|
||||
if (!query)
|
||||
return -1;
|
||||
memcpy(query + AA_QUERY_CMD_LABEL_SIZE, label, label_len);
|
||||
/* null separator */
|
||||
query[AA_QUERY_CMD_LABEL_SIZE + label_len] = 0;
|
||||
query[AA_QUERY_CMD_LABEL_SIZE + label_len + 1] = AA_CLASS_FILE;
|
||||
memcpy(query + AA_QUERY_CMD_LABEL_SIZE + label_len + 2, path, path_len);
|
||||
return aa_query_label(mask, query, size , allowed, audited);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_query_file_path - query access permissions for a file @path
|
||||
* @mask: permission bits to query
|
||||
* @label: apparmor label
|
||||
* @path: file path to query permissions for
|
||||
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
|
||||
* @audited: upon successful return, will be 1 if query should be audited and 0
|
||||
* if not
|
||||
*
|
||||
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
|
||||
* ENOENT, the subject label in the query string is unknown to the
|
||||
* kernel.
|
||||
*/
|
||||
int aa_query_file_path(uint32_t mask, const char *label, const char *path,
|
||||
int *allowed, int *audited)
|
||||
{
|
||||
return aa_query_file_path_len(mask, label, strlen(label), path,
|
||||
strlen(path), allowed, audited);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_query_link_path_len - query access permissions for a hard link @link
|
||||
* @label: apparmor label
|
||||
* @label_len: length of @label (does not include any terminating nul byte)
|
||||
* @target: file path that hard link will point to
|
||||
* @target_len: length of @target (does not include any terminating nul byte)
|
||||
* @link: file path of hard link
|
||||
* @link_len: length of @link (does not include any terminating nul byte)
|
||||
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
|
||||
* @audited: upon successful return, will be 1 if query should be audited and 0
|
||||
* if not
|
||||
*
|
||||
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
|
||||
* ENOENT, the subject label in the query string is unknown to the
|
||||
* kernel.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
autofree char *query = NULL;
|
||||
int rc;
|
||||
|
||||
/* + 1 for null separators */
|
||||
size_t size = AA_QUERY_CMD_LABEL_SIZE + label_len + 1 + target_len +
|
||||
1 + link_len;
|
||||
size_t pos = AA_QUERY_CMD_LABEL_SIZE;
|
||||
|
||||
query = malloc(size);
|
||||
if (!query)
|
||||
return -1;
|
||||
memcpy(query + pos, label, label_len);
|
||||
/* null separator */
|
||||
pos += label_len;
|
||||
query[pos] = 0;
|
||||
query[++pos] = AA_CLASS_FILE;
|
||||
memcpy(query + pos + 1, link, link_len);
|
||||
/* The kernel does the query in two parts we could similate this
|
||||
* doing the following, however as long as policy is compiled
|
||||
* correctly this isn't requied, and it requires and extra round
|
||||
* trip to the kernel and adds a race on policy replacement between
|
||||
* the two queries.
|
||||
*
|
||||
rc = aa_query_label(AA_MAY_LINK, query, size, allowed, audited);
|
||||
if (rc || !*allowed)
|
||||
return rc;
|
||||
*/
|
||||
pos += 1 + link_len;
|
||||
query[pos] = 0;
|
||||
memcpy(query + pos + 1, target, target_len);
|
||||
return aa_query_label(AA_MAY_LINK, query, size, allowed, audited);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_query_link_path - query access permissions for a hard link @link
|
||||
* @label: apparmor label
|
||||
* @target: file path that hard link will point to
|
||||
* @link: file path of hard link
|
||||
* @allowed: upon successful return, will be 1 if query is allowed and 0 if not
|
||||
* @audited: upon successful return, will be 1 if query should be audited and 0
|
||||
* if not
|
||||
*
|
||||
* Returns: 0 on success else -1 and sets errno. If -1 is returned and errno is
|
||||
* ENOENT, the subject label in the query string is unknown to the
|
||||
* kernel.
|
||||
*/
|
||||
int aa_query_link_path(const char *label, const char *target, const char *link,
|
||||
int *allowed, int *audited)
|
||||
{
|
||||
return aa_query_link_path_len(label, strlen(label), target,
|
||||
strlen(target), link, strlen(link),
|
||||
allowed, audited);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -51,49 +51,3 @@ APPARMOR_2.9 {
|
||||
local:
|
||||
*;
|
||||
} APPARMOR_1.1;
|
||||
|
||||
APPARMOR_2.10 {
|
||||
global:
|
||||
aa_query_file_path;
|
||||
aa_query_file_path_len;
|
||||
aa_query_link_path;
|
||||
aa_query_link_path_len;
|
||||
aa_features_new;
|
||||
aa_features_new_from_string;
|
||||
aa_features_new_from_kernel;
|
||||
aa_features_ref;
|
||||
aa_features_unref;
|
||||
aa_features_write_to_file;
|
||||
aa_features_is_equal;
|
||||
aa_features_supports;
|
||||
aa_kernel_interface_new;
|
||||
aa_kernel_interface_ref;
|
||||
aa_kernel_interface_unref;
|
||||
aa_kernel_interface_load_policy;
|
||||
aa_kernel_interface_load_policy_from_file;
|
||||
aa_kernel_interface_load_policy_from_fd;
|
||||
aa_kernel_interface_replace_policy;
|
||||
aa_kernel_interface_replace_policy_from_file;
|
||||
aa_kernel_interface_replace_policy_from_fd;
|
||||
aa_kernel_interface_remove_policy;
|
||||
aa_kernel_interface_write_policy;
|
||||
aa_policy_cache_new;
|
||||
aa_policy_cache_ref;
|
||||
aa_policy_cache_unref;
|
||||
aa_policy_cache_remove;
|
||||
aa_policy_cache_replace_all;
|
||||
aa_splitcon;
|
||||
local:
|
||||
*;
|
||||
} APPARMOR_2.9;
|
||||
|
||||
PRIVATE {
|
||||
global:
|
||||
_aa_is_blacklisted;
|
||||
_aa_autofree;
|
||||
_aa_autoclose;
|
||||
_aa_autofclose;
|
||||
_aa_dirat_for_each;
|
||||
local:
|
||||
*;
|
||||
};
|
||||
|
@@ -1,277 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2014
|
||||
* 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 <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/apparmor.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#define CACHE_FEATURES_FILE ".features"
|
||||
|
||||
struct aa_policy_cache {
|
||||
unsigned int ref_count;
|
||||
aa_features *features;
|
||||
aa_features *kernel_features;
|
||||
int dirfd;
|
||||
};
|
||||
|
||||
static int clear_cache_cb(int dirfd, const char *path, struct stat *st,
|
||||
void *data unused)
|
||||
{
|
||||
/* remove regular files */
|
||||
if (S_ISREG(st->st_mode))
|
||||
return unlinkat(dirfd, path, 0);
|
||||
|
||||
/* do nothing with other file types */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
||||
{
|
||||
if (aa_policy_cache_remove(policy_cache->dirfd, "."))
|
||||
return -1;
|
||||
|
||||
if (aa_features_write_to_file(features, policy_cache->dirfd,
|
||||
CACHE_FEATURES_FILE) == -1)
|
||||
return -1;
|
||||
|
||||
aa_features_unref(policy_cache->features);
|
||||
policy_cache->features = aa_features_ref(features);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_cache_features(aa_policy_cache *policy_cache,
|
||||
aa_features *kernel_features, bool create)
|
||||
{
|
||||
bool call_create_cache = false;
|
||||
|
||||
if (aa_features_new(&policy_cache->features, policy_cache->dirfd,
|
||||
CACHE_FEATURES_FILE)) {
|
||||
policy_cache->features = NULL;
|
||||
if (!create || errno != ENOENT)
|
||||
return -1;
|
||||
|
||||
/* The cache directory needs to be created */
|
||||
call_create_cache = true;
|
||||
} else if (!aa_features_is_equal(policy_cache->features,
|
||||
kernel_features)) {
|
||||
if (!create) {
|
||||
errno = EEXIST;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The cache directory needs to be refreshed */
|
||||
call_create_cache = true;
|
||||
}
|
||||
|
||||
return call_create_cache ?
|
||||
create_cache(policy_cache, kernel_features) : 0;
|
||||
}
|
||||
|
||||
struct replace_all_cb_data {
|
||||
aa_policy_cache *policy_cache;
|
||||
aa_kernel_interface *kernel_interface;
|
||||
};
|
||||
|
||||
static int replace_all_cb(int dirfd unused, const char *name, struct stat *st,
|
||||
void *cb_data)
|
||||
{
|
||||
int retval = 0;
|
||||
|
||||
if (!S_ISDIR(st->st_mode) && !_aa_is_blacklisted(name)) {
|
||||
struct replace_all_cb_data *data;
|
||||
|
||||
data = (struct replace_all_cb_data *) cb_data;
|
||||
retval = aa_kernel_interface_replace_policy_from_file(data->kernel_interface,
|
||||
data->policy_cache->dirfd,
|
||||
name);
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_new - create a new aa_policy_cache object from a path
|
||||
* @policy_cache: will point to the address of an allocated and initialized
|
||||
* aa_policy_cache_new object upon success
|
||||
* @kernel_features: features representing a kernel (may be NULL if you want to
|
||||
* use the features of the currently running kernel)
|
||||
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
|
||||
* @path: path to the policy cache
|
||||
* @max_caches: The maximum number of policy caches, one for each unique set of
|
||||
* kernel features, before older caches are auto-reaped. 0 means
|
||||
* that no new caches should be created (existing, valid caches
|
||||
* will be used) and auto-reaping is disabled. UINT16_MAX means
|
||||
* that a cache can be created and auto-reaping is disabled.
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and *@policy_cache
|
||||
* pointing to NULL
|
||||
*/
|
||||
int aa_policy_cache_new(aa_policy_cache **policy_cache,
|
||||
aa_features *kernel_features,
|
||||
int dirfd, const char *path, uint16_t max_caches)
|
||||
{
|
||||
aa_policy_cache *pc;
|
||||
bool create = max_caches > 0;
|
||||
|
||||
*policy_cache = NULL;
|
||||
|
||||
if (!path) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (max_caches > 1) {
|
||||
errno = ENOTSUP;
|
||||
return -1;
|
||||
}
|
||||
|
||||
pc = calloc(1, sizeof(*pc));
|
||||
if (!pc) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
pc->dirfd = -1;
|
||||
aa_policy_cache_ref(pc);
|
||||
|
||||
open:
|
||||
pc->dirfd = openat(dirfd, path, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
|
||||
if (pc->dirfd < 0) {
|
||||
int save;
|
||||
|
||||
/* does the dir exist? */
|
||||
if (create && errno == ENOENT) {
|
||||
if (mkdirat(dirfd, path, 0700) == 0)
|
||||
goto open;
|
||||
PERROR("Can't create cache directory '%s': %m\n", path);
|
||||
} else if (create) {
|
||||
PERROR("Can't update cache directory '%s': %m\n", path);
|
||||
} else {
|
||||
PDEBUG("Cache directory '%s' does not exist\n", path);
|
||||
}
|
||||
|
||||
save = errno;
|
||||
aa_policy_cache_unref(pc);
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (kernel_features) {
|
||||
aa_features_ref(kernel_features);
|
||||
} else if (aa_features_new_from_kernel(&kernel_features) == -1) {
|
||||
int save = errno;
|
||||
|
||||
aa_policy_cache_unref(pc);
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
pc->kernel_features = kernel_features;
|
||||
|
||||
if (init_cache_features(pc, kernel_features, create)) {
|
||||
int save = errno;
|
||||
|
||||
aa_policy_cache_unref(pc);
|
||||
errno = save;
|
||||
return -1;
|
||||
}
|
||||
|
||||
*policy_cache = pc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_ref - increments the ref count of an aa_policy_cache object
|
||||
* @policy_cache: the policy_cache
|
||||
*
|
||||
* Returns: the policy_cache
|
||||
*/
|
||||
aa_policy_cache *aa_policy_cache_ref(aa_policy_cache *policy_cache)
|
||||
{
|
||||
atomic_inc(&policy_cache->ref_count);
|
||||
return policy_cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_unref - decrements the ref count and frees the aa_policy_cache object when 0
|
||||
* @policy_cache: the policy_cache (can be NULL)
|
||||
*/
|
||||
void aa_policy_cache_unref(aa_policy_cache *policy_cache)
|
||||
{
|
||||
if (policy_cache && atomic_dec_and_test(&policy_cache->ref_count)) {
|
||||
aa_features_unref(policy_cache->features);
|
||||
aa_features_unref(policy_cache->kernel_features);
|
||||
if (policy_cache->dirfd != -1)
|
||||
close(policy_cache->dirfd);
|
||||
free(policy_cache);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_remove - removes all policy cache files under a path
|
||||
* @dirfd: directory file descriptor or AT_FDCWD (see openat(2))
|
||||
* @path: the path to a policy cache directory
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set
|
||||
*/
|
||||
int aa_policy_cache_remove(int dirfd, const char *path)
|
||||
{
|
||||
return _aa_dirat_for_each(dirfd, path, NULL, clear_cache_cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* aa_policy_cache_replace_all - performs a kernel policy replacement of all cached policies
|
||||
* @policy_cache: the policy_cache
|
||||
* @kernel_interface: the kernel interface to use when doing the replacement
|
||||
* (may be NULL if the currently running kernel features
|
||||
* were used when calling aa_policy_cache_new())
|
||||
*
|
||||
* Returns: 0 on success, -1 on error with errno set and features pointing to
|
||||
* NULL
|
||||
*/
|
||||
int aa_policy_cache_replace_all(aa_policy_cache *policy_cache,
|
||||
aa_kernel_interface *kernel_interface)
|
||||
{
|
||||
struct replace_all_cb_data cb_data;
|
||||
int retval;
|
||||
|
||||
if (kernel_interface) {
|
||||
aa_kernel_interface_ref(kernel_interface);
|
||||
} else if (aa_kernel_interface_new(&kernel_interface,
|
||||
policy_cache->kernel_features,
|
||||
NULL) == -1) {
|
||||
kernel_interface = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cb_data.policy_cache = policy_cache;
|
||||
cb_data.kernel_interface = kernel_interface;
|
||||
retval = _aa_dirat_for_each(policy_cache->dirfd, ".", &cb_data,
|
||||
replace_all_cb);
|
||||
|
||||
aa_kernel_interface_unref(kernel_interface);
|
||||
|
||||
return retval;
|
||||
}
|
@@ -1,252 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 Canonical Ltd.
|
||||
*
|
||||
* The libapparmor library is licensed under the terms of the GNU
|
||||
* Lesser General Public License, version 2.1. Please see the file
|
||||
* COPYING.LGPL.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
/**
|
||||
* Allow libapparmor to build on older systems where secure_getenv() is still
|
||||
* named __secure_getenv(). This snippet was taken from the glibc wiki
|
||||
* (https://sourceware.org/glibc/wiki/Tips_and_Tricks/secure_getenv).
|
||||
*/
|
||||
#ifndef HAVE_SECURE_GETENV
|
||||
#ifdef HAVE___SECURE_GETENV
|
||||
#define secure_getenv __secure_getenv
|
||||
#else
|
||||
#error neither secure_getenv nor __secure_getenv is available
|
||||
#endif
|
||||
#endif
|
||||
|
||||
struct ignored_suffix_t {
|
||||
const char * text;
|
||||
int len;
|
||||
int silent;
|
||||
};
|
||||
|
||||
static struct ignored_suffix_t ignored_suffixes[] = {
|
||||
/* Debian packging files, which are in flux during install
|
||||
should be silently ignored. */
|
||||
{ ".dpkg-new", 9, 1 },
|
||||
{ ".dpkg-old", 9, 1 },
|
||||
{ ".dpkg-dist", 10, 1 },
|
||||
{ ".dpkg-bak", 9, 1 },
|
||||
/* RPM packaging files have traditionally not been silently
|
||||
ignored */
|
||||
{ ".rpmnew", 7, 0 },
|
||||
{ ".rpmsave", 8, 0 },
|
||||
/* patch file backups/conflicts */
|
||||
{ ".orig", 5, 0 },
|
||||
{ ".rej", 4, 0 },
|
||||
/* Backup files should be mentioned */
|
||||
{ "~", 1, 0 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
#define DEBUG_ENV_VAR "LIBAPPARMOR_DEBUG"
|
||||
|
||||
void print_error(bool honor_env_var, const char *ident, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int openlog_options = 0;
|
||||
|
||||
if (honor_env_var && secure_getenv(DEBUG_ENV_VAR))
|
||||
openlog_options |= LOG_PERROR;
|
||||
|
||||
openlog(ident, openlog_options, LOG_ERR);
|
||||
va_start(args, fmt);
|
||||
vsyslog(LOG_ERR, fmt, args);
|
||||
va_end(args);
|
||||
closelog();
|
||||
}
|
||||
|
||||
void print_debug(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (!secure_getenv(DEBUG_ENV_VAR))
|
||||
return;
|
||||
|
||||
va_start(args, fmt);
|
||||
vfprintf(stderr, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void atomic_inc(unsigned int *v)
|
||||
{
|
||||
__sync_add_and_fetch(v, 1);
|
||||
}
|
||||
|
||||
bool atomic_dec_and_test(unsigned int *v)
|
||||
{
|
||||
return __sync_sub_and_fetch(v, 1) == 0;
|
||||
}
|
||||
|
||||
int _aa_is_blacklisted(const char *name)
|
||||
{
|
||||
size_t name_len = strlen(name);
|
||||
struct ignored_suffix_t *suffix;
|
||||
|
||||
/* skip dot files and files with no name */
|
||||
if (!name_len || *name == '.' || !strcmp(name, "README"))
|
||||
return 1;
|
||||
|
||||
/* skip blacklisted suffixes */
|
||||
for (suffix = ignored_suffixes; suffix->text; suffix++) {
|
||||
char *found;
|
||||
if ( (found = strstr((char *) name, suffix->text)) &&
|
||||
found - name + suffix->len == name_len ) {
|
||||
if (!suffix->silent)
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* automaticly free allocated variables tagged with autofree on fn exit */
|
||||
void _aa_autofree(void *p)
|
||||
{
|
||||
void **_p = (void**)p;
|
||||
free(*_p);
|
||||
}
|
||||
|
||||
void _aa_autoclose(int *fd)
|
||||
{
|
||||
if (*fd != -1) {
|
||||
/* if close was interrupted retry */
|
||||
while(close(*fd) == -1 && errno == EINTR);
|
||||
*fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void _aa_autofclose(FILE **f)
|
||||
{
|
||||
if (*f) {
|
||||
fclose(*f);
|
||||
*f = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int _aa_asprintf(char **strp, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
int rc;
|
||||
|
||||
va_start(args, fmt);
|
||||
rc = vasprintf(strp, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (rc == -1)
|
||||
*strp = NULL;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dot_or_dot_dot_filter(const struct dirent *ent)
|
||||
{
|
||||
if (strcmp(ent->d_name, ".") == 0 ||
|
||||
strcmp(ent->d_name, "..") == 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* _aa_dirat_for_each: iterate over a directory calling cb for each entry
|
||||
* @dirfd: already opened directory
|
||||
* @name: name of the directory (NOT NULL)
|
||||
* @data: data pointer to pass to the callback fn (MAY BE NULL)
|
||||
* @cb: the callback to pass entry too (NOT NULL)
|
||||
*
|
||||
* Iterate over the entries in a directory calling cb for each entry.
|
||||
* The directory to iterate is determined by a combination of @dirfd and
|
||||
* @name.
|
||||
*
|
||||
* See the openat section of the open(2) man page for details on valid @dirfd
|
||||
* and @name combinations. This function does accept AT_FDCWD as @dirfd if
|
||||
* @name should be considered relative to the current working directory.
|
||||
*
|
||||
* Pass "." for @name if @dirfd is the directory to iterate over.
|
||||
*
|
||||
* The cb function is called with the DIR in use and the name of the
|
||||
* file in that directory. If the file is to be opened it should
|
||||
* use the openat, fstatat, and related fns.
|
||||
*
|
||||
* Returns: 0 on success, else -1 and errno is set to the error code
|
||||
*/
|
||||
int _aa_dirat_for_each(int dirfd, const char *name, void *data,
|
||||
int (* cb)(int, const char *, struct stat *, void *))
|
||||
{
|
||||
autofree struct dirent **namelist = NULL;
|
||||
autoclose int cb_dirfd = -1;
|
||||
int i, num_dirs, rc;
|
||||
|
||||
if (!cb || !name) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
cb_dirfd = openat(dirfd, name, O_RDONLY | O_CLOEXEC | O_DIRECTORY);
|
||||
if (cb_dirfd == -1) {
|
||||
PDEBUG("could not open directory '%s': %m\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
num_dirs = scandirat(cb_dirfd, ".", &namelist,
|
||||
dot_or_dot_dot_filter, NULL);
|
||||
if (num_dirs == -1) {
|
||||
PDEBUG("scandirat of directory '%s' failed: %m\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (rc = 0, i = 0; i < num_dirs; i++) {
|
||||
/* Must cycle through all dirs so that each one is autofreed */
|
||||
autofree struct dirent *dir = namelist[i];
|
||||
struct stat my_stat;
|
||||
|
||||
if (rc)
|
||||
continue;
|
||||
|
||||
if (fstatat(cb_dirfd, dir->d_name, &my_stat, 0)) {
|
||||
PDEBUG("stat failed for '%s': %m\n", dir->d_name);
|
||||
rc = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cb(cb_dirfd, dir->d_name, &my_stat, data)) {
|
||||
PDEBUG("dir_for_each callback failed for '%s'\n",
|
||||
dir->d_name);
|
||||
rc = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2014 Canonical Ltd.
|
||||
*
|
||||
* The libapparmor library is licensed under the terms of the GNU
|
||||
* Lesser General Public License, version 2.1. Please see the file
|
||||
* COPYING.LGPL.
|
||||
*
|
||||
* This library 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 Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _AA_PRIVATE_H
|
||||
#define _AA_PRIVATE_H 1
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <sys/apparmor_private.h>
|
||||
|
||||
#define autofree __attribute((cleanup(_aa_autofree)))
|
||||
#define autoclose __attribute((cleanup(_aa_autoclose)))
|
||||
#define autofclose __attribute((cleanup(_aa_autofclose)))
|
||||
#define unused __attribute__ ((unused))
|
||||
|
||||
#define asprintf _aa_asprintf
|
||||
|
||||
#if ENABLE_DEBUG_OUTPUT
|
||||
|
||||
#define PERROR(fmt, args...) print_error(true, "libapparmor", fmt, ## args)
|
||||
#define PDEBUG(fmt, args...) print_debug("libapparmor: " fmt, ## args)
|
||||
|
||||
#else /* ENABLE_DEBUG_OUTPUT */
|
||||
|
||||
#define PERROR(fmt, args...) print_error(false, "libapparmor", fmt, ## args)
|
||||
#define PDEBUG(fmt, args...) /* do nothing */
|
||||
|
||||
#endif /* ENABLE_DEBUG_OUTPUT */
|
||||
|
||||
#define MY_TEST(statement, error) \
|
||||
if (!(statement)) { \
|
||||
fprintf(stderr, "FAIL: %s\n", error); \
|
||||
rc = 1; \
|
||||
}
|
||||
|
||||
void print_error(bool honor_env_var, const char *ident, const char *fmt, ...);
|
||||
void print_debug(const char *fmt, ...);
|
||||
|
||||
void atomic_inc(unsigned int *v);
|
||||
bool atomic_dec_and_test(unsigned int *v);
|
||||
|
||||
#endif /* _AA_PRIVATE_H */
|
@@ -178,7 +178,7 @@ syslog_month Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(
|
||||
hhmmss {digit}{2}{colon}{digit}{2}{colon}{digit}{2}
|
||||
timezone ({plus}|{minus}){digit}{2}{colon}{digit}{2}
|
||||
syslog_time {hhmmss}({period}{digits})?{timezone}?
|
||||
syslog_hostname [[:alnum:]._-]+
|
||||
syslog_hostname [[:alnum:]_-]+
|
||||
dmesg_timestamp \[[[:digit:] ]{5,}\.[[:digit:]]{6,}\]
|
||||
|
||||
%x single_quoted_string
|
||||
@@ -355,7 +355,6 @@ yy_flex_debug = 0;
|
||||
{syslog_time} { yylval->t_str = strdup(yytext); BEGIN(hostname); return(TOK_TIME); }
|
||||
|
||||
{audit} { yy_push_state(audit_id, yyscanner); return(TOK_AUDIT); }
|
||||
{dmesg_timestamp} { yylval->t_str = strdup(yytext); return(TOK_DMESG_STAMP); }
|
||||
|
||||
. { /* ignore any non-matched input */ BEGIN(unknown_message); yyless(0); }
|
||||
|
||||
|
@@ -20,7 +20,13 @@
|
||||
#include <stdio.h>
|
||||
#include <aalogparse.h>
|
||||
#include "parser.h"
|
||||
#include "private.h"
|
||||
|
||||
|
||||
#define MY_TEST(statement, error) \
|
||||
if (!(statement)) { \
|
||||
fprintf(stderr, "FAIL: %s\n", error); \
|
||||
rc = 1; \
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
@@ -34,25 +40,19 @@ int main(void)
|
||||
retstr = hex_to_string("2F746D702F646F6573206E6F74206578697374");
|
||||
MY_TEST(retstr, "basic allocation");
|
||||
MY_TEST(strcmp(retstr, "/tmp/does not exist") == 0, "basic dehex 1");
|
||||
free(retstr);
|
||||
|
||||
retstr = hex_to_string("61");
|
||||
MY_TEST(strcmp(retstr, "a") == 0, "basic dehex 2");
|
||||
free(retstr);
|
||||
|
||||
retstr = hex_to_string("");
|
||||
MY_TEST(strcmp(retstr, "") == 0, "empty string");
|
||||
free(retstr);
|
||||
|
||||
/* ipproto_to_string() tests */
|
||||
retstr = ipproto_to_string((unsigned) 99999);
|
||||
MY_TEST(strcmp(retstr, "unknown(99999)") == 0, "invalid protocol test");
|
||||
free(retstr);
|
||||
|
||||
retstr = ipproto_to_string((unsigned) 6);
|
||||
MY_TEST(strcmp(retstr, "tcp") == 0, "protocol=tcp");
|
||||
free(retstr);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@@ -1,247 +0,0 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "private.h"
|
||||
|
||||
#include "features.c"
|
||||
|
||||
static int test_tokenize_path_components(void)
|
||||
{
|
||||
struct component components[32];
|
||||
size_t max = sizeof(components) / sizeof(*components);
|
||||
size_t num;
|
||||
int rc = 0;
|
||||
|
||||
num = tokenize_path_components(NULL, components, max);
|
||||
MY_TEST(num == 0, "basic NULL test");
|
||||
|
||||
num = tokenize_path_components("", components, max);
|
||||
MY_TEST(num == 0, "basic empty string test");
|
||||
|
||||
num = tokenize_path_components("a", components, 0);
|
||||
MY_TEST(num == 0, "basic empty array test");
|
||||
|
||||
num = tokenize_path_components("a", components, 1);
|
||||
MY_TEST(num == 1, "one component full test (num)");
|
||||
MY_TEST(!strncmp(components[0].str, "a", components[0].len),
|
||||
"one component full test (components[0])");
|
||||
|
||||
num = tokenize_path_components("a/b", components, 2);
|
||||
MY_TEST(num == 2, "two component full test (num)");
|
||||
MY_TEST(!strncmp(components[0].str, "a", components[0].len),
|
||||
"two component full test (components[0])");
|
||||
MY_TEST(!strncmp(components[1].str, "b", components[0].len),
|
||||
"two component full test (components[1])");
|
||||
|
||||
num = tokenize_path_components("a/b/c", components, 1);
|
||||
MY_TEST(num == 1, "not enough components full test (num)");
|
||||
MY_TEST(!strncmp(components[0].str, "a/b/c", components[0].len),
|
||||
"not enough components full test (components[0])");
|
||||
|
||||
num = tokenize_path_components("/", components, max);
|
||||
MY_TEST(num == 0, "no valid components #1 (num)");
|
||||
|
||||
num = tokenize_path_components("////////", components, max);
|
||||
MY_TEST(num == 0, "no valid components #2 (num)");
|
||||
|
||||
num = tokenize_path_components("////////////foo////", components, max);
|
||||
MY_TEST(num == 1, "many invalid components (num)");
|
||||
MY_TEST(!strncmp(components[0].str, "foo", components[0].len),
|
||||
"many invalid components (components[0])");
|
||||
|
||||
num = tokenize_path_components("file", components, max);
|
||||
MY_TEST(num == 1, "file (num)");
|
||||
MY_TEST(!strncmp(components[0].str, "file", components[0].len),
|
||||
"file (components[0])");
|
||||
|
||||
num = tokenize_path_components("/policy///versions//v7/", components, max);
|
||||
MY_TEST(num == 3, "v7 (num)");
|
||||
MY_TEST(!strncmp(components[0].str, "policy", components[0].len),
|
||||
"v7 (components[0])");
|
||||
MY_TEST(!strncmp(components[1].str, "versions", components[1].len),
|
||||
"v7 (components[1])");
|
||||
MY_TEST(!strncmp(components[2].str, "v7", components[2].len),
|
||||
"v7 (components[2])");
|
||||
|
||||
num = tokenize_path_components("dbus/mask/send", components, max);
|
||||
MY_TEST(num == 3, "dbus send (num)");
|
||||
MY_TEST(!strncmp(components[0].str, "dbus", components[0].len),
|
||||
"dbus send (components[0])");
|
||||
MY_TEST(!strncmp(components[1].str, "mask", components[1].len),
|
||||
"dbus send (components[1])");
|
||||
MY_TEST(!strncmp(components[2].str, "send", components[2].len),
|
||||
"dbus send (components[2])");
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int do_test_walk_one(const char **str, const struct component *component,
|
||||
bool is_top_level, bool expect_walk, const char *e1,
|
||||
const char *e2, const char *e3)
|
||||
{
|
||||
const char *save = str ? *str : NULL;
|
||||
bool walked = walk_one(str, component, is_top_level);
|
||||
int rc = 0;
|
||||
|
||||
/* Check if the result of the walk matches the expected result*/
|
||||
MY_TEST(expect_walk == walked, e1);
|
||||
if (save) {
|
||||
/**
|
||||
* If a walk was expected, @*str should have changed. It
|
||||
* shouldn't change if a walk was unexpected.
|
||||
*/
|
||||
if (expect_walk) {
|
||||
MY_TEST(*str != save, e2);
|
||||
} else {
|
||||
MY_TEST(*str == save, e3);
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define MY_WALK_TEST(str, component, is_top_level, expect_walk, error) \
|
||||
if (do_test_walk_one(str, component, is_top_level, \
|
||||
expect_walk, \
|
||||
error " (walk check)", \
|
||||
error " (str didn't change)", \
|
||||
error " (str changed)")) { \
|
||||
rc = 1; \
|
||||
}
|
||||
|
||||
#define MY_GOOD_WALK_TEST(str, component, is_top_level, error) \
|
||||
MY_WALK_TEST(str, component, is_top_level, true, error)
|
||||
#define MY_BAD_WALK_TEST(str, component, is_top_level, error) \
|
||||
MY_WALK_TEST(str, component, is_top_level, false, error)
|
||||
|
||||
static int test_walk_one(void)
|
||||
{
|
||||
struct component c;
|
||||
const char *str;
|
||||
int rc = 0;
|
||||
|
||||
MY_BAD_WALK_TEST(NULL, &c, true, "basic NULL str test");
|
||||
|
||||
str = NULL;
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "basic NULL *str test");
|
||||
|
||||
str = "test { a b }";
|
||||
MY_BAD_WALK_TEST(&str, NULL, true, "basic NULL component test");
|
||||
|
||||
str = "test { a b }";
|
||||
c = (struct component) { NULL, 8 };
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "basic NULL c.str test");
|
||||
|
||||
str = "test { a b }";
|
||||
c = (struct component) { "", 0 };
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "basic empty c.str test");
|
||||
|
||||
str = "test";
|
||||
c = (struct component) { "test", 4 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, true, "single component");
|
||||
|
||||
str = "testX";
|
||||
c = (struct component) { "test", 4 };
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "single component bad str");
|
||||
|
||||
str = "test";
|
||||
c = (struct component) { "testX", 5 };
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "single component bad c.str");
|
||||
|
||||
str = "test { }";
|
||||
c = (struct component) { "test", 4 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #1");
|
||||
|
||||
str = "test {\n\t}";
|
||||
c = (struct component) { "test", 4 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #2");
|
||||
|
||||
str = "test{}";
|
||||
c = (struct component) { "test", 4 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #3");
|
||||
|
||||
str = "test\t{}\n ";
|
||||
c = (struct component) { "test", 4 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, true, "single component empty braces #4");
|
||||
|
||||
str = "test {}";
|
||||
c = (struct component) { "test", 4 };
|
||||
MY_BAD_WALK_TEST(&str, &c, false, "single component bad is_top_level");
|
||||
|
||||
str = "front{back";
|
||||
c = (struct component) { "frontback", 9};
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "brace in the middle #1");
|
||||
MY_BAD_WALK_TEST(&str, &c, false, "brace in the middle #2");
|
||||
|
||||
str = "ardvark { bear cat { deer } }";
|
||||
c = (struct component) { "ardvark", 7 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, true, "animal walk good ardvark");
|
||||
c = (struct component) { "deer", 4 };
|
||||
MY_BAD_WALK_TEST(&str, &c, false, "animal walk bad deer");
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "animal walk bad top-level deer");
|
||||
c = (struct component) { "bear", 4 };
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "animal walk bad bear");
|
||||
c = (struct component) { "cat", 3 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, false, "animal walk good cat");
|
||||
c = (struct component) { "ardvark", 7 };
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "animal walk bad ardvark");
|
||||
c = (struct component) { "deer", 4 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, false, "animal walk good deer");
|
||||
|
||||
str = "dbus {mask {acquire send receive\n}\n}\nsignal {mask {hup int\n}\n}";
|
||||
c = (struct component) { "hup", 3 };
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "dbus/signal bad hup #1");
|
||||
MY_BAD_WALK_TEST(&str, &c, false, "dbus/signal bad hup #2");
|
||||
c = (struct component) { "signal", 6 };
|
||||
MY_BAD_WALK_TEST(&str, &c, false, "dbus/signal bad signal");
|
||||
MY_GOOD_WALK_TEST(&str, &c, true, "dbus/signal good signal");
|
||||
c = (struct component) { "mask", 4 };
|
||||
MY_BAD_WALK_TEST(&str, &c, true, "dbus/signal bad mask");
|
||||
MY_GOOD_WALK_TEST(&str, &c, false, "dbus/signal good mask");
|
||||
c = (struct component) { "hup", 3 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, false, "dbus/signal good hup");
|
||||
|
||||
str = "policy {set_load {yes\n}\nversions {v7 {yes\n}\nv6 {yes\n}";
|
||||
c = (struct component) { "policy", 6 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, true, "policy good");
|
||||
c = (struct component) { "versions", 8 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, false, "versions good");
|
||||
c = (struct component) { "v7", 2 };
|
||||
MY_GOOD_WALK_TEST(&str, &c, false, "v7 good");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int retval, rc = 0;
|
||||
|
||||
retval = test_tokenize_path_components();
|
||||
if (retval)
|
||||
rc = retval;
|
||||
|
||||
retval = test_walk_one();
|
||||
if (retval)
|
||||
rc = retval;
|
||||
|
||||
return rc;
|
||||
}
|
@@ -1,228 +0,0 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "kernel.c"
|
||||
|
||||
static int nullcmp_and_strcmp(const void *s1, const void *s2)
|
||||
{
|
||||
/* Return 0 if both pointers are NULL & non-zero if only one is NULL */
|
||||
if (!s1 || !s2)
|
||||
return s1 != s2;
|
||||
|
||||
return strcmp(s1, s2);
|
||||
}
|
||||
|
||||
static int do_test_splitcon(char *con, int size, bool strip_nl, char **mode,
|
||||
const char *expected_label,
|
||||
const char *expected_mode, const char *error)
|
||||
{
|
||||
char *label;
|
||||
int rc = 0;
|
||||
|
||||
label = splitcon(con, size, strip_nl, mode);
|
||||
|
||||
if (nullcmp_and_strcmp(label, expected_label)) {
|
||||
fprintf(stderr, "FAIL: %s: label \"%s\" != \"%s\"\n",
|
||||
error, label, expected_label);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
if (mode && nullcmp_and_strcmp(*mode, expected_mode)) {
|
||||
fprintf(stderr, "FAIL: %s: mode \"%s\" != \"%s\"\n",
|
||||
error, *mode, expected_mode);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int do_test_aa_splitcon(char *con, char **mode,
|
||||
const char *expected_label,
|
||||
const char *expected_mode, const char *error)
|
||||
{
|
||||
char *label;
|
||||
int rc = 0;
|
||||
|
||||
label = aa_splitcon(con, mode);
|
||||
|
||||
if (nullcmp_and_strcmp(label, expected_label)) {
|
||||
fprintf(stderr, "FAIL: %s: label \"%s\" != \"%s\"\n",
|
||||
error, label, expected_label);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
if (mode && nullcmp_and_strcmp(*mode, expected_mode)) {
|
||||
fprintf(stderr, "FAIL: %s: mode \"%s\" != \"%s\"\n",
|
||||
error, *mode, expected_mode);
|
||||
rc = 1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#define TEST_SPLITCON(con, size, strip_nl, expected_label, \
|
||||
expected_mode, error) \
|
||||
do { \
|
||||
char c1[] = con; \
|
||||
char c2[] = con; \
|
||||
size_t sz = size < 0 ? strlen(con) : size; \
|
||||
char *mode; \
|
||||
\
|
||||
if (do_test_splitcon(c1, sz, strip_nl, &mode, \
|
||||
expected_label, expected_mode, \
|
||||
"splitcon: " error)) { \
|
||||
rc = 1; \
|
||||
} else if (do_test_splitcon(c2, sz, strip_nl, NULL, \
|
||||
expected_label, NULL, \
|
||||
"splitcon: " error " (NULL mode)")) { \
|
||||
rc = 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define TEST_AA_SPLITCON(con, expected_label, expected_mode, error) \
|
||||
do { \
|
||||
char c1[] = con; \
|
||||
char c2[] = con; \
|
||||
char c3[] = con "\n"; \
|
||||
char *mode; \
|
||||
\
|
||||
if (do_test_aa_splitcon(c1, &mode, expected_label, \
|
||||
expected_mode, "aa_splitcon: " error)) {\
|
||||
rc = 1; \
|
||||
} else if (do_test_aa_splitcon(c2, NULL, expected_label,\
|
||||
NULL, \
|
||||
"aa_splitcon: " error " (NULL mode)")) {\
|
||||
rc = 1; \
|
||||
} else if (do_test_aa_splitcon(c3, &mode, \
|
||||
expected_label, expected_mode, \
|
||||
"aa_splitcon: " error " (newline)")) { \
|
||||
rc = 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int test_splitcon(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/**
|
||||
* NOTE: the TEST_SPLITCON() macro automatically generates
|
||||
* corresponding tests with a NULL mode pointer.
|
||||
*/
|
||||
|
||||
TEST_SPLITCON("", 0, true, NULL, NULL, "empty string test #1");
|
||||
TEST_SPLITCON("", 0, false, NULL, NULL, "empty string test #2");
|
||||
|
||||
TEST_SPLITCON("unconfined", -1, true, "unconfined", NULL,
|
||||
"unconfined #1");
|
||||
TEST_SPLITCON("unconfined", -1, false, "unconfined", NULL,
|
||||
"unconfined #2");
|
||||
TEST_SPLITCON("unconfined\n", -1, true, "unconfined", NULL,
|
||||
"unconfined #3");
|
||||
TEST_SPLITCON("unconfined\n", -1, false, NULL, NULL,
|
||||
"unconfined #4");
|
||||
|
||||
TEST_SPLITCON("label (mode)", -1, true, "label", "mode",
|
||||
"basic split #1");
|
||||
TEST_SPLITCON("label (mode)", -1, false, "label", "mode",
|
||||
"basic split #2");
|
||||
TEST_SPLITCON("label (mode)\n", -1, true, "label", "mode",
|
||||
"basic split #3");
|
||||
TEST_SPLITCON("label (mode)\n", -1, false, NULL, NULL,
|
||||
"basic split #4");
|
||||
|
||||
TEST_SPLITCON("/a/b/c (enforce)", -1, true, "/a/b/c", "enforce",
|
||||
"path enforce split #1");
|
||||
TEST_SPLITCON("/a/b/c (enforce)", -1, false, "/a/b/c", "enforce",
|
||||
"path enforce split #2");
|
||||
TEST_SPLITCON("/a/b/c (enforce)\n", -1, true, "/a/b/c", "enforce",
|
||||
"path enforce split #3");
|
||||
TEST_SPLITCON("/a/b/c (enforce)\n", -1, false, NULL, NULL,
|
||||
"path enforce split #4");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static int test_aa_splitcon(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/**
|
||||
* NOTE: the TEST_AA_SPLITCON() macro automatically generates
|
||||
* corresponding tests with a NULL mode pointer and contexts with
|
||||
* trailing newline characters.
|
||||
*/
|
||||
|
||||
TEST_AA_SPLITCON("label (mode)", "label", "mode", "basic split");
|
||||
|
||||
TEST_AA_SPLITCON("/a/b/c (enforce)", "/a/b/c", "enforce",
|
||||
"path enforce split");
|
||||
|
||||
TEST_AA_SPLITCON("/a/b/c (complain)", "/a/b/c", "complain",
|
||||
"path complain split");
|
||||
|
||||
TEST_AA_SPLITCON("profile_name (enforce)", "profile_name", "enforce",
|
||||
"name enforce split");
|
||||
|
||||
TEST_AA_SPLITCON("profile_name (complain)", "profile_name", "complain",
|
||||
"name complain split");
|
||||
|
||||
TEST_AA_SPLITCON("unconfined", "unconfined", NULL, "unconfined");
|
||||
|
||||
TEST_AA_SPLITCON("(odd) (enforce)", "(odd)", "enforce",
|
||||
"parenthesized label #1");
|
||||
|
||||
TEST_AA_SPLITCON("(odd) (enforce) (enforce)", "(odd) (enforce)",
|
||||
"enforce", "parenthesized label #2");
|
||||
|
||||
TEST_AA_SPLITCON("/usr/bin/😺 (enforce)", "/usr/bin/😺", "enforce",
|
||||
"non-ASCII path");
|
||||
|
||||
TEST_AA_SPLITCON("👍 (enforce)", "👍", "enforce",
|
||||
"non-ASCII profile name");
|
||||
|
||||
/* Negative tests */
|
||||
|
||||
TEST_AA_SPLITCON("", NULL, NULL, "empty string test");
|
||||
|
||||
TEST_AA_SPLITCON("profile\t(enforce)", NULL, NULL,
|
||||
"invalid tab separator");
|
||||
|
||||
TEST_AA_SPLITCON("profile(enforce)", NULL, NULL,
|
||||
"invalid missing separator");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int retval, rc = 0;
|
||||
|
||||
retval = test_splitcon();
|
||||
if (retval)
|
||||
rc = retval;
|
||||
|
||||
retval = test_aa_splitcon();
|
||||
if (retval)
|
||||
rc = retval;
|
||||
|
||||
return rc;
|
||||
}
|
@@ -3,30 +3,12 @@
|
||||
%{
|
||||
#include <aalogparse.h>
|
||||
#include <sys/apparmor.h>
|
||||
#include <sys/apparmor_private.h>
|
||||
|
||||
%}
|
||||
|
||||
%include "typemaps.i"
|
||||
%include <aalogparse.h>
|
||||
|
||||
/**
|
||||
* swig doesn't like the macro magic we do in apparmor.h and apparmor_private.h
|
||||
* so the function prototypes must be manually inserted.
|
||||
*
|
||||
* Functions that return a negative int and set errno upon error use a special
|
||||
* %exception directive and must be listed after the %exception below. All
|
||||
* other functions go here.
|
||||
*/
|
||||
|
||||
/* apparmor.h */
|
||||
|
||||
extern char *aa_splitcon(char *con, char **mode);
|
||||
|
||||
/* apparmor_private.h */
|
||||
|
||||
extern int _aa_is_blacklisted(const char *name);
|
||||
|
||||
#ifdef SWIGPYTHON
|
||||
%exception {
|
||||
$action
|
||||
@@ -37,9 +19,9 @@ extern int _aa_is_blacklisted(const char *name);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Functions that return a negative int and set errno upon error go here. */
|
||||
|
||||
/* apparmor.h */
|
||||
/* swig doesn't like the macro magic we do in apparmor.h so the fn prototypes
|
||||
* are manually inserted here
|
||||
*/
|
||||
|
||||
extern int aa_is_enabled(void);
|
||||
extern int aa_find_mountpoint(char **mnt);
|
||||
@@ -51,22 +33,11 @@ extern int aa_change_hat_vargs(unsigned long token, int count, ...);
|
||||
extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
|
||||
char **mode);
|
||||
extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
|
||||
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
||||
extern int aa_getcon(char **label, char **mode);
|
||||
extern int aa_gettaskcon(pid_t target, char **con, char **mode);
|
||||
extern int aa_getcon(char **con, char **mode);
|
||||
extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
|
||||
extern int aa_getpeercon(int fd, char **label, char **mode);
|
||||
extern int aa_getpeercon(int fd, char **con, char **mode);
|
||||
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
||||
int *audit);
|
||||
extern 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);
|
||||
extern int aa_query_file_path(uint32_t mask, const char *label,
|
||||
const char *path, int *allowed, int *audited);
|
||||
extern 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);
|
||||
extern int aa_query_link_path(const char *label, const char *target,
|
||||
const char *link, int *allowed, int *audited);
|
||||
|
||||
%exception;
|
||||
|
@@ -6,8 +6,9 @@ SUBDIRS = test
|
||||
|
||||
libapparmor_wrap.c: $(srcdir)/../SWIG/libapparmor.i
|
||||
$(SWIG) -python -I$(srcdir)/../../include -module LibAppArmor -o $@ $(srcdir)/../SWIG/libapparmor.i
|
||||
mv LibAppArmor.py __init__.py
|
||||
|
||||
MOSTLYCLEANFILES=libapparmor_wrap.c LibAppArmor.py
|
||||
MOSTLYCLEANFILES=libapparmor_wrap.c __init__.py
|
||||
|
||||
all-local: libapparmor_wrap.c setup.py
|
||||
if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi
|
||||
|
@@ -1,6 +0,0 @@
|
||||
import sys
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
from LibAppArmor.LibAppArmor import *
|
||||
else:
|
||||
from .LibAppArmor import *
|
@@ -1 +0,0 @@
|
||||
[103975.623545] audit: type=1400 audit(1481284511.494:2807): apparmor="DENIED" operation="change_onexec" info="no new privs" error=-1 namespace="root//lxd-tor_<var-lib-lxd>" profile="unconfined" name="system_tor" pid=18593 comm="(tor)" target="system_tor"
|
@@ -1,15 +0,0 @@
|
||||
START
|
||||
File: change_onexec_lp1648143.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1481284511.494:2807
|
||||
Operation: change_onexec
|
||||
Profile: unconfined
|
||||
Name: system_tor
|
||||
Command: (tor)
|
||||
Name2: system_tor
|
||||
Namespace: root//lxd-tor_<var-lib-lxd>
|
||||
Info: no new privs
|
||||
ErrorCode: 1
|
||||
PID: 18593
|
||||
Epoch: 1481284511
|
||||
Audit subid: 2807
|
@@ -1 +0,0 @@
|
||||
type=AVC msg=audit(1465133533.431:728): apparmor="DENIED" operation="chown" profile="/usr/sbin/cupsd" name="/run/cups/certs/" pid=8515 comm="cupsd" requested_mask="w" denied_mask="w" fsuid=0 ouid=4
|
@@ -1,15 +0,0 @@
|
||||
START
|
||||
File: file_chown.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1465133533.431:728
|
||||
Operation: chown
|
||||
Mask: w
|
||||
Denied Mask: w
|
||||
fsuid: 0
|
||||
ouid: 4
|
||||
Profile: /usr/sbin/cupsd
|
||||
Name: /run/cups/certs/
|
||||
Command: cupsd
|
||||
PID: 8515
|
||||
Epoch: 1465133533
|
||||
Audit subid: 728
|
@@ -1 +0,0 @@
|
||||
Oct 22 15:57:38 NR021AA kernel: [ 69.827705] audit: type=1400 audit(1445522258.769:1054): apparmor="DENIED" operation="file_inherit" profile="/usr/lib/NetworkManager/nm-dhcp-client.action" pid=2407 comm="nm-dhcp-client." lport=10580 family="inet6" sock_type="dgram" protocol=17
|
@@ -1,14 +0,0 @@
|
||||
START
|
||||
File: file_inherit_network_lp1509030.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1445522258.769:1054
|
||||
Operation: file_inherit
|
||||
Profile: /usr/lib/NetworkManager/nm-dhcp-client.action
|
||||
Command: nm-dhcp-client.
|
||||
PID: 2407
|
||||
Network family: inet6
|
||||
Socket type: dgram
|
||||
Protocol: udp
|
||||
Local port: 10580
|
||||
Epoch: 1445522258
|
||||
Audit subid: 1054
|
@@ -1 +0,0 @@
|
||||
Jun 19 12:00:55 piorun kernel: [4475115.459952] audit: type=1400 audit(1434708055.676:19629): apparmor="ALLOWED" operation="file_perm" profile="/usr/sbin/apache2" pid=3512 comm="apache2" laddr=::ffff:192.168.236.159 lport=80 faddr=::ffff:192.168.103.80 fport=61985 family="inet6" sock_type="stream" protocol=6
|
@@ -1,17 +0,0 @@
|
||||
START
|
||||
File: file_perm_network_lp1466812.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1434708055.676:19629
|
||||
Operation: file_perm
|
||||
Profile: /usr/sbin/apache2
|
||||
Command: apache2
|
||||
PID: 3512
|
||||
Network family: inet6
|
||||
Socket type: stream
|
||||
Protocol: tcp
|
||||
Local addr: ::ffff:192.168.236.159
|
||||
Foreign addr: ::ffff:192.168.103.80
|
||||
Local port: 80
|
||||
Foreign port: 61985
|
||||
Epoch: 1434708055
|
||||
Audit subid: 19629
|
@@ -1 +0,0 @@
|
||||
type=AVC msg=audit(1463403689.381:267599): apparmor="ALLOWED" operation="file_perm" profile="/usr/sbin/apache2//www.xxxxxxxxxx.co.uk" pid=13215 comm="apache2" laddr=::ffff:192.168.1.100 lport=80 faddr=::ffff:192.168.1.100 fport=45658 family="inet6" sock_type="stream" protocol=6 requested_mask="send" denied_mask="send"
|
@@ -1,19 +0,0 @@
|
||||
START
|
||||
File: file_perm_network_receive_lp1577051.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1463403689.381:267599
|
||||
Operation: file_perm
|
||||
Mask: send
|
||||
Denied Mask: send
|
||||
Profile: /usr/sbin/apache2//www.xxxxxxxxxx.co.uk
|
||||
Command: apache2
|
||||
PID: 13215
|
||||
Network family: inet6
|
||||
Socket type: stream
|
||||
Protocol: tcp
|
||||
Local addr: ::ffff:192.168.1.100
|
||||
Foreign addr: ::ffff:192.168.1.100
|
||||
Local port: 80
|
||||
Foreign port: 45658
|
||||
Epoch: 1463403689
|
||||
Audit subid: 267599
|
@@ -1 +0,0 @@
|
||||
Apr 30 21:53:05 nova kernel: [24668.960760] audit: type=1400 audit(1462045985.636:2154): apparmor="ALLOWED" operation="file_perm" profile="/usr/local/apache-tomcat-8.0.33/bin/catalina.sh///usr/local/jdk1.8.0_92/bin/java" pid=12529 comm="java" laddr=::ffff:127.0.0.1 lport=8080 faddr=::ffff:127.0.0.1 fport=52308 family="inet6" sock_type="stream" protocol=6 requested_mask="receive" denied_mask="receive"
|
@@ -1,19 +0,0 @@
|
||||
START
|
||||
File: file_perm_network_receive_lp1582374.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1462045985.636:2154
|
||||
Operation: file_perm
|
||||
Mask: receive
|
||||
Denied Mask: receive
|
||||
Profile: /usr/local/apache-tomcat-8.0.33/bin/catalina.sh///usr/local/jdk1.8.0_92/bin/java
|
||||
Command: java
|
||||
PID: 12529
|
||||
Network family: inet6
|
||||
Socket type: stream
|
||||
Protocol: tcp
|
||||
Local addr: ::ffff:127.0.0.1
|
||||
Foreign addr: ::ffff:127.0.0.1
|
||||
Local port: 8080
|
||||
Foreign port: 52308
|
||||
Epoch: 1462045985
|
||||
Audit subid: 2154
|
@@ -1 +0,0 @@
|
||||
Sep 14 18:49:13 mfa-mia-74-app-rabbitmq-1.mia.ix.int kernel: [964718.247816] type=1400 audit(1442256553.643:40143): apparmor="ALLOWED" operation="open" profile="/opt/evoke/venv/bin/gunicorn" name="/opt/evoke/venv/lib/python2.7/warnings.pyc" pid=28943 comm="gunicorn" requested_mask="r" denied_mask="r" fsuid=1000 ouid=110
|
@@ -1,15 +0,0 @@
|
||||
START
|
||||
File: syslog_hostname_with_dot.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1442256553.643:40143
|
||||
Operation: open
|
||||
Mask: r
|
||||
Denied Mask: r
|
||||
fsuid: 1000
|
||||
ouid: 110
|
||||
Profile: /opt/evoke/venv/bin/gunicorn
|
||||
Name: /opt/evoke/venv/lib/python2.7/warnings.pyc
|
||||
Command: gunicorn
|
||||
PID: 28943
|
||||
Epoch: 1442256553
|
||||
Audit subid: 40143
|
@@ -1 +0,0 @@
|
||||
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"
|
@@ -1,11 +0,0 @@
|
||||
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
|
@@ -1 +0,0 @@
|
||||
Sep 9 12:51:36 ubuntu-desktop kernel: [ 97.492562] audit: type=1400 audit(1431116353.523:77): apparmor="DENIED" operation="change_profile" profile="/tests/regression/apparmor/changeprofile" pid=3459 comm="changeprofile" target="/tests/regression/apparmor/rename"
|
@@ -1,11 +0,0 @@
|
||||
START
|
||||
File: testcase_changeprofile_01.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1431116353.523:77
|
||||
Operation: change_profile
|
||||
Profile: /tests/regression/apparmor/changeprofile
|
||||
Command: changeprofile
|
||||
Name2: /tests/regression/apparmor/rename
|
||||
PID: 3459
|
||||
Epoch: 1431116353
|
||||
Audit subid: 77
|
@@ -1 +0,0 @@
|
||||
[ 1612.746129] audit: type=1400 audit(1284061910.975:672): apparmor="DENIED" operation="capable" parent=2663 profile="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/syscall_setpriority" pid=7292 comm="syscall_setprio" capability=23 capname="sys_nice"
|
@@ -1,12 +0,0 @@
|
||||
START
|
||||
File: testcase_dmesg_capability.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1284061910.975:672
|
||||
Operation: capable
|
||||
Profile: /home/ubuntu/bzr/apparmor/tests/regression/apparmor/syscall_setpriority
|
||||
Name: sys_nice
|
||||
Command: syscall_setprio
|
||||
Parent: 2663
|
||||
PID: 7292
|
||||
Epoch: 1284061910
|
||||
Audit subid: 672
|
@@ -1 +0,0 @@
|
||||
[ 1597.774866] audit: type=1400 audit(1284061896.005:28): apparmor="DENIED" operation="change_hat" info="unconfined" error=-1 pid=2698 comm="syscall_ptrace"
|
@@ -1,11 +0,0 @@
|
||||
START
|
||||
File: testcase_dmesg_changehat_negative_error.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1284061896.005:28
|
||||
Operation: change_hat
|
||||
Command: syscall_ptrace
|
||||
Info: unconfined
|
||||
ErrorCode: 1
|
||||
PID: 2698
|
||||
Epoch: 1284061896
|
||||
Audit subid: 28
|
@@ -1 +0,0 @@
|
||||
[ 97.492562] audit: type=1400 audit(1431116353.523:77): apparmor="DENIED" operation="change_profile" profile="/tests/regression/apparmor/changeprofile" pid=3459 comm="changeprofile" target="/tests/regression/apparmor/rename"
|
@@ -1,11 +0,0 @@
|
||||
START
|
||||
File: testcase_dmesg_changeprofile_01.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1431116353.523:77
|
||||
Operation: change_profile
|
||||
Profile: /tests/regression/apparmor/changeprofile
|
||||
Command: changeprofile
|
||||
Name2: /tests/regression/apparmor/rename
|
||||
PID: 3459
|
||||
Epoch: 1431116353
|
||||
Audit subid: 77
|
@@ -1 +0,0 @@
|
||||
[ 2010.738449] audit: type=1400 audit(1284062308.965:276251): apparmor="DENIED" operation="link" parent=19088 profile="/home/ubuntu/bzr/apparmor/tests/regression/apparmor/link" name="/tmp/sdtest.19088-12382-HWH57d/linkfile" pid=19142 comm="link" requested_mask="l" denied_mask="l" fsuid=0 ouid=0 target="/tmp/sdtest.19088-12382-HWH57d/target"
|
@@ -1,17 +0,0 @@
|
||||
START
|
||||
File: testcase_dmesg_link_01.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1284062308.965:276251
|
||||
Operation: link
|
||||
Mask: l
|
||||
Denied Mask: l
|
||||
fsuid: 0
|
||||
ouid: 0
|
||||
Profile: /home/ubuntu/bzr/apparmor/tests/regression/apparmor/link
|
||||
Name: /tmp/sdtest.19088-12382-HWH57d/linkfile
|
||||
Command: link
|
||||
Name2: /tmp/sdtest.19088-12382-HWH57d/target
|
||||
Parent: 19088
|
||||
PID: 19142
|
||||
Epoch: 1284062308
|
||||
Audit subid: 276251
|
@@ -1 +0,0 @@
|
||||
[45334.755142] audit: type=1503 audit(1282671283.411:2199): operation="mkdir" pid=4786 parent=4708 profile="/usr/sbin/sshd//ubuntu" requested_mask="c::" denied_mask="c::" fsuid=1000 ouid=1000 name="/tmp/ssh-gRozJw4786/"
|
@@ -1,15 +0,0 @@
|
||||
START
|
||||
File: testcase_dmesg_mkdir.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1282671283.411:2199
|
||||
Operation: mkdir
|
||||
Mask: c::
|
||||
Denied Mask: c::
|
||||
fsuid: 1000
|
||||
ouid: 1000
|
||||
Profile: /usr/sbin/sshd//ubuntu
|
||||
Name: /tmp/ssh-gRozJw4786/
|
||||
Parent: 4708
|
||||
PID: 4786
|
||||
Epoch: 1282671283
|
||||
Audit subid: 2199
|
@@ -1 +0,0 @@
|
||||
[ 878.663418] audit: type=1502 audit(1282626827.320:413): operation="rename_dest" pid=1881 parent=650 profile="/usr/sbin/sshd" requested_mask="wc::" denied_mask="wc::" fsuid=0 ouid=0 name="/var/run/motd"
|
@@ -1,15 +0,0 @@
|
||||
START
|
||||
File: testcase_dmesg_rename_dest.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1282626827.320:413
|
||||
Operation: rename_dest
|
||||
Mask: wc::
|
||||
Denied Mask: wc::
|
||||
fsuid: 0
|
||||
ouid: 0
|
||||
Profile: /usr/sbin/sshd
|
||||
Name: /var/run/motd
|
||||
Parent: 650
|
||||
PID: 1881
|
||||
Epoch: 1282626827
|
||||
Audit subid: 413
|
@@ -1 +0,0 @@
|
||||
[ 878.663410] audit: type=1502 audit(1282626827.320:412): operation="rename_src" pid=1881 parent=650 profile="/usr/sbin/sshd" requested_mask="r::" denied_mask="r::" fsuid=0 ouid=0 name="/var/run/motd.new"
|
@@ -1,15 +0,0 @@
|
||||
START
|
||||
File: testcase_dmesg_rename_src.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1282626827.320:412
|
||||
Operation: rename_src
|
||||
Mask: r::
|
||||
Denied Mask: r::
|
||||
fsuid: 0
|
||||
ouid: 0
|
||||
Profile: /usr/sbin/sshd
|
||||
Name: /var/run/motd.new
|
||||
Parent: 650
|
||||
PID: 1881
|
||||
Epoch: 1282626827
|
||||
Audit subid: 412
|
@@ -1 +0,0 @@
|
||||
[ 2143.902340] audit: type=1400 audit(1283989336.064:272335): apparmor="STATUS" info="failed to unpack profile" error=-71 pid=4958 comm="apparmor_parser" name="/home/jj/master/tests/regression/apparmor/net_raw" offset=159
|
@@ -1,11 +0,0 @@
|
||||
START
|
||||
File: testcase_dmesg_status_offset.in
|
||||
Event type: AA_RECORD_STATUS
|
||||
Audit ID: 1283989336.064:272335
|
||||
Name: /home/jj/master/tests/regression/apparmor/net_raw
|
||||
Command: apparmor_parser
|
||||
Info: failed to unpack profile
|
||||
ErrorCode: 71
|
||||
PID: 4958
|
||||
Epoch: 1283989336
|
||||
Audit subid: 272335
|
@@ -1 +0,0 @@
|
||||
[ 878.662172] audit: type=1503 audit(1282626827.320:411): operation="truncate" pid=1957 parent=1 profile="/etc/update-motd.d/91-release-upgrade" requested_mask="w::" denied_mask="w::" fsuid=0 ouid=0 name="/var/lib/update-notifier/release-upgrade-available"
|
@@ -1,15 +0,0 @@
|
||||
START
|
||||
File: testcase_dmesg_truncate.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1282626827.320:411
|
||||
Operation: truncate
|
||||
Mask: w::
|
||||
Denied Mask: w::
|
||||
fsuid: 0
|
||||
ouid: 0
|
||||
Profile: /etc/update-motd.d/91-release-upgrade
|
||||
Name: /var/lib/update-notifier/release-upgrade-available
|
||||
Parent: 1
|
||||
PID: 1957
|
||||
Epoch: 1282626827
|
||||
Audit subid: 411
|
@@ -1 +0,0 @@
|
||||
Jul 29 11:42:05 files kernel: [483212.877816] audit: type=1400 audit(1469785325.122:21021): apparmor="ALLOWED" operation="file_inherit" profile="/usr/bin/nginx-amplify-agent.py//null-/bin/dash" pid=18239 comm="sh" laddr=192.168.10.3 lport=50758 faddr=54.153.70.241 fport=443 family="inet" sock_type="stream" protocol=6 requested_mask="send receive" denied_mask="send receive"
|
@@ -1,19 +0,0 @@
|
||||
START
|
||||
File: testcase_network_send_receive.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1469785325.122:21021
|
||||
Operation: file_inherit
|
||||
Mask: send receive
|
||||
Denied Mask: send receive
|
||||
Profile: /usr/bin/nginx-amplify-agent.py//null-/bin/dash
|
||||
Command: sh
|
||||
PID: 18239
|
||||
Network family: inet
|
||||
Socket type: stream
|
||||
Protocol: tcp
|
||||
Local addr: 192.168.10.3
|
||||
Foreign addr: 54.153.70.241
|
||||
Local port: 50758
|
||||
Foreign port: 443
|
||||
Epoch: 1469785325
|
||||
Audit subid: 21021
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user