mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-31 22:35:35 +00:00
Compare commits
13 Commits
v4.0.0-bet
...
v3.1.2
Author | SHA1 | Date | |
---|---|---|---|
|
1fe80c0f85 | ||
|
8043dda3f6 | ||
|
e95080e140 | ||
|
45125cedd3 | ||
|
969a8f7618 | ||
|
770b8f1e88 | ||
|
3345250f72 | ||
|
51cf0848c7 | ||
|
e0c0a6a6a5 | ||
|
ea127f13cd | ||
|
480cb56553 | ||
|
075c69a4eb | ||
|
f9dbaa38ec |
15
.gitignore
vendored
15
.gitignore
vendored
@@ -6,7 +6,6 @@ binutils/aa-exec
|
|||||||
binutils/aa-exec.1
|
binutils/aa-exec.1
|
||||||
binutils/aa-features-abi
|
binutils/aa-features-abi
|
||||||
binutils/aa-features-abi.1
|
binutils/aa-features-abi.1
|
||||||
binutils/aa-load
|
|
||||||
binutils/aa-status
|
binutils/aa-status
|
||||||
binutils/aa-status.8
|
binutils/aa-status.8
|
||||||
binutils/cJSON.o
|
binutils/cJSON.o
|
||||||
@@ -29,7 +28,6 @@ parser/parser_yacc.h
|
|||||||
parser/pod2htm*.tmp
|
parser/pod2htm*.tmp
|
||||||
parser/af_rule.o
|
parser/af_rule.o
|
||||||
parser/af_unix.o
|
parser/af_unix.o
|
||||||
parser/all_rule.o
|
|
||||||
parser/common_optarg.o
|
parser/common_optarg.o
|
||||||
parser/dbus.o
|
parser/dbus.o
|
||||||
parser/default_features.o
|
parser/default_features.o
|
||||||
@@ -41,7 +39,6 @@ parser/libapparmor_re/hfa.o
|
|||||||
parser/libapparmor_re/libapparmor_re.a
|
parser/libapparmor_re/libapparmor_re.a
|
||||||
parser/libapparmor_re/parse.o
|
parser/libapparmor_re/parse.o
|
||||||
parser/mount.o
|
parser/mount.o
|
||||||
parser/mqueue.o
|
|
||||||
parser/network.o
|
parser/network.o
|
||||||
parser/parser_alias.o
|
parser/parser_alias.o
|
||||||
parser/parser_common.o
|
parser/parser_common.o
|
||||||
@@ -61,8 +58,6 @@ parser/profile.o
|
|||||||
parser/ptrace.o
|
parser/ptrace.o
|
||||||
parser/rule.o
|
parser/rule.o
|
||||||
parser/signal.o
|
parser/signal.o
|
||||||
parser/userns.o
|
|
||||||
parser/io_uring.o
|
|
||||||
parser/*.7
|
parser/*.7
|
||||||
parser/*.5
|
parser/*.5
|
||||||
parser/*.8
|
parser/*.8
|
||||||
@@ -258,23 +253,17 @@ tests/regression/apparmor/fd_inheritance
|
|||||||
tests/regression/apparmor/fd_inheritor
|
tests/regression/apparmor/fd_inheritor
|
||||||
tests/regression/apparmor/fork
|
tests/regression/apparmor/fork
|
||||||
tests/regression/apparmor/introspect
|
tests/regression/apparmor/introspect
|
||||||
tests/regression/apparmor/io_uring
|
|
||||||
tests/regression/apparmor/link
|
tests/regression/apparmor/link
|
||||||
tests/regression/apparmor/link_subset
|
tests/regression/apparmor/link_subset
|
||||||
tests/regression/apparmor/mkdir
|
tests/regression/apparmor/mkdir
|
||||||
tests/regression/apparmor/mmap
|
tests/regression/apparmor/mmap
|
||||||
tests/regression/apparmor/mount
|
tests/regression/apparmor/mount
|
||||||
tests/regression/apparmor/move_mount
|
|
||||||
tests/regression/apparmor/named_pipe
|
tests/regression/apparmor/named_pipe
|
||||||
tests/regression/apparmor/net_finegrained_rcv
|
|
||||||
tests/regression/apparmor/net_finegrained_snd
|
|
||||||
tests/regression/apparmor/net_raw
|
tests/regression/apparmor/net_raw
|
||||||
tests/regression/apparmor/open
|
tests/regression/apparmor/open
|
||||||
tests/regression/apparmor/openat
|
tests/regression/apparmor/openat
|
||||||
tests/regression/apparmor/pipe
|
tests/regression/apparmor/pipe
|
||||||
tests/regression/apparmor/pivot_root
|
tests/regression/apparmor/pivot_root
|
||||||
tests/regression/apparmor/posix_mq_rcv
|
|
||||||
tests/regression/apparmor/posix_mq_snd
|
|
||||||
tests/regression/apparmor/ptrace
|
tests/regression/apparmor/ptrace
|
||||||
tests/regression/apparmor/ptrace_helper
|
tests/regression/apparmor/ptrace_helper
|
||||||
tests/regression/apparmor/pwrite
|
tests/regression/apparmor/pwrite
|
||||||
@@ -298,8 +287,6 @@ tests/regression/apparmor/syscall_setpriority
|
|||||||
tests/regression/apparmor/syscall_setscheduler
|
tests/regression/apparmor/syscall_setscheduler
|
||||||
tests/regression/apparmor/syscall_sysctl
|
tests/regression/apparmor/syscall_sysctl
|
||||||
tests/regression/apparmor/sysctl_proc
|
tests/regression/apparmor/sysctl_proc
|
||||||
tests/regression/apparmor/sysv_mq_rcv
|
|
||||||
tests/regression/apparmor/sysv_mq_snd
|
|
||||||
tests/regression/apparmor/tcp
|
tests/regression/apparmor/tcp
|
||||||
tests/regression/apparmor/transition
|
tests/regression/apparmor/transition
|
||||||
tests/regression/apparmor/unix_fd_client
|
tests/regression/apparmor/unix_fd_client
|
||||||
@@ -307,8 +294,6 @@ tests/regression/apparmor/unix_fd_server
|
|||||||
tests/regression/apparmor/unix_socket
|
tests/regression/apparmor/unix_socket
|
||||||
tests/regression/apparmor/unix_socket_client
|
tests/regression/apparmor/unix_socket_client
|
||||||
tests/regression/apparmor/unlink
|
tests/regression/apparmor/unlink
|
||||||
tests/regression/apparmor/userns
|
|
||||||
tests/regression/apparmor/userns_setns
|
|
||||||
tests/regression/apparmor/uservars.inc
|
tests/regression/apparmor/uservars.inc
|
||||||
tests/regression/apparmor/xattrs
|
tests/regression/apparmor/xattrs
|
||||||
tests/regression/apparmor/xattrs_profile
|
tests/regression/apparmor/xattrs_profile
|
||||||
|
@@ -17,7 +17,7 @@ stages:
|
|||||||
- uname -a
|
- uname -a
|
||||||
|
|
||||||
.install-c-build-deps: &install-c-build-deps
|
.install-c-build-deps: &install-c-build-deps
|
||||||
- apt-get install --no-install-recommends -y build-essential apache2-dev autoconf autoconf-archive automake bison dejagnu flex libpam-dev libtool pkg-config python3-all-dev python3-setuptools ruby-dev swig zlib1g-dev
|
- apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool pkg-config python3-all-dev python3-setuptools ruby-dev swig zlib1g-dev
|
||||||
|
|
||||||
build-all:
|
build-all:
|
||||||
stage: build
|
stage: build
|
||||||
@@ -104,7 +104,6 @@ test-profiles:
|
|||||||
script:
|
script:
|
||||||
- make -C profiles check-parser
|
- make -C profiles check-parser
|
||||||
- make -C profiles check-abstractions.d
|
- make -C profiles check-abstractions.d
|
||||||
- make -C profiles check-extras
|
|
||||||
|
|
||||||
shellcheck:
|
shellcheck:
|
||||||
stage: test
|
stage: test
|
||||||
@@ -137,30 +136,3 @@ include:
|
|||||||
variables:
|
variables:
|
||||||
SAST_EXCLUDED_ANALYZERS: "eslint,flawfinder,semgrep,spotbugs"
|
SAST_EXCLUDED_ANALYZERS: "eslint,flawfinder,semgrep,spotbugs"
|
||||||
SAST_BANDIT_EXCLUDED_PATHS: "*/tst/*, */test/*"
|
SAST_BANDIT_EXCLUDED_PATHS: "*/tst/*, */test/*"
|
||||||
|
|
||||||
.send-to-coverity: &send-to-coverity
|
|
||||||
- curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
|
|
||||||
--form token=$COVERITY_SCAN_TOKEN --form email=$GITLAB_USER_EMAIL
|
|
||||||
--form file=@$(ls apparmor-*-cov-int.tar.gz) --form version="$(git describe --tags)"
|
|
||||||
--form description="$(git describe --tags) / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID"
|
|
||||||
|
|
||||||
coverity:
|
|
||||||
stage: .post
|
|
||||||
extends:
|
|
||||||
- .ubuntu-before_script
|
|
||||||
only:
|
|
||||||
refs:
|
|
||||||
- master
|
|
||||||
script:
|
|
||||||
- apt-get install --no-install-recommends -y curl git texlive-latex-recommended
|
|
||||||
- *install-c-build-deps
|
|
||||||
- curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64
|
|
||||||
--form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN
|
|
||||||
- tar xfz /tmp/cov-analysis-linux64.tgz
|
|
||||||
- COV_VERSION=$(ls -dt cov-analysis-linux64-* | head -1)
|
|
||||||
- PATH=$PATH:$(pwd)/$COV_VERSION/bin
|
|
||||||
- make coverity
|
|
||||||
- *send-to-coverity
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- "apparmor-*.tar.gz"
|
|
||||||
|
@@ -181,9 +181,6 @@ $ make check # depends on the parser having been built first
|
|||||||
$ make install
|
$ make install
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the empty local/* profile sniplets no longer get created by default.
|
|
||||||
If you want them, run `make local` before running `make check`.
|
|
||||||
|
|
||||||
[Note that for the parser, binutils, and utils, if you only wish to build/use
|
[Note that for the parser, binutils, and utils, if you only wish to build/use
|
||||||
some of the locale languages, you can override the default by passing
|
some of the locale languages, you can override the default by passing
|
||||||
the LANGS arguments to make; e.g. make all install "LANGS=en_US fr".]
|
the LANGS arguments to make; e.g. make all install "LANGS=en_US fr".]
|
||||||
|
@@ -48,10 +48,10 @@ endif
|
|||||||
# Internationalization support. Define a package and a LOCALEDIR
|
# Internationalization support. Define a package and a LOCALEDIR
|
||||||
EXTRA_CFLAGS+=-DPACKAGE=\"${NAME}\" -DLOCALEDIR=\"${LOCALEDIR}\"
|
EXTRA_CFLAGS+=-DPACKAGE=\"${NAME}\" -DLOCALEDIR=\"${LOCALEDIR}\"
|
||||||
|
|
||||||
SRCS = aa_enabled.c aa_load.c
|
SRCS = aa_enabled.c
|
||||||
HDRS =
|
HDRS =
|
||||||
BINTOOLS = aa-enabled aa-exec aa-features-abi
|
BINTOOLS = aa-enabled aa-exec aa-features-abi
|
||||||
SBINTOOLS = aa-status aa-load
|
SBINTOOLS = aa-status
|
||||||
|
|
||||||
AALIB = -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread
|
AALIB = -Wl,-Bstatic -lapparmor -Wl,-Bdynamic -lpthread
|
||||||
|
|
||||||
@@ -126,9 +126,6 @@ endif
|
|||||||
aa-features-abi: aa_features_abi.c $(LIBAPPARMOR_A)
|
aa-features-abi: aa_features_abi.c $(LIBAPPARMOR_A)
|
||||||
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
||||||
|
|
||||||
aa-load: aa_load.c $(LIBAPPARMOR_A)
|
|
||||||
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
|
||||||
|
|
||||||
aa-enabled: aa_enabled.c $(LIBAPPARMOR_A)
|
aa-enabled: aa_enabled.c $(LIBAPPARMOR_A)
|
||||||
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
$(CC) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $< $(LIBS) $(AALIB)
|
||||||
|
|
||||||
|
@@ -72,18 +72,11 @@ displays the number of loaded non-enforcing AppArmor policies.
|
|||||||
|
|
||||||
=item --kill
|
=item --kill
|
||||||
|
|
||||||
displays the number of loaded enforcing AppArmor policies that will
|
displays the number of loaded enforcing AppArmor policies that will kill tasks on policy violations.
|
||||||
kill tasks on policy violations.
|
|
||||||
|
|
||||||
=item --prompt
|
|
||||||
|
|
||||||
displays the number of loaded enforcing AppArmor policies, with
|
|
||||||
fallback to userspace mediation.
|
|
||||||
|
|
||||||
=item --special-unconfined
|
=item --special-unconfined
|
||||||
|
|
||||||
displays the number of loaded non-enforcing AppArmor policies that are
|
displays the number of loaded non-enforcing AppArmor policies that are in the special unconfined mode.
|
||||||
in the special unconfined mode.
|
|
||||||
|
|
||||||
=item --process-mixed
|
=item --process-mixed
|
||||||
displays the number of processes confined by profile stacks with
|
displays the number of processes confined by profile stacks with
|
||||||
@@ -104,40 +97,6 @@ set in a JSON format, fit for machine consumption.
|
|||||||
same as --json, formatted to be readable by humans as well
|
same as --json, formatted to be readable by humans as well
|
||||||
as by machines.
|
as by machines.
|
||||||
|
|
||||||
=item --show
|
|
||||||
|
|
||||||
what data sets to show information about. Currently I<processes>,
|
|
||||||
I<profiles>, I<all> for both processes and profiles. The default is
|
|
||||||
I<all>.
|
|
||||||
|
|
||||||
=item --count
|
|
||||||
|
|
||||||
display only counts for selected information.
|
|
||||||
|
|
||||||
=item --filter.mode=filter
|
|
||||||
|
|
||||||
Allows specifying a posix regular expression filter that will be
|
|
||||||
applied against the displayed processess and profiles apparmor profile
|
|
||||||
mode, reducing the output.
|
|
||||||
|
|
||||||
=item --filter.profiles=filter
|
|
||||||
|
|
||||||
Allows specifying a posix regular expression filter that will be
|
|
||||||
applied against the displayed processess and profiles confining
|
|
||||||
profile, reducing the output.
|
|
||||||
|
|
||||||
=item --filter.pid=filter
|
|
||||||
|
|
||||||
Allows specifying a posix regular expression filter that will be
|
|
||||||
applied against the displayed processes, so that only processes pids
|
|
||||||
matching the expression will be displayed.
|
|
||||||
|
|
||||||
=item --filter.exe=filter
|
|
||||||
|
|
||||||
Allows specifying a posix regular expression filter that will be
|
|
||||||
applied against the displayed processes, so that only processes
|
|
||||||
executable name matching the expression will be displayed.
|
|
||||||
|
|
||||||
=item --help
|
=item --help
|
||||||
|
|
||||||
displays a short usage statement.
|
displays a short usage statement.
|
||||||
@@ -165,8 +124,7 @@ if apparmor is enabled but no policy is loaded.
|
|||||||
|
|
||||||
=item B<3>
|
=item B<3>
|
||||||
|
|
||||||
if the apparmor control files aren't available under
|
if the apparmor control files aren't available under /sys/kernel/security/.
|
||||||
/sys/kernel/security/.
|
|
||||||
|
|
||||||
=item B<4>
|
=item B<4>
|
||||||
|
|
||||||
@@ -182,9 +140,8 @@ if an internal error occurred.
|
|||||||
=head1 BUGS
|
=head1 BUGS
|
||||||
|
|
||||||
B<aa-status> must be run as root to read the state of the loaded
|
B<aa-status> must be run as root to read the state of the loaded
|
||||||
policy from the apparmor module. It uses the /proc filesystem to
|
policy from the apparmor module. It uses the /proc filesystem to determine
|
||||||
determine which processes are confined and so is susceptible to race
|
which processes are confined and so is susceptible to race conditions.
|
||||||
conditions.
|
|
||||||
|
|
||||||
If you find any additional bugs, please report them at
|
If you find any additional bugs, please report them at
|
||||||
L<https://gitlab.com/apparmor/apparmor/-/issues>.
|
L<https://gitlab.com/apparmor/apparmor/-/issues>.
|
||||||
|
@@ -1,408 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2020 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define _GNU_SOURCE /* for asprintf() */
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <getopt.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <dirent.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
|
|
||||||
#include <sys/apparmor.h>
|
|
||||||
|
|
||||||
#include <libintl.h>
|
|
||||||
#define _(s) gettext(s)
|
|
||||||
|
|
||||||
/* TODO: implement config locations - value can change */
|
|
||||||
#define DEFAULT_CONFIG_LOCATIONS "/etc/apparmor/parser.conf"
|
|
||||||
#define DEFAULT_POLICY_LOCATIONS "/var/cache/apparmor:/etc/apparmor.d/cache.d:/etc/apparmor.d/cache"
|
|
||||||
#define CACHE_FEATURES_FILE ".features"
|
|
||||||
|
|
||||||
bool opt_debug = false;
|
|
||||||
bool opt_verbose = false;
|
|
||||||
bool opt_dryrun = false;
|
|
||||||
bool opt_force = false;
|
|
||||||
bool opt_config = false;
|
|
||||||
|
|
||||||
#define warning(fmt, args...) _error(_("aa-load: WARN: " fmt "\n"), ## args)
|
|
||||||
#define error(fmt, args...) _error(_("aa-load: ERROR: " fmt "\n"), ## args)
|
|
||||||
static void _error(const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
vfprintf(stderr, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define verbose(fmt, args...) _debug(opt_verbose, _(fmt "\n"), ## args)
|
|
||||||
#define debug(fmt, args...) _debug(opt_debug, _("aa-load: DEBUG: " fmt "\n"), ## args)
|
|
||||||
static void _debug(bool opt_displayit, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
if (!opt_displayit)
|
|
||||||
return;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
vfprintf(stderr, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int have_enough_privilege(const char *command)
|
|
||||||
{
|
|
||||||
uid_t uid, euid;
|
|
||||||
|
|
||||||
uid = getuid();
|
|
||||||
euid = geteuid();
|
|
||||||
|
|
||||||
if (uid != 0 && euid != 0) {
|
|
||||||
error("%s: Sorry. You need root privileges to run this program.\n",
|
|
||||||
command);
|
|
||||||
return EPERM;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (uid != 0 && euid == 0) {
|
|
||||||
error("%s: Aborting! You've set this program setuid root.\n"
|
|
||||||
"Anybody who can run this program can update "
|
|
||||||
"your AppArmor profiles.\n", command);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int load_config(const char *file)
|
|
||||||
{
|
|
||||||
/* TODO */
|
|
||||||
return ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load a single policy cache file to the kernel
|
|
||||||
*/
|
|
||||||
static int load_policy_file(const char *file)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
struct aa_kernel_interface *kernel_interface;
|
|
||||||
|
|
||||||
if (aa_kernel_interface_new(&kernel_interface, NULL, NULL)) {
|
|
||||||
rc = -errno;
|
|
||||||
error("Failed to open kernel interface '%s': %m", file);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
if (!opt_dryrun &&
|
|
||||||
aa_kernel_interface_replace_policy_from_file(kernel_interface,
|
|
||||||
AT_FDCWD, file)) {
|
|
||||||
rc = -errno;
|
|
||||||
error("Failed to load policy into kernel '%s': %m", file);
|
|
||||||
}
|
|
||||||
aa_kernel_interface_unref(kernel_interface);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void validate_features(const char *dir_path)
|
|
||||||
{
|
|
||||||
aa_features *kernel_features;
|
|
||||||
|
|
||||||
if (aa_features_new_from_kernel(&kernel_features) == -1) {
|
|
||||||
error("Failed to obtain features: %m");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aa_features_check(AT_FDCWD, dir_path, kernel_features) == -1) {
|
|
||||||
if (errno == ENOENT) {
|
|
||||||
/* features file does not exist
|
|
||||||
* not an issue when loading cache policies from dir
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
else if (errno == EEXIST) {
|
|
||||||
warning("Overlay features do not match kernel features");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aa_features_unref(kernel_features);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load a directory of policy cache files to the kernel
|
|
||||||
* This does not do a subdir search to find the kernel match but
|
|
||||||
* tries to load the dir regardless of whether its features match
|
|
||||||
*
|
|
||||||
* The hierarchy looks like
|
|
||||||
*
|
|
||||||
* dir/
|
|
||||||
* .features
|
|
||||||
* profile1
|
|
||||||
* ...
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int load_policy_dir(const char *dir_path)
|
|
||||||
{
|
|
||||||
DIR *d;
|
|
||||||
struct dirent *dir;
|
|
||||||
int rc = 0;
|
|
||||||
char *file;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
validate_features(dir_path);
|
|
||||||
|
|
||||||
d = opendir(dir_path);
|
|
||||||
if (!d) {
|
|
||||||
rc = -errno;
|
|
||||||
error("Failed to open directory '%s': %m", dir_path);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((dir = readdir(d)) != NULL) {
|
|
||||||
/* Only check regular files for now */
|
|
||||||
if (dir->d_type == DT_REG) {
|
|
||||||
len = strnlen(dir->d_name, PATH_MAX);
|
|
||||||
/* Ignores .features */
|
|
||||||
if (strncmp(dir->d_name, CACHE_FEATURES_FILE, len) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (asprintf(&file, "%s/%s", dir_path, dir->d_name) == -1) {
|
|
||||||
error("Failure allocating memory");
|
|
||||||
closedir(d);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
load_policy_file(file);
|
|
||||||
free(file);
|
|
||||||
file = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(d);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load_hashed_policy - find policy hashed dir and load it
|
|
||||||
*
|
|
||||||
* load/replace all policy from a policy hierarchy directory
|
|
||||||
*
|
|
||||||
* Returns: 0 on success < -errno
|
|
||||||
*
|
|
||||||
* It will find the subdir that matches the kernel and load all
|
|
||||||
* precompiled policy files from it.
|
|
||||||
*
|
|
||||||
* The hierarchy looks something like
|
|
||||||
*
|
|
||||||
* location/
|
|
||||||
* kernel_hash1.0/
|
|
||||||
* .features
|
|
||||||
* profile1
|
|
||||||
* ...
|
|
||||||
* kernel_hash2.0/
|
|
||||||
* .features
|
|
||||||
* profile1
|
|
||||||
* ...
|
|
||||||
*/
|
|
||||||
static int load_policy_by_hash(const char *location)
|
|
||||||
{
|
|
||||||
aa_policy_cache *policy_cache = NULL;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if ((rc = aa_policy_cache_new(&policy_cache, NULL, AT_FDCWD, location, 0))) {
|
|
||||||
rc = -errno;
|
|
||||||
error("Failed to open policy cache '%s': %m", location);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (opt_debug) {
|
|
||||||
/* show hash directory under location that matches the
|
|
||||||
* current kernel
|
|
||||||
*/
|
|
||||||
char *cache_loc = aa_policy_cache_dir_path_preview(NULL, AT_FDCWD, location);
|
|
||||||
if (!cache_loc) {
|
|
||||||
rc = -errno;
|
|
||||||
error("Failed to find cache location '%s': %m", location);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
debug("Loading cache from '%s'\n", cache_loc);
|
|
||||||
free(cache_loc);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opt_dryrun) {
|
|
||||||
if ((rc = aa_policy_cache_replace_all(policy_cache, NULL)) < 0) {
|
|
||||||
error("Failed to load policy cache '%s': %m", location);
|
|
||||||
} else {
|
|
||||||
verbose("Success - Loaded policy cache '%s'", location);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
|
||||||
aa_policy_cache_unref(policy_cache);
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* load_arg - calls specific load functions for files and directories
|
|
||||||
*
|
|
||||||
* load/replace all policy files/dir in arg
|
|
||||||
*
|
|
||||||
* Returns: 0 on success, 1 on failure.
|
|
||||||
*
|
|
||||||
* It will load by hash subtree first, and fallback to a cache dir
|
|
||||||
* If not a directory, it will try to load it as a cache file
|
|
||||||
*/
|
|
||||||
static int load_arg(char *arg)
|
|
||||||
{
|
|
||||||
char **location = NULL;
|
|
||||||
int i, n, rc = 0;
|
|
||||||
|
|
||||||
|
|
||||||
/* arg can specify an overlay of multiple cache locations */
|
|
||||||
if ((n = aa_split_overlay_str(arg, &location, 0, true)) == -1) {
|
|
||||||
error("Failed to parse overlay locations: %m");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
struct stat st;
|
|
||||||
debug("Trying to open %s", location[i]);
|
|
||||||
if (stat(location[i], &st) == -1) {
|
|
||||||
error("Failed stat of '%s': %m", location[i]);
|
|
||||||
rc = 1;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (S_ISDIR(st.st_mode)) {
|
|
||||||
/* try hash dir subtree first */
|
|
||||||
if (load_policy_by_hash(location[i]) < 0) {
|
|
||||||
error("Failed load policy by hash '%s': %m", location[i]);
|
|
||||||
rc = 1;
|
|
||||||
}
|
|
||||||
/* fall back to cache dir */
|
|
||||||
if (load_policy_dir(location[i]) < 0) {
|
|
||||||
error("Failed load policy by directory '%s': %m", location[i]);
|
|
||||||
rc = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (load_policy_file(location[i]) < 0) {
|
|
||||||
rc = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
free(location[i]);
|
|
||||||
free(location);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void print_usage(const char *command)
|
|
||||||
{
|
|
||||||
printf("Usage: %s [OPTIONS] (cache file|cache dir|cache base dir)]*\n"
|
|
||||||
"Load Precompiled AppArmor policy from a cache location or \n"
|
|
||||||
"locations.\n\n"
|
|
||||||
"Options:\n"
|
|
||||||
" -f, --force load policy even if abi does not match the kernel\n"
|
|
||||||
" -d, --debug display debug messages\n"
|
|
||||||
" -v, --verbose display progress and error messages\n"
|
|
||||||
" -n, --dry-run do everything except actual load\n"
|
|
||||||
" -h, --help this message\n",
|
|
||||||
command);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *short_options = "c:dfvnh";
|
|
||||||
struct option long_options[] = {
|
|
||||||
{"config", 1, 0, 'c'},
|
|
||||||
{"debug", 0, 0, 'd'},
|
|
||||||
{"force", 0, 0, 'f'},
|
|
||||||
{"verbose", 0, 0, 'v'},
|
|
||||||
{"dry-run", 0, 0, 'n'},
|
|
||||||
{"help", 0, 0, 'h'},
|
|
||||||
{NULL, 0, 0, 0},
|
|
||||||
};
|
|
||||||
|
|
||||||
static int process_args(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int c, o;
|
|
||||||
|
|
||||||
opterr = 1;
|
|
||||||
while ((c = getopt_long(argc, argv, short_options, long_options, &o)) != -1) {
|
|
||||||
switch(c) {
|
|
||||||
case 0:
|
|
||||||
error("error in argument processing\n");
|
|
||||||
exit(1);
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
opt_debug = true;
|
|
||||||
break;
|
|
||||||
case 'f':
|
|
||||||
opt_force = true;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
opt_verbose = true;
|
|
||||||
break;
|
|
||||||
case 'n':
|
|
||||||
opt_dryrun = true;
|
|
||||||
break;
|
|
||||||
case 'h':
|
|
||||||
print_usage(argv[0]);
|
|
||||||
exit(0);
|
|
||||||
break;
|
|
||||||
case 'c':
|
|
||||||
/* TODO: reserved config location,
|
|
||||||
* act as a bad arg for now, when added update usage
|
|
||||||
*/
|
|
||||||
//opt_config = true; uncomment when implemented
|
|
||||||
/* Fall through */
|
|
||||||
default:
|
|
||||||
error("unknown argument: '%s'\n\n", optarg);
|
|
||||||
print_usage(argv[1]);
|
|
||||||
exit(1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return optind;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
|
||||||
{
|
|
||||||
int i, rc = 0;
|
|
||||||
|
|
||||||
optind = process_args(argc, argv);
|
|
||||||
|
|
||||||
if (!opt_dryrun && have_enough_privilege(argv[0]))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* if no location use the default one */
|
|
||||||
if (optind == argc) {
|
|
||||||
if (!opt_config && load_config(DEFAULT_CONFIG_LOCATIONS) == 0) {
|
|
||||||
verbose("Loaded policy config");
|
|
||||||
}
|
|
||||||
if ((rc = load_arg(DEFAULT_POLICY_LOCATIONS)))
|
|
||||||
verbose("Loading policy from default location '%s'", DEFAULT_POLICY_LOCATIONS);
|
|
||||||
else
|
|
||||||
debug("No policy specified, and no policy config or policy in default locations");
|
|
||||||
}
|
|
||||||
for (i = optind; i < argc; i++) {
|
|
||||||
/* Try to load all policy locations even if one fails
|
|
||||||
* but always return an error if any fail
|
|
||||||
*/
|
|
||||||
|
|
||||||
int tmp = load_arg(argv[i]);
|
|
||||||
if (!rc)
|
|
||||||
rc = tmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@@ -67,10 +67,10 @@ to syslog.
|
|||||||
References
|
References
|
||||||
----------
|
----------
|
||||||
Project webpage:
|
Project webpage:
|
||||||
https://apparmor.net/
|
http://developer.novell.com/wiki/index.php/Novell_AppArmor
|
||||||
|
|
||||||
To provide feedback or ask questions please contact the
|
To provide feedback or ask questions please contact the
|
||||||
apparmor@lists.ubuntu.com mail list. This is the development list
|
apparmor-dev@forge.novell.com mail list. This is the development list
|
||||||
for the AppArmor team.
|
for the AppArmor team.
|
||||||
|
|
||||||
See also: change_hat(3), and the Linux-PAM online documentation at
|
See also: change_hat(3), and the Linux-PAM online documentation at
|
||||||
|
@@ -188,9 +188,10 @@ parent context.
|
|||||||
8. Feedback/Resources
|
8. Feedback/Resources
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Project webpage:
|
To provide feedback or ask questions please contact the
|
||||||
https://apparmor.net/
|
apparmor-dev@forge.novell.com mail list. This is the development list for the
|
||||||
|
AppArmor team.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
To provide feedback or ask questions please contact the
|
|
||||||
apparmor@lists.ubuntu.com mail list. This is the development list
|
|
||||||
for the AppArmor team.
|
|
||||||
|
@@ -188,9 +188,10 @@ parent context.
|
|||||||
8. Feedback/Resources
|
8. Feedback/Resources
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Project webpage:
|
To provide feedback or ask questions please contact the
|
||||||
https://apparmor.net/
|
apparmor-dev@forge.novell.com mail list. This is the development list for the
|
||||||
|
AppArmor team.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
To provide feedback or ask questions please contact the
|
|
||||||
apparmor@lists.ubuntu.com mail list. This is the development list
|
|
||||||
for the AppArmor team.
|
|
||||||
|
@@ -42,7 +42,6 @@ endif
|
|||||||
|
|
||||||
define nl
|
define nl
|
||||||
|
|
||||||
|
|
||||||
endef
|
endef
|
||||||
|
|
||||||
REPO_VERSION_CMD=[ -x /usr/bin/git ] && /usr/bin/git describe --tags --long --abbrev=16 --match 'v*' 2> /dev/null || awk '{ print $2 }' common/.stamp_rev
|
REPO_VERSION_CMD=[ -x /usr/bin/git ] && /usr/bin/git describe --tags --long --abbrev=16 --match 'v*' 2> /dev/null || awk '{ print $2 }' common/.stamp_rev
|
||||||
|
@@ -1 +1 @@
|
|||||||
4.0.0~beta2
|
3.1.2
|
||||||
|
Binary file not shown.
@@ -92,14 +92,6 @@ if test "$ac_cv_prog_cc_c99" = "no"; then
|
|||||||
AC_MSG_ERROR([C99 mode is required to build libapparmor])
|
AC_MSG_ERROR([C99 mode is required to build libapparmor])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
m4_ifndef([AX_CHECK_COMPILE_FLAG], [AC_MSG_ERROR(['autoconf-archive' missing])])
|
|
||||||
EXTRA_CFLAGS="-Wall $(EXTRA_WARNINGS) -fPIC"
|
|
||||||
AX_CHECK_COMPILE_FLAG([-flto-partition=none], , , [-Werror])
|
|
||||||
AS_VAR_IF([ax_cv_check_cflags__Werror__flto_partition_none], [yes],
|
|
||||||
[EXTRA_CFLAGS="$EXTRA_CFLAGS -flto-partition=none"]
|
|
||||||
,)
|
|
||||||
AC_SUBST([AM_CFLAGS], ["$EXTRA_CFLAGS"])
|
|
||||||
|
|
||||||
AC_OUTPUT(
|
AC_OUTPUT(
|
||||||
Makefile
|
Makefile
|
||||||
doc/Makefile
|
doc/Makefile
|
||||||
|
@@ -116,14 +116,6 @@ The specified I<file/task> does not exist or is not visible.
|
|||||||
|
|
||||||
The confinement data is too large to fit in the supplied buffer.
|
The confinement data is too large to fit in the supplied buffer.
|
||||||
|
|
||||||
=item B<ENOPROTOOPT>
|
|
||||||
|
|
||||||
The kernel doesn't support the SO_PEERLABEL option in sockets. This happens
|
|
||||||
mainly when the kernel lacks 'fine grained unix mediation' support. It also
|
|
||||||
can happen on LSM stacking kernels where another LSM has claimed this
|
|
||||||
interface and decides to return this error, although this is really a
|
|
||||||
corner case.
|
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head1 NOTES
|
=head1 NOTES
|
||||||
|
@@ -109,12 +109,12 @@ To immediately stack a profile named "profile_a", as performed with
|
|||||||
aa_stack_profile("profile_a"), the equivalent of this shell command can be
|
aa_stack_profile("profile_a"), the equivalent of this shell command can be
|
||||||
used:
|
used:
|
||||||
|
|
||||||
$ echo -n "stack profile_a" > /proc/self/attr/current
|
$ echo -n "stackprofile profile_a" > /proc/self/attr/current
|
||||||
|
|
||||||
To stack a profile named "profile_a" at the next exec, as performed with
|
To stack a profile named "profile_a" at the next exec, as performed with
|
||||||
aa_stack_onexec("profile_a"), the equivalent of this shell command can be used:
|
aa_stack_onexec("profile_a"), the equivalent of this shell command can be used:
|
||||||
|
|
||||||
$ echo -n "stack profile_a" > /proc/self/attr/exec
|
$ echo -n "stackexec profile_a" > /proc/self/attr/exec
|
||||||
|
|
||||||
These raw AppArmor filesystem operations must only be used when using
|
These raw AppArmor filesystem operations must only be used when using
|
||||||
libapparmor is not a viable option.
|
libapparmor is not a viable option.
|
||||||
@@ -184,7 +184,6 @@ with apparmor_parser(8):
|
|||||||
/etc/passwd r,
|
/etc/passwd r,
|
||||||
|
|
||||||
# Needed for aa_stack_profile()
|
# Needed for aa_stack_profile()
|
||||||
change-profile -> &i_cant_be_trusted_anymore,
|
|
||||||
/usr/lib/libapparmor*.so* mr,
|
/usr/lib/libapparmor*.so* mr,
|
||||||
/proc/[0-9]*/attr/current w,
|
/proc/[0-9]*/attr/current w,
|
||||||
}
|
}
|
||||||
|
@@ -159,8 +159,6 @@ typedef struct
|
|||||||
char *fs_type;
|
char *fs_type;
|
||||||
char *flags;
|
char *flags;
|
||||||
char *src_name;
|
char *src_name;
|
||||||
|
|
||||||
char *class;
|
|
||||||
} aa_log_record;
|
} aa_log_record;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -157,8 +157,6 @@ extern int aa_features_write_to_file(aa_features *features,
|
|||||||
int dirfd, const char *path);
|
int dirfd, const char *path);
|
||||||
extern bool aa_features_is_equal(aa_features *features1,
|
extern bool aa_features_is_equal(aa_features *features1,
|
||||||
aa_features *features2);
|
aa_features *features2);
|
||||||
extern int aa_features_check(int dirfd, const char *path,
|
|
||||||
aa_features *features);
|
|
||||||
extern bool aa_features_supports(aa_features *features, const char *str);
|
extern bool aa_features_supports(aa_features *features, const char *str);
|
||||||
extern char *aa_features_id(aa_features *features);
|
extern char *aa_features_id(aa_features *features);
|
||||||
extern char *aa_features_value(aa_features *features, const char *str, size_t *len);
|
extern char *aa_features_value(aa_features *features, const char *str, size_t *len);
|
||||||
@@ -211,8 +209,6 @@ extern char *aa_policy_cache_filename(aa_policy_cache *policy_cache, const char
|
|||||||
extern char *aa_policy_cache_dir_path_preview(aa_features *kernel_features,
|
extern char *aa_policy_cache_dir_path_preview(aa_features *kernel_features,
|
||||||
int dirfd, const char *path);
|
int dirfd, const char *path);
|
||||||
|
|
||||||
extern int aa_split_overlay_str(char *str, char ***vec, size_t max_size, bool immutable);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -32,10 +32,10 @@ INCLUDES = $(all_includes)
|
|||||||
#
|
#
|
||||||
# After changing the AA_LIB_* variables, also update EXPECTED_SO_NAME.
|
# After changing the AA_LIB_* variables, also update EXPECTED_SO_NAME.
|
||||||
|
|
||||||
AA_LIB_CURRENT = 18
|
AA_LIB_CURRENT = 13
|
||||||
AA_LIB_REVISION = 1
|
AA_LIB_REVISION = 1
|
||||||
AA_LIB_AGE = 17
|
AA_LIB_AGE = 12
|
||||||
EXPECTED_SO_NAME = libapparmor.so.1.17.1
|
EXPECTED_SO_NAME = libapparmor.so.1.12.1
|
||||||
|
|
||||||
SUFFIXES = .pc.in .pc
|
SUFFIXES = .pc.in .pc
|
||||||
|
|
||||||
@@ -45,6 +45,7 @@ include $(COMMONDIR)/Make.rules
|
|||||||
BUILT_SOURCES = grammar.h scanner.h af_protos.h
|
BUILT_SOURCES = grammar.h scanner.h af_protos.h
|
||||||
AM_LFLAGS = -v
|
AM_LFLAGS = -v
|
||||||
AM_YFLAGS = -d -p aalogparse_
|
AM_YFLAGS = -d -p aalogparse_
|
||||||
|
AM_CFLAGS = -Wall $(EXTRA_WARNINGS) -fPIC -flto-partition=none
|
||||||
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
|
AM_CPPFLAGS = -D_GNU_SOURCE -I$(top_srcdir)/include/
|
||||||
scanner.h: scanner.l
|
scanner.h: scanner.l
|
||||||
$(LEX) -v $<
|
$(LEX) -v $<
|
||||||
@@ -58,7 +59,7 @@ lib_LTLIBRARIES = libapparmor.la
|
|||||||
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
|
noinst_HEADERS = grammar.h parser.h scanner.h af_protos.h private.h PMurHash.h
|
||||||
|
|
||||||
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c PMurHash.c
|
libapparmor_la_SOURCES = grammar.y libaalogparse.c kernel.c scanner.c private.c features.c kernel_interface.c policy_cache.c PMurHash.c
|
||||||
libapparmor_la_LDFLAGS = -version-info $(AA_LIB_CURRENT):$(AA_LIB_REVISION):$(AA_LIB_AGE) -XCClinker -Bdynamic -pthread \
|
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
|
-Wl,--version-script=$(top_srcdir)/src/libapparmor.map
|
||||||
|
|
||||||
pkgconfigdir = $(libdir)/pkgconfig
|
pkgconfigdir = $(libdir)/pkgconfig
|
||||||
|
@@ -35,7 +35,6 @@
|
|||||||
#include "PMurHash.h"
|
#include "PMurHash.h"
|
||||||
|
|
||||||
#define FEATURES_FILE "/sys/kernel/security/apparmor/features"
|
#define FEATURES_FILE "/sys/kernel/security/apparmor/features"
|
||||||
#define CACHE_FEATURES_FILE ".features"
|
|
||||||
|
|
||||||
#define HASH_SIZE (8 + 1) /* 32 bits binary to hex + NUL terminator */
|
#define HASH_SIZE (8 + 1) /* 32 bits binary to hex + NUL terminator */
|
||||||
#define STRING_SIZE 8192
|
#define STRING_SIZE 8192
|
||||||
@@ -659,44 +658,6 @@ bool aa_features_is_equal(aa_features *features1, aa_features *features2)
|
|||||||
strcmp(features1->string, features2->string) == 0;
|
strcmp(features1->string, features2->string) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* aa_features_check - check if features from a directory matches an aa_features object
|
|
||||||
* @dirfd: a directory file descriptory or AT_FDCWD (see openat(2))
|
|
||||||
* @path: the path containing the features
|
|
||||||
* @features: features to be matched against
|
|
||||||
*
|
|
||||||
* Returns: 0 on success, -1 on failure. errno is set to EEXIST when there's not a match
|
|
||||||
*/
|
|
||||||
int aa_features_check(int dirfd, const char *path,
|
|
||||||
aa_features *features)
|
|
||||||
{
|
|
||||||
aa_features *local_features = NULL;
|
|
||||||
autofree char *name = NULL;
|
|
||||||
bool rc;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
len = asprintf(&name, "%s/%s", path, CACHE_FEATURES_FILE);
|
|
||||||
if (len == -1) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* verify that path dir .features matches */
|
|
||||||
if (aa_features_new(&local_features, dirfd, name)) {
|
|
||||||
PDEBUG("could not setup new features object for dirfd '%d' '%s'\n", dirfd, name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = aa_features_is_equal(local_features, features);
|
|
||||||
aa_features_unref(local_features);
|
|
||||||
if (!rc) {
|
|
||||||
errno = EEXIST;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *features_lookup(aa_features *features, const char *str)
|
static const char *features_lookup(aa_features *features, const char *str)
|
||||||
{
|
{
|
||||||
const char *features_string = features->string;
|
const char *features_string = features->string;
|
||||||
|
@@ -187,7 +187,6 @@ aa_record_event_type lookup_aa_event(unsigned int type)
|
|||||||
%token TOK_KEY_FSTYPE
|
%token TOK_KEY_FSTYPE
|
||||||
%token TOK_KEY_FLAGS
|
%token TOK_KEY_FLAGS
|
||||||
%token TOK_KEY_SRCNAME
|
%token TOK_KEY_SRCNAME
|
||||||
%token TOK_KEY_CLASS
|
|
||||||
|
|
||||||
%token TOK_SOCKLOGD_KERNEL
|
%token TOK_SOCKLOGD_KERNEL
|
||||||
%token TOK_SYSLOG_KERNEL
|
%token TOK_SYSLOG_KERNEL
|
||||||
@@ -249,7 +248,7 @@ syslog_type:
|
|||||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||||
| syslog_date syslog_id TOK_DMESG_STAMP key_type audit_id key_list
|
| syslog_date syslog_id TOK_DMESG_STAMP key_type audit_id key_list
|
||||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||||
/* needs update: hard newline in handling multiline log messages */
|
/* needs update: hard newline in handling mutiline log messages */
|
||||||
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_partial_tail
|
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_partial_tail
|
||||||
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
{ ret_record->version = AA_RECORD_SYNTAX_V2; free($3); }
|
||||||
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_tail
|
| syslog_date syslog_id TOK_DMESG_STAMP TOK_AUDIT TOK_COLON key_type audit_id audit_user_msg_tail
|
||||||
@@ -432,8 +431,6 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
|
|||||||
ret_record->event = AA_RECORD_INVALID;
|
ret_record->event = AA_RECORD_INVALID;
|
||||||
ret_record->info = $1;
|
ret_record->info = $1;
|
||||||
}
|
}
|
||||||
| TOK_KEY_CLASS TOK_EQUALS TOK_QUOTED_STRING
|
|
||||||
{ ret_record->class = $3; }
|
|
||||||
;
|
;
|
||||||
|
|
||||||
apparmor_event:
|
apparmor_event:
|
||||||
|
@@ -463,7 +463,7 @@ static char *procattr_path(pid_t pid, const char *attr)
|
|||||||
|
|
||||||
static int procattr_open(pid_t tid, const char *attr, int flags)
|
static int procattr_open(pid_t tid, const char *attr, int flags)
|
||||||
{
|
{
|
||||||
autofree char *tmp = NULL;
|
char *tmp;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
tmp = procattr_path(tid, attr);
|
tmp = procattr_path(tid, attr);
|
||||||
@@ -471,7 +471,7 @@ static int procattr_open(pid_t tid, const char *attr, int flags)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fd = open(tmp, flags);
|
fd = open(tmp, flags);
|
||||||
|
free(tmp);
|
||||||
/* Test is we can fallback to the old interface (this is ugly).
|
/* Test is we can fallback to the old interface (this is ugly).
|
||||||
* If we haven't tried the old interface already
|
* If we haven't tried the old interface already
|
||||||
* proc_attr_base == proc_attr_base_old - no fallback
|
* proc_attr_base == proc_attr_base_old - no fallback
|
||||||
@@ -483,14 +483,11 @@ static int procattr_open(pid_t tid, const char *attr, int flags)
|
|||||||
* old interface where is_enabled() is only successful if
|
* old interface where is_enabled() is only successful if
|
||||||
* the old interface is available to apparmor.
|
* the old interface is available to apparmor.
|
||||||
*/
|
*/
|
||||||
if (fd == -1 && param_check_enabled() != 0 && strncmp(tmp, proc_attr_base_old, strlen(proc_attr_base_old)) != 0) {
|
if (fd == -1 && tmp != proc_attr_base_old && param_check_enabled() != 0) {
|
||||||
free(tmp);
|
if (asprintf(&tmp, proc_attr_base_old, tid, attr) < 0)
|
||||||
if (asprintf(&tmp, proc_attr_base_old, tid, attr) < 0) {
|
|
||||||
/* tmp is undefined, make sure it is null for autofree*/
|
|
||||||
tmp = NULL;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
fd = open(tmp, flags);
|
fd = open(tmp, flags);
|
||||||
|
free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd;
|
return fd;
|
||||||
@@ -1358,121 +1355,3 @@ int aa_query_link_path(const char *label, const char *target, const char *link,
|
|||||||
strlen(target), link, strlen(link),
|
strlen(target), link, strlen(link),
|
||||||
allowed, audited);
|
allowed, audited);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alloc_substring(char ***v, char *s, char *p,
|
|
||||||
size_t max_size, size_t n, bool immutable)
|
|
||||||
{
|
|
||||||
if (max_size) {
|
|
||||||
if (n >= max_size) {
|
|
||||||
errno = E2BIG;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
char ** tmpv;
|
|
||||||
tmpv = (char **) realloc(*v, (n + 1) * sizeof(char *));
|
|
||||||
if (tmpv == NULL) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*v = tmpv;
|
|
||||||
}
|
|
||||||
if (immutable) {
|
|
||||||
char *tmp;
|
|
||||||
tmp = (char *) malloc(p - s + 1);
|
|
||||||
if (tmp == NULL) {
|
|
||||||
errno = ENOMEM;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
memcpy(tmp, s, p - s);
|
|
||||||
tmp[p - s] = 0;
|
|
||||||
(*v)[n] = tmp;
|
|
||||||
} else {
|
|
||||||
(*v)[n] = s;
|
|
||||||
if (*p)
|
|
||||||
*p = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* aa_split_overlay_str - split a string into potentially multiple strings
|
|
||||||
* @str: the string to split
|
|
||||||
* @vec: vector to put string pointers into, IF null will be allocated
|
|
||||||
* @max_size: maximum number of ents to put in @vec, IF 0 dynamic
|
|
||||||
* @immutable: true if @str should not be modified.
|
|
||||||
*
|
|
||||||
* Returns: the number of entries in vec on success. -1 on error and errno set.
|
|
||||||
*
|
|
||||||
* Split a comma or colon separated string into substrings.
|
|
||||||
*
|
|
||||||
* IF @vec == NULL
|
|
||||||
* the vec will be dynamically allocated
|
|
||||||
* ELSE
|
|
||||||
* passed in @vec will be used, and NOT updated/extended
|
|
||||||
*
|
|
||||||
* IF @max_size == 0 && @vec == NULL
|
|
||||||
* @vec will be dynamically resized
|
|
||||||
* ELSE
|
|
||||||
* @vec will be fixed at @max_size
|
|
||||||
*
|
|
||||||
* IF @immutable is true
|
|
||||||
* the substrings placed in @vec will be allocated copies.
|
|
||||||
* ELSE
|
|
||||||
* @str will be updated in place and @vec[x] will point into @str
|
|
||||||
*/
|
|
||||||
int aa_split_overlay_str(char *str, char ***vec, size_t max_size, bool immutable)
|
|
||||||
{
|
|
||||||
char *s = str;
|
|
||||||
char *p = str;
|
|
||||||
int rc, n = 0;
|
|
||||||
char **v = *vec;
|
|
||||||
|
|
||||||
if (!*vec) {
|
|
||||||
if (max_size) {
|
|
||||||
v = (char **) malloc(max_size * sizeof(char *));
|
|
||||||
if (v == NULL) {
|
|
||||||
rc = ENOMEM;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (*p) {
|
|
||||||
if (*p == '\\') {
|
|
||||||
if (*(p + 1) != 0)
|
|
||||||
p++;
|
|
||||||
} else if (*p == ',' || *p == ':') {
|
|
||||||
if (p != s) {
|
|
||||||
if (alloc_substring(&v, s, p, max_size, n, immutable) == -1) {
|
|
||||||
rc = errno;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
p++;
|
|
||||||
s = p;
|
|
||||||
} else
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
if (p != s) {
|
|
||||||
if (alloc_substring(&v, s, p, max_size, n, immutable) == -1) {
|
|
||||||
rc = errno;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
|
|
||||||
*vec = v;
|
|
||||||
return n;
|
|
||||||
err:
|
|
||||||
if (immutable) {
|
|
||||||
for (int i = 0; i < n; i++) {
|
|
||||||
free(v[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!*vec)
|
|
||||||
free(v);
|
|
||||||
errno = rc;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
@@ -103,8 +103,6 @@ void free_record(aa_log_record *record)
|
|||||||
free(record->flags);
|
free(record->flags);
|
||||||
if (record->src_name != NULL)
|
if (record->src_name != NULL)
|
||||||
free(record->src_name);
|
free(record->src_name);
|
||||||
if (record->class != NULL)
|
|
||||||
free(record->class);
|
|
||||||
|
|
||||||
free(record);
|
free(record);
|
||||||
}
|
}
|
||||||
|
@@ -124,13 +124,6 @@ APPARMOR_3.0 {
|
|||||||
*;
|
*;
|
||||||
} APPARMOR_2.13.1;
|
} APPARMOR_2.13.1;
|
||||||
|
|
||||||
APPARMOR_3.1 {
|
|
||||||
global:
|
|
||||||
aa_features_check;
|
|
||||||
local:
|
|
||||||
*;
|
|
||||||
} APPARMOR_3.0;
|
|
||||||
|
|
||||||
PRIVATE {
|
PRIVATE {
|
||||||
global:
|
global:
|
||||||
_aa_is_blacklisted;
|
_aa_is_blacklisted;
|
||||||
|
@@ -147,6 +147,36 @@ repeat:
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cache_check_features(int dirfd, const char *cache_name,
|
||||||
|
aa_features *features)
|
||||||
|
{
|
||||||
|
aa_features *local_features = NULL;
|
||||||
|
autofree char *name = NULL;
|
||||||
|
bool rc;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = asprintf(&name, "%s/%s", cache_name, CACHE_FEATURES_FILE);
|
||||||
|
if (len == -1) {
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* verify that cache dir .features matches */
|
||||||
|
if (aa_features_new(&local_features, dirfd, name)) {
|
||||||
|
PDEBUG("could not setup new features object for dirfd '%d' '%s'\n", dirfd, name);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = aa_features_is_equal(local_features, features);
|
||||||
|
aa_features_unref(local_features);
|
||||||
|
if (!rc) {
|
||||||
|
errno = EEXIST;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
||||||
{
|
{
|
||||||
if (aa_policy_cache_remove(policy_cache->dirfd[0], "."))
|
if (aa_policy_cache_remove(policy_cache->dirfd[0], "."))
|
||||||
@@ -164,8 +194,8 @@ static int create_cache(aa_policy_cache *policy_cache, aa_features *features)
|
|||||||
static int init_cache_features(aa_policy_cache *policy_cache,
|
static int init_cache_features(aa_policy_cache *policy_cache,
|
||||||
aa_features *kernel_features, bool create)
|
aa_features *kernel_features, bool create)
|
||||||
{
|
{
|
||||||
if (aa_features_check(policy_cache->dirfd[0], ".",
|
if (cache_check_features(policy_cache->dirfd[0], ".",
|
||||||
kernel_features)) {
|
kernel_features)) {
|
||||||
/* EEXIST must come before ENOENT for short circuit eval */
|
/* EEXIST must come before ENOENT for short circuit eval */
|
||||||
if (!create || errno == EEXIST || errno != ENOENT)
|
if (!create || errno == EEXIST || errno != ENOENT)
|
||||||
return -1;
|
return -1;
|
||||||
@@ -201,13 +231,13 @@ static int cache_miss_cb(int dirfd, const struct dirent *ent, void *arg)
|
|||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (!aa_features_check(dirfd, cache_name, data->features) || errno == ENOENT) {
|
if (!cache_check_features(dirfd, cache_name, data->features) || errno == ENOENT) {
|
||||||
/* found cache dir matching pattern */
|
/* found cache dir matching pattern */
|
||||||
data->cache_name = cache_name;
|
data->cache_name = cache_name;
|
||||||
/* return 1 to stop iteration and signal dir found */
|
/* return 1 to stop iteration and signal dir found */
|
||||||
return 1;
|
return 1;
|
||||||
} else if (errno != EEXIST) {
|
} else if (errno != EEXIST) {
|
||||||
PDEBUG("aa_features_check() failed for dirfd '%d' '%s'\n", dirfd, cache_name);
|
PDEBUG("cache_check_features() failed for dirfd '%d' '%s'\n", dirfd, cache_name);
|
||||||
free(cache_name);
|
free(cache_name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -243,12 +273,12 @@ static int cache_dir_from_path_and_features(char **cache_path,
|
|||||||
if (len == -1)
|
if (len == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!aa_features_check(dirfd, cache_dir, features) || errno == ENOENT) {
|
if (!cache_check_features(dirfd, cache_dir, features) || errno == ENOENT) {
|
||||||
PDEBUG("cache_dir_from_path_and_features() found '%s'\n", cache_dir);
|
PDEBUG("cache_dir_from_path_and_features() found '%s'\n", cache_dir);
|
||||||
*cache_path = cache_dir;
|
*cache_path = cache_dir;
|
||||||
return 0;
|
return 0;
|
||||||
} else if (errno != EEXIST) {
|
} else if (errno != EEXIST) {
|
||||||
PDEBUG("aa_features_check() failed for dirfd '%d' %s\n", dirfd, cache_dir);
|
PDEBUG("cache_check_features() failed for dirfd '%d' %s\n", dirfd, cache_dir);
|
||||||
free(cache_dir);
|
free(cache_dir);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@@ -121,8 +121,6 @@ key_namespace "namespace"
|
|||||||
key_mask "mask"
|
key_mask "mask"
|
||||||
key_denied_mask "denied_mask"
|
key_denied_mask "denied_mask"
|
||||||
key_requested_mask "requested_mask"
|
key_requested_mask "requested_mask"
|
||||||
key_denied "denied"
|
|
||||||
key_requested "requested"
|
|
||||||
key_attribute "attribute"
|
key_attribute "attribute"
|
||||||
key_task "task"
|
key_task "task"
|
||||||
key_parent "parent"
|
key_parent "parent"
|
||||||
@@ -165,14 +163,11 @@ key_dest "dest"
|
|||||||
key_path "path"
|
key_path "path"
|
||||||
key_interface "interface"
|
key_interface "interface"
|
||||||
key_member "member"
|
key_member "member"
|
||||||
key_method "method"
|
|
||||||
key_signal "signal"
|
key_signal "signal"
|
||||||
key_peer "peer"
|
key_peer "peer"
|
||||||
key_fstype "fstype"
|
key_fstype "fstype"
|
||||||
key_flags "flags"
|
key_flags "flags"
|
||||||
key_srcname "srcname"
|
key_srcname "srcname"
|
||||||
key_class "class"
|
|
||||||
key_tcontext "tcontext"
|
|
||||||
audit "audit"
|
audit "audit"
|
||||||
|
|
||||||
/* network addrs */
|
/* network addrs */
|
||||||
@@ -314,8 +309,6 @@ yy_flex_debug = 0;
|
|||||||
{key_mask} { return(TOK_KEY_MASK); }
|
{key_mask} { return(TOK_KEY_MASK); }
|
||||||
{key_denied_mask} { return(TOK_KEY_DENIED_MASK); }
|
{key_denied_mask} { return(TOK_KEY_DENIED_MASK); }
|
||||||
{key_requested_mask} { return(TOK_KEY_REQUESTED_MASK); }
|
{key_requested_mask} { return(TOK_KEY_REQUESTED_MASK); }
|
||||||
{key_denied} { return(TOK_KEY_DENIED_MASK); }
|
|
||||||
{key_requested} { return(TOK_KEY_REQUESTED_MASK); }
|
|
||||||
{key_attribute} { BEGIN(sub_id); return(TOK_KEY_ATTRIBUTE); }
|
{key_attribute} { BEGIN(sub_id); return(TOK_KEY_ATTRIBUTE); }
|
||||||
{key_task} { return(TOK_KEY_TASK); }
|
{key_task} { return(TOK_KEY_TASK); }
|
||||||
{key_parent} { return(TOK_KEY_PARENT); }
|
{key_parent} { return(TOK_KEY_PARENT); }
|
||||||
@@ -328,7 +321,6 @@ yy_flex_debug = 0;
|
|||||||
{key_peer_profile} { BEGIN(safe_string); return(TOK_KEY_PEER_PROFILE); }
|
{key_peer_profile} { BEGIN(safe_string); return(TOK_KEY_PEER_PROFILE); }
|
||||||
{key_label} { BEGIN(safe_string); return(TOK_KEY_LABEL); }
|
{key_label} { BEGIN(safe_string); return(TOK_KEY_LABEL); }
|
||||||
{key_peer_label} { BEGIN(safe_string); return(TOK_KEY_PEER_LABEL); }
|
{key_peer_label} { BEGIN(safe_string); return(TOK_KEY_PEER_LABEL); }
|
||||||
{key_tcontext} { BEGIN(safe_string); return(TOK_KEY_PEER_LABEL); }
|
|
||||||
{key_family} { return(TOK_KEY_FAMILY); }
|
{key_family} { return(TOK_KEY_FAMILY); }
|
||||||
{key_sock_type} { return(TOK_KEY_SOCK_TYPE); }
|
{key_sock_type} { return(TOK_KEY_SOCK_TYPE); }
|
||||||
{key_protocol} { return(TOK_KEY_PROTOCOL); }
|
{key_protocol} { return(TOK_KEY_PROTOCOL); }
|
||||||
@@ -358,13 +350,11 @@ yy_flex_debug = 0;
|
|||||||
{key_path} { return(TOK_KEY_PATH); }
|
{key_path} { return(TOK_KEY_PATH); }
|
||||||
{key_interface} { return(TOK_KEY_INTERFACE); }
|
{key_interface} { return(TOK_KEY_INTERFACE); }
|
||||||
{key_member} { return(TOK_KEY_MEMBER); }
|
{key_member} { return(TOK_KEY_MEMBER); }
|
||||||
{key_method} { return(TOK_KEY_MEMBER); }
|
|
||||||
{key_signal} { BEGIN(sub_id); return(TOK_KEY_SIGNAL); }
|
{key_signal} { BEGIN(sub_id); return(TOK_KEY_SIGNAL); }
|
||||||
{key_peer} { BEGIN(safe_string); return(TOK_KEY_PEER); }
|
{key_peer} { BEGIN(safe_string); return(TOK_KEY_PEER); }
|
||||||
{key_fstype} { return(TOK_KEY_FSTYPE); }
|
{key_fstype} { return(TOK_KEY_FSTYPE); }
|
||||||
{key_flags} { BEGIN(safe_string); return(TOK_KEY_FLAGS); }
|
{key_flags} { BEGIN(safe_string); return(TOK_KEY_FLAGS); }
|
||||||
{key_srcname} { BEGIN(safe_string); return(TOK_KEY_SRCNAME); }
|
{key_srcname} { BEGIN(safe_string); return(TOK_KEY_SRCNAME); }
|
||||||
{key_class} { BEGIN(safe_string); return(TOK_KEY_CLASS); }
|
|
||||||
|
|
||||||
{socklogd_kernel} { BEGIN(dmesg_timestamp); return(TOK_SOCKLOGD_KERNEL); }
|
{socklogd_kernel} { BEGIN(dmesg_timestamp); return(TOK_SOCKLOGD_KERNEL); }
|
||||||
{syslog_kernel} { BEGIN(dmesg_timestamp); return(TOK_SYSLOG_KERNEL); }
|
{syslog_kernel} { BEGIN(dmesg_timestamp); return(TOK_SYSLOG_KERNEL); }
|
||||||
|
@@ -11,4 +11,4 @@ if tuple(map(int, setuptools.__version__.split("."))) >= (62, 1):
|
|||||||
identifier = sys.implementation.cache_tag
|
identifier = sys.implementation.cache_tag
|
||||||
else:
|
else:
|
||||||
identifier = "%d.%d" % sys.version_info[:2]
|
identifier = "%d.%d" % sys.version_info[:2]
|
||||||
print("lib.{}-{}".format(sysconfig.get_platform(), identifier))
|
print("lib.%s-%s" % (sysconfig.get_platform(), identifier))
|
||||||
|
@@ -35,7 +35,6 @@ OUTPUT_MAP = {
|
|||||||
'Local port': 'net_local_port',
|
'Local port': 'net_local_port',
|
||||||
'Foreign port': 'net_foreign_port',
|
'Foreign port': 'net_foreign_port',
|
||||||
'Audit subid': 'audit_sub_id',
|
'Audit subid': 'audit_sub_id',
|
||||||
'Class': '_class',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# FIXME: pull this automatically out of LibAppArmor, but swig
|
# FIXME: pull this automatically out of LibAppArmor, but swig
|
||||||
@@ -64,8 +63,8 @@ class AAPythonBindingsTests(unittest.TestCase):
|
|||||||
self.maxDiff = None
|
self.maxDiff = None
|
||||||
|
|
||||||
def _runtest(self, testname):
|
def _runtest(self, testname):
|
||||||
infile = testname + ".in"
|
infile = "%s.in" % (testname)
|
||||||
outfile = testname + ".out"
|
outfile = "%s.out" % (testname)
|
||||||
# infile *should* only contain one line
|
# infile *should* only contain one line
|
||||||
with open(os.path.join(TESTDIR, infile), 'r') as f:
|
with open(os.path.join(TESTDIR, infile), 'r') as f:
|
||||||
line = f.read()
|
line = f.read()
|
||||||
@@ -78,7 +77,7 @@ class AAPythonBindingsTests(unittest.TestCase):
|
|||||||
expected = self.parse_output_file(outfile)
|
expected = self.parse_output_file(outfile)
|
||||||
self.assertEqual(expected, record,
|
self.assertEqual(expected, record,
|
||||||
"expected records did not match\n"
|
"expected records did not match\n"
|
||||||
"expected = {}\nactual = {}".format(expected, record))
|
"expected = %s\nactual = %s" % (expected, record))
|
||||||
|
|
||||||
def parse_output_file(self, outfile):
|
def parse_output_file(self, outfile):
|
||||||
"""parse testcase .out file and return dict"""
|
"""parse testcase .out file and return dict"""
|
||||||
@@ -93,7 +92,7 @@ class AAPythonBindingsTests(unittest.TestCase):
|
|||||||
count += 1
|
count += 1
|
||||||
if line == "START":
|
if line == "START":
|
||||||
self.assertEqual(count, 1,
|
self.assertEqual(count, 1,
|
||||||
"Unexpected output format in " + outfile)
|
"Unexpected output format in %s" % (outfile))
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
key, value = line.split(": ", 1)
|
key, value = line.split(": ", 1)
|
||||||
@@ -110,7 +109,7 @@ class AAPythonBindingsTests(unittest.TestCase):
|
|||||||
"""parse the swig created record and construct a dict from it"""
|
"""parse the swig created record and construct a dict from it"""
|
||||||
|
|
||||||
new_record = dict()
|
new_record = dict()
|
||||||
for key in [x for x in dir(record) if not (x.startswith('__') or x == 'this')]:
|
for key in [x for x in dir(record) if not (x.startswith('_') or x == 'this')]:
|
||||||
value = getattr(record, key)
|
value = getattr(record, key)
|
||||||
if key == "event" and value in EVENT_MAP:
|
if key == "event" and value in EVENT_MAP:
|
||||||
new_record[key] = EVENT_MAP[value]
|
new_record[key] = EVENT_MAP[value]
|
||||||
@@ -141,8 +140,8 @@ def main():
|
|||||||
for f in find_testcases(TESTDIR):
|
for f in find_testcases(TESTDIR):
|
||||||
def stub_test(self, testname=f):
|
def stub_test(self, testname=f):
|
||||||
self._runtest(testname)
|
self._runtest(testname)
|
||||||
stub_test.__doc__ = "test " + f
|
stub_test.__doc__ = "test %s" % (f)
|
||||||
setattr(AAPythonBindingsTests, 'test_' + f, stub_test)
|
setattr(AAPythonBindingsTests, 'test_%s' % (f), stub_test)
|
||||||
return unittest.main(verbosity=2)
|
return unittest.main(verbosity=2)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -134,8 +134,6 @@ int print_results(aa_log_record *record)
|
|||||||
print_string("Flags", record->flags);
|
print_string("Flags", record->flags);
|
||||||
print_string("Src name", record->src_name);
|
print_string("Src name", record->src_name);
|
||||||
|
|
||||||
print_string("Class", record->class);
|
|
||||||
|
|
||||||
print_long("Epoch", record->epoch, 0);
|
print_long("Epoch", record->epoch, 0);
|
||||||
print_long("Audit subid", (long) record->audit_sub_id, 0);
|
print_long("Audit subid", (long) record->audit_sub_id, 0);
|
||||||
return(0);
|
return(0);
|
||||||
|
@@ -1 +0,0 @@
|
|||||||
type=AVC msg=audit(1676978994.840:1493): apparmor="DENIED" operation="link" profile="cargo" name="/var/tmp/portage/dev-lang/rust-1.67.1/work/rustc-1.67.1-src/build/bootstrap/debug/libbootstrap.rlib" pid=12412 comm="cargo" requested_mask="xm" denied_mask="xm" fsuid=250 ouid=250 target="/var/tmp/portage/dev-lang/rust-1.67.1/work/rustc-1.67.1-src/build/bootstrap/debug/deps/libbootstrap-4542dd99e796257e.rlib"FSUID="portage" OUID="portage"
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: file_xm.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1676978994.840:1493
|
|
||||||
Operation: link
|
|
||||||
Mask: xm
|
|
||||||
Denied Mask: xm
|
|
||||||
fsuid: 250
|
|
||||||
ouid: 250
|
|
||||||
Profile: cargo
|
|
||||||
Name: /var/tmp/portage/dev-lang/rust-1.67.1/work/rustc-1.67.1-src/build/bootstrap/debug/libbootstrap.rlib
|
|
||||||
Command: cargo
|
|
||||||
Name2: /var/tmp/portage/dev-lang/rust-1.67.1/work/rustc-1.67.1-src/build/bootstrap/debug/deps/libbootstrap-4542dd99e796257e.rlib
|
|
||||||
PID: 12412
|
|
||||||
Epoch: 1676978994
|
|
||||||
Audit subid: 1493
|
|
@@ -1,4 +0,0 @@
|
|||||||
profile cargo {
|
|
||||||
owner /var/tmp/portage/dev-lang/rust-1.67.1/work/rustc-1.67.1-src/build/bootstrap/debug/libbootstrap.rlib m,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Dec 15 17:32:17 kinetic kernel: [4835959.046111] audit: type=1107 audit(1671125537.724:209): pid=7308 uid=0 auid=4294967295 ses=4294967295 msg='apparmor="DENIED" operation="dbus_method_call" bus="session" path="/org/freedesktop/DBus" interface="org.freedesktop.DBus" method="Hello" mask="send" label="/tmp/apparmor/tests/regression/apparmor/dbus_message" peer_label="unconfined" exe="/usr/local/bin/dbus-broker" sauid=0 hostname=? addr=? terminal=?'
|
|
@@ -1,15 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_dbus_11.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1671125537.724:209
|
|
||||||
Operation: dbus_method_call
|
|
||||||
Denied Mask: send
|
|
||||||
Profile: /tmp/apparmor/tests/regression/apparmor/dbus_message
|
|
||||||
Peer profile: unconfined
|
|
||||||
Command: /usr/local/bin/dbus-broker
|
|
||||||
DBus bus: session
|
|
||||||
DBus path: /org/freedesktop/DBus
|
|
||||||
DBus interface: org.freedesktop.DBus
|
|
||||||
DBus member: Hello
|
|
||||||
Epoch: 1671125537
|
|
||||||
Audit subid: 209
|
|
@@ -1,4 +0,0 @@
|
|||||||
/tmp/apparmor/tests/regression/apparmor/dbus_message {
|
|
||||||
dbus send bus=session path=/org/freedesktop/DBus interface=org.freedesktop.DBus member=Hello peer=(label=unconfined),
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
[ 4584.703379] audit: type=1400 audit(1680266735.359:69): apparmor="DENIED" operation="uring_sqpoll" class="io_uring" profile="/root/apparmor/tests/regression/apparmor/io_uring" pid=1320 comm="io_uring" requested="sqpoll" denied="sqpoll"
|
|
@@ -1,13 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_io_uring_01.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1680266735.359:69
|
|
||||||
Operation: uring_sqpoll
|
|
||||||
Mask: sqpoll
|
|
||||||
Denied Mask: sqpoll
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/io_uring
|
|
||||||
Command: io_uring
|
|
||||||
PID: 1320
|
|
||||||
Class: io_uring
|
|
||||||
Epoch: 1680266735
|
|
||||||
Audit subid: 69
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/io_uring {
|
|
||||||
io_uring sqpoll,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
[ 4584.491076] audit: type=1400 audit(1680266735.147:63): apparmor="DENIED" operation="uring_override" class="io_uring" profile="/root/apparmor/tests/regression/apparmor/io_uring" pid=1193 comm="io_uring" requested="override_creds" denied="override_creds" tcontext="/root/apparmor/tests/regression/apparmor/io_uring"
|
|
@@ -1,14 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_io_uring_02.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1680266735.147:63
|
|
||||||
Operation: uring_override
|
|
||||||
Mask: override_creds
|
|
||||||
Denied Mask: override_creds
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/io_uring
|
|
||||||
Peer profile: /root/apparmor/tests/regression/apparmor/io_uring
|
|
||||||
Command: io_uring
|
|
||||||
PID: 1193
|
|
||||||
Class: io_uring
|
|
||||||
Epoch: 1680266735
|
|
||||||
Audit subid: 63
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/io_uring {
|
|
||||||
io_uring override_creds label=/root/apparmor/tests/regression/apparmor/io_uring,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Apr 05 19:36:19 ubuntu kernel: audit: type=1400 audit(1649187379.660:255): apparmor="DENIED" operation="create" profile="/root/apparmor/tests/regression/apparmor/posix_mq_rcv" name="/queuename" pid=791 comm="posix_mq_rcv" requested="create" denied="create" class="posix_mqueue" fsuid=0 ouid=0
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_01.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1649187379.660:255
|
|
||||||
Operation: create
|
|
||||||
Mask: create
|
|
||||||
Denied Mask: create
|
|
||||||
fsuid: 0
|
|
||||||
ouid: 0
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/posix_mq_rcv
|
|
||||||
Name: /queuename
|
|
||||||
Command: posix_mq_rcv
|
|
||||||
PID: 791
|
|
||||||
Class: posix_mqueue
|
|
||||||
Epoch: 1649187379
|
|
||||||
Audit subid: 255
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/posix_mq_rcv {
|
|
||||||
mqueue create type=posix /queuename,
|
|
||||||
|
|
||||||
}
|
|
@@ -1,2 +0,0 @@
|
|||||||
Apr 05 19:36:29 ubuntu kernel: audit: type=1400 audit(1649187389.828:262): apparmor="DENIED" operation="open" profile="/root/apparmor/tests/regression/apparmor/posix_mq_rcv" name="/queuename" pid=848 comm="posix_mq_rcv" requested="read create" denied="read" class="posix_mqueue" fsuid=0 ouid=0
|
|
||||||
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_02.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1649187389.828:262
|
|
||||||
Operation: open
|
|
||||||
Mask: read create
|
|
||||||
Denied Mask: read
|
|
||||||
fsuid: 0
|
|
||||||
ouid: 0
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/posix_mq_rcv
|
|
||||||
Name: /queuename
|
|
||||||
Command: posix_mq_rcv
|
|
||||||
PID: 848
|
|
||||||
Class: posix_mqueue
|
|
||||||
Epoch: 1649187389
|
|
||||||
Audit subid: 262
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/posix_mq_rcv {
|
|
||||||
mqueue read type=posix /queuename,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Apr 05 19:36:39 ubuntu kernel: audit: type=1400 audit(1649187399.973:265): apparmor="DENIED" operation="unlink" profile="/root/apparmor/tests/regression/apparmor/posix_mq_rcv" name="/queuename" pid=897 comm="posix_mq_rcv" requested="delete" denied="delete" class="posix_mqueue" fsuid=0 ouid=0
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_03.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1649187399.973:265
|
|
||||||
Operation: unlink
|
|
||||||
Mask: delete
|
|
||||||
Denied Mask: delete
|
|
||||||
fsuid: 0
|
|
||||||
ouid: 0
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/posix_mq_rcv
|
|
||||||
Name: /queuename
|
|
||||||
Command: posix_mq_rcv
|
|
||||||
PID: 897
|
|
||||||
Class: posix_mqueue
|
|
||||||
Epoch: 1649187399
|
|
||||||
Audit subid: 265
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/posix_mq_rcv {
|
|
||||||
mqueue delete type=posix /queuename,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Jun 02 16:58:20 ubuntu kernel: audit: type=1400 audit(1654189100.680:1011): apparmor="DENIED" operation="sysv_mqueue" profile="/root/apparmor/tests/regression/apparmor/sysv_mq_rcv" name="123" pid=13574 comm="sysv_mq_rcv" requested="create" denied="create" class="sysv_mqueue" fsuid=0 ouid=0
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_04.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1654189100.680:1011
|
|
||||||
Operation: sysv_mqueue
|
|
||||||
Mask: create
|
|
||||||
Denied Mask: create
|
|
||||||
fsuid: 0
|
|
||||||
ouid: 0
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/sysv_mq_rcv
|
|
||||||
Name: 123
|
|
||||||
Command: sysv_mq_rcv
|
|
||||||
PID: 13574
|
|
||||||
Class: sysv_mqueue
|
|
||||||
Epoch: 1654189100
|
|
||||||
Audit subid: 1011
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/sysv_mq_rcv {
|
|
||||||
mqueue create type=sysv 123,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Jun 02 17:15:45 ubuntu kernel: audit: type=1400 audit(1654190145.439:1135): apparmor="DENIED" operation="sysv_mqueue" profile="/root/apparmor/tests/regression/apparmor/sysv_mq_snd" name="123" pid=15849 comm="sysv_mq_snd" requested="open" denied="open" class="sysv_mqueue"
|
|
@@ -1,14 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_05.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1654190145.439:1135
|
|
||||||
Operation: sysv_mqueue
|
|
||||||
Mask: open
|
|
||||||
Denied Mask: open
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/sysv_mq_snd
|
|
||||||
Name: 123
|
|
||||||
Command: sysv_mq_snd
|
|
||||||
PID: 15849
|
|
||||||
Class: sysv_mqueue
|
|
||||||
Epoch: 1654190145
|
|
||||||
Audit subid: 1135
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/sysv_mq_snd {
|
|
||||||
mqueue open type=sysv 123,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Jun 02 17:15:37 ubuntu kernel: audit: type=1400 audit(1654190137.559:1122): apparmor="DENIED" operation="sysv_mqueue" profile="/root/apparmor/tests/regression/apparmor/sysv_mq_rcv" name="123" pid=15632 comm="sysv_mq_rcv" requested="read" denied="read" class="sysv_mqueue" fsuid=0 ouid=0
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_06.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1654190137.559:1122
|
|
||||||
Operation: sysv_mqueue
|
|
||||||
Mask: read
|
|
||||||
Denied Mask: read
|
|
||||||
fsuid: 0
|
|
||||||
ouid: 0
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/sysv_mq_rcv
|
|
||||||
Name: 123
|
|
||||||
Command: sysv_mq_rcv
|
|
||||||
PID: 15632
|
|
||||||
Class: sysv_mqueue
|
|
||||||
Epoch: 1654190137
|
|
||||||
Audit subid: 1122
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/sysv_mq_rcv {
|
|
||||||
mqueue read type=sysv 123,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Jun 02 17:15:51 ubuntu kernel: audit: type=1400 audit(1654190151.003:1145): apparmor="DENIED" operation="sysv_mqueue" profile="/root/apparmor/tests/regression/apparmor/sysv_mq_rcv" name="123" pid=15973 comm="sysv_mq_rcv" requested="delete" denied="delete" class="sysv_mqueue" fsuid=1001 ouid=1001
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_07.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1654190151.003:1145
|
|
||||||
Operation: sysv_mqueue
|
|
||||||
Mask: delete
|
|
||||||
Denied Mask: delete
|
|
||||||
fsuid: 1001
|
|
||||||
ouid: 1001
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/sysv_mq_rcv
|
|
||||||
Name: 123
|
|
||||||
Command: sysv_mq_rcv
|
|
||||||
PID: 15973
|
|
||||||
Class: sysv_mqueue
|
|
||||||
Epoch: 1654190151
|
|
||||||
Audit subid: 1145
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/sysv_mq_rcv {
|
|
||||||
mqueue delete type=sysv 123,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
Jun 02 17:15:55 ubuntu kernel: audit: type=1400 audit(1654190155.699:1155): apparmor="DENIED" operation="sysv_mqueue" profile="/root/apparmor/tests/regression/apparmor/sysv_mq_snd" name="123" pid=16148 comm="sysv_mq_snd" requested="write" denied="write" class="sysv_mqueue" fsuid=1001 ouid=1001
|
|
@@ -1,16 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_mqueue_08.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1654190155.699:1155
|
|
||||||
Operation: sysv_mqueue
|
|
||||||
Mask: write
|
|
||||||
Denied Mask: write
|
|
||||||
fsuid: 1001
|
|
||||||
ouid: 1001
|
|
||||||
Profile: /root/apparmor/tests/regression/apparmor/sysv_mq_snd
|
|
||||||
Name: 123
|
|
||||||
Command: sysv_mq_snd
|
|
||||||
PID: 16148
|
|
||||||
Class: sysv_mqueue
|
|
||||||
Epoch: 1654190155
|
|
||||||
Audit subid: 1155
|
|
@@ -1,4 +0,0 @@
|
|||||||
/root/apparmor/tests/regression/apparmor/sysv_mq_snd {
|
|
||||||
mqueue write type=sysv 123,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
type=AVC msg=audit(1709108389.303:12383): apparmor="DENIED" operation="mount" class="mount" info="failed mntpnt match" error=-13 profile="/home/user/test/testmount" name="/tmp/foo/" pid=14155 comm="testmount" flags="ro, remount"
|
|
@@ -1,15 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_remount_01.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1709108389.303:12383
|
|
||||||
Operation: mount
|
|
||||||
Profile: /home/user/test/testmount
|
|
||||||
Name: /tmp/foo/
|
|
||||||
Command: testmount
|
|
||||||
Info: failed mntpnt match
|
|
||||||
ErrorCode: 13
|
|
||||||
PID: 14155
|
|
||||||
Flags: ro, remount
|
|
||||||
Class: mount
|
|
||||||
Epoch: 1709108389
|
|
||||||
Audit subid: 12383
|
|
@@ -1,4 +0,0 @@
|
|||||||
/home/user/test/testmount {
|
|
||||||
mount options=(remount, ro) -> /tmp/foo/,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
type=AVC msg=audit(1709025786.045:43147): apparmor="DENIED" operation="umount" class="mount" profile="/home/user/test/testmount" name="/mnt/a/" pid=26697 comm="testmount"
|
|
@@ -1,12 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_umount_01.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1709025786.045:43147
|
|
||||||
Operation: umount
|
|
||||||
Profile: /home/user/test/testmount
|
|
||||||
Name: /mnt/a/
|
|
||||||
Command: testmount
|
|
||||||
PID: 26697
|
|
||||||
Class: mount
|
|
||||||
Epoch: 1709025786
|
|
||||||
Audit subid: 43147
|
|
@@ -1,4 +0,0 @@
|
|||||||
/home/user/test/testmount {
|
|
||||||
umount /mnt/a/,
|
|
||||||
|
|
||||||
}
|
|
@@ -1 +0,0 @@
|
|||||||
[ 176.385388] audit: type=1400 audit(1666891380.570:78): apparmor="DENIED" operation="userns_create" class="namespace" profile="/usr/bin/userns_child_exec" pid=1785 comm="userns_child_ex" requested="userns_create" denied="userns_create"
|
|
@@ -1,13 +0,0 @@
|
|||||||
START
|
|
||||||
File: testcase_userns_01.in
|
|
||||||
Event type: AA_RECORD_DENIED
|
|
||||||
Audit ID: 1666891380.570:78
|
|
||||||
Operation: userns_create
|
|
||||||
Mask: userns_create
|
|
||||||
Denied Mask: userns_create
|
|
||||||
Profile: /usr/bin/userns_child_exec
|
|
||||||
Command: userns_child_ex
|
|
||||||
PID: 1785
|
|
||||||
Class: namespace
|
|
||||||
Epoch: 1666891380
|
|
||||||
Audit subid: 78
|
|
@@ -1,4 +0,0 @@
|
|||||||
/usr/bin/userns_child_exec {
|
|
||||||
userns create,
|
|
||||||
|
|
||||||
}
|
|
116
parser/Makefile
116
parser/Makefile
@@ -70,10 +70,7 @@ CFLAGS = -g -pg -fprofile-arcs -ftest-coverage
|
|||||||
endif
|
endif
|
||||||
endif #CFLAGS
|
endif #CFLAGS
|
||||||
|
|
||||||
HAVE_FLTO_PARTITION_NONE:=$(shell ${CC} -E -flto-partition=none /dev/null 1>/dev/null 2>&1 && echo true)
|
CFLAGS += -flto-partition=none
|
||||||
ifeq ($(HAVE_FLTO_PARTITION_NONE),true)
|
|
||||||
CFLAGS += -flto-partition=none
|
|
||||||
endif
|
|
||||||
|
|
||||||
EXTRA_CXXFLAGS = ${CFLAGS} ${CPPFLAGS} ${CXX_WARNINGS} -std=gnu++0x
|
EXTRA_CXXFLAGS = ${CFLAGS} ${CPPFLAGS} ${CXX_WARNINGS} -std=gnu++0x
|
||||||
EXTRA_CFLAGS = ${EXTRA_CXXFLAGS} ${CPP_WARNINGS}
|
EXTRA_CFLAGS = ${EXTRA_CXXFLAGS} ${CPP_WARNINGS}
|
||||||
@@ -102,21 +99,12 @@ EXTRA_CFLAGS+=-DPACKAGE=\"${NAME}\" -DLOCALEDIR=\"${LOCALEDIR}\"
|
|||||||
SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \
|
SRCS = parser_common.c parser_include.c parser_interface.c parser_lex.c \
|
||||||
parser_main.c parser_misc.c parser_merge.c parser_symtab.c \
|
parser_main.c parser_misc.c parser_merge.c parser_symtab.c \
|
||||||
parser_yacc.c parser_regex.c parser_variable.c parser_policy.c \
|
parser_yacc.c parser_regex.c parser_variable.c parser_policy.c \
|
||||||
parser_alias.c common_optarg.c lib.c network.cc \
|
parser_alias.c common_optarg.c lib.c network.c \
|
||||||
mount.cc dbus.cc profile.cc rule.cc signal.cc ptrace.cc \
|
mount.cc dbus.cc profile.cc rule.cc signal.cc ptrace.cc \
|
||||||
af_rule.cc af_unix.cc policy_cache.c default_features.c userns.cc \
|
af_rule.cc af_unix.cc policy_cache.c default_features.c
|
||||||
mqueue.cc io_uring.cc all_rule.cc
|
HDRS = parser.h parser_include.h immunix.h mount.h dbus.h lib.h profile.h \
|
||||||
STATIC_HDRS = af_rule.h af_unix.h capability.h common_optarg.h dbus.h \
|
rule.h common_optarg.h signal.h ptrace.h network.h af_rule.h af_unix.h \
|
||||||
file_cache.h immunix.h lib.h mount.h network.h parser.h \
|
policy_cache.h file_cache.h
|
||||||
parser_include.h parser_version.h policy_cache.h policydb.h \
|
|
||||||
profile.h ptrace.h rule.h signal.h userns.h mqueue.h io_uring.h \
|
|
||||||
common_flags.h bignum.h all_rule.h
|
|
||||||
|
|
||||||
SPECIAL_HDRS = parser_yacc.h unit_test.h base_cap_names.h
|
|
||||||
GENERATED_HDRS = af_names.h generated_af_names.h \
|
|
||||||
cap_names.h generated_cap_names.h parser_version.h
|
|
||||||
LIBAA_HDRS = libapparmor_re/apparmor_re.h libapparmor_re/aare_rules.h
|
|
||||||
|
|
||||||
TOOLS = apparmor_parser
|
TOOLS = apparmor_parser
|
||||||
|
|
||||||
OBJECTS = $(patsubst %.cc, %.o, $(SRCS:.c=.o))
|
OBJECTS = $(patsubst %.cc, %.o, $(SRCS:.c=.o))
|
||||||
@@ -178,11 +166,8 @@ else
|
|||||||
endif
|
endif
|
||||||
export Q VERBOSE BUILD_OUTPUT
|
export Q VERBOSE BUILD_OUTPUT
|
||||||
|
|
||||||
HDRS=$(STATIC_HDRS) $(GENERATED_HDRS) parser_yacc.h $(LIBAA_HDRS) $(APPARMOR_H)
|
po/${NAME}.pot: ${SRCS} ${HDRS}
|
||||||
|
$(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${SRCS} ${HDRS}"
|
||||||
|
|
||||||
po/${NAME}.pot: ${SRCS} ${STATIC_HDRS}
|
|
||||||
$(MAKE) -C po ${NAME}.pot NAME=${NAME} SOURCES="${SRCS} ${STATIC_HDRS}"
|
|
||||||
|
|
||||||
techdoc.pdf: techdoc.tex
|
techdoc.pdf: techdoc.tex
|
||||||
timestamp=$(shell date --utc "+%Y%m%d%H%M%S%z" -r $< );\
|
timestamp=$(shell date --utc "+%Y%m%d%H%M%S%z" -r $< );\
|
||||||
@@ -232,100 +217,88 @@ apparmor_parser: $(OBJECTS) $(AAREOBJECTS) $(LIBAPPARMOR_A)
|
|||||||
$(CXX) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $(OBJECTS) $(LIBS) \
|
$(CXX) $(LDFLAGS) $(EXTRA_CFLAGS) -o $@ $(OBJECTS) $(LIBS) \
|
||||||
${LEXLIB} $(AAREOBJECTS) $(AARE_LDFLAGS) $(AALIB)
|
${LEXLIB} $(AAREOBJECTS) $(AARE_LDFLAGS) $(AALIB)
|
||||||
|
|
||||||
parser_yacc.c parser_yacc.h: parser_yacc.y $(STATIC_HDRS) $(DYNAMIC_HDRS)
|
parser_yacc.c parser_yacc.h: parser_yacc.y parser.h profile.h file_cache.h
|
||||||
$(YACC) $(YFLAGS) -o parser_yacc.c parser_yacc.y
|
$(YACC) $(YFLAGS) -o parser_yacc.c parser_yacc.y
|
||||||
|
|
||||||
parser_lex.c: parser_lex.l $(HDRS)
|
parser_lex.c: parser_lex.l parser_yacc.h parser.h profile.h mount.h dbus.h policy_cache.h file_cache.h
|
||||||
$(LEX) ${LEXFLAGS} -o$@ $<
|
$(LEX) ${LEXFLAGS} -o$@ $<
|
||||||
|
|
||||||
parser_lex.o: parser_lex.c $(HDRS)
|
parser_lex.o: parser_lex.c parser.h parser_yacc.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_misc.o: parser_misc.c $(HDRS) unit_test.h
|
parser_misc.o: parser_misc.c parser.h parser_yacc.h profile.h cap_names.h $(APPARMOR_H)
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_yacc.o: parser_yacc.c $(HDRS)
|
parser_yacc.o: parser_yacc.c parser_yacc.h $(APPARMOR_H)
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_main.o: parser_main.c $(HDRS)
|
parser_main.o: parser_main.c parser.h parser_version.h policy_cache.h file_cache.h libapparmor_re/apparmor_re.h $(APPARMOR_H)
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_interface.o: parser_interface.c $(HDRS)
|
parser_interface.o: parser_interface.c parser.h profile.h libapparmor_re/apparmor_re.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_include.o: parser_include.c $(HDRS)
|
parser_include.o: parser_include.c parser.h parser_include.h file_cache.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_merge.o: parser_merge.c $(HDRS)
|
parser_merge.o: parser_merge.c parser.h profile.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_regex.o: parser_regex.c $(HDRS) unit_test.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 $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_symtab.o: parser_symtab.c $(HDRS) unit_test.h
|
parser_symtab.o: parser_symtab.c parser.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_variable.o: parser_variable.c $(HDRS) unit_test.h
|
parser_variable.o: parser_variable.c parser.h profile.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_policy.o: parser_policy.c $(HDRS)
|
parser_policy.o: parser_policy.c parser.h parser_yacc.h profile.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_alias.o: parser_alias.c $(HDRS)
|
parser_alias.o: parser_alias.c parser.h profile.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_common.o: parser_common.c $(HDRS)
|
parser_common.o: parser_common.c parser.h file_cache.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
mount.o: mount.cc mount.h $(HDRS)
|
mount.o: mount.cc mount.h parser.h immunix.h rule.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
common_optarg.o: common_optarg.c $(HDRS)
|
common_optarg.o: common_optarg.c common_optarg.h parser.h libapparmor_re/apparmor_re.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
policy_cache.o: policy_cache.c $(HDRS)
|
policy_cache.o: policy_cache.c policy_cache.h parser.h lib.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
lib.o: lib.c $(HDRS) unit_test.h
|
lib.o: lib.c lib.h parser.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
dbus.o: dbus.cc $(HDRS)
|
dbus.o: dbus.cc dbus.h parser.h immunix.h parser_yacc.h rule.h $(APPARMOR_H)
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
signal.o: signal.cc $(HDRS)
|
signal.o: signal.cc signal.h parser.h immunix.h parser_yacc.h rule.h $(APPARMOR_H)
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
ptrace.o: ptrace.cc $(HDRS)
|
ptrace.o: ptrace.cc ptrace.h parser.h immunix.h parser_yacc.h rule.h $(APPARMOR_H)
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
network.o: network.cc $(HDRS)
|
network.o: network.c network.h parser.h immunix.h parser_yacc.h rule.h af_names.h $(APPARMOR_H)
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
default_features.o: default_features.c $(HDRS)
|
default_features.o: default_features.c parser.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
af_rule.o: af_rule.cc $(HDRS)
|
af_rule.o: af_rule.cc af_rule.h network.h parser.h profile.h immunix.h parser_yacc.h rule.h $(APPARMOR_H)
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
af_unix.o: af_unix.cc $(HDRS)
|
af_unix.o: af_unix.cc af_unix.h network.h af_rule.h parser.h profile.h immunix.h parser_yacc.h $(APPARMOR_H)
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
profile.o: profile.cc $(HDRS)
|
profile.o: profile.cc profile.h parser.h network.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
rule.o: rule.cc $(HDRS)
|
rule.o: rule.cc rule.h policydb.h
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
|
||||||
|
|
||||||
userns.o: userns.cc $(HDRS)
|
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
|
||||||
|
|
||||||
mqueue.o: mqueue.cc $(HDRS)
|
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
|
||||||
|
|
||||||
io_uring.o: io_uring.cc $(HDRS)
|
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
|
||||||
|
|
||||||
all_rule.o: all_rule.cc $(HDRS)
|
|
||||||
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
$(CXX) $(EXTRA_CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
parser_version.h: Makefile
|
parser_version.h: Makefile
|
||||||
@@ -340,7 +313,7 @@ generated_af_names.h: ../common/list_af_names.sh
|
|||||||
../common/list_af_names.sh > $@
|
../common/list_af_names.sh > $@
|
||||||
|
|
||||||
af_names.h: generated_af_names.h base_af_names.h
|
af_names.h: generated_af_names.h base_af_names.h
|
||||||
@cat base_af_names.h | diff -u - generated_af_names.h | grep -v '^.AF_MAX' | grep '^\+[^+]' ; \
|
cat base_af_names.h | diff -u - generated_af_names.h | grep -v '^.AF_MAX' | grep '^\+[^+]' ; \
|
||||||
if [ $$? -eq 1 ] ; then \
|
if [ $$? -eq 1 ] ; then \
|
||||||
cat base_af_names.h | LC_ALL=C sed -n -e 's/[ \t]\?AF_MAX[ \t]\+[0-9]\+,//g' -e 's/[ \t]\+\?AF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\),/#ifndef AF_\1\n# define AF_\1 \2\n#endif\nAA_GEN_NET_ENT("\L\1", \UAF_\1)\n/pg' > $@ ; \
|
cat base_af_names.h | LC_ALL=C sed -n -e 's/[ \t]\?AF_MAX[ \t]\+[0-9]\+,//g' -e 's/[ \t]\+\?AF_\([A-Z0-9_]\+\)[ \t]\+\([0-9]\+\),/#ifndef AF_\1\n# define AF_\1 \2\n#endif\nAA_GEN_NET_ENT("\L\1", \UAF_\1)\n/pg' > $@ ; \
|
||||||
cat base_af_names.h | LC_ALL=C sed -n -e 's/AF_MAX[ \t]\+\([0-9]\+\),\?.*/\n#define AA_AF_MAX \1\n/p' >> $@ ; \
|
cat base_af_names.h | LC_ALL=C sed -n -e 's/AF_MAX[ \t]\+\([0-9]\+\),\?.*/\n#define AA_AF_MAX \1\n/p' >> $@ ; \
|
||||||
@@ -379,8 +352,13 @@ tests: apparmor_parser ${TESTS}
|
|||||||
$(AAREOBJECT): FORCE
|
$(AAREOBJECT): FORCE
|
||||||
$(MAKE) -C $(AAREDIR) CFLAGS="$(EXTRA_CXXFLAGS)"
|
$(MAKE) -C $(AAREDIR) CFLAGS="$(EXTRA_CXXFLAGS)"
|
||||||
|
|
||||||
|
.PHONY: install-rhel4
|
||||||
|
install-rhel4: install-redhat
|
||||||
|
|
||||||
.PHONY: install-redhat
|
.PHONY: install-redhat
|
||||||
install-redhat: install-systemd
|
install-redhat:
|
||||||
|
install -m 755 -d $(DESTDIR)/etc/init.d
|
||||||
|
install -m 755 rc.apparmor.$(subst install-,,$@) $(DESTDIR)/etc/init.d/apparmor
|
||||||
|
|
||||||
.PHONY: install-suse
|
.PHONY: install-suse
|
||||||
install-suse: install-systemd
|
install-suse: install-systemd
|
||||||
@@ -411,9 +389,9 @@ DISTRO=$(shell if [ -f /etc/slackware-version ] ; then \
|
|||||||
if [ "$$(rpm --eval '0%{?suse_version}')" != "0" ] ; then \
|
if [ "$$(rpm --eval '0%{?suse_version}')" != "0" ] ; then \
|
||||||
echo suse ;\
|
echo suse ;\
|
||||||
elif [ "$$(rpm --eval '%{_host_vendor}')" = redhat ] ; then \
|
elif [ "$$(rpm --eval '%{_host_vendor}')" = redhat ] ; then \
|
||||||
echo redhat ;\
|
echo rhel4 ;\
|
||||||
elif [ "$$(rpm --eval '0%{?fedora}')" != "0" ] ; then \
|
elif [ "$$(rpm --eval '0%{?fedora}')" != "0" ] ; then \
|
||||||
echo redhat ;\
|
echo rhel4 ;\
|
||||||
else \
|
else \
|
||||||
echo unknown ;\
|
echo unknown ;\
|
||||||
fi ;\
|
fi ;\
|
||||||
@@ -465,8 +443,10 @@ clean: pod_clean
|
|||||||
rm -f $(TOOLS) $(TESTS)
|
rm -f $(TOOLS) $(TESTS)
|
||||||
rm -f $(LEX_C_FILES)
|
rm -f $(LEX_C_FILES)
|
||||||
rm -f $(YACC_C_FILES)
|
rm -f $(YACC_C_FILES)
|
||||||
|
rm -f parser_version.h
|
||||||
rm -f $(NAME)*.tar.gz $(NAME)*.tgz
|
rm -f $(NAME)*.tar.gz $(NAME)*.tgz
|
||||||
rm -f $(GENERATED_HDRS)
|
rm -f af_names.h generated_af_names.h
|
||||||
|
rm -f cap_names.h generated_cap_names.h
|
||||||
rm -rf techdoc.aux techdoc.out techdoc.log techdoc.pdf techdoc.toc techdoc.txt techdoc/
|
rm -rf techdoc.aux techdoc.out techdoc.log techdoc.pdf techdoc.toc techdoc.txt techdoc/
|
||||||
$(MAKE) -s -C $(AAREDIR) clean
|
$(MAKE) -s -C $(AAREDIR) clean
|
||||||
$(MAKE) -s -C po clean
|
$(MAKE) -s -C po clean
|
||||||
|
@@ -90,34 +90,43 @@ int af_rule::move_base_cond(struct cond_entry *ent, bool peer)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ostream &af_rule::dump_prefix(ostream &os)
|
||||||
|
{
|
||||||
|
if (audit)
|
||||||
|
os << "audit ";
|
||||||
|
if (deny)
|
||||||
|
os << "deny ";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
ostream &af_rule::dump_local(ostream &os)
|
ostream &af_rule::dump_local(ostream &os)
|
||||||
{
|
{
|
||||||
if (perms != AA_VALID_NET_PERMS) {
|
if (mode != AA_VALID_NET_PERMS) {
|
||||||
os << " (";
|
os << " (";
|
||||||
|
|
||||||
if (perms & AA_NET_SEND)
|
if (mode & AA_NET_SEND)
|
||||||
os << "send ";
|
os << "send ";
|
||||||
if (perms & AA_NET_RECEIVE)
|
if (mode & AA_NET_RECEIVE)
|
||||||
os << "receive ";
|
os << "receive ";
|
||||||
if (perms & AA_NET_CREATE)
|
if (mode & AA_NET_CREATE)
|
||||||
os << "create ";
|
os << "create ";
|
||||||
if (perms & AA_NET_SHUTDOWN)
|
if (mode & AA_NET_SHUTDOWN)
|
||||||
os << "shutdown ";
|
os << "shutdown ";
|
||||||
if (perms & AA_NET_CONNECT)
|
if (mode & AA_NET_CONNECT)
|
||||||
os << "connect ";
|
os << "connect ";
|
||||||
if (perms & AA_NET_SETATTR)
|
if (mode & AA_NET_SETATTR)
|
||||||
os << "setattr ";
|
os << "setattr ";
|
||||||
if (perms & AA_NET_GETATTR)
|
if (mode & AA_NET_GETATTR)
|
||||||
os << "getattr ";
|
os << "getattr ";
|
||||||
if (perms & AA_NET_BIND)
|
if (mode & AA_NET_BIND)
|
||||||
os << "bind ";
|
os << "bind ";
|
||||||
if (perms & AA_NET_ACCEPT)
|
if (mode & AA_NET_ACCEPT)
|
||||||
os << "accept ";
|
os << "accept ";
|
||||||
if (perms & AA_NET_LISTEN)
|
if (mode & AA_NET_LISTEN)
|
||||||
os << "listen ";
|
os << "listen ";
|
||||||
if (perms & AA_NET_SETOPT)
|
if (mode & AA_NET_SETOPT)
|
||||||
os << "setopt ";
|
os << "setopt ";
|
||||||
if (perms & AA_NET_GETOPT)
|
if (mode & AA_NET_GETOPT)
|
||||||
os << "getopt ";
|
os << "getopt ";
|
||||||
os << ")";
|
os << ")";
|
||||||
}
|
}
|
||||||
@@ -139,8 +148,8 @@ ostream &af_rule::dump_peer(ostream &os)
|
|||||||
|
|
||||||
ostream &af_rule::dump(ostream &os)
|
ostream &af_rule::dump(ostream &os)
|
||||||
{
|
{
|
||||||
prefix_rule_t::dump(os);
|
dump_prefix(os);
|
||||||
os << af_name();
|
os << af_name;
|
||||||
dump_local(os);
|
dump_local(os);
|
||||||
if (has_peer_conds()) {
|
if (has_peer_conds()) {
|
||||||
os << " peer=(";
|
os << " peer=(";
|
||||||
|
@@ -25,8 +25,6 @@
|
|||||||
|
|
||||||
#include "rule.h"
|
#include "rule.h"
|
||||||
|
|
||||||
#define AF_ANY -1
|
|
||||||
|
|
||||||
enum cond_side { local_cond, peer_cond, either_cond };
|
enum cond_side { local_cond, peer_cond, either_cond };
|
||||||
|
|
||||||
struct supported_cond {
|
struct supported_cond {
|
||||||
@@ -37,21 +35,23 @@ struct supported_cond {
|
|||||||
enum cond_side side ;
|
enum cond_side side ;
|
||||||
};
|
};
|
||||||
|
|
||||||
class af_rule: public perms_rule_t {
|
class af_rule: public rule_t {
|
||||||
public:
|
public:
|
||||||
int af;
|
std::string af_name;
|
||||||
char *sock_type;
|
char *sock_type;
|
||||||
int sock_type_n;
|
int sock_type_n;
|
||||||
char *proto;
|
char *proto;
|
||||||
int proto_n;
|
int proto_n;
|
||||||
char *label;
|
char *label;
|
||||||
char *peer_label;
|
char *peer_label;
|
||||||
|
int mode;
|
||||||
|
int audit;
|
||||||
|
bool deny;
|
||||||
|
|
||||||
af_rule(int f):
|
af_rule(const char *name): af_name(name), sock_type(NULL),
|
||||||
perms_rule_t(AA_CLASS_NET),
|
|
||||||
af(f), sock_type(NULL),
|
|
||||||
sock_type_n(-1), proto(NULL), proto_n(0), label(NULL),
|
sock_type_n(-1), proto(NULL), proto_n(0), label(NULL),
|
||||||
peer_label(NULL) { }
|
peer_label(NULL), mode(0), audit(0), deny(0)
|
||||||
|
{}
|
||||||
|
|
||||||
virtual ~af_rule()
|
virtual ~af_rule()
|
||||||
{
|
{
|
||||||
@@ -61,50 +61,18 @@ public:
|
|||||||
free(peer_label);
|
free(peer_label);
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *af_name(void) {
|
|
||||||
if (af != AF_ANY)
|
|
||||||
return net_find_af_name(af);
|
|
||||||
return "*";
|
|
||||||
}
|
|
||||||
bool cond_check(struct supported_cond *cond, struct cond_entry *ent,
|
bool cond_check(struct supported_cond *cond, struct cond_entry *ent,
|
||||||
bool peer, const char *rname);
|
bool peer, const char *rname);
|
||||||
int move_base_cond(struct cond_entry *conds, bool peer);
|
int move_base_cond(struct cond_entry *conds, bool peer);
|
||||||
|
|
||||||
virtual bool has_peer_conds(void) { return peer_label ? true : false; }
|
virtual bool has_peer_conds(void) { return peer_label ? true : false; }
|
||||||
|
virtual ostream &dump_prefix(ostream &os);
|
||||||
virtual ostream &dump_local(ostream &os);
|
virtual ostream &dump_local(ostream &os);
|
||||||
virtual ostream &dump_peer(ostream &os);
|
virtual ostream &dump_peer(ostream &os);
|
||||||
virtual ostream &dump(ostream &os);
|
virtual ostream &dump(ostream &os);
|
||||||
virtual int expand_variables(void);
|
virtual int expand_variables(void);
|
||||||
virtual int gen_policy_re(Profile &prof) = 0;
|
virtual int gen_policy_re(Profile &prof) = 0;
|
||||||
|
virtual void post_process(Profile &prof unused) { };
|
||||||
virtual bool is_mergeable(void) { return true; }
|
|
||||||
virtual int cmp(rule_t const &rhs) const
|
|
||||||
{
|
|
||||||
int res = perms_rule_t::cmp(rhs);
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
af_rule const &trhs = (rule_cast<af_rule const &>(rhs));
|
|
||||||
res = af - trhs.af;
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
res = sock_type_n - trhs.sock_type_n;
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
res = proto_n - trhs.proto_n;
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
res = null_strcmp(sock_type, trhs.sock_type);
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
res = null_strcmp(proto, trhs.proto);
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
res = null_strcmp(label, trhs.label);
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
return null_strcmp(peer_label, trhs.peer_label);
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __AA_AF_RULE_H */
|
#endif /* __AA_AF_RULE_H */
|
||||||
|
@@ -24,7 +24,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "common_optarg.h"
|
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "profile.h"
|
#include "profile.h"
|
||||||
@@ -33,9 +32,9 @@
|
|||||||
/* See unix(7) for autobind address definition */
|
/* See unix(7) for autobind address definition */
|
||||||
#define autobind_address_pattern "\\x00[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]";
|
#define autobind_address_pattern "\\x00[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]";
|
||||||
|
|
||||||
int parse_unix_perms(const char *str_perms, perms_t *perms, int fail)
|
int parse_unix_mode(const char *str_mode, int *mode, int fail)
|
||||||
{
|
{
|
||||||
return parse_X_perms("unix", AA_VALID_NET_PERMS, str_perms, perms, fail);
|
return parse_X_mode("unix", AA_VALID_NET_PERMS, str_mode, mode, fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -96,8 +95,8 @@ void unix_rule::move_peer_conditionals(struct cond_entry *conds)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unix_rule::unix_rule(unsigned int type_p, audit_t audit_p, rule_mode_t rule_mode_p):
|
unix_rule::unix_rule(unsigned int type_p, bool audit_p, bool denied):
|
||||||
af_rule(AF_UNIX), addr(NULL), peer_addr(NULL)
|
af_rule("unix"), addr(NULL), peer_addr(NULL)
|
||||||
{
|
{
|
||||||
if (type_p != 0xffffffff) {
|
if (type_p != 0xffffffff) {
|
||||||
sock_type_n = type_p;
|
sock_type_n = type_p;
|
||||||
@@ -105,29 +104,27 @@ unix_rule::unix_rule(unsigned int type_p, audit_t audit_p, rule_mode_t rule_mode
|
|||||||
if (!sock_type)
|
if (!sock_type)
|
||||||
yyerror("socket rule: invalid socket type '%d'", type_p);
|
yyerror("socket rule: invalid socket type '%d'", type_p);
|
||||||
}
|
}
|
||||||
perms = AA_VALID_NET_PERMS;
|
mode = AA_VALID_NET_PERMS;
|
||||||
audit = audit_p;
|
audit = audit_p ? AA_VALID_NET_PERMS : 0;
|
||||||
rule_mode = rule_mode_p;
|
deny = denied;
|
||||||
/* if this constructor is used, then there's already a
|
|
||||||
* downgraded network_rule in profile */
|
|
||||||
downgrade = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unix_rule::unix_rule(perms_t perms_p, struct cond_entry *conds,
|
unix_rule::unix_rule(int mode_p, struct cond_entry *conds,
|
||||||
struct cond_entry *peer_conds):
|
struct cond_entry *peer_conds):
|
||||||
af_rule(AF_UNIX), addr(NULL), peer_addr(NULL)
|
af_rule("unix"), addr(NULL), peer_addr(NULL),
|
||||||
|
audit(0), deny(0)
|
||||||
{
|
{
|
||||||
move_conditionals(conds);
|
move_conditionals(conds);
|
||||||
move_peer_conditionals(peer_conds);
|
move_peer_conditionals(peer_conds);
|
||||||
|
|
||||||
if (perms_p) {
|
if (mode_p) {
|
||||||
perms = perms_p;
|
mode = mode_p;
|
||||||
if (perms & ~AA_VALID_NET_PERMS)
|
if (mode & ~AA_VALID_NET_PERMS)
|
||||||
yyerror("perms contains invalid permissions for unix socket rules\n");
|
yyerror("mode contains invalid permissions for unix socket rules\n");
|
||||||
else if ((perms & ~AA_PEER_NET_PERMS) && has_peer_conds())
|
else if ((mode & ~AA_PEER_NET_PERMS) && has_peer_conds())
|
||||||
yyerror("unix socket 'create', 'shutdown', 'setattr', 'getattr', 'bind', 'listen', 'setopt', and/or 'getopt' accesses cannot be used with peer socket conditionals\n");
|
yyerror("unix socket 'create', 'shutdown', 'setattr', 'getattr', 'bind', 'listen', 'setopt', and/or 'getopt' accesses cannot be used with peer socket conditionals\n");
|
||||||
} else {
|
} else {
|
||||||
perms = AA_VALID_NET_PERMS;
|
mode = AA_VALID_NET_PERMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_cond_list(conds);
|
free_cond_list(conds);
|
||||||
@@ -139,7 +136,7 @@ ostream &unix_rule::dump_local(ostream &os)
|
|||||||
{
|
{
|
||||||
af_rule::dump_local(os);
|
af_rule::dump_local(os);
|
||||||
if (addr)
|
if (addr)
|
||||||
os << " addr='" << addr << "'";
|
os << "addr='" << addr << "'";
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +144,7 @@ ostream &unix_rule::dump_peer(ostream &os)
|
|||||||
{
|
{
|
||||||
af_rule::dump_peer(os);
|
af_rule::dump_peer(os);
|
||||||
if (peer_addr)
|
if (peer_addr)
|
||||||
os << " addr='" << peer_addr << "'";
|
os << "addr='" << peer_addr << "'";
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,28 +188,23 @@ static void writeu16(std::ostringstream &o, int v)
|
|||||||
#define CMD_OPT 4
|
#define CMD_OPT 4
|
||||||
|
|
||||||
void unix_rule::downgrade_rule(Profile &prof) {
|
void unix_rule::downgrade_rule(Profile &prof) {
|
||||||
perms_t mask = (perms_t) -1;
|
unsigned int mask = (unsigned int) -1;
|
||||||
|
|
||||||
if (!prof.net.allow && !prof.net.alloc_net_table())
|
if (!prof.net.allow && !prof.alloc_net_table())
|
||||||
yyerror(_("Memory allocation error."));
|
yyerror(_("Memory allocation error."));
|
||||||
if (sock_type_n != -1)
|
if (sock_type_n != -1)
|
||||||
mask = 1 << sock_type_n;
|
mask = 1 << sock_type_n;
|
||||||
if (rule_mode != RULE_DENY) {
|
if (!deny) {
|
||||||
prof.net.allow[AF_UNIX] |= mask;
|
prof.net.allow[AF_UNIX] |= mask;
|
||||||
if (audit == AUDIT_FORCE)
|
if (audit)
|
||||||
prof.net.audit[AF_UNIX] |= mask;
|
prof.net.audit[AF_UNIX] |= mask;
|
||||||
const char *error;
|
|
||||||
network_rule *netv8 = new network_rule(perms, AF_UNIX, sock_type_n);
|
|
||||||
if(!netv8->add_prefix({audit, rule_mode, owner}, error))
|
|
||||||
yyerror(error);
|
|
||||||
prof.rule_ents.push_back(netv8);
|
|
||||||
} else {
|
} else {
|
||||||
/* deny rules have to be dropped because the downgrade makes
|
/* deny rules have to be dropped because the downgrade makes
|
||||||
* the rule less specific meaning it will make the profile more
|
* the rule less specific meaning it will make the profile more
|
||||||
* restrictive and may end up denying accesses that might be
|
* restrictive and may end up denying accesses that might be
|
||||||
* allowed by the profile.
|
* allowed by the profile.
|
||||||
*/
|
*/
|
||||||
if (parseopts.warn & WARN_RULE_NOT_ENFORCED)
|
if (warnflags & WARN_RULE_NOT_ENFORCED)
|
||||||
rule_t::warn_once(prof.name, "deny unix socket rule not enforced, can't be downgraded to generic network rule\n");
|
rule_t::warn_once(prof.name, "deny unix socket rule not enforced, can't be downgraded to generic network rule\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -318,20 +310,19 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||||||
std::ostringstream buffer;
|
std::ostringstream buffer;
|
||||||
std::string buf;
|
std::string buf;
|
||||||
|
|
||||||
perms_t mask = perms;
|
int mask = mode;
|
||||||
|
|
||||||
/* always generate a downgraded rule. This doesn't change generated
|
/* always generate a downgraded rule. This doesn't change generated
|
||||||
* policy size and allows the binary policy to be loaded against
|
* policy size and allows the binary policy to be loaded against
|
||||||
* older kernels and be enforced to the best of the old network
|
* older kernels and be enforced to the best of the old network
|
||||||
* rules ability
|
* rules ability
|
||||||
*/
|
*/
|
||||||
if (downgrade)
|
downgrade_rule(prof);
|
||||||
downgrade_rule(prof);
|
|
||||||
if (!features_supports_unix) {
|
if (!features_supports_unix) {
|
||||||
if (features_supports_network || features_supports_networkv8) {
|
if (features_supports_network || features_supports_networkv8) {
|
||||||
/* only warn if we are building against a kernel
|
/* only warn if we are building against a kernel
|
||||||
* that requires downgrading */
|
* that requires downgrading */
|
||||||
if (parseopts.warn & WARN_RULE_DOWNGRADED)
|
if (warnflags & WARN_RULE_DOWNGRADED)
|
||||||
rule_t::warn_once(prof.name, "downgrading extended network unix socket rule to generic network rule\n");
|
rule_t::warn_once(prof.name, "downgrading extended network unix socket rule to generic network rule\n");
|
||||||
/* TODO: add ability to abort instead of downgrade */
|
/* TODO: add ability to abort instead of downgrade */
|
||||||
return RULE_OK;
|
return RULE_OK;
|
||||||
@@ -344,10 +335,10 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||||||
write_to_prot(buffer);
|
write_to_prot(buffer);
|
||||||
if ((mask & AA_NET_CREATE) && !has_peer_conds()) {
|
if ((mask & AA_NET_CREATE) && !has_peer_conds()) {
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
|
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
||||||
map_perms(AA_NET_CREATE),
|
map_perms(AA_NET_CREATE),
|
||||||
map_perms(audit == AUDIT_FORCE ? AA_NET_CREATE : 0),
|
map_perms(audit & AA_NET_CREATE),
|
||||||
parseopts))
|
dfaflags))
|
||||||
goto fail;
|
goto fail;
|
||||||
mask &= ~AA_NET_CREATE;
|
mask &= ~AA_NET_CREATE;
|
||||||
}
|
}
|
||||||
@@ -369,10 +360,10 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||||||
tmp << "\\x00";
|
tmp << "\\x00";
|
||||||
|
|
||||||
buf = tmp.str();
|
buf = tmp.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
|
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
||||||
map_perms(AA_NET_BIND),
|
map_perms(AA_NET_BIND),
|
||||||
map_perms(audit == AUDIT_FORCE ? AA_NET_BIND : 0),
|
map_perms(audit & AA_NET_BIND),
|
||||||
parseopts))
|
dfaflags))
|
||||||
goto fail;
|
goto fail;
|
||||||
/* clear if auto, else generic need to generate addr below */
|
/* clear if auto, else generic need to generate addr below */
|
||||||
if (addr)
|
if (addr)
|
||||||
@@ -394,10 +385,10 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||||||
AA_LOCAL_NET_PERMS & ~AA_LOCAL_NET_CMD;
|
AA_LOCAL_NET_PERMS & ~AA_LOCAL_NET_CMD;
|
||||||
if (mask & local_mask) {
|
if (mask & local_mask) {
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
|
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
||||||
map_perms(mask & local_mask),
|
map_perms(mask & local_mask),
|
||||||
map_perms(audit == AUDIT_FORCE ? mask & local_mask : 0),
|
map_perms(audit & local_mask),
|
||||||
parseopts))
|
dfaflags))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -408,10 +399,10 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||||||
/* TODO: backlog conditional: for now match anything*/
|
/* TODO: backlog conditional: for now match anything*/
|
||||||
tmp << "..";
|
tmp << "..";
|
||||||
buf = tmp.str();
|
buf = tmp.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
|
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
||||||
map_perms(AA_NET_LISTEN),
|
map_perms(AA_NET_LISTEN),
|
||||||
map_perms(audit == AUDIT_FORCE ? AA_NET_LISTEN : 0),
|
map_perms(audit & AA_NET_LISTEN),
|
||||||
parseopts))
|
dfaflags))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ((mask & AA_NET_OPT) && !has_peer_conds()) {
|
if ((mask & AA_NET_OPT) && !has_peer_conds()) {
|
||||||
@@ -421,10 +412,10 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||||||
/* TODO: sockopt conditional: for now match anything */
|
/* TODO: sockopt conditional: for now match anything */
|
||||||
tmp << "..";
|
tmp << "..";
|
||||||
buf = tmp.str();
|
buf = tmp.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY,
|
if (!prof.policy.rules->add_rule(buf.c_str(), deny,
|
||||||
map_perms(mask & AA_NET_OPT),
|
map_perms(mask & AA_NET_OPT),
|
||||||
map_perms(audit == AUDIT_FORCE ? AA_NET_OPT : 0),
|
map_perms(audit & AA_NET_OPT),
|
||||||
parseopts))
|
dfaflags))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
mask &= ~AA_LOCAL_NET_PERMS | AA_NET_ACCEPT;
|
mask &= ~AA_LOCAL_NET_PERMS | AA_NET_ACCEPT;
|
||||||
@@ -442,7 +433,7 @@ int unix_rule::gen_policy_re(Profile &prof)
|
|||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms & AA_PEER_NET_PERMS), map_perms(audit == AUDIT_FORCE ? perms & AA_PEER_NET_PERMS : 0), parseopts))
|
if (!prof.policy.rules->add_rule(buf.c_str(), deny, map_perms(mode & AA_PEER_NET_PERMS), map_perms(audit), dfaflags))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -24,7 +24,7 @@
|
|||||||
#include "profile.h"
|
#include "profile.h"
|
||||||
#include "af_rule.h"
|
#include "af_rule.h"
|
||||||
|
|
||||||
int parse_unix_perms(const char *str_mode, perms_t *perms, int fail);
|
int parse_unix_mode(const char *str_mode, int *mode, int fail);
|
||||||
|
|
||||||
class unix_rule: public af_rule {
|
class unix_rule: public af_rule {
|
||||||
void write_to_prot(std::ostringstream &buffer);
|
void write_to_prot(std::ostringstream &buffer);
|
||||||
@@ -36,10 +36,12 @@ class unix_rule: public af_rule {
|
|||||||
public:
|
public:
|
||||||
char *addr;
|
char *addr;
|
||||||
char *peer_addr;
|
char *peer_addr;
|
||||||
bool downgrade = true;
|
int mode;
|
||||||
|
int audit;
|
||||||
|
bool deny;
|
||||||
|
|
||||||
unix_rule(unsigned int type_p, audit_t audit_p, rule_mode_t rule_mode_p);
|
unix_rule(unsigned int type_p, bool audit_p, bool denied);
|
||||||
unix_rule(perms_t perms, struct cond_entry *conds,
|
unix_rule(int mode, struct cond_entry *conds,
|
||||||
struct cond_entry *peer_conds);
|
struct cond_entry *peer_conds);
|
||||||
virtual ~unix_rule()
|
virtual ~unix_rule()
|
||||||
{
|
{
|
||||||
@@ -47,13 +49,6 @@ public:
|
|||||||
free(peer_addr);
|
free(peer_addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
|
||||||
if (p.owner) {
|
|
||||||
error = "owner prefix not allowed on unix rules";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
virtual bool has_peer_conds(void) {
|
virtual bool has_peer_conds(void) {
|
||||||
return af_rule::has_peer_conds() || peer_addr;
|
return af_rule::has_peer_conds() || peer_addr;
|
||||||
}
|
}
|
||||||
@@ -62,19 +57,7 @@ public:
|
|||||||
virtual ostream &dump_peer(ostream &os);
|
virtual ostream &dump_peer(ostream &os);
|
||||||
virtual int expand_variables(void);
|
virtual int expand_variables(void);
|
||||||
virtual int gen_policy_re(Profile &prof);
|
virtual int gen_policy_re(Profile &prof);
|
||||||
|
virtual void post_process(Profile &prof unused) { };
|
||||||
// inherit is_mergable() from af_rule
|
|
||||||
virtual int cmp(rule_t const &rhs) const
|
|
||||||
{
|
|
||||||
int res = af_rule::cmp(rhs);
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
unix_rule const &trhs = (rule_cast<unix_rule const &>(rhs));
|
|
||||||
res = null_strcmp(addr, trhs.addr);
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
return null_strcmp(peer_addr, trhs.peer_addr);
|
|
||||||
};
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void warn_once(const char *name) override;
|
virtual void warn_once(const char *name) override;
|
||||||
|
@@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023
|
|
||||||
* 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 Canonical Ltd.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "profile.h"
|
|
||||||
#include "all_rule.h"
|
|
||||||
#include "af_unix.h"
|
|
||||||
#include "dbus.h"
|
|
||||||
#include "io_uring.h"
|
|
||||||
#include "mqueue.h"
|
|
||||||
#include "ptrace.h"
|
|
||||||
#include "signal.h"
|
|
||||||
#include "userns.h"
|
|
||||||
#include "mount.h"
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
#include <iomanip>
|
|
||||||
#include <string>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void all_rule::add_implied_rules(Profile &prof)
|
|
||||||
{
|
|
||||||
prefix_rule_t *rule;
|
|
||||||
const prefixes *prefix = this;
|
|
||||||
|
|
||||||
rule = new unix_rule(0, audit, rule_mode);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new dbus_rule(0, NULL, NULL);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new io_uring_rule(0, NULL, NULL);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new mqueue_rule(0, NULL);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new ptrace_rule(0, NULL);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new signal_rule(0, NULL);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new userns_rule(0, NULL);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new mnt_rule(NULL, NULL, NULL, NULL, 0);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new mnt_rule(NULL, NULL, NULL, NULL, AA_DUMMY_REMOUNT);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new mnt_rule(NULL, NULL, NULL, NULL, AA_MAY_UMOUNT);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new mnt_rule(NULL, NULL, NULL, NULL, AA_MAY_PIVOTROOT);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
rule = new network_rule(0, (struct cond_entry *)NULL, (struct cond_entry *)NULL);
|
|
||||||
(void) rule->add_prefix(*prefix);
|
|
||||||
prof.rule_ents.push_back(rule);
|
|
||||||
|
|
||||||
/* rules that have not been converted to use rule.h */
|
|
||||||
|
|
||||||
//file
|
|
||||||
{
|
|
||||||
const char *error;
|
|
||||||
struct cod_entry *entry;
|
|
||||||
char *path = strdup("/{**,}");
|
|
||||||
int perms = ((AA_BASE_PERMS & ~AA_EXEC_TYPE) |
|
|
||||||
(AA_MAY_EXEC));
|
|
||||||
if (rule_mode != RULE_DENY)
|
|
||||||
perms |= AA_EXEC_INHERIT;
|
|
||||||
/* duplicate to other permission set */
|
|
||||||
perms |= perms << AA_OTHER_SHIFT;
|
|
||||||
if (!path)
|
|
||||||
yyerror(_("Memory allocation error."));
|
|
||||||
entry = new_entry(path, perms, NULL);
|
|
||||||
if (!entry_add_prefix(entry, *prefix, error)) {
|
|
||||||
yyerror(_("%s"), error);
|
|
||||||
}
|
|
||||||
add_entry_to_policy(&prof, entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// caps
|
|
||||||
{
|
|
||||||
if (prefix->owner)
|
|
||||||
yyerror(_("owner prefix not allowed on capability rules"));
|
|
||||||
|
|
||||||
if (rule_mode == RULE_DENY && audit == AUDIT_FORCE) {
|
|
||||||
prof.caps.deny |= 0xffffffffffffffff;
|
|
||||||
} else if (rule_mode == RULE_DENY) {
|
|
||||||
prof.caps.deny |= 0xffffffffffffffff;
|
|
||||||
prof.caps.quiet |= 0xffffffffffffffff;
|
|
||||||
} else {
|
|
||||||
prof.caps.allow |= 0xffffffffffffffff;
|
|
||||||
if (audit != AUDIT_UNSPECIFIED)
|
|
||||||
prof.caps.audit |= 0xffffffffffffffff;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: rlimit
|
|
||||||
}
|
|
@@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2023
|
|
||||||
* 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 Canonical Ltd.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __AA_ALL_H
|
|
||||||
#define __AA_ALL_H
|
|
||||||
|
|
||||||
#include "rule.h"
|
|
||||||
|
|
||||||
#define AA_IO_URING_OVERRIDE_CREDS AA_MAY_APPEND
|
|
||||||
#define AA_IO_URING_SQPOLL AA_MAY_CREATE
|
|
||||||
|
|
||||||
#define AA_VALID_IO_URING_PERMS (AA_IO_URING_OVERRIDE_CREDS | \
|
|
||||||
AA_IO_URING_SQPOLL)
|
|
||||||
|
|
||||||
class all_rule: public prefix_rule_t {
|
|
||||||
void move_conditionals(struct cond_entry *conds);
|
|
||||||
public:
|
|
||||||
char *label;
|
|
||||||
|
|
||||||
all_rule(void): prefix_rule_t(RULE_TYPE_ALL) { }
|
|
||||||
|
|
||||||
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
|
||||||
if (p.owner) {
|
|
||||||
error = _("owner prefix not allowed on all rules");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
int expand_variables(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
virtual ostream &dump(ostream &os) {
|
|
||||||
prefix_rule_t::dump(os);
|
|
||||||
|
|
||||||
os << "all";
|
|
||||||
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
virtual bool is_mergeable(void) { return true; }
|
|
||||||
virtual int cmp(rule_t const &rhs) const
|
|
||||||
{
|
|
||||||
return prefix_rule_t::cmp(rhs);
|
|
||||||
};
|
|
||||||
|
|
||||||
virtual void add_implied_rules(Profile &prof);
|
|
||||||
|
|
||||||
virtual int gen_policy_re(Profile &prof unused) { return RULE_OK; };
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void warn_once(const char *name unused, const char *msg unused) { };
|
|
||||||
virtual void warn_once(const char *name unused) { };
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* __AA_ALL_H */
|
|
@@ -113,11 +113,9 @@ B<XATTR VALUE FILEGLOB> = I<FILEGLOB>
|
|||||||
|
|
||||||
B<PROFILE FLAG CONDS> = [ 'flags=' ] '(' comma or white space separated list of I<PROFILE FLAGS> ')'
|
B<PROFILE FLAG CONDS> = [ 'flags=' ] '(' comma or white space separated list of I<PROFILE FLAGS> ')'
|
||||||
|
|
||||||
B<PROFILE FLAGS> = I<PROFILE MODE> | I<AUDIT_MODE> | 'mediate_deleted'
|
B<PROFILE FLAGS> = I<PROFILE MODE> | I<AUDIT_MODE> | 'mediate_deleted' | 'attach_disconnected' | 'chroot_relative'
|
||||||
| 'attach_disconnected' | 'attach_disconneced.path='I<ABS PATH> | 'chroot_relative'
|
|
||||||
| 'debug' | 'interruptible' | 'kill.signal='I<SIGNAL>
|
|
||||||
|
|
||||||
B<PROFILE MODE> = 'enforce' | 'complain' | 'kill' | 'default_allow' | 'unconfined' | 'prompt'
|
B<PROFILE MODE> = 'enforce' | 'complain' | 'kill' | 'unconfined'
|
||||||
|
|
||||||
B<AUDIT MODE> = 'audit'
|
B<AUDIT MODE> = 'audit'
|
||||||
|
|
||||||
@@ -125,7 +123,7 @@ B<RULES> = [ ( I<LINE RULES> | I<COMMA RULES> ',' | I<BLOCK RULES> )
|
|||||||
|
|
||||||
B<LINE RULES> = ( I<COMMENT> | I<INCLUDE> ) [ '\r' ] '\n'
|
B<LINE RULES> = ( I<COMMENT> | I<INCLUDE> ) [ '\r' ] '\n'
|
||||||
|
|
||||||
B<COMMA RULES> = ( I<CAPABILITY RULE> | I<NETWORK RULE> | I<MOUNT RULE> | I<PIVOT ROOT RULE> | I<UNIX RULE> | I<FILE RULE> | I<LINK RULE> | I<CHANGE_PROFILE RULE> | I<RLIMIT RULE> | I<DBUS RULE> | I<MQUEUE RULE> | I<IO_URING RULE> | I<USERNS RULE> | I<ALL RULE>)
|
B<COMMA RULES> = ( I<CAPABILITY RULE> | I<NETWORK RULE> | I<MOUNT RULE> | I<PIVOT ROOT RULE> | I<UNIX RULE> | I<FILE RULE> | I<LINK RULE> | I<CHANGE_PROFILE RULE> | I<RLIMIT RULE> | I<DBUS RULE> )
|
||||||
|
|
||||||
B<BLOCK RULES> = ( I<SUBPROFILE> | I<HAT> | I<QUALIFIER BLOCK> )
|
B<BLOCK RULES> = ( I<SUBPROFILE> | I<HAT> | I<QUALIFIER BLOCK> )
|
||||||
|
|
||||||
@@ -174,34 +172,10 @@ B<MOUNT FLAGS EXPRESSION> = ( I<MOUNT FLAGS LIST> | I<MOUNT EXPRESSION> )
|
|||||||
|
|
||||||
B<MOUNT FLAGS LIST> = Comma separated list of I<MOUNT FLAGS>.
|
B<MOUNT FLAGS LIST> = Comma separated list of I<MOUNT FLAGS>.
|
||||||
|
|
||||||
B<MOUNT FLAGS> = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | 'noexec' | 'exec' | 'sync' | 'async' | 'remount' | 'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' | 'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' | 'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' | 'unbindable' | 'runbindable' | 'private' | 'rprivate' | 'slave' | 'rslave' | 'shared' | 'rshared' | 'relatime' | 'norelatime' | 'iversion' | 'noiversion' | 'strictatime' | 'nostrictatime' | 'lazytime' | 'nolazytime' | 'nouser' | 'user' | 'symfollow' | 'nosymfollow' )
|
B<MOUNT FLAGS> = ( 'ro' | 'rw' | 'nosuid' | 'suid' | 'nodev' | 'dev' | 'noexec' | 'exec' | 'sync' | 'async' | 'remount' | 'mand' | 'nomand' | 'dirsync' | 'noatime' | 'atime' | 'nodiratime' | 'diratime' | 'bind' | 'rbind' | 'move' | 'verbose' | 'silent' | 'loud' | 'acl' | 'noacl' | 'unbindable' | 'runbindable' | 'private' | 'rprivate' | 'slave' | 'rslave' | 'shared' | 'rshared' | 'relatime' | 'norelatime' | 'iversion' | 'noiversion' | 'strictatime' | 'nouser' | 'user' )
|
||||||
|
|
||||||
B<MOUNT EXPRESSION> = ( I<ALPHANUMERIC> | I<AARE> ) ...
|
B<MOUNT EXPRESSION> = ( I<ALPHANUMERIC> | I<AARE> ) ...
|
||||||
|
|
||||||
B<MQUEUE_RULE> = [ I<QUALIFIERS> ] 'mqueue' [ I<MQUEUE ACCESS PERMISSIONS> ] [ I<MQUEUE TYPE> ] [ I<MQUEUE LABEL> ] [ I<MQUEUE NAME> ]
|
|
||||||
|
|
||||||
B<MQUEUE ACCESS PERMISSIONS> = I<MQUEUE ACCESS> | I<MQUEUE ACCESS LIST>
|
|
||||||
|
|
||||||
B<MQUEUE ACCESS LIST> = '(' Comma or space separated list of I<MQUEUE ACCESS> ')'
|
|
||||||
|
|
||||||
B<MQUEUE ACCESS> = ( 'r' | 'w' | 'rw' | 'read' | 'write' | 'create' | 'open' | 'delete' | 'getattr' | 'setattr' )
|
|
||||||
|
|
||||||
B<MQUEUE TYPE> = 'type' '=' ( 'posix' | 'sysv' )
|
|
||||||
|
|
||||||
B<MQUEUE LABEL> = 'label' '=' '(' '"' I<AARE> '"' | I<AARE> ')'
|
|
||||||
|
|
||||||
B<MQUEUE NAME> = I<AARE>
|
|
||||||
|
|
||||||
B<USERNS RULE> = [ I<QUALIFIERS> ] 'userns' [ I<USERNS ACCESS PERMISSIONS> ]
|
|
||||||
|
|
||||||
B<USERNS ACCESS PERMISSIONS> = ( 'create' )
|
|
||||||
|
|
||||||
B<IO_URING RULE> = [ I<QUALIFIERS> ] 'io_uring' [ I<IO_URING ACCESS PERMISSIONS> [ I<IO_URING LABEL> ]
|
|
||||||
|
|
||||||
B<IO_URING ACCESS PERMISSIONS> = ( 'sqpoll' | 'override_creds' )
|
|
||||||
|
|
||||||
B<IO_URING LABEL> = 'label' '=' '(' '"' I<AARE> '"' | I<AARE> ')'
|
|
||||||
|
|
||||||
B<PIVOT ROOT RULE> = [ I<QUALIFIERS> ] pivot_root [ oldroot=I<OLD PUT FILEGLOB> ] [ I<NEW ROOT FILEGLOB> ] [ '-E<gt>' I<PROFILE NAME> ]
|
B<PIVOT ROOT RULE> = [ I<QUALIFIERS> ] pivot_root [ oldroot=I<OLD PUT FILEGLOB> ] [ I<NEW ROOT FILEGLOB> ] [ '-E<gt>' I<PROFILE NAME> ]
|
||||||
|
|
||||||
B<SOURCE FILEGLOB> = I<FILEGLOB>
|
B<SOURCE FILEGLOB> = I<FILEGLOB>
|
||||||
@@ -230,9 +204,9 @@ B<SIGNAL ACCESS> = ( 'r' | 'w' | 'rw' | 'read' | 'write' | 'send' | 'receive' )
|
|||||||
|
|
||||||
B<SIGNAL SET> = 'set' '=' '(' I<SIGNAL LIST> ')'
|
B<SIGNAL SET> = 'set' '=' '(' I<SIGNAL LIST> ')'
|
||||||
|
|
||||||
B<SIGNAL LIST> = Comma or space separated list of I<SIGNAL>s
|
B<SIGNAL LIST> = Comma or space separated list of I<SIGNALS>
|
||||||
|
|
||||||
B<SIGNAL> = ( '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<SIGNALS> = ( 'hup' | 'int' | 'quit' | 'ill' | 'trap' | 'abrt' | 'bus' | 'fpe' | 'kill' | 'usr1' | 'segv' | 'usr2' | 'pipe' | 'alrm' | 'term' | 'stkflt' | 'chld' | 'cont' | 'stop' | 'stp' | 'ttin' | 'ttou' | 'urg' | 'xcpu' | 'xfsz' | 'vtalrm' | 'prof' | 'winch' | 'io' | 'pwr' | 'sys' | 'emt' | 'exists' | 'rtmin+0' ... 'rtmin+32' )
|
||||||
|
|
||||||
B<SIGNAL PEER> = 'peer' '=' I<AARE>
|
B<SIGNAL PEER> = 'peer' '=' I<AARE>
|
||||||
|
|
||||||
@@ -346,8 +320,6 @@ B<EXEC_MODE> = ( 'safe' | 'unsafe' )
|
|||||||
|
|
||||||
B<EXEC COND> = I<FILEGLOB>
|
B<EXEC COND> = I<FILEGLOB>
|
||||||
|
|
||||||
B<ALL RULE> = 'all'
|
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
All resources and programs need a full path. There may be any number of
|
All resources and programs need a full path. There may be any number of
|
||||||
@@ -466,41 +438,12 @@ a signal to kill it.
|
|||||||
permission the action will be allowed, but the violation will be logged
|
permission the action will be allowed, but the violation will be logged
|
||||||
with a tag of the access being B<ALLOWED>.
|
with a tag of the access being B<ALLOWED>.
|
||||||
|
|
||||||
=item B<default_allow> This mode changes the default behavior of
|
|
||||||
apparmor from default deny to default allow. When default_allow is
|
|
||||||
specified the resulting profile will allow operations that the profile
|
|
||||||
does not have a rule for. This mode is similar to I<unconfined> but
|
|
||||||
allows for allow and deny rules, specifying audit, and domain
|
|
||||||
transitions. Profiles in this mode may be be reported as being in
|
|
||||||
I<enforce> mode or I<allow> mode when introspected from the kernel.
|
|
||||||
|
|
||||||
Note: default_allow is similar and for many profiles will be equivalent
|
|
||||||
to specifying an I<allow all,> rule in the profile. The default_allow
|
|
||||||
flag does not provide all the same option that the I<allow all,> rule
|
|
||||||
provides.
|
|
||||||
|
|
||||||
=item B<unconfined> This mode allows a task confined by the profile to
|
=item B<unconfined> This mode allows a task confined by the profile to
|
||||||
behave as though it is I<unconfined>. The unconfined behavior can be
|
behave as though they are I<unconfined>. This mode allow for an
|
||||||
later changed to confinement by using profile replacement. This mode
|
unconfined behavior that can be later changed to confinement by using
|
||||||
should not be used under regular deployment but can be useful during
|
profile replacement. This mode is should not be used under regular
|
||||||
debugging and some system initialization scenarios.
|
deployment but can be useful during debugging and some system
|
||||||
|
initialization scenarios.
|
||||||
This mode is similar to default_allow and may be emulated by
|
|
||||||
default_allow in kernels that no longer support a true unconfined
|
|
||||||
mode. It does not generally allow for specifying deny rules, or allow
|
|
||||||
rules that override the default behavior, except in a few custom
|
|
||||||
kernels where unconfined restricts a few operations. It relies on
|
|
||||||
special customized behavior of the unconfined profile in the kernel
|
|
||||||
and as such should only be used for debugging.
|
|
||||||
|
|
||||||
Note: true unconfined is being phased out, with unconfined becoming a
|
|
||||||
replaceable profile. As such unconfined mode will be emulated by a
|
|
||||||
special profile compiled with the default_allow flag in newer kernels.
|
|
||||||
|
|
||||||
=item B<prompt> This mode allows task mediation to send an up call to
|
|
||||||
userspace to ask for a decision when there isn't a rule covering the
|
|
||||||
permission request. If userspace does not respond then the access
|
|
||||||
will be denied.
|
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
@@ -529,24 +472,9 @@ though they are part of the namespace. WARNING this mode is unsafe and
|
|||||||
can result in aliasing and access to objects that should not be
|
can result in aliasing and access to objects that should not be
|
||||||
allowed. Its intent is a debug and policy development tool.
|
allowed. Its intent is a debug and policy development tool.
|
||||||
|
|
||||||
=item B<attach_disconnected.path>=I<ABS PATH> Like attach_disconnected, but
|
|
||||||
attach disconnected objects to the supplied path instead of the root of
|
|
||||||
the namespace.
|
|
||||||
|
|
||||||
=item B<chroot_relative> This forces file names to be relative to a
|
=item B<chroot_relative> This forces file names to be relative to a
|
||||||
chroot and behave as if the chroot is a mount namespace.
|
chroot and behave as if the chroot is a mount namespace.
|
||||||
|
|
||||||
=item B<debug> This flag allows turning on kernel debug messages on
|
|
||||||
a per profile basis. It works in conjunction with other kernel debug
|
|
||||||
flags to control what messages will be output. Its effect is kernel
|
|
||||||
dependent, and it should never appear in policy except when trying
|
|
||||||
to debug kernel or policy problems.
|
|
||||||
|
|
||||||
=item B<interruptible> Enables interrupts for prompt upcall to userspace.
|
|
||||||
|
|
||||||
=item B<kill.signal>=I<SIGNAL> This changes the signal that will be
|
|
||||||
sent by AppArmor when in kill mode or a kill rule has been violated.
|
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head2 Access Modes
|
=head2 Access Modes
|
||||||
@@ -1129,134 +1057,6 @@ Matches only:
|
|||||||
|
|
||||||
=back
|
=back
|
||||||
|
|
||||||
=head2 Message Queue rules
|
|
||||||
|
|
||||||
AppArmor supports mediation of POSIX and SYSV message queues.
|
|
||||||
|
|
||||||
AppArmor Message Queue permissions are implied when a rule does not explicitly
|
|
||||||
state an access list. By default, all Message Queue permissions are implied.
|
|
||||||
|
|
||||||
AppArmor Message Queue permissions become more restricted as further information
|
|
||||||
is specified. Policy can be specified by determining its access mode, type,
|
|
||||||
label, and message queue name.
|
|
||||||
|
|
||||||
Regarding access modes, 'r' and 'read' are used to read messages from the queue.
|
|
||||||
'w' and 'write' are used to write to the message queue. 'create' is used to create
|
|
||||||
the message queue, and 'open' is used to get the message queue identifier when the
|
|
||||||
queue is already created. 'delete' is used to remove the message queue. The access
|
|
||||||
modes to get and set attributes of the message queue are 'setattr' and 'getattr'.
|
|
||||||
|
|
||||||
The type of the policy can be either 'posix' or 'sysv'. This information is
|
|
||||||
relevant when the message queue name is not specified, and when specified can be
|
|
||||||
inferred by the queue name, since message queues' name for posix must start with '/',
|
|
||||||
and message queues' key for SYSV must be a positive integer.
|
|
||||||
|
|
||||||
The policy label is the label assigned to the message queue when it is created.
|
|
||||||
|
|
||||||
The message queue name can be either a string starting with '/' if the type
|
|
||||||
is POSIX, or a positive integer if the type is SYSV. If the type is not
|
|
||||||
specified, then it will be inferred by the queue name.
|
|
||||||
|
|
||||||
Example AppArmor Message Queue rules:
|
|
||||||
|
|
||||||
# Allow all Message Queue access
|
|
||||||
mqueue,
|
|
||||||
|
|
||||||
# Explicitly allow all Message Queue access,
|
|
||||||
mqueue (create, open, delete, read, write, getattr, setattr),
|
|
||||||
|
|
||||||
# Explicitly deny use of Message Queue
|
|
||||||
deny mqueue,
|
|
||||||
|
|
||||||
# Allow all access for POSIX queue of name /bar
|
|
||||||
mqueue type=posix /bar,
|
|
||||||
|
|
||||||
# Allow create permission for a SYSV queue of label foo
|
|
||||||
mqueue create label=foo 123,
|
|
||||||
|
|
||||||
=head2 User Namespace Rules
|
|
||||||
|
|
||||||
User namespaces are part of many sandboxing and containerization
|
|
||||||
solutions. They provide a way for a non-system root process to be
|
|
||||||
root within the container. Unfortunately this opens up attack surface
|
|
||||||
in the kernel and has been part of several exploit chains. As such
|
|
||||||
AppArmor can be used to restrict the creation of user namespaces to
|
|
||||||
select processes.
|
|
||||||
|
|
||||||
User namespace permission are implied when a rule does not explicitly
|
|
||||||
state an access list. The rule becomes more restrictive as further
|
|
||||||
information is specified.
|
|
||||||
|
|
||||||
Note: user namespace creation may be restricted so that it is not
|
|
||||||
available to unprivieged unconfined processes. If this is the case any
|
|
||||||
process trying to create user namespaces will require a profile that
|
|
||||||
allows the necessary permissions.
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item B<create>
|
|
||||||
|
|
||||||
Allow creation of user namespaces.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
Example userns rules:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
# Allow all userns perms
|
|
||||||
userns,
|
|
||||||
|
|
||||||
# Allow creation of a userns
|
|
||||||
userns create,
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head2 IO_URing Rules
|
|
||||||
|
|
||||||
AppArmor supports mediation of the new Linux high speed IO interface.
|
|
||||||
There is limited mediation at this time to just a few permissions at
|
|
||||||
the moment.
|
|
||||||
|
|
||||||
IO Uring permission are implied when a rule does not explicitly state
|
|
||||||
an access list. The rule becomes more restrictive as further
|
|
||||||
information is specified.
|
|
||||||
|
|
||||||
Note: io_uring access may be restricted so that it is not available to
|
|
||||||
unprivileged unconfined processes. If this is the case any process
|
|
||||||
trying to use io_uring will require a profile that allows the
|
|
||||||
necessary io_uring permissions.
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
=item B<sqpoll>
|
|
||||||
|
|
||||||
All the task confined by the profile to spawn a io_uring polling
|
|
||||||
thread.
|
|
||||||
|
|
||||||
=item B<override_creds>
|
|
||||||
|
|
||||||
Grants the task confined by the profile to override (change) its
|
|
||||||
credentials to the specified label, when executing an io_uring
|
|
||||||
operation.
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
Example IO_URING rules:
|
|
||||||
|
|
||||||
=over 4
|
|
||||||
|
|
||||||
# Allow io_uring operations
|
|
||||||
io_ring,
|
|
||||||
|
|
||||||
# Allow creation of a polling thread
|
|
||||||
io_uring sqpoll,
|
|
||||||
|
|
||||||
# Allow task to override credentials during io_uring operation
|
|
||||||
io_uring override_creds label=new_creds,
|
|
||||||
|
|
||||||
=back
|
|
||||||
|
|
||||||
=head2 Pivot Root Rules
|
=head2 Pivot Root Rules
|
||||||
|
|
||||||
AppArmor mediates changing of the root filesystem through the pivot_root(2)
|
AppArmor mediates changing of the root filesystem through the pivot_root(2)
|
||||||
@@ -1630,26 +1430,6 @@ Not all kernels support B<safe> mode and the parser will downgrade rules to
|
|||||||
B<unsafe> mode in that situation. If no exec mode is specified, the default is
|
B<unsafe> mode in that situation. If no exec mode is specified, the default is
|
||||||
B<safe> mode in kernels that support it.
|
B<safe> mode in kernels that support it.
|
||||||
|
|
||||||
=head2 all rule
|
|
||||||
|
|
||||||
The all rule is used to add a generic rule for all supported rule types.
|
|
||||||
This is useful when policy wants to define a black list instead of
|
|
||||||
white list, but can also be useful to add an access qualifier to all
|
|
||||||
rules.
|
|
||||||
|
|
||||||
Eg. Black list
|
|
||||||
|
|
||||||
allow all,
|
|
||||||
# begin blacklist
|
|
||||||
deny file,
|
|
||||||
deny unix,
|
|
||||||
|
|
||||||
|
|
||||||
Eg. Adding audit qualifier
|
|
||||||
|
|
||||||
audit access all,
|
|
||||||
|
|
||||||
|
|
||||||
=head2 rlimit rules
|
=head2 rlimit rules
|
||||||
|
|
||||||
AppArmor can set and control the resource limits associated with a
|
AppArmor can set and control the resource limits associated with a
|
||||||
@@ -2037,6 +1817,8 @@ An example AppArmor profile:
|
|||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
|
=item F</etc/init.d/boot.apparmor>
|
||||||
|
|
||||||
=item F</etc/apparmor.d/>
|
=item F</etc/apparmor.d/>
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
@@ -36,11 +36,12 @@ of resources. AppArmor's unique security model is to bind access control
|
|||||||
attributes to programs rather than to users.
|
attributes to programs rather than to users.
|
||||||
|
|
||||||
AppArmor confinement is provided via I<profiles> loaded into the kernel
|
AppArmor confinement is provided via I<profiles> loaded into the kernel
|
||||||
via apparmor_parser(8), typically through the F<apparmor.service>
|
via apparmor_parser(8), typically through the F</etc/init.d/apparmor>
|
||||||
systemd unit, which is used like this:
|
SysV initscript, which is used like this:
|
||||||
|
|
||||||
# systemctl start apparmor
|
# /etc/init.d/apparmor start
|
||||||
# systemctl reload apparmor
|
# /etc/init.d/apparmor stop
|
||||||
|
# /etc/init.d/apparmor restart
|
||||||
|
|
||||||
AppArmor can operate in two modes: I<enforcement>, and I<complain or learning>:
|
AppArmor can operate in two modes: I<enforcement>, and I<complain or learning>:
|
||||||
|
|
||||||
@@ -272,9 +273,11 @@ Else, if auditd is running, see auditd(8) and auditd.conf(5).
|
|||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
|
=item F</etc/init.d/apparmor>
|
||||||
|
|
||||||
=item F</etc/apparmor.d/>
|
=item F</etc/apparmor.d/>
|
||||||
|
|
||||||
=item F</var/cache/apparmor/>
|
=item F</var/lib/apparmor/>
|
||||||
|
|
||||||
=item F</var/log/audit/audit.log>
|
=item F</var/log/audit/audit.log>
|
||||||
|
|
||||||
|
@@ -6,8 +6,6 @@ After=systemd-journald-audit.socket
|
|||||||
# profile cache: /var/cache/apparmor/ and /usr/share/apparmor/cache/
|
# profile cache: /var/cache/apparmor/ and /usr/share/apparmor/cache/
|
||||||
After=var.mount var-cache.mount usr.mount usr-share.mount
|
After=var.mount var-cache.mount usr.mount usr-share.mount
|
||||||
ConditionSecurity=apparmor
|
ConditionSecurity=apparmor
|
||||||
Documentation=man:apparmor(7)
|
|
||||||
Documentation=https://gitlab.com/apparmor/apparmor/wikis/home/
|
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=oneshot
|
Type=oneshot
|
||||||
|
@@ -299,11 +299,11 @@ Enable various warnings during policy compilation. A single warn flag
|
|||||||
can be specified per --warn option, but the --warn flag can be passed
|
can be specified per --warn option, but the --warn flag can be passed
|
||||||
multiple times.
|
multiple times.
|
||||||
|
|
||||||
apparmor_parser --warn=rule-not-enforced ...
|
apparmor_parser --warn=rules-not-enforced ...
|
||||||
|
|
||||||
A specific warning can be disabled by prepending I<no>- to the flag
|
A specific warning can be disabled by prepending I<no>- to the flag
|
||||||
|
|
||||||
apparmor_parser --warn=no-rule-not-enforced ...
|
apparmor_parser --warn=no-rules-not-enforced ...
|
||||||
|
|
||||||
Use --help=warn to see a full list of which warn flags are supported.
|
Use --help=warn to see a full list of which warn flags are supported.
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user