...
 
Commits (272)
......@@ -45,16 +45,25 @@ 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/sys/Makefile
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
......@@ -70,12 +79,18 @@ 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/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/__init__.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/ruby/Makefile
libraries/libapparmor/swig/ruby/Makefile.in
libraries/libapparmor/testsuite/.deps
......
......@@ -14,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/master
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/"
......
......@@ -60,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) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
EXTRA_CFLAGS=$(CFLAGS) $(CPPFLAGS) -fPIC -shared -Wall $(LIBAPPARMOR_INCLUDE)
LINK_FLAGS=-Xlinker -x $(AA_LINK_FLAGS)
LIBS=-lpam $(AA_LDLIBS)
OBJECTS=${NAME}.o get_options.o
......
......@@ -111,6 +111,7 @@ 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)));
......
......@@ -198,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_UNSPEC PF_UNIX
FILTER_FAMILIES=PF_UNIX
__FILTER=$(shell echo $(strip $(FILTER_FAMILIES)) | sed -e 's/ /\\\|/g')
......
......@@ -38,6 +38,6 @@ aclocal
echo "Running autoconf"
autoconf --force
echo "Running libtoolize"
libtoolize --automake -c
libtoolize --automake -c --force
echo "Running automake"
automake -ac
......@@ -40,16 +40,15 @@ 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. 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.
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.
If a program wants to return out of the current profile to the
original profile, it should use aa_change_hat(2) instead.
original profile, it may use aa_change_hat(2). Otherwise, the two profiles must
have rules permitting changing between the two profiles.
Open file descriptors are not remediated after a call to aa_change_profile()
Open file descriptors may not be 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
......@@ -84,8 +83,8 @@ Insufficient kernel memory was available.
=item B<EPERM>
The calling application is not confined by apparmor, or the no_new_privs
bit is set.
The calling application is confined by apparmor and the no_new_privs bit is
set.
=item B<EACCES>
......
......@@ -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
......
[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"
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
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
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
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
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
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"
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
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"
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
Jul 25 15:02:00 redacted kernel: [ 296.524447] audit: type=1400 audit(1437850920.403:64): apparmor="ALLOWED" operation="open" profile="/usr/sbin/vsftpd" name="/home/bane/foo" pid=1811 comm="vsftpd" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
START
File: testcase_syslog_read.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1437850920.403:64
Operation: open
Mask: r
Denied Mask: r
fsuid: 1000
ouid: 1000
Profile: /usr/sbin/vsftpd
Name: /home/bane/foo
Command: vsftpd
PID: 1811
Epoch: 1437850920
Audit subid: 64
Feb 21 23:22:01 mail-20170118 kernel: [1222198.459750] audit: type=1400 audit(1487719321.954:218): apparmor="ALLOWED" operation="change_hat" info="unconfined can not change_hat" error=-1 profile="unconfined" pid=19941 comm="apache2"
START
File: unconfined-change_hat.in
Event type: AA_RECORD_ALLOWED
Audit ID: 1487719321.954:218
Operation: change_hat
Profile: unconfined
Command: apache2
Info: unconfined can not change_hat
ErrorCode: 1
PID: 19941
Epoch: 1487719321
Audit subid: 218
......@@ -56,7 +56,7 @@ CFLAGS = -g -pg -fprofile-arcs -ftest-coverage
endif
endif #CFLAGS
EXTRA_CXXFLAGS = ${CFLAGS} ${CXX_WARNINGS} -std=gnu++0x -D_GNU_SOURCE
EXTRA_CXXFLAGS = ${CFLAGS} ${CPPFLAGS} ${CXX_WARNINGS} -std=gnu++0x -D_GNU_SOURCE
EXTRA_CFLAGS = ${EXTRA_CXXFLAGS} ${CPP_WARNINGS}
#LEXLIB := -lfl
......@@ -181,7 +181,7 @@ $(LIBAPPARMOR_A):
echo "error: $@ is missing. Pick one of these possible solutions:" 1>&2; \
echo " 1) Build against the in-tree libapparmor by building it first and then trying again. See the top-level README for help." 1>&2; \
echo " 2) Build against the system libapparmor by adding USE_SYSTEM=1 to your make command." 1>&2;\
return 1; \
exit 1; \
fi
endif
......@@ -216,7 +216,7 @@ parser_include.o: parser_include.c parser.h parser_include.h
parser_merge.o: parser_merge.c parser.h profile.h
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
parser_regex.o: parser_regex.c parser.h profile.h libapparmor_re/apparmor_re.h $(APPARMOR_H)
parser_regex.o: parser_regex.c parser.h profile.h libapparmor_re/apparmor_re.h libapparmor_re/aare_rules.h $(APPARMOR_H)
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
parser_symtab.o: parser_symtab.c parser.h
......
......@@ -148,11 +148,14 @@ ostream &af_rule::dump_peer(ostream &os)
ostream &af_rule::dump(ostream &os)
{
os << dump_prefix(os);
dump_prefix(os);
os << af_name;
os << dump_local(os);
if (has_peer_conds())
os << " peer=(" << dump_peer(os) << ")";
dump_local(os);
if (has_peer_conds()) {
os << " peer=(";
dump_peer(os);
os << ")";
}
os << ",\n";
return os;
......
......@@ -196,16 +196,20 @@ static void writeu16(std::ostringstream &o, int v)
#define CMD_OPT 4
void unix_rule::downgrade_rule(Profile &prof) {
unsigned int mask = (unsigned int) -1;
if (!prof.net.allow && !prof.alloc_net_table())
yyerror(_("Memory allocation error."));
if (sock_type_n != -1)
mask = 1 << sock_type_n;
if (deny) {
prof.net.deny[AF_UNIX] |= 1 << sock_type_n;
prof.net.deny[AF_UNIX] |= mask;
if (!audit)
prof.net.quiet[AF_UNIX] |= 1 << sock_type_n;
prof.net.quiet[AF_UNIX] |= mask;
} else {
prof.net.allow[AF_UNIX] |= 1 << sock_type_n;
prof.net.allow[AF_UNIX] |= mask;
if (audit)
prof.net.audit[AF_UNIX] |= 1 << sock_type_n;
prof.net.audit[AF_UNIX] |= mask;
}
}
......
......@@ -61,7 +61,7 @@ B<SUBPROFILE> = [ I<COMMENT> ... ] ( I<PROGRAMHAT> | 'profile ' I<PROGRAMCHILD>
B<CAPABILITY> = (lowercase capability name without 'CAP_' prefix; see
capabilities(7))
B<NETWORK RULE> = 'network' [ [ I<DOMAIN> ] [ I<TYPE> ] [ I<PROTOCOL> ] ] ','
B<NETWORK RULE> = 'network' [ [ I<DOMAIN> [ I<TYPE> | I<PROTOCOL> ] ] | [ I<PROTOCOL> ] ] ','
B<DOMAIN> = ( 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'bluetooth' | 'netlink' ) ','
......@@ -121,7 +121,7 @@ B<SIGNAL SET> = 'set' '=' '(' I<SIGNAL LIST> ')'
B<SIGNAL LIST> = Comma or space separated list of I<SIGNALS>
B<SIGNALS> = ( 'hup' | 'int' | 'quit' | 'ill' | 'trap' | 'abrt' | 'bus' | 'fpe' | 'kill' | 'usr1' | 'segv' | 'usr2' | 'pipe' | 'alrm' | 'term' | 'stkflt' | 'chld' | 'cont' | 'stop' | 'stp' | 'ttin' | 'ttou' | 'urg' | 'xcpu' | 'xfsz' | 'vtalrm' | 'prof' | 'winch' | 'io' | 'pwr' | 'sys' | 'emt' | 'exists' )
B<SIGNALS> = ( 'hup' | 'int' | 'quit' | 'ill' | 'trap' | 'abrt' | 'bus' | 'fpe' | 'kill' | 'usr1' | 'segv' | 'usr2' | 'pipe' | 'alrm' | 'term' | 'stkflt' | 'chld' | 'cont' | 'stop' | 'stp' | 'ttin' | 'ttou' | 'urg' | 'xcpu' | 'xfsz' | 'vtalrm' | 'prof' | 'winch' | 'io' | 'pwr' | 'sys' | 'emt' | 'exists' | 'rtmin+0' ... 'rtmin+32' )
B<SIGNAL PEER> = 'peer' '=' I<AARE>
......@@ -770,6 +770,9 @@ Example AppArmor signal rules:
# Allow us to signal ourselves using the built-in @{profile_name} variable
signal peer=@{profile_name},
# Allow two real-time signals
signal set=(rtmin+0 rtmin+32),
=head2 DBus rules
AppArmor supports DBus mediation. The mediation is performed in conjunction
......@@ -963,7 +966,8 @@ must be made before the start of the profile.
The parser will automatically expand variables to include all values
that they have been assigned; it is an error to reference a variable
without setting at least one value.
without setting at least one value. You can use empty quotes ("") to
explicitly add an empty value.
At the time of this writing, the following variables are defined in the
provided AppArmor policy:
......@@ -972,8 +976,10 @@ provided AppArmor policy:
@{HOMEDIRS}
@{multiarch}
@{pid}
@{pids}
@{PROC}
@{securityfs}
@{apparmorfs}
@{sys}
@{tid}
@{XDG_DESKTOP_DIR}
......@@ -1192,10 +1198,6 @@ files, and the X socket.
=back
The abstractions stored in F</etc/apparmor.d/program-chunks/> are
intended for use by specific program suites, and are not generally
useful.
Some of the abstractions rely on variables that are set in files in the
F</etc/apparmor.d/tunables/> directory. These variables are currently
B<@{HOME}> and B<@{HOMEDIRS}>. Variables cannot be set in profile scope;
......
......@@ -46,7 +46,7 @@ program. The B<profiles> may be specified by file name or a directory
name containing a set of profiles. If a directory is specified then the
B<apparmor_parser> will try to do a profile load for each file in the
directory that is not a dot file, or explicitly black listed (*.dpkg-new,
*.dpkg-old, *.dpkg-dist, *-dpkg-bak, *.repnew, *.rpmsave, *orig, *.rej,
*.dpkg-old, *.dpkg-dist, *-dpkg-bak, *.rpmnew, *.rpmsave, *orig, *.rej,
*~). The B<apparmor_parser> will fall back to taking input from standard
input if a profile or directory is not supplied.
......@@ -282,7 +282,7 @@ it so that policy can't complete compilation due to size constraints
take days or longer to compile).
Note: The parser is set to use a balanced default set of flags, that
will result in resonable compression but not take excessive amounts
will result in reasonable compression but not take excessive amounts
of time to complete.
Use --help=optimize to see a full list of which optimization flags are
......
......@@ -149,7 +149,7 @@ ostream &dbus_rule::dump(ostream &os)
if (interface)
os << " interface=\"" << interface << "\"";
if (member)
os << " member=\"" << member << os << "\"";
os << " member=\"" << member << "\"";
if (!(mode & AA_DBUS_BIND) && (peer_label || name)) {
os << " peer=( ";
......
......@@ -62,9 +62,9 @@
int dirat_for_each(DIR *dir, const char *name, void *data,
int (* cb)(DIR *, const char *, struct stat *, void *))
{
struct dirent *dirent = NULL, *ent;
struct dirent *dirent = NULL;
DIR *d = NULL;
int error = 0;
int error;
if (!cb || (!dir && !name)) {
errno = EINVAL;
......@@ -102,11 +102,19 @@ int dirat_for_each(DIR *dir, const char *name, void *data,
d = dir;
}
for (error = readdir_r(d, dirent, &ent);
error == 0 && ent != NULL;
error = readdir_r(d, dirent, &ent)) {
for (;;) {
struct dirent *ent;
struct stat my_stat;
error = readdir_r(d, dirent, &ent);
if (error) {
PDEBUG("readdir_r failed");
errno = error; /* readdir_r directly returns an errno */
goto fail;
} else if (!ent) {
break;
}
if (strcmp(ent->d_name, ".") == 0 ||
strcmp(ent->d_name, "..") == 0)
continue;
......@@ -126,7 +134,7 @@ int dirat_for_each(DIR *dir, const char *name, void *data,
closedir(d);
free(dirent);
return error;
return 0;
fail:
error = errno;
......
......@@ -672,7 +672,7 @@ public:
~hashedNodeVec()
{
delete nodes;
delete [] nodes;
}
unsigned long size()const { return len; }
......
......@@ -1335,19 +1335,16 @@ int accept_perms(NodeSet *state, perms_t &perms)
}
perms.allow |= exact_match_allow & ~(ALL_AA_EXEC_TYPE);
if (exact_match_allow & AA_USER_EXEC_TYPE) {
perms.audit |= exact_audit & ~(ALL_AA_EXEC_TYPE);
if (exact_match_allow & AA_USER_EXEC) {
perms.allow = (exact_match_allow & AA_USER_EXEC_TYPE) |
(perms.allow & ~AA_USER_EXEC_TYPE);
perms.audit = (exact_audit & AA_USER_EXEC_TYPE) |
(perms.audit & ~AA_USER_EXEC_TYPE);
perms.exact = AA_USER_EXEC_TYPE;
}
if (exact_match_allow & AA_OTHER_EXEC_TYPE) {
if (exact_match_allow & AA_OTHER_EXEC) {
perms.allow = (exact_match_allow & AA_OTHER_EXEC_TYPE) |
(perms.allow & ~AA_OTHER_EXEC_TYPE);
perms.audit = (exact_audit & AA_OTHER_EXEC_TYPE) |
(perms.audit & ~AA_OTHER_EXEC_TYPE);
perms.exact |= AA_OTHER_EXEC_TYPE;
}
if (AA_USER_EXEC & perms.deny)
......
......@@ -321,31 +321,19 @@ struct aa_network_entry *network_entry(const char *family, const char *type,
#define ALL_TYPES 0x43e
/* another case of C++ not supporting non-trivial designated initializers */
#undef AA_GEN_NET_ENT
#define AA_GEN_NET_ENT(name, AF) name, /* [AF] = name, */
static const char *network_families[] = {
#include "af_names.h"
};
int net_find_af_val(const char *af)
{
int i;
for (i = 0; network_families[i]; i++) {
if (strcmp(network_families[i], af) == 0)
return i;
}
return -1;
}
const char *net_find_af_name(unsigned int af)
{
size_t i;
if (af < 0 || af > get_af_max())
return NULL;
return network_families[af];
for (i = 0; i < sizeof(network_mappings) / sizeof(*network_mappings); i++) {
if (network_mappings[i].family == af)
return network_mappings[i].family_name;
}
return NULL;
}
void __debug_network(unsigned int *array, const char *name)
......@@ -375,7 +363,7 @@ void __debug_network(unsigned int *array, const char *name)
for (i = 0; i < af_max; i++) {
if (array[i]) {
const char *fam = network_families[i];
const char *fam = net_find_af_name(i);
if (fam)
printf("%s ", fam);
else
......
......@@ -125,7 +125,6 @@ struct network {
int net_find_type_val(const char *type);
const char *net_find_type_name(int type);
int net_find_af_val(const char *af);
const char *net_find_af_name(unsigned int af);
const struct network_tuple *net_find_mapping(const struct network_tuple *map,
const char *family,
......
......@@ -172,7 +172,7 @@ extern int preprocess_only;
#ifdef DEBUG
#define PDEBUG(fmt, args...) printf("parser: " fmt, ## args)
#define PDEBUG(fmt, args...) fprintf(stderr, "parser: " fmt, ## args)
#else
#define PDEBUG(fmt, args...) /* Do nothing */
#endif
......
......@@ -38,6 +38,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/apparmor.h>
#include <sys/time.h>
#include <utime.h>
#include "lib.h"
#include "parser.h"
......@@ -587,7 +589,9 @@ static int features_dir_cb(DIR *dir, const char *name, struct stat *st,
if (S_ISREG(st->st_mode)) {
int len, file;
int remaining = fst->size - (fst->pos - *fst->buffer);
if (!(file = openat(dirfd(dir), name, O_RDONLY))) {
file = openat(dirfd(dir), name, O_RDONLY);
if (file == -1) {
PDEBUG("Could not open '%s'", name);
return -1;
}
......@@ -871,17 +875,18 @@ static bool valid_cached_file_version(const char *cachename)
return true;
}
/* returns true if time is more recent than mru_tstamp */
#define mru_t_cmp(a) \
(((a).tv_sec == (mru_tstamp).tv_sec) ? \
(a).tv_nsec > (mru_tstamp).tv_nsec : (a).tv_sec > (mru_tstamp).tv_sec)
#define tstamp_cmp(a, b) \
(((a).tv_sec == (b).tv_sec) ? \
((a).tv_nsec - (b).tv_nsec) : \
((a).tv_sec - (b).tv_sec))
#define tstamp_is_null(a) ((a).tv_sec == 0 && (a).tv_nsec == 0)
void update_mru_tstamp(FILE *file)
{
struct stat stat_file;
if (fstat(fileno(file), &stat_file))
return;
if (mru_t_cmp(stat_file.st_mtim))
if (tstamp_cmp(stat_file.st_mtim, mru_tstamp) > 0)
mru_tstamp = stat_file.st_mtim;
}
......@@ -967,7 +972,8 @@ int process_profile(int option, const char *profilename)
/* Load a binary cache if it exists and is newest */
if (!skip_read_cache &&
stat(cachename, &stat_bin) == 0 &&
stat_bin.st_size > 0 && (mru_t_cmp(stat_bin.st_mtim)) &&
stat_bin.st_size > 0 &&
(tstamp_cmp(mru_tstamp, stat_bin.st_mtim) < 0) &&
valid_cached_file_version(cachename)) {
if (show_cache)
PERROR("Cache hit: %s\n", cachename);
......@@ -1035,6 +1041,12 @@ out:
}
if (useable_cache) {
struct timeval t;
/* set the mtime of the cache file to the most newest
* mtime of policy files used to generate it
*/
TIMESPEC_TO_TIMEVAL(&t, &mru_tstamp);
utimes(cachetemp, &t);
if (rename(cachetemp, cachename) < 0) {
pwarn("Warning failed to write cache: %s\n", cachename);
unlink(cachetemp);
......
......@@ -43,7 +43,7 @@
/* #define DEBUG */
#ifdef DEBUG
#undef PDEBUG
#define PDEBUG(fmt, args...) printf("Lexer: " fmt, ## args)
#define PDEBUG(fmt, args...) fprintf(stderr, "Lexer: " fmt, ## args)
#else
#undef PDEBUG
#define PDEBUG(fmt, args...) /* Do nothing */
......@@ -534,7 +534,7 @@ static int parse_X_sub_mode(const char *X, const char *str_mode, int *result, in
int mode = 0;
const char *p;
PDEBUG("Parsing X mode: %s\n", X, str_mode);
PDEBUG("Parsing %s mode: %s\n", X, str_mode);
if (!str_mode)
return 0;
......@@ -759,7 +759,7 @@ static const char *capnames[] = {
"audit_write",
"audit_control",
"setfcap",
"mac_override"
"mac_override",
"syslog",
};
......
......@@ -34,8 +34,10 @@
/* #define DEBUG */
#ifdef DEBUG
#define PDEBUG(fmt, args...) printf("Lexer: " fmt, ## args)
#undef PDEBUG
#define PDEBUG(fmt, args...) fprintf(stderr, "Lexer: " fmt, ## args)
#else
#undef PDEBUG
#define PDEBUG(fmt, args...) /* Do nothing */
#endif
#define NPDEBUG(fmt, args...) /* Do nothing */
......
......@@ -491,9 +491,14 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
* out by a deny rule, as both pieces of the link pair must
* match. audit info for the link is carried on the second
* entry of the pair
*
* So if a deny rule only record it if there are permissions other
* than link in the entry.
* TODO: split link and change_profile entries earlier
*/
if (entry->deny && (entry->mode & AA_LINK_BITS)) {
if (!dfarules->add_rule(tbuf.c_str(), entry->deny,
if (entry->deny) {
if ((entry->mode & ~(AA_LINK_BITS | AA_CHANGE_PROFILE)) &&
!dfarules->add_rule(tbuf.c_str(), entry->deny,
entry->mode & ~AA_LINK_BITS,
entry->audit & ~AA_LINK_BITS, dfaflags))
return FALSE;
......
......@@ -451,34 +451,7 @@ __apparmor_restart() {
configure_owlsm
parse_profiles reload
# Clean out running profiles not associated with the current profile
# set, excluding the libvirt dynamically generated profiles.
# Note that we reverse sort the list of profiles to remove to
# ensure that child profiles (e.g. hats) are removed before the
# parent. We *do* need to remove the child profile and not rely
# on removing the parent profile when the profile has had its
# child profile names changed.
profiles_names_list | awk '
BEGIN {
while (getline < "'${SFS_MOUNTPOINT}'/profiles" ) {
str = sub(/ \((enforce|complain)\)$/, "", $0);
if (match($0, /^libvirt-[0-9a-f\-]+$/) == 0)
arr[$str] = $str
}
}
{ if (length(arr[$0]) > 0) { delete arr[$0] } }
END {
for (key in arr)
if (length(arr[key]) > 0) {
printf("%s\n", arr[key])
}
}
' | LC_COLLATE=C sort -r | while IFS= read profile ; do
echo -n "$profile" > "$SFS_MOUNTPOINT/.remove"
done
# will not catch all errors, but still better than nothing
rc=$?
aa_log_end_msg $rc
return $rc
......
......@@ -94,12 +94,13 @@ aa_log_skipped_msg() {
echo -e "$rc_skipped"
}
_set_status() {
return $1
}
aa_log_end_msg() {
v="-v"
if [ "$1" != '0' ]; then
rc="-v$1"
fi
rc_status $v
_set_status $1
rc_status -v
}
usage() {
......
......@@ -9,6 +9,8 @@ PROVE_ARG=-f
ifeq ($(VERBOSE),1)
PROVE_ARG+=-v
PYTEST_ARG = -v
else
VERBOSE=
endif
all: tests
......
This diff is collapsed.
#=DESCRIPTON simple stress test nested ifs
#=DESCRIPTION simple stress test nested ifs
#=EXRESULT PASS
$a1 = true
$a2 = true
......
#
#=DESCRIPTION simple link access test
#=EXRESULT PASS
#
profile test {
audit deny link /alpha/beta -> /tmp/**,
}
#
#=DESCRIPTION simple link access test
#=EXRESULT PASS
#
profile test {
deny link /alpha/beta -> /tmp/**,
}
......@@ -3,6 +3,7 @@
#=EXRESULT PASS
#
/usr/bin/foo {
network unspec,
network inet,
network ax25,
network ipx,
......
#
#=DESCRIPTION basic unspec network tests
#=EXRESULT PASS
#
/usr/bin/foo {
network unspec stream,
network unspec dgram,
network unspec raw,
}
#
#=DESCRIPTION simple rtsig test
#=EXRESULT=PASS
#=EXRESULT PASS
#
/usr/bin/signal-test {
......
#
#=DESCRIPTION simple rtsig test
#=EXRESULT=PASS
#=EXRESULT PASS
#
/usr/bin/signal-test {
......
#=DESCRIPTION set variable assignment using set variable as rvalue
#=EXRESULT
#=EXRESULT PASS
@{FOO}=bar baz
@{BAR}=${FOO} blort
......@@ -42,7 +42,7 @@ class AAParserValgrindTests(testlib.AATestTemplate):
self.maxDiff = None
def _runtest(self, testname, config):
parser_args = ['-Q', '-I', config.testdir]
parser_args = ['-Q', '-I', config.testdir, '-M', './features_files/features.all']
failure_rc = [VALGRIND_ERROR_CODE, testlib.TIMEOUT_ERROR_CODE]
command = [config.valgrind]
command.extend(VALGRIND_ARGS)
......
......@@ -40,6 +40,9 @@ EXTRAS_SOURCE=./apparmor/profiles/extras/
SUBDIRS=$(shell find ${PROFILES_SOURCE} -type d -print)
TOPLEVEL_PROFILES=$(filter-out ${SUBDIRS}, $(wildcard ${PROFILES_SOURCE}/*))
# $(PWD) is wrong when using "make -C profiles" - explicitely set it here to get the right value
PWD=$(shell pwd)
local:
for profile in ${TOPLEVEL_PROFILES}; do \
fn=$$(basename $$profile); \
......
......@@ -17,15 +17,21 @@
# .Xauthority files required for X connections, per user
owner @{HOME}/.Xauthority r,
owner @{HOME}/.local/share/sddm/.Xauthority r,
owner /{,var/}run/gdm{,3}/*/database r,
owner /{,var/}run/lightdm/authority/[0-9]* r,
owner /{,var/}run/lightdm/*/xauthority r,
owner /{,var/}run/user/*/gdm/Xauthority r,
owner /{,var/}run/user/*/X11/Xauthority r,
# the unix socket to use to connect to the display
/tmp/.X11-unix/* w,
/tmp/.X11-unix/* rw,
unix (connect, receive, send)
type=stream
peer=(addr="@/tmp/.X11-unix/X[0-9]*"),
unix (connect, receive, send)
type=stream
peer=(addr="@/tmp/.ICE-unix/[0-9]*"),
/usr/include/X11/ r,
/usr/include/X11/** r,
......
......@@ -8,6 +8,8 @@
signal (receive) peer=unconfined,
# Allow apache to send us signals by default
signal (receive) peer=/usr/sbin/apache2,
# Allow other hats to signal by default
signal peer=/usr/sbin/apache2//*,
# Allow us to signal ourselves
signal peer=@{profile_name},
......@@ -25,3 +27,8 @@
/dev/urandom r,
# sasl-auth
/run/saslauthd/mux rw,
# OCSP stapling
/var/log/apache2/stapling-cache rw,
......@@ -8,4 +8,6 @@
/usr/lib/aspell/ r,
/usr/lib/aspell/* r,
/usr/lib/aspell/*.so m,
/usr/share/aspell/ r,
/usr/share/aspell/* r,
/var/lib/aspell/* r,
......@@ -49,7 +49,7 @@ owner @{HOME}/.cache/event-sound-cache.* rwk,
# pulse
/etc/pulse/ r,
/etc/pulse/* r,
/etc/pulse/** r,
/{run,dev}/shm/ r,
owner /{run,dev}/shm/pulse-shm* rwk,
owner @{HOME}/.pulse-cookie rwk,
......@@ -57,6 +57,8 @@ owner @{HOME}/.pulse/ rw,
owner @{HOME}/.pulse/* rwk,
owner /{,var/}run/user/*/pulse/ rw,
owner /{,var/}run/user/*/pulse/{native,pid} rwk,
owner @{HOME}/.config/pulse/*.conf r,
owner @{HOME}/.config/pulse/client.conf.d/{,*.conf} r,
owner @{HOME}/.config/pulse/cookie rwk,
owner /tmp/pulse-*/ rw,
owner /tmp/pulse-*/* rw,
......@@ -68,6 +70,8 @@ owner /tmp/pulse-*/* rw,
# openal
/etc/openal/alsoft.conf r,
owner @{HOME}/.alsoftrc r,
/usr/{,local/}share/openal/hrtf/{,**} r,
owner @{HOME}/.local/share/openal/hrtf/{,**} r,
# wildmidi
/etc/wildmidi/wildmidi.cfg r,
......@@ -26,12 +26,14 @@
/etc/locale/** r,
/etc/locale.alias r,
/etc/localtime r,
/usr/share/locale-bundle/** r,
/usr/share/locale-langpack/** r,
/usr/share/locale/** r,
/usr/share/**/locale/** r,
/usr/share/zoneinfo/ r,
/usr/share/zoneinfo/** r,
/usr/share/X11/locale/** r,
/{,var/}run/systemd/journal/dev-log w,
/usr/lib{,32,64}/locale/** mr,
/usr/lib{,32,64}/gconv/*.so mr,
......@@ -89,7 +91,7 @@
/sys/devices/system/cpu/online r,
# glibc's *printf protections read the maps file
@{PROC}/@{pid}/maps r,
@{PROC}/@{pid}/{maps,auxv,status} r,
# libgcrypt reads some flags from /proc
@{PROC}/sys/crypto/* r,
......
......@@ -17,6 +17,9 @@
type=stream
peer=(addr="@/tmp/dbus-*"),
# dbus with systemd and --enable-user-session
owner /run/user/[0-9]*/bus rw,
dbus send
bus=session
path=/org/freedesktop/DBus
......
......@@ -10,10 +10,10 @@
# ------------------------------------------------------------------
# system configuration
/usr/share/applications/ r,
/usr/share/applications/defaults.list r,
/usr/share/applications/mimeinfo.cache r,
/usr/share/applications/*.desktop r,
/usr/{,local/}share/applications/{*/,} r,
/usr/{,local/}share/applications/{*/,}defaults.list r,
/usr/{,local/}share/applications/{*/,}mimeinfo.cache r,
/usr/{,local/}share/applications/{*/,}*.desktop r,
/usr/share/icons/ r,
/usr/share/icons/** r,
/usr/share/pixmaps/ r,
......
......@@ -21,6 +21,8 @@
/etc/gtk/* r,
/usr/lib{,32,64}/gtk/** mr,
/usr/lib/@{multiarch}/gtk/** mr,
/usr/lib{,32,64}/gtk-[0-9]*/** mr,
/usr/lib/@{multiarch}/gtk-[0-9]*/** mr,
/usr/share/themes/ r,
/usr/share/themes/** r,
......
......@@ -4,6 +4,7 @@
# user configurations
owner @{HOME}/.gnupg/options r,
owner @{HOME}/.gnupg/pubring.gpg r,
owner @{HOME}/.gnupg/pubring.kbx r,
owner @{HOME}/.gnupg/random_seed rw,
owner @{HOME}/.gnupg/secring.gpg r,
owner @{HOME}/.gnupg/so/*.x86_64 mr,
......
# vim:syntax=apparmor
# ------------------------------------------------------------------
#
# Copyright (C) 2015 Canonical Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# mir libraries sometimes do not have a lib prefix
# see LP: #1422521
/usr/lib/@{multiarch}/mir/*.so* mr,
/usr/lib/@{multiarch}/mir/**/*.so* mr,
# unprivileged mir socket for clients
......@@ -21,6 +21,9 @@
/etc/passwd r,
/etc/protocols r,
# libtirpc (used for NIS/YP login) needs this
/etc/netconfig r,
# When using libnss-extrausers, the passwd and group files are merged from
# an alternate path
/var/lib/extrausers/group r,
......@@ -29,6 +32,7 @@
# When using sssd, the passwd and group files are stored in an alternate path
# and the nss plugin also needs to talk to a pipe
/var/lib/sss/mc/group r,
/var/lib/sss/mc/initgroups r,
/var/lib/sss/mc/passwd r,
/var/lib/sss/pipes/nss rw,
......@@ -38,6 +42,9 @@
# /etc/resolvconf/run/resolv.conf
/{,var/}run/resolvconf/resolv.conf r,
/etc/resolvconf/run/resolv.conf r,
# on systems using systemd's networkd, /etc/resolv.conf is a symlink to
# /run/systemd/resolve/resolv.conf
/{,var/}run/systemd/resolve/resolv.conf r,
/etc/samba/lmhosts r,
/etc/services r,
......@@ -47,7 +54,7 @@
# to vast speed increases when working with network-based lookups.
/{,var/}run/.nscd_socket rw,
/{,var/}run/nscd/socket rw,
/{var/db,var/cache,var/run,run}/nscd/{passwd,group,services,hosts} r,
/{var/db,var/cache,var/lib,var/run,run}/nscd/{passwd,group,services,hosts} r,
# nscd renames and unlinks files in it's operation that clients will
# have open
/{,var/}run/nscd/db* rmix,
......
......@@ -16,5 +16,6 @@
@{PROC}/driver/nvidia/params r,
@{PROC}/modules r,
owner @{HOME}/.nv/GLCache/ r,
owner @{HOME}/.nv/ w,
owner @{HOME}/.nv/GLCache/ rw,
owner @{HOME}/.nv/GLCache/** rwk,
# vim:syntax=apparmor
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2006 Novell/SUSE
# Copyright (C) 2009-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
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# shared snippets for config files
/etc/php{,5,7}/**/ r,
/etc/php{,5,7}/**.ini r,
# Xlibs
/usr/X11R6/lib{,32,64}/lib*.so* mr,
# php extensions
/usr/lib{64,}/php{,5,7}/*/*.so mr,
# php session mmap socket
/var/lib/php{,5,7}/session_mm_* rwlk,
# file based session handler
/var/lib/php{,5,7}/sess_* rwlk,
/var/lib/php{,5,7}/sessions/* rwlk,
# php libraries
/usr/share/php{,5,7}/ r,
/usr/share/php{,5,7}/** mr,
# MySQL extension
/usr/share/mysql/** r,
# Zend opcache
/tmp/.ZendSem.* rwlk,
# vim:syntax=apparmor
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2006 Novell/SUSE
# Copyright (C) 2009-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
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
#backwards compatibility include, actual abstraction moved from php5 to php
# shared snippets for config files
/etc/php5/**/ r,
/etc/php5/**.ini r,
# Xlibs
/usr/X11R6/lib{,32,64}/lib*.so* mr,
# php extensions
/usr/lib{64,}/php5/*/*.so mr,
# php5 session mmap socket
/var/lib/php5/session_mm_* rwlk,
# file based session handler
/var/lib/php5/sess_* rwlk,
# php libraries
/usr/share/php{,5}/ r,
/usr/share/php{,5}/** mr,
# MySQL extension
/usr/share/mysql/** r,
# Zend opcache
/tmp/.ZendSem.* rwlk,
#include <abstractions/php>
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2005 Novell/SUSE
# Copyright (C) 2015 Canonical, Ltd.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
......@@ -14,11 +15,21 @@
capability setgid,
capability sys_chroot,
# postfix's master can send us signals
signal receive peer=/usr/lib/postfix/master,
unix (send, receive) peer=(label=/usr/lib/postfix/master),
/etc/mailname r,
/etc/postfix/*.cf r,
/etc/postfix/*.db r,
/etc/postfix/*.db rk,
@{PROC}/net/if_inet6 r,
/usr/lib/postfix/*.so mr,
/usr/lib64/sasl2/* mr,
/usr/lib64/sasl2/ r,
/usr/lib/sasl2/* mr,
/usr/lib/sasl2/ r,
/usr/lib{,32,64}/sasl2/* mr,
/usr/lib{,32,64}/sasl2/ r,
/usr/lib/@{multiarch}/sasl2/* mr,
/usr/lib/@{multiarch}/sasl2/ r,
/var/spool/postfix/etc/* r,
/var/spool/postfix/lib/lib*.so* mr,
/var/spool/postfix/lib/@{multiarch}/lib*.so* mr,
......@@ -10,18 +10,18 @@
#
# ------------------------------------------------------------------
/usr/lib{,32,64}/python{2.[4-7],3.[0-4]}/**.{pyc,so} mr,
/usr/lib{,32,64}/python{2.[4-7],3.[0-4]}/**.{egg,py,pth} r,
/usr/lib{,32,64}/python{2.[4-7],3.[0-4]}/{site,dist}-packages/ r,
/usr/lib{,32,64}/python3.[0-4]/lib-dynload/*.so mr,
/usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{pyc,so} mr,
/usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{egg,py,pth} r,
/usr/lib{,32,64}/python{2.[4-7],3.[0-9]}/{site,dist}-packages/ r,
/usr/lib{,32,64}/python3.[0-9]/lib-dynload/*.so mr,
/usr/local/lib{,32,64}/python{2.[4-7],3.[0-4]}/**.{pyc,so} mr,
/usr/local/lib{,32,64}/python{2.[4-7],3.[0-4]}/**.{egg,py,pth} r,
/usr/local/lib{,32,64}/python{2.[4-7],3.[0-4]}/{site,dist}-packages/ r,
/usr/local/lib{,32,64}/python3.[0-4]/lib-dynload/*.so mr,
/usr/local/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{pyc,so} mr,
/usr/local/lib{,32,64}/python{2.[4-7],3.[0-9]}/**.{egg,py,pth} r,
/usr/local/lib{,32,64}/python{2.[4-7],3.[0-9]}/{site,dist}-packages/ r,
/usr/local/lib{,32,64}/python3.[0-9]/lib-dynload/*.so mr,
# Site-wide configuration
/etc/python{2.[4-7],3.[0-4]}/** r,
/etc/python{2.[4-7],3.[0-9]}/** r,
# shared python paths
/usr/share/{pyshared,pycentral,python-support}/** r,
......@@ -34,4 +34,4 @@
/usr/lib/wx/python/*.pth r,
# python build configuration and headers
/usr/include/python{2.[4-7],3.[0-4]}*/pyconfig.h r,
/usr/include/python{2.[4-7],3.[0-9]}*/pyconfig.h r,
......@@ -10,10 +10,13 @@
# ------------------------------------------------------------------
/etc/samba/* r,
/usr/lib*/ldb/*.so mr,
/usr/lib*/samba/ldb/*.so mr,
/usr/share/samba/*.dat r,
/usr/share/samba/codepages/{lowcase,upcase,valid}.dat r,
/var/cache/samba/ w,
/var/lib/samba/**.tdb rwk,
/var/cache/samba/lck/* rwk,
/var/lib/samba/** rwk,
/var/log/samba/cores/ rw,
/var/log/samba/cores/** rw,
/var/log/samba/log.* w,
......
......@@ -12,6 +12,10 @@
/etc/ssl/ r,
/etc/ssl/certs/ r,
/etc/ssl/certs/* r,
/etc/pki/trust/ r,
/etc/pki/trust/* r,
/etc/pki/trust/anchors/ r,
/etc/pki/trust/anchors/** r,
/usr/share/ca-certificates/ r,
/usr/share/ca-certificates/** r,
/usr/share/ssl/certs/ca-bundle.crt r,
......@@ -19,3 +23,7 @@
/usr/local/share/ca-certificates/** r,
/var/lib/ca-certificates/ r,
/var/lib/ca-certificates/** r,
# acmetool
/var/lib/acme/certs/*/chain r,
/var/lib/acme/certs/*/cert r,
......@@ -16,3 +16,7 @@
/etc/ssl/ r,
/etc/ssl/** r,
# acmetool
/var/lib/acme/live/* r,
/var/lib/acme/certs/** r,
/var/lib/acme/keys/** r,
......@@ -5,10 +5,10 @@
#
@{PROC}/@{pid}/fd/ r,
/usr/lib/** rm,
/bin/bash ixr,
/bin/dash ixr,
/bin/grep ixr,
/bin/sed ixr,