mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-04 08:15:21 +00:00
Compare commits
77 Commits
fix-priori
...
v4.0.3
Author | SHA1 | Date | |
---|---|---|---|
|
b4dfdf50f5 | ||
|
5dd04c3389 | ||
|
1e9e52f243 | ||
|
9f57cbcb15 | ||
|
8146d3a6a3 | ||
|
d3d1c02b4e | ||
|
eb523cf53b | ||
|
507be2a990 | ||
|
3c24bc68b6 | ||
|
0193009b8b | ||
|
84a6bc1b6d | ||
|
9f849247b9 | ||
|
3fe2d323fc | ||
|
f0f7420f6c | ||
|
efef7d1b28 | ||
|
d61109d47e | ||
|
113ce2cfcd | ||
|
af7a10b5d9 | ||
|
4bb134e4bb | ||
|
4569381ec3 | ||
|
73a29ade16 | ||
|
d8e17207e8 | ||
|
0f51513a11 | ||
|
a07a8e69e0 | ||
|
24a0ebb5ef | ||
|
0310a122d4 | ||
|
6cad7b889e | ||
|
e2aff72f53 | ||
|
046fe9c1bd | ||
|
e4e60f1a4f | ||
|
ae01582798 | ||
|
98a0a2fee9 | ||
|
aada708bc1 | ||
|
dca6ac3b73 | ||
|
9d1388fdb6 | ||
|
a8637a5aa1 | ||
|
a866d77e72 | ||
|
527205bda9 | ||
|
e3be2e52ea | ||
|
d1311cc93f | ||
|
2a3cf471ab | ||
|
c31da2ec55 | ||
|
e8b2597676 | ||
|
6dee9d0a6a | ||
|
aa74b9b12d | ||
|
9ec5134322 | ||
|
fcd02fb69b | ||
|
1f4bba0448 | ||
|
af88a13712 | ||
|
8e74855531 | ||
|
951ea5b2fb | ||
|
eee50538da | ||
|
86be5d35f3 | ||
|
b7f9b66cba | ||
|
6d1e5dbbe6 | ||
|
f1173379ff | ||
|
b0eb95457b | ||
|
5ad4efec50 | ||
|
a635a86e1d | ||
|
c8e25e4689 | ||
|
68dd052873 | ||
|
4cef932170 | ||
|
8108a217a3 | ||
|
2284e99613 | ||
|
f763c44cd0 | ||
|
1d36e1f196 | ||
|
22ee6c19bc | ||
|
6198edb3d0 | ||
|
4d2a171466 | ||
|
e88cf3cd02 | ||
|
6f856dfee3 | ||
|
a6d8171bd6 | ||
|
26e7249f44 | ||
|
117d0cc444 | ||
|
1c7127d30d | ||
|
d111ddcc21 | ||
|
fa26623e6d |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -266,8 +266,8 @@ tests/regression/apparmor/mmap
|
|||||||
tests/regression/apparmor/mount
|
tests/regression/apparmor/mount
|
||||||
tests/regression/apparmor/move_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_inet_rcv
|
||||||
tests/regression/apparmor/net_finegrained_snd
|
tests/regression/apparmor/net_inet_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
|
||||||
|
@@ -112,7 +112,7 @@ shellcheck:
|
|||||||
extends:
|
extends:
|
||||||
- .ubuntu-before_script
|
- .ubuntu-before_script
|
||||||
script:
|
script:
|
||||||
- apt-get install --no-install-recommends -y file shellcheck xmlstarlet
|
- apt-get install --no-install-recommends -y python3-minimal file shellcheck xmlstarlet
|
||||||
- shellcheck --version
|
- shellcheck --version
|
||||||
- './tests/bin/shellcheck-tree --format=checkstyle
|
- './tests/bin/shellcheck-tree --format=checkstyle
|
||||||
| xmlstarlet tr tests/checkstyle2junit.xslt
|
| xmlstarlet tr tests/checkstyle2junit.xslt
|
||||||
|
@@ -172,7 +172,8 @@ static int load_policy_dir(const char *dir_path)
|
|||||||
while ((dir = readdir(d)) != NULL) {
|
while ((dir = readdir(d)) != NULL) {
|
||||||
/* Only check regular files for now */
|
/* Only check regular files for now */
|
||||||
if (dir->d_type == DT_REG) {
|
if (dir->d_type == DT_REG) {
|
||||||
len = strnlen(dir->d_name, PATH_MAX);
|
/* As per POSIX dir->d_name has at most NAME_MAX characters */
|
||||||
|
len = strnlen(dir->d_name, NAME_MAX);
|
||||||
/* Ignores .features */
|
/* Ignores .features */
|
||||||
if (strncmp(dir->d_name, CACHE_FEATURES_FILE, len) == 0) {
|
if (strncmp(dir->d_name, CACHE_FEATURES_FILE, len) == 0) {
|
||||||
continue;
|
continue;
|
||||||
|
@@ -1 +1 @@
|
|||||||
4.0.0~beta3
|
4.0.3
|
||||||
|
@@ -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 = 20
|
||||||
AA_LIB_REVISION = 1
|
AA_LIB_REVISION = 0
|
||||||
AA_LIB_AGE = 17
|
AA_LIB_AGE = 19
|
||||||
EXPECTED_SO_NAME = libapparmor.so.1.17.1
|
EXPECTED_SO_NAME = libapparmor.so.1.19.0
|
||||||
|
|
||||||
SUFFIXES = .pc.in .pc
|
SUFFIXES = .pc.in .pc
|
||||||
|
|
||||||
|
@@ -127,6 +127,7 @@ APPARMOR_3.0 {
|
|||||||
APPARMOR_3.1 {
|
APPARMOR_3.1 {
|
||||||
global:
|
global:
|
||||||
aa_features_check;
|
aa_features_check;
|
||||||
|
aa_split_overlay_str;
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
} APPARMOR_3.0;
|
} APPARMOR_3.0;
|
||||||
|
@@ -157,9 +157,13 @@ key_capname "capname"
|
|||||||
key_offset "offset"
|
key_offset "offset"
|
||||||
key_target "target"
|
key_target "target"
|
||||||
key_laddr "laddr"
|
key_laddr "laddr"
|
||||||
|
key_saddr "saddr"
|
||||||
key_faddr "faddr"
|
key_faddr "faddr"
|
||||||
|
key_daddr "daddr"
|
||||||
key_lport "lport"
|
key_lport "lport"
|
||||||
|
key_srcport "src"
|
||||||
key_fport "fport"
|
key_fport "fport"
|
||||||
|
key_destport "dest"
|
||||||
key_bus "bus"
|
key_bus "bus"
|
||||||
key_dest "dest"
|
key_dest "dest"
|
||||||
key_path "path"
|
key_path "path"
|
||||||
@@ -351,9 +355,13 @@ yy_flex_debug = 0;
|
|||||||
{key_offset} { return(TOK_KEY_OFFSET); }
|
{key_offset} { return(TOK_KEY_OFFSET); }
|
||||||
{key_target} { return(TOK_KEY_TARGET); }
|
{key_target} { return(TOK_KEY_TARGET); }
|
||||||
{key_laddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_LADDR); }
|
{key_laddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_LADDR); }
|
||||||
|
{key_saddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_LADDR); }
|
||||||
{key_faddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_FADDR); }
|
{key_faddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_FADDR); }
|
||||||
|
{key_daddr} { yy_push_state(ip_addr, yyscanner); return(TOK_KEY_FADDR); }
|
||||||
{key_lport} { return(TOK_KEY_LPORT); }
|
{key_lport} { return(TOK_KEY_LPORT); }
|
||||||
|
{key_srcport} { return(TOK_KEY_LPORT); }
|
||||||
{key_fport} { return(TOK_KEY_FPORT); }
|
{key_fport} { return(TOK_KEY_FPORT); }
|
||||||
|
{key_destport} { return(TOK_KEY_FPORT); }
|
||||||
{key_bus} { return(TOK_KEY_BUS); }
|
{key_bus} { return(TOK_KEY_BUS); }
|
||||||
{key_path} { return(TOK_KEY_PATH); }
|
{key_path} { return(TOK_KEY_PATH); }
|
||||||
{key_interface} { return(TOK_KEY_INTERFACE); }
|
{key_interface} { return(TOK_KEY_INTERFACE); }
|
||||||
|
@@ -135,7 +135,7 @@ static int do_test_walk_one(const char **str, const struct component *component,
|
|||||||
|
|
||||||
static int test_walk_one(void)
|
static int test_walk_one(void)
|
||||||
{
|
{
|
||||||
struct component c;
|
struct component c = (struct component) { NULL, 0 };
|
||||||
const char *str;
|
const char *str;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
@@ -55,7 +55,7 @@ extern int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
|
|||||||
extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
|
extern int aa_getprocattr(pid_t tid, const char *attr, char **buf, char **mode);
|
||||||
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
extern int aa_gettaskcon(pid_t target, char **label, char **mode);
|
||||||
extern int aa_getcon(char **label, char **mode);
|
extern int aa_getcon(char **label, char **mode);
|
||||||
extern int aa_getpeercon_raw(int fd, char *buf, int *len, char **mode);
|
extern int aa_getpeercon_raw(int fd, char *buf, socklen_t *len, char **mode);
|
||||||
extern int aa_getpeercon(int fd, char **label, char **mode);
|
extern int aa_getpeercon(int fd, char **label, char **mode);
|
||||||
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
extern int aa_query_label(uint32_t mask, char *query, size_t size, int *allow,
|
||||||
int *audit);
|
int *audit);
|
||||||
|
@@ -14,7 +14,7 @@ MOSTLYCLEANFILES=libapparmor_wrap.c LibAppArmor.py
|
|||||||
|
|
||||||
all-local: libapparmor_wrap.c setup.py
|
all-local: libapparmor_wrap.c setup.py
|
||||||
if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi
|
if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi
|
||||||
CC="$(CC)" CFLAGS="$(PYTHON_CPPFLAGS) $(EXTRA_WARNINGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(PYTHON_LDFLAGS) $(LDFLAGS)" $(PYTHON) setup.py build
|
CC="$(CC)" CFLAGS="$(PYTHON_CPPFLAGS) $(CFLAGS) $(EXTRA_WARNINGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(PYTHON_LDFLAGS) $(LDFLAGS)" $(PYTHON) setup.py build
|
||||||
|
|
||||||
install-exec-local:
|
install-exec-local:
|
||||||
$(PYTHON) setup.py install --root="/$(DESTDIR)" --prefix="$(prefix)"
|
$(PYTHON) setup.py install --root="/$(DESTDIR)" --prefix="$(prefix)"
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
/home/ubuntu/bzr/apparmor/tests/regression/apparmor/mount {
|
/home/ubuntu/bzr/apparmor/tests/regression/apparmor/mount {
|
||||||
mount fstype=ext2 options="rw, mand" /dev/loop0/ -> /tmp/sdtest.19033-29001-MPfz98/mountpoint/,
|
mount fstype=(ext2) options=(mand, rw) /dev/loop0/ -> /tmp/sdtest.19033-29001-MPfz98/mountpoint/,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -0,0 +1 @@
|
|||||||
|
type=AVC msg=audit(1715045678.914:344186): apparmor="ALLOWED" operation="mount" info="failed flags match" error=-13 profile="steam" name="/newroot/dev/" pid=26487 comm="srt-bwrap" flags="rw, nosuid, nodev, remount, bind, silent, relatime"
|
@@ -0,0 +1,14 @@
|
|||||||
|
START
|
||||||
|
File: testcase_mount_02.in
|
||||||
|
Event type: AA_RECORD_ALLOWED
|
||||||
|
Audit ID: 1715045678.914:344186
|
||||||
|
Operation: mount
|
||||||
|
Profile: steam
|
||||||
|
Name: /newroot/dev/
|
||||||
|
Command: srt-bwrap
|
||||||
|
Info: failed flags match
|
||||||
|
ErrorCode: 13
|
||||||
|
PID: 26487
|
||||||
|
Flags: rw, nosuid, nodev, remount, bind, silent, relatime
|
||||||
|
Epoch: 1715045678
|
||||||
|
Audit subid: 344186
|
@@ -0,0 +1,4 @@
|
|||||||
|
profile steam {
|
||||||
|
mount options=(bind, nodev, nosuid, relatime, remount, rw, silent) -> /newroot/dev/,
|
||||||
|
|
||||||
|
}
|
@@ -39,7 +39,7 @@ void all_rule::add_implied_rules(Profile &prof)
|
|||||||
prefix_rule_t *rule;
|
prefix_rule_t *rule;
|
||||||
const prefixes *prefix = this;
|
const prefixes *prefix = this;
|
||||||
|
|
||||||
rule = new unix_rule(0, audit, rule_mode);
|
rule = new unix_rule(0xffffffff, audit, rule_mode);
|
||||||
(void) rule->add_prefix(*prefix);
|
(void) rule->add_prefix(*prefix);
|
||||||
prof.rule_ents.push_back(rule);
|
prof.rule_ents.push_back(rule);
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ void all_rule::add_implied_rules(Profile &prof)
|
|||||||
(void) rule->add_prefix(*prefix);
|
(void) rule->add_prefix(*prefix);
|
||||||
prof.rule_ents.push_back(rule);
|
prof.rule_ents.push_back(rule);
|
||||||
|
|
||||||
rule = new mnt_rule(NULL, NULL, NULL, NULL, 0);
|
rule = new mnt_rule(NULL, NULL, NULL, NULL, AA_MAY_MOUNT);
|
||||||
(void) rule->add_prefix(*prefix);
|
(void) rule->add_prefix(*prefix);
|
||||||
prof.rule_ents.push_back(rule);
|
prof.rule_ents.push_back(rule);
|
||||||
|
|
||||||
|
@@ -148,7 +148,14 @@ B<CAPABILITY LIST> = ( I<CAPABILITY> )+
|
|||||||
B<CAPABILITY> = (lowercase capability name without 'CAP_' prefix; see
|
B<CAPABILITY> = (lowercase capability name without 'CAP_' prefix; see
|
||||||
capabilities(7))
|
capabilities(7))
|
||||||
|
|
||||||
B<NETWORK RULE> = [ I<QUALIFIERS> ] 'network' [ I<DOMAIN> ] [ I<TYPE> | I<PROTOCOL> ]
|
B<NETWORK RULE> = [ I<QUALIFIERS> ] 'network' [ I<NETWORK ACCESS EXPR> ] [ I<DOMAIN> ] [ I<TYPE> | I<PROTOCOL> ] [ I<NETWORK LOCAL EXPR> ] [ I<NETWORK PEER EXPR> ]
|
||||||
|
|
||||||
|
B<NETWORK ACCESS EXPR> = ( I<NETWORK ACCESS> | I<NETWORK ACCESS LIST> )
|
||||||
|
|
||||||
|
B<NETWORK ACCESS> = ( 'create' | 'bind' | 'listen' | 'accept' | 'connect' | 'shutdown' | 'getattr' | 'setattr' | 'getopt' | 'setopt' | 'send' | 'receive' | 'r' | 'w' | 'rw' )
|
||||||
|
Some access modes are incompatible with some rules.
|
||||||
|
|
||||||
|
B<NETWORK ACCESS LIST> = '(' I<NETWORK ACCESS> ( [','] I<NETWORK ACCESS> )* ')'
|
||||||
|
|
||||||
B<DOMAIN> = ( 'unix' | 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'netlink' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'rds' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'llc' | 'ib' | 'mpls' | 'can' | 'tipc' | 'bluetooth' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'kcm' | 'qipcrtr' | 'smc' | 'xdp' | 'mctp' ) ','
|
B<DOMAIN> = ( 'unix' | 'inet' | 'ax25' | 'ipx' | 'appletalk' | 'netrom' | 'bridge' | 'atmpvc' | 'x25' | 'inet6' | 'rose' | 'netbeui' | 'security' | 'key' | 'netlink' | 'packet' | 'ash' | 'econet' | 'atmsvc' | 'rds' | 'sna' | 'irda' | 'pppox' | 'wanpipe' | 'llc' | 'ib' | 'mpls' | 'can' | 'tipc' | 'bluetooth' | 'iucv' | 'rxrpc' | 'isdn' | 'phonet' | 'ieee802154' | 'caif' | 'alg' | 'nfc' | 'vsock' | 'kcm' | 'qipcrtr' | 'smc' | 'xdp' | 'mctp' ) ','
|
||||||
|
|
||||||
@@ -156,6 +163,22 @@ B<TYPE> = ( 'stream' | 'dgram' | 'seqpacket' | 'rdm' | 'raw' | 'packet' )
|
|||||||
|
|
||||||
B<PROTOCOL> = ( 'tcp' | 'udp' | 'icmp' )
|
B<PROTOCOL> = ( 'tcp' | 'udp' | 'icmp' )
|
||||||
|
|
||||||
|
B<NETWORK LOCAL EXPR> = ( I<NETWORK IP COND> | I<NETWORK PORT COND> )*
|
||||||
|
Each cond can appear at most once.
|
||||||
|
|
||||||
|
B<NETWORK PEER EXPR> = 'peer' '=' '(' ( I<NETWORK IP COND> | I<NETWORK PORT COND> )+ ')'
|
||||||
|
Each cond can appear at most once.
|
||||||
|
|
||||||
|
B<NETWORK IP COND> = 'ip' '=' ( 'none' | I<NETWORK IPV4> | I<NETWORK IPV6> )
|
||||||
|
|
||||||
|
B<NETWORK PORT COND> = 'port' '=' ( I<NETWORK PORT> )
|
||||||
|
|
||||||
|
B<NETWORK IPV4> = IPv4, represented by four 8-bit decimal numbers separated by '.'
|
||||||
|
|
||||||
|
B<NETWORK IPV6> = IPv6, represented by eight groups of four hexadecimal numbers separated by ':'. Shortened representation of contiguous zeros is allowed by using '::'
|
||||||
|
|
||||||
|
B<NETWORK PORT> = 16-bit number ranging from 0 to 65535
|
||||||
|
|
||||||
B<MOUNT RULE> = ( I<MOUNT> | I<REMOUNT> | I<UMOUNT> )
|
B<MOUNT RULE> = ( I<MOUNT> | I<REMOUNT> | I<UMOUNT> )
|
||||||
|
|
||||||
B<MOUNT> = [ I<QUALIFIERS> ] 'mount' [ I<MOUNT CONDITIONS> ] [ I<SOURCE FILEGLOB> ] [ '-E<gt>' [ I<MOUNTPOINT FILEGLOB> ]
|
B<MOUNT> = [ I<QUALIFIERS> ] 'mount' [ I<MOUNT CONDITIONS> ] [ I<SOURCE FILEGLOB> ] [ '-E<gt>' [ I<MOUNTPOINT FILEGLOB> ]
|
||||||
@@ -912,11 +935,10 @@ and other operations that are typically reserved for the root user.
|
|||||||
|
|
||||||
=head2 Network Rules
|
=head2 Network Rules
|
||||||
|
|
||||||
AppArmor supports simple coarse grained network mediation. The network
|
AppArmor supports simple coarse grained network mediation. The
|
||||||
rule restrict all socket(2) based operations. The mediation done is
|
network rule restrict all socket(2) based operations. The mediation
|
||||||
a coarse-grained check on whether a socket of a given type and family
|
done is a coarse-grained check on whether a socket of a given type and
|
||||||
can be created, read, or written. There is no mediation based of port
|
family can be created, read, or written. Network netlink(7) rules may
|
||||||
number or protocol beyond tcp, udp, and raw. Network netlink(7) rules may
|
|
||||||
only specify type 'dgram' and 'raw'.
|
only specify type 'dgram' and 'raw'.
|
||||||
|
|
||||||
AppArmor network rules are accumulated so that the granted network
|
AppArmor network rules are accumulated so that the granted network
|
||||||
@@ -933,6 +955,48 @@ eg.
|
|||||||
network inet6 tcp, #allow access to tcp only for inet6 addresses
|
network inet6 tcp, #allow access to tcp only for inet6 addresses
|
||||||
network netlink raw, #allow access to AF_NETLINK SOCK_RAW
|
network netlink raw, #allow access to AF_NETLINK SOCK_RAW
|
||||||
|
|
||||||
|
=head3 Network permissions
|
||||||
|
|
||||||
|
Network rule permissions are implied when a rule does not explicitly
|
||||||
|
state an access list. By default if a rule does not have an access
|
||||||
|
list all permissions that are compatible with the specified set of
|
||||||
|
local and peer conditionals are implied.
|
||||||
|
|
||||||
|
The create, bind, listen, shutdown, getattr, setattr, getopt, and
|
||||||
|
setopt permissions are local socket permissions. They are only applied
|
||||||
|
to the local socket and can't be specified in rules that have a peer
|
||||||
|
conditional. The accept permission applies to the combination of a
|
||||||
|
local and peer socket. The connect, send, and receive permissions are
|
||||||
|
peer socket permissions.
|
||||||
|
|
||||||
|
=head3 Mediation of inet/inet6 family
|
||||||
|
|
||||||
|
AppArmor supports fine grained mediation of the inet and inet6
|
||||||
|
families by using the ip and port conditionals. The ip conditional
|
||||||
|
accepts both IPv4 and IPv6 using the regular representation of four
|
||||||
|
octets separated by '.' for IPv4 and eight groups of four hexadecimal
|
||||||
|
numbers separated by ':' for IPv6. Contiguous leading zeros can be
|
||||||
|
replaced by '::' once. On a connected socket, the sender and receiver
|
||||||
|
don't need to be specified in the recvfrom and sendto system calls. In
|
||||||
|
that case, and with unbounded sockets, the IP address is none, or
|
||||||
|
unknown. Unknown or Unbound IP addresses are represented in policy by the
|
||||||
|
'none' keyword. When the ip conditional is omitted, then all IP
|
||||||
|
addresses will be allowed: IPv4, IPv6 and none. If INADDR_ANY or
|
||||||
|
in6addr_any is used, then the ip conditional can be omitted or they
|
||||||
|
can be represented by:
|
||||||
|
|
||||||
|
network ip=::, #allow in6addr_any
|
||||||
|
network ip=0.0.0.0; #allow INADDR_ANY
|
||||||
|
|
||||||
|
The network rules support the specification of local and remote IP
|
||||||
|
addresses and ports.
|
||||||
|
|
||||||
|
network ip=127.0.0.1 port=8080,
|
||||||
|
network peer=(ip=10.139.15.23 port=8081),
|
||||||
|
network ip=fd74:1820:b03a:b361::cf32 peer=(ip=fd74:1820:b03a:b361::a0f9),
|
||||||
|
network port=8080 peer=(port=8081),
|
||||||
|
network ip=127.0.0.1 port=8080 peer=(ip=10.139.15.23 port=8081),
|
||||||
|
|
||||||
=head2 Mount Rules
|
=head2 Mount Rules
|
||||||
|
|
||||||
AppArmor supports mount mediation and allows specifying filesystem types and
|
AppArmor supports mount mediation and allows specifying filesystem types and
|
||||||
|
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions
|
APPARMOR_FUNCTIONS=/lib/apparmor/rc.apparmor.functions
|
||||||
|
|
||||||
|
# This function is used in rc.apparmor.functions
|
||||||
|
# shellcheck disable=SC2317
|
||||||
aa_action()
|
aa_action()
|
||||||
{
|
{
|
||||||
echo "$1"
|
echo "$1"
|
||||||
@@ -25,36 +27,50 @@ aa_action()
|
|||||||
return $?
|
return $?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This function is used in rc.apparmor.functions
|
||||||
|
# shellcheck disable=SC2317
|
||||||
aa_log_warning_msg()
|
aa_log_warning_msg()
|
||||||
{
|
{
|
||||||
echo "Warning: $*"
|
echo "Warning: $*"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This function is used in rc.apparmor.functions
|
||||||
|
# shellcheck disable=SC2317
|
||||||
aa_log_failure_msg()
|
aa_log_failure_msg()
|
||||||
{
|
{
|
||||||
echo "Error: $*"
|
echo "Error: $*"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This function is used in rc.apparmor.functions
|
||||||
|
# shellcheck disable=SC2317
|
||||||
aa_log_action_start()
|
aa_log_action_start()
|
||||||
{
|
{
|
||||||
echo "$@"
|
echo "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This function is used in rc.apparmor.functions
|
||||||
|
# shellcheck disable=SC2317
|
||||||
aa_log_action_end()
|
aa_log_action_end()
|
||||||
{
|
{
|
||||||
printf ""
|
printf ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This function is used in rc.apparmor.functions
|
||||||
|
# shellcheck disable=SC2317
|
||||||
aa_log_daemon_msg()
|
aa_log_daemon_msg()
|
||||||
{
|
{
|
||||||
echo "$@"
|
echo "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This function is used in rc.apparmor.functions
|
||||||
|
# shellcheck disable=SC2317
|
||||||
aa_log_skipped_msg()
|
aa_log_skipped_msg()
|
||||||
{
|
{
|
||||||
echo "Skipped: $*"
|
echo "Skipped: $*"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# This function is used in rc.apparmor.functions
|
||||||
|
# shellcheck disable=SC2317
|
||||||
aa_log_end_msg()
|
aa_log_end_msg()
|
||||||
{
|
{
|
||||||
printf ""
|
printf ""
|
||||||
|
@@ -189,6 +189,19 @@ void Node::dump_syntax_tree(ostream &os)
|
|||||||
* a b c T
|
* a b c T
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static Node *simplify_eps_pair(Node *t)
|
||||||
|
{
|
||||||
|
if (t->is_type(NODE_TYPE_TWOCHILD) &&
|
||||||
|
t->child[0] == &epsnode &&
|
||||||
|
t->child[1] == &epsnode) {
|
||||||
|
t->release();
|
||||||
|
return &epsnode;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
static void rotate_node(Node *t, int dir)
|
static void rotate_node(Node *t, int dir)
|
||||||
{
|
{
|
||||||
// (a | b) | c -> a | (b | c)
|
// (a | b) | c -> a | (b | c)
|
||||||
@@ -197,7 +210,9 @@ static void rotate_node(Node *t, int dir)
|
|||||||
t->child[dir] = left->child[dir];
|
t->child[dir] = left->child[dir];
|
||||||
left->child[dir] = left->child[!dir];
|
left->child[dir] = left->child[!dir];
|
||||||
left->child[!dir] = t->child[!dir];
|
left->child[!dir] = t->child[!dir];
|
||||||
t->child[!dir] = left;
|
|
||||||
|
// check that rotation didn't create (E | E)
|
||||||
|
t->child[!dir] = simplify_eps_pair(left);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return False if no work done */
|
/* return False if no work done */
|
||||||
@@ -209,13 +224,7 @@ int TwoChildNode::normalize_eps(int dir)
|
|||||||
// Ea -> aE
|
// Ea -> aE
|
||||||
// Test for E | (E | E) and E . (E . E) which will
|
// Test for E | (E | E) and E . (E . E) which will
|
||||||
// result in an infinite loop
|
// result in an infinite loop
|
||||||
Node *c = child[!dir];
|
Node *c = simplify_eps_pair(child[!dir]);
|
||||||
if (c->is_type(NODE_TYPE_TWOCHILD) &&
|
|
||||||
&epsnode == c->child[dir] &&
|
|
||||||
&epsnode == c->child[!dir]) {
|
|
||||||
c->release();
|
|
||||||
c = &epsnode;
|
|
||||||
}
|
|
||||||
child[!dir] = child[dir];
|
child[!dir] = child[dir];
|
||||||
child[dir] = c;
|
child[dir] = c;
|
||||||
return 1;
|
return 1;
|
||||||
|
@@ -192,14 +192,14 @@ int mqueue_rule::gen_policy_re(Profile &prof)
|
|||||||
return RULE_NOT_SUPPORTED;
|
return RULE_NOT_SUPPORTED;
|
||||||
} else if (qtype == mqueue_sysv && !features_supports_sysv_mqueue) {
|
} else if (qtype == mqueue_sysv && !features_supports_sysv_mqueue) {
|
||||||
warn_once(prof.name);
|
warn_once(prof.name);
|
||||||
// return RULE_NOT_SUPPORTED;
|
return RULE_NOT_SUPPORTED;
|
||||||
} else if (qtype == mqueue_unspecified &&
|
} else if (qtype == mqueue_unspecified &&
|
||||||
!(features_supports_posix_mqueue ||
|
!(features_supports_posix_mqueue ||
|
||||||
features_supports_sysv_mqueue)) {
|
features_supports_sysv_mqueue)) {
|
||||||
warn_once(prof.name);
|
warn_once(prof.name);
|
||||||
// should split into warning where posix and sysv can
|
// should split into warning where posix and sysv can
|
||||||
// be separated from nothing being enforced
|
// be separated from nothing being enforced
|
||||||
// return RULE_NOT_SUPPORTED;
|
return RULE_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* always generate a label and mqueue entry */
|
/* always generate a label and mqueue entry */
|
||||||
@@ -231,10 +231,10 @@ int mqueue_rule::gen_policy_re(Profile &prof)
|
|||||||
/* store perms at name match so label doesn't need
|
/* store perms at name match so label doesn't need
|
||||||
* to be checked
|
* to be checked
|
||||||
*/
|
*/
|
||||||
if (!label && !prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0, 1, vec, parseopts, false))
|
if (!label && !prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1, vec, parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
/* also provide label match with perm */
|
/* also provide label match with perm */
|
||||||
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0, size, vec, parseopts, false))
|
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, size, vec, parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -266,10 +266,10 @@ int mqueue_rule::gen_policy_re(Profile &prof)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (perms & AA_VALID_SYSV_MQ_PERMS) {
|
if (perms & AA_VALID_SYSV_MQ_PERMS) {
|
||||||
if (!label && !prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0, 1, vec, parseopts, false))
|
if (!label && !prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, 1, vec, parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
/* also provide label match with perm */
|
/* also provide label match with perm */
|
||||||
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, perms, audit == AUDIT_FORCE ? perms : 0, size, vec, parseopts, false))
|
if (!prof.policy.rules->add_rule_vec(rule_mode == RULE_DENY, map_mqueue_perms(perms), audit == AUDIT_FORCE ? map_mqueue_perms(perms) : 0, size, vec, parseopts, false))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -52,13 +52,13 @@
|
|||||||
* kernel doesn't allow for us to control
|
* kernel doesn't allow for us to control
|
||||||
* - posix
|
* - posix
|
||||||
* - notify
|
* - notify
|
||||||
* - getattr/setattr
|
|
||||||
* - labels at anything other than mqueue label, via mqueue inode.
|
* - labels at anything other than mqueue label, via mqueue inode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define AA_VALID_POSIX_MQ_PERMS (AA_MQUEUE_WRITE | AA_MQUEUE_READ | \
|
#define AA_VALID_POSIX_MQ_PERMS (AA_MQUEUE_WRITE | AA_MQUEUE_READ | \
|
||||||
AA_MQUEUE_CREATE | AA_MQUEUE_DELETE | \
|
AA_MQUEUE_CREATE | AA_MQUEUE_DELETE | \
|
||||||
AA_MQUEUE_OPEN)
|
AA_MQUEUE_OPEN | \
|
||||||
|
AA_MQUEUE_SETATTR | AA_MQUEUE_GETATTR)
|
||||||
|
|
||||||
/* TBD - for now make it wider than posix */
|
/* TBD - for now make it wider than posix */
|
||||||
#define AA_VALID_SYSV_MQ_PERMS (AA_MQUEUE_WRITE | AA_MQUEUE_READ | \
|
#define AA_VALID_SYSV_MQ_PERMS (AA_MQUEUE_WRITE | AA_MQUEUE_READ | \
|
||||||
@@ -78,6 +78,11 @@ typedef enum mqueue_type {
|
|||||||
mqueue_sysv
|
mqueue_sysv
|
||||||
} mqueue_type;
|
} mqueue_type;
|
||||||
|
|
||||||
|
static inline uint32_t map_mqueue_perms(uint32_t mask)
|
||||||
|
{
|
||||||
|
return (mask & 0x7f) |
|
||||||
|
((mask & (AA_MQUEUE_GETATTR | AA_MQUEUE_SETATTR)) << (AA_OTHER_SHIFT - 8));
|
||||||
|
}
|
||||||
|
|
||||||
int parse_mqueue_perms(const char *str_perms, perms_t *perms, int fail);
|
int parse_mqueue_perms(const char *str_perms, perms_t *perms, int fail);
|
||||||
|
|
||||||
|
@@ -360,8 +360,8 @@ bool network_rule::parse_port(ip_conds &entry)
|
|||||||
|
|
||||||
bool network_rule::parse_address(ip_conds &entry)
|
bool network_rule::parse_address(ip_conds &entry)
|
||||||
{
|
{
|
||||||
if (strcmp(entry.sip, "anon") == 0) {
|
if (strcmp(entry.sip, "none") == 0) {
|
||||||
entry.is_anonymous = true;
|
entry.is_none = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
entry.is_ip = true;
|
entry.is_ip = true;
|
||||||
@@ -405,17 +405,31 @@ network_rule::network_rule(perms_t perms_p, struct cond_entry *conds,
|
|||||||
struct cond_entry *peer_conds):
|
struct cond_entry *peer_conds):
|
||||||
dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL)
|
dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL)
|
||||||
{
|
{
|
||||||
size_t family_index;
|
size_t family_index, i;
|
||||||
for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) {
|
|
||||||
network_map[family_index].push_back({ family_index, 0xFFFFFFFF, 0xFFFFFFFF });
|
|
||||||
set_netperm(family_index, 0xFFFFFFFF, 0xFFFFFFFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
move_conditionals(conds, local);
|
move_conditionals(conds, local);
|
||||||
move_conditionals(peer_conds, peer);
|
move_conditionals(peer_conds, peer);
|
||||||
free_cond_list(conds);
|
free_cond_list(conds);
|
||||||
free_cond_list(peer_conds);
|
free_cond_list(peer_conds);
|
||||||
|
|
||||||
|
if (has_local_conds() || has_peer_conds()) {
|
||||||
|
const char *family[] = { "inet", "inet6" };
|
||||||
|
for (i = 0; i < sizeof(family)/sizeof(family[0]); i++) {
|
||||||
|
const struct network_tuple *mapping = NULL;
|
||||||
|
while ((mapping = net_find_mapping(mapping, family[i], NULL, NULL))) {
|
||||||
|
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
|
||||||
|
set_netperm(mapping->family, mapping->type, mapping->protocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) {
|
||||||
|
network_map[family_index].push_back({ family_index, 0xFFFFFFFF, 0xFFFFFFFF });
|
||||||
|
set_netperm(family_index, 0xFFFFFFFF, 0xFFFFFFFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (perms_p) {
|
if (perms_p) {
|
||||||
perms = perms_p;
|
perms = perms_p;
|
||||||
if (perms & ~AA_VALID_NET_PERMS)
|
if (perms & ~AA_VALID_NET_PERMS)
|
||||||
@@ -433,13 +447,34 @@ network_rule::network_rule(perms_t perms_p, const char *family, const char *type
|
|||||||
dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL)
|
dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL)
|
||||||
{
|
{
|
||||||
const struct network_tuple *mapping = NULL;
|
const struct network_tuple *mapping = NULL;
|
||||||
|
|
||||||
|
move_conditionals(conds, local);
|
||||||
|
move_conditionals(peer_conds, peer);
|
||||||
|
free_cond_list(conds);
|
||||||
|
free_cond_list(peer_conds);
|
||||||
|
|
||||||
while ((mapping = net_find_mapping(mapping, family, type, protocol))) {
|
while ((mapping = net_find_mapping(mapping, family, type, protocol))) {
|
||||||
|
/* if inet conds and family are specified, fail if
|
||||||
|
* family is not af_inet or af_inet6
|
||||||
|
*/
|
||||||
|
if ((has_local_conds() || has_peer_conds()) &&
|
||||||
|
mapping->family != AF_INET && mapping->family != AF_INET6) {
|
||||||
|
yyerror("network family does not support local or peer conditionals\n");
|
||||||
|
}
|
||||||
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
|
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
|
||||||
set_netperm(mapping->family, mapping->type, mapping->protocol);
|
set_netperm(mapping->family, mapping->type, mapping->protocol);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == NULL && network_map.empty()) {
|
if (type == NULL && network_map.empty()) {
|
||||||
while ((mapping = net_find_mapping(mapping, type, family, protocol))) {
|
while ((mapping = net_find_mapping(mapping, type, family, protocol))) {
|
||||||
|
/* if inet conds and type/protocol are
|
||||||
|
* specified, only add rules for af_inet and
|
||||||
|
* af_inet6
|
||||||
|
*/
|
||||||
|
if ((has_local_conds() || has_peer_conds()) &&
|
||||||
|
mapping->family != AF_INET && mapping->family != AF_INET6)
|
||||||
|
continue;
|
||||||
|
|
||||||
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
|
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
|
||||||
set_netperm(mapping->family, mapping->type, mapping->protocol);
|
set_netperm(mapping->family, mapping->type, mapping->protocol);
|
||||||
}
|
}
|
||||||
@@ -448,11 +483,6 @@ network_rule::network_rule(perms_t perms_p, const char *family, const char *type
|
|||||||
if (network_map.empty())
|
if (network_map.empty())
|
||||||
yyerror(_("Invalid network entry."));
|
yyerror(_("Invalid network entry."));
|
||||||
|
|
||||||
move_conditionals(conds, local);
|
|
||||||
move_conditionals(peer_conds, peer);
|
|
||||||
free_cond_list(conds);
|
|
||||||
free_cond_list(peer_conds);
|
|
||||||
|
|
||||||
if (perms_p) {
|
if (perms_p) {
|
||||||
perms = perms_p;
|
perms = perms_p;
|
||||||
if (perms & ~AA_VALID_NET_PERMS)
|
if (perms & ~AA_VALID_NET_PERMS)
|
||||||
@@ -585,13 +615,13 @@ std::string gen_port_cond(uint16_t port)
|
|||||||
std::list<std::ostringstream> gen_all_ip_options(std::ostringstream &oss) {
|
std::list<std::ostringstream> gen_all_ip_options(std::ostringstream &oss) {
|
||||||
|
|
||||||
std::list<std::ostringstream> all_streams;
|
std::list<std::ostringstream> all_streams;
|
||||||
std::ostringstream anon, ipv4, ipv6;
|
std::ostringstream none, ipv4, ipv6;
|
||||||
int i;
|
int i;
|
||||||
anon << oss.str();
|
none << oss.str();
|
||||||
ipv4 << oss.str();
|
ipv4 << oss.str();
|
||||||
ipv6 << oss.str();
|
ipv6 << oss.str();
|
||||||
|
|
||||||
anon << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ANON_SIZE;
|
none << "\\x" << std::setfill('0') << std::setw(2) << std::hex << NONE_SIZE;
|
||||||
|
|
||||||
/* add a byte containing the size of the following ip */
|
/* add a byte containing the size of the following ip */
|
||||||
ipv4 << "\\x" << std::setfill('0') << std::setw(2) << std::hex << IPV4_SIZE;
|
ipv4 << "\\x" << std::setfill('0') << std::setw(2) << std::hex << IPV4_SIZE;
|
||||||
@@ -603,7 +633,7 @@ std::list<std::ostringstream> gen_all_ip_options(std::ostringstream &oss) {
|
|||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
ipv6 << ".";
|
ipv6 << ".";
|
||||||
|
|
||||||
all_streams.push_back(std::move(anon));
|
all_streams.push_back(std::move(none));
|
||||||
all_streams.push_back(std::move(ipv4));
|
all_streams.push_back(std::move(ipv4));
|
||||||
all_streams.push_back(std::move(ipv6));
|
all_streams.push_back(std::move(ipv6));
|
||||||
|
|
||||||
@@ -627,7 +657,7 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
|
|||||||
std::list<std::ostringstream> ip_streams;
|
std::list<std::ostringstream> ip_streams;
|
||||||
|
|
||||||
for (auto &oss : streams) {
|
for (auto &oss : streams) {
|
||||||
if (entry.is_port && !(entry.is_ip && entry.is_anonymous)) {
|
if (entry.is_port && !(entry.is_ip && entry.is_none)) {
|
||||||
/* encode port type (privileged - 1, remote - 2, unprivileged - 0) */
|
/* encode port type (privileged - 1, remote - 2, unprivileged - 0) */
|
||||||
if (!is_peer && perms & AA_NET_BIND && entry.port < IPPORT_RESERVED)
|
if (!is_peer && perms & AA_NET_BIND && entry.port < IPPORT_RESERVED)
|
||||||
oss << "\\x01";
|
oss << "\\x01";
|
||||||
@@ -650,8 +680,8 @@ bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &st
|
|||||||
if (entry.is_ip) {
|
if (entry.is_ip) {
|
||||||
oss << gen_ip_cond(entry.ip);
|
oss << gen_ip_cond(entry.ip);
|
||||||
streams.push_back(std::move(oss));
|
streams.push_back(std::move(oss));
|
||||||
} else if (entry.is_anonymous) {
|
} else if (entry.is_none) {
|
||||||
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ANON_SIZE;
|
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << NONE_SIZE;
|
||||||
streams.push_back(std::move(oss));
|
streams.push_back(std::move(oss));
|
||||||
} else {
|
} else {
|
||||||
streams.splice(streams.end(), gen_all_ip_options(oss));
|
streams.splice(streams.end(), gen_all_ip_options(oss));
|
||||||
@@ -898,7 +928,7 @@ static int cmp_ip_conds(ip_conds const &lhs, ip_conds const &rhs)
|
|||||||
res = null_strcmp(lhs.sport, rhs.sport);
|
res = null_strcmp(lhs.sport, rhs.sport);
|
||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
return lhs.is_anonymous - rhs.is_anonymous;
|
return lhs.is_none - rhs.is_none;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmp_network_map(std::unordered_map<unsigned int, std::pair<unsigned int, unsigned int>> lhs,
|
static int cmp_network_map(std::unordered_map<unsigned int, std::pair<unsigned int, unsigned int>> lhs,
|
||||||
|
@@ -80,7 +80,7 @@
|
|||||||
#define CMD_LISTEN 2
|
#define CMD_LISTEN 2
|
||||||
#define CMD_OPT 4
|
#define CMD_OPT 4
|
||||||
|
|
||||||
#define ANON_SIZE 0
|
#define NONE_SIZE 0
|
||||||
#define IPV4_SIZE 1
|
#define IPV4_SIZE 1
|
||||||
#define IPV6_SIZE 2
|
#define IPV6_SIZE 2
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ public:
|
|||||||
uint16_t port;
|
uint16_t port;
|
||||||
struct ip_address ip;
|
struct ip_address ip;
|
||||||
|
|
||||||
bool is_anonymous = false;
|
bool is_none = false;
|
||||||
|
|
||||||
void free_conds() {
|
void free_conds() {
|
||||||
if (sip)
|
if (sip)
|
||||||
|
@@ -255,9 +255,11 @@ MODES {MODE_CHARS}+
|
|||||||
WS [[:blank:]]
|
WS [[:blank:]]
|
||||||
NUMBER [[:digit:]]+
|
NUMBER [[:digit:]]+
|
||||||
|
|
||||||
|
ID_FIRST_CHARS [^ \t\r\n"!,#]
|
||||||
|
ID_FIRST {ID_CHARS}|(,{ID_CHARS}|\\[ ]|\\\t|\\\"|\\!|\\,|\\#)
|
||||||
ID_CHARS [^ \t\r\n"!,]
|
ID_CHARS [^ \t\r\n"!,]
|
||||||
ID {ID_CHARS}|(,{ID_CHARS}|\\[ ]|\\\t|\\\"|\\!|\\,)
|
ID {ID_CHARS}|(,{ID_CHARS}|\\[ ]|\\\t|\\\"|\\!|\\,)
|
||||||
IDS {ID}+
|
IDS {ID_FIRST}{ID}*
|
||||||
INC_ID [^ \t\r\n"!,<>]|(,[^ \t\r\n"!,<>]|\\[ ]|\\\t|\\\"|\\!|\\,)
|
INC_ID [^ \t\r\n"!,<>]|(,[^ \t\r\n"!,<>]|\\[ ]|\\\t|\\\"|\\!|\\,)
|
||||||
INC_IDS {INC_ID}+
|
INC_IDS {INC_ID}+
|
||||||
POST_VAR_ID_CHARS [^ \t\n"!,]{-}[=\+]
|
POST_VAR_ID_CHARS [^ \t\n"!,]{-}[=\+]
|
||||||
@@ -507,6 +509,12 @@ GT >
|
|||||||
yyerror(_("Variable declarations do not accept trailing commas"));
|
yyerror(_("Variable declarations do not accept trailing commas"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#.*\r?\n { /* normal comment */
|
||||||
|
DUMP_AND_DEBUG("comment(%d): %s\n", current_lineno, yytext);
|
||||||
|
current_lineno++;
|
||||||
|
POP();
|
||||||
|
}
|
||||||
|
|
||||||
\\\n { DUMP_PREPROCESS; current_lineno++ ; }
|
\\\n { DUMP_PREPROCESS; current_lineno++ ; }
|
||||||
|
|
||||||
\r?\n {
|
\r?\n {
|
||||||
|
@@ -1000,41 +1000,46 @@ int process_profile_policydb(Profile *prof)
|
|||||||
* to be supported
|
* to be supported
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* note: this activates fs based unix domain sockets mediation on connect */
|
|
||||||
if (kernel_abi_version > 5 &&
|
|
||||||
!prof->policy.rules->add_rule(mediates_file, 0, AA_MAY_READ, 0, parseopts))
|
|
||||||
goto out;
|
|
||||||
if (features_supports_mount &&
|
|
||||||
!prof->policy.rules->add_rule(mediates_mount, 0, AA_MAY_READ, 0, parseopts))
|
|
||||||
goto out;
|
|
||||||
if (features_supports_dbus &&
|
|
||||||
!prof->policy.rules->add_rule(mediates_dbus, 0, AA_MAY_READ, 0, parseopts))
|
|
||||||
goto out;
|
|
||||||
if (features_supports_signal &&
|
|
||||||
!prof->policy.rules->add_rule(mediates_signal, 0, AA_MAY_READ, 0, parseopts))
|
|
||||||
goto out;
|
|
||||||
if (features_supports_ptrace &&
|
|
||||||
!prof->policy.rules->add_rule(mediates_ptrace, 0, AA_MAY_READ, 0, parseopts))
|
|
||||||
goto out;
|
|
||||||
if (features_supports_networkv8 &&
|
|
||||||
!prof->policy.rules->add_rule(mediates_netv8, 0, AA_MAY_READ, 0, parseopts))
|
|
||||||
goto out;
|
|
||||||
if (features_supports_unix &&
|
|
||||||
(!prof->policy.rules->add_rule(mediates_extended_net, 0, AA_MAY_READ, 0, parseopts) ||
|
|
||||||
!prof->policy.rules->add_rule(mediates_net_unix, 0, AA_MAY_READ, 0, parseopts)))
|
|
||||||
goto out;
|
|
||||||
if (features_supports_userns &&
|
if (features_supports_userns &&
|
||||||
!prof->policy.rules->add_rule(mediates_ns, 0, AA_MAY_READ, 0, parseopts))
|
!prof->policy.rules->add_rule(mediates_ns, 0, AA_MAY_READ, 0, parseopts))
|
||||||
goto out;
|
goto out;
|
||||||
if (features_supports_posix_mqueue &&
|
|
||||||
!prof->policy.rules->add_rule(mediates_posix_mqueue, 0, AA_MAY_READ, 0, parseopts))
|
/* don't add mediated classes to unconfined profiles */
|
||||||
goto out;
|
if (prof->flags.mode != MODE_UNCONFINED &&
|
||||||
if (features_supports_sysv_mqueue &&
|
prof->flags.mode != MODE_DEFAULT_ALLOW) {
|
||||||
!prof->policy.rules->add_rule(mediates_sysv_mqueue, 0, AA_MAY_READ, 0, parseopts))
|
/* note: this activates fs based unix domain sockets mediation on connect */
|
||||||
goto out;
|
if (kernel_abi_version > 5 &&
|
||||||
if (features_supports_io_uring &&
|
!prof->policy.rules->add_rule(mediates_file, 0, AA_MAY_READ, 0, parseopts))
|
||||||
!prof->policy.rules->add_rule(mediates_io_uring, 0, AA_MAY_READ, 0, parseopts))
|
goto out;
|
||||||
goto out;
|
if (features_supports_mount &&
|
||||||
|
!prof->policy.rules->add_rule(mediates_mount, 0, AA_MAY_READ, 0, parseopts))
|
||||||
|
goto out;
|
||||||
|
if (features_supports_dbus &&
|
||||||
|
!prof->policy.rules->add_rule(mediates_dbus, 0, AA_MAY_READ, 0, parseopts))
|
||||||
|
goto out;
|
||||||
|
if (features_supports_signal &&
|
||||||
|
!prof->policy.rules->add_rule(mediates_signal, 0, AA_MAY_READ, 0, parseopts))
|
||||||
|
goto out;
|
||||||
|
if (features_supports_ptrace &&
|
||||||
|
!prof->policy.rules->add_rule(mediates_ptrace, 0, AA_MAY_READ, 0, parseopts))
|
||||||
|
goto out;
|
||||||
|
if (features_supports_networkv8 &&
|
||||||
|
!prof->policy.rules->add_rule(mediates_netv8, 0, AA_MAY_READ, 0, parseopts))
|
||||||
|
goto out;
|
||||||
|
if (features_supports_unix &&
|
||||||
|
(!prof->policy.rules->add_rule(mediates_extended_net, 0, AA_MAY_READ, 0, parseopts) ||
|
||||||
|
!prof->policy.rules->add_rule(mediates_net_unix, 0, AA_MAY_READ, 0, parseopts)))
|
||||||
|
goto out;
|
||||||
|
if (features_supports_posix_mqueue &&
|
||||||
|
!prof->policy.rules->add_rule(mediates_posix_mqueue, 0, AA_MAY_READ, 0, parseopts))
|
||||||
|
goto out;
|
||||||
|
if (features_supports_sysv_mqueue &&
|
||||||
|
!prof->policy.rules->add_rule(mediates_sysv_mqueue, 0, AA_MAY_READ, 0, parseopts))
|
||||||
|
goto out;
|
||||||
|
if (features_supports_io_uring &&
|
||||||
|
!prof->policy.rules->add_rule(mediates_io_uring, 0, AA_MAY_READ, 0, parseopts))
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
if (prof->policy.rules->rule_count > 0) {
|
if (prof->policy.rules->rule_count > 0) {
|
||||||
int xmatch_len = 0;
|
int xmatch_len = 0;
|
||||||
|
@@ -253,13 +253,14 @@ remove_profiles() {
|
|||||||
retval=0
|
retval=0
|
||||||
# We filter child profiles as removing the parent will remove
|
# We filter child profiles as removing the parent will remove
|
||||||
# the children
|
# the children
|
||||||
sed -e "s/ (\(enforce\|complain\))$//" "$SFS_MOUNTPOINT/profiles" | \
|
sed -e "s/ (\(enforce\|complain\|unconfined\))$//" "$SFS_MOUNTPOINT/profiles" | \
|
||||||
LC_COLLATE=C sort | grep -v // | {
|
LC_COLLATE=C sort | grep -v // | {
|
||||||
while read -r profile ; do
|
while read -r profile ; do
|
||||||
printf "%s" "$profile" > "$SFS_MOUNTPOINT/.remove"
|
printf "%s" "$profile" > "$SFS_MOUNTPOINT/.remove"
|
||||||
rc=$?
|
rc=$?
|
||||||
if [ "$rc" -ne 0 ] ; then
|
if [ "$rc" -ne 0 ] ; then
|
||||||
retval=$rc
|
retval=$rc
|
||||||
|
aa_log_failure_msg "Unloading profile '$profile' failed"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
return "$retval"
|
return "$retval"
|
||||||
|
@@ -643,6 +643,18 @@ verify_binary_equality "attachment slash filtering" \
|
|||||||
@{FOO}=/foo
|
@{FOO}=/foo
|
||||||
/t @{BAR}/@{FOO} { }"
|
/t @{BAR}/@{FOO} { }"
|
||||||
|
|
||||||
|
# verify comment at end of variable assignment is not treated as a value
|
||||||
|
verify_binary_equality "comment at end of set var" \
|
||||||
|
"/t { /bin/ r, }" \
|
||||||
|
"@{BAR}=/bin/ #a tail comment
|
||||||
|
/t { @{BAR} r, }"
|
||||||
|
|
||||||
|
verify_binary_equality "value like comment at end of set var" \
|
||||||
|
"/t { /{bin/,#value} r, }" \
|
||||||
|
"@{BAR}=bin/ \#value
|
||||||
|
/t { /@{BAR} r, }"
|
||||||
|
|
||||||
|
|
||||||
# This can potentially fail as ideally it requires a better dfa comparison
|
# This can potentially fail as ideally it requires a better dfa comparison
|
||||||
# routine as it can generates hormomorphic dfas. The enumeration of the
|
# routine as it can generates hormomorphic dfas. The enumeration of the
|
||||||
# dfas dumped will be different, even if the binary is the same
|
# dfas dumped will be different, even if the binary is the same
|
||||||
|
9
parser/tst/simple_tests/mount/ok_opt_85.sd
Normal file
9
parser/tst/simple_tests/mount/ok_opt_85.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
#=Description test globbed destination MR 1195
|
||||||
|
#=EXRESULT PASS
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount options=(rw, make-slave) -> **,
|
||||||
|
mount options=(rw) foo -> **,
|
||||||
|
mount fstype=tmpfs options=(rw) foo -> **,
|
||||||
|
mount -> **,
|
||||||
|
}
|
9
parser/tst/simple_tests/mount/ok_quoted_1.sd
Normal file
9
parser/tst/simple_tests/mount/ok_quoted_1.sd
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#
|
||||||
|
#=Description basic mount rules with quoted paths
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
mount "" -> "/",
|
||||||
|
mount "" -> "/tmp/",
|
||||||
|
umount "/",
|
||||||
|
}
|
8
parser/tst/simple_tests/network/network_bad_83.sd
Normal file
8
parser/tst/simple_tests/network/network_bad_83.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION invalid family for inet conditionals
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
network unix ip=127.0.0.1 port=1234 peer=(ip=127.0.0.1 port=1234),
|
||||||
|
|
||||||
|
}
|
8
parser/tst/simple_tests/network/network_bad_84.sd
Normal file
8
parser/tst/simple_tests/network/network_bad_84.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION invalid family for inet conditionals
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
network netlink ip=127.0.0.1,
|
||||||
|
|
||||||
|
}
|
8
parser/tst/simple_tests/network/network_bad_85.sd
Normal file
8
parser/tst/simple_tests/network/network_bad_85.sd
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION invalid family for inet conditionals
|
||||||
|
#=EXRESULT FAIL
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
network packet peer=(port=1234),
|
||||||
|
|
||||||
|
}
|
@@ -5,5 +5,7 @@
|
|||||||
/usr/bin/foo {
|
/usr/bin/foo {
|
||||||
network inet ip=10.0.2.1 peer=(ip=10.0.2.1),
|
network inet ip=10.0.2.1 peer=(ip=10.0.2.1),
|
||||||
network inet tcp ip=192.168.2.254 peer=(ip=192.168.2.254),
|
network inet tcp ip=192.168.2.254 peer=(ip=192.168.2.254),
|
||||||
|
network stream ip=192.168.2.254 peer=(ip=192.168.2.254),
|
||||||
|
network raw ip=10.0.2.1 peer=(ip=10.0.2.1),
|
||||||
|
|
||||||
}
|
}
|
||||||
|
11
parser/tst/simple_tests/network/network_ok_44.sd
Normal file
11
parser/tst/simple_tests/network/network_ok_44.sd
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#
|
||||||
|
#=DESCRIPTION network none ip conditional test
|
||||||
|
#=EXRESULT PASS
|
||||||
|
#
|
||||||
|
/usr/bin/foo {
|
||||||
|
network ip=none,
|
||||||
|
network peer=(ip=none),
|
||||||
|
network inet ip=none peer=(ip=none),
|
||||||
|
network inet tcp ip=none peer=(ip=none),
|
||||||
|
|
||||||
|
}
|
25
parser/tst/simple_tests/regressions/ok_normalize.sd
Normal file
25
parser/tst/simple_tests/regressions/ok_normalize.sd
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#
|
||||||
|
#=Description caused an infinite loop in expr normalization
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
# This test triggers an infinite loop bug in expr normalization
|
||||||
|
# Note: this test might be able to be reduced more but, each element appears
|
||||||
|
# to be required to trigger the bug.
|
||||||
|
# that is the initial var assignment, += with the "comment" at the end
|
||||||
|
# (which is a separate bug), the expansion in the 2nd variable and then
|
||||||
|
# the use of the 2nd variable.
|
||||||
|
# This seems to be due to difference in consistency check between expansion
|
||||||
|
# at parse time and variable expansion.
|
||||||
|
# eg. expanding @{exec_path} manually will result in a failure to parse
|
||||||
|
# see: https://gitlab.com/apparmor/apparmor/-/issues/398
|
||||||
|
|
||||||
|
@{var}=*-linux-gnu*
|
||||||
|
@{var}+=*-suse-linux* #aa:only opensuse
|
||||||
|
|
||||||
|
@{exec_path} = /{,@{var}/}t
|
||||||
|
|
||||||
|
profile test {
|
||||||
|
|
||||||
|
|
||||||
|
@{exec_path} mr,
|
||||||
|
}
|
@@ -28,6 +28,7 @@
|
|||||||
owner @{run}/user/*/gdm/Xauthority r,
|
owner @{run}/user/*/gdm/Xauthority r,
|
||||||
owner @{run}/user/*/X11/Xauthority r,
|
owner @{run}/user/*/X11/Xauthority r,
|
||||||
owner @{run}/user/*/xauth_* r,
|
owner @{run}/user/*/xauth_* r,
|
||||||
|
owner /tmp/xauth_?????? r,
|
||||||
|
|
||||||
# the unix socket to use to connect to the display
|
# the unix socket to use to connect to the display
|
||||||
/tmp/.X11-unix/* rw,
|
/tmp/.X11-unix/* rw,
|
||||||
|
@@ -35,6 +35,13 @@
|
|||||||
owner /proc/@{pid}/loginuid r,
|
owner /proc/@{pid}/loginuid r,
|
||||||
/{,usr/}{,s}bin/unix_chkpwd Px,
|
/{,usr/}{,s}bin/unix_chkpwd Px,
|
||||||
|
|
||||||
|
# pam_env
|
||||||
|
@{etc_ro}/environment r,
|
||||||
|
|
||||||
|
# pam_limit
|
||||||
|
@{etc_ro}/security/limits.d/ r,
|
||||||
|
@{etc_ro}/security/limits.d/*.conf r,
|
||||||
|
|
||||||
# gssapi
|
# gssapi
|
||||||
@{etc_ro}/gss/mech r,
|
@{etc_ro}/gss/mech r,
|
||||||
@{etc_ro}/gss/mech.d/ r,
|
@{etc_ro}/gss/mech.d/ r,
|
||||||
|
@@ -98,6 +98,9 @@
|
|||||||
# best place -- but many profiles require it, and it is quite harmless.
|
# best place -- but many profiles require it, and it is quite harmless.
|
||||||
@{PROC}/sys/kernel/ngroups_max r,
|
@{PROC}/sys/kernel/ngroups_max r,
|
||||||
|
|
||||||
|
# Used to determine if Linux is running in FIPS mode
|
||||||
|
@{PROC}/sys/crypto/fips_enabled r,
|
||||||
|
|
||||||
# glibc's sysconf(3) routine to determine free memory, etc
|
# glibc's sysconf(3) routine to determine free memory, etc
|
||||||
@{PROC}/meminfo r,
|
@{PROC}/meminfo r,
|
||||||
@{PROC}/stat r,
|
@{PROC}/stat r,
|
||||||
|
@@ -22,5 +22,18 @@
|
|||||||
|
|
||||||
owner @{HOME}/.config/fcitx/dbus/* r,
|
owner @{HOME}/.config/fcitx/dbus/* r,
|
||||||
|
|
||||||
|
# Allow access to the Fcitx portal, supported by fcitx/fcitx5
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
path=/{,org/freedesktop/portal/}inputmethod
|
||||||
|
interface=org.fcitx.Fcitx.InputMethod1
|
||||||
|
member={CreateInputContext,Version}
|
||||||
|
peer=(name=org.freedesktop.portal.Fcitx),
|
||||||
|
|
||||||
|
dbus (send, receive)
|
||||||
|
bus=session
|
||||||
|
path=/{,org/freedesktop/portal/}inputcontext/**
|
||||||
|
interface=org.fcitx.Fcitx.InputContext1,
|
||||||
|
|
||||||
# Include additions to the abstraction
|
# Include additions to the abstraction
|
||||||
include if exists <abstractions/fcitx-strict.d>
|
include if exists <abstractions/fcitx-strict.d>
|
||||||
|
@@ -116,6 +116,7 @@
|
|||||||
network netlink raw,
|
network netlink raw,
|
||||||
|
|
||||||
# interface details
|
# interface details
|
||||||
|
@{PROC}/@{pid}/net/ipv6_route r,
|
||||||
@{PROC}/@{pid}/net/route r,
|
@{PROC}/@{pid}/net/route r,
|
||||||
|
|
||||||
# Include additions to the abstraction
|
# Include additions to the abstraction
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
abi <abi/4.0>,
|
abi <abi/4.0>,
|
||||||
|
|
||||||
/etc/samba/* r,
|
/etc/samba/* r,
|
||||||
|
/etc/gnutls/config r,
|
||||||
/usr/lib*/ldb/*.so mr,
|
/usr/lib*/ldb/*.so mr,
|
||||||
/usr/lib*/ldb2/*.so mr,
|
/usr/lib*/ldb2/*.so mr,
|
||||||
/usr/lib*/ldb2/modules/ldb/*.so mr,
|
/usr/lib*/ldb2/modules/ldb/*.so mr,
|
||||||
|
153
profiles/apparmor.d/abstractions/transmission-common
Normal file
153
profiles/apparmor.d/abstractions/transmission-common
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
# vim:syntax=apparmor
|
||||||
|
# LOGPROF-SUGGEST: no
|
||||||
|
# Author: Daniel Richard G. <skunk@iSKUNK.ORG>
|
||||||
|
|
||||||
|
include <abstractions/base>
|
||||||
|
include <abstractions/freedesktop.org>
|
||||||
|
include <abstractions/nameservice>
|
||||||
|
include <abstractions/openssl>
|
||||||
|
|
||||||
|
network inet dgram,
|
||||||
|
network inet6 dgram,
|
||||||
|
network netlink dgram,
|
||||||
|
network inet stream,
|
||||||
|
network inet6 stream,
|
||||||
|
|
||||||
|
dbus (bind)
|
||||||
|
bus=session
|
||||||
|
name=com.transmissionbt.Transmission,
|
||||||
|
dbus (bind)
|
||||||
|
bus=session
|
||||||
|
name=com.transmissionbt.transmission_*,
|
||||||
|
|
||||||
|
dbus (receive)
|
||||||
|
bus=session
|
||||||
|
path=/ca/desrt/dconf/Writer/user
|
||||||
|
interface=ca.desrt.dconf.Writer
|
||||||
|
member=Notify,
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
path=/ca/desrt/dconf/Writer/user
|
||||||
|
interface=ca.desrt.dconf.Writer
|
||||||
|
member=Change
|
||||||
|
peer=(name=ca.desrt.dconf),
|
||||||
|
|
||||||
|
dbus (receive)
|
||||||
|
bus=accessibility
|
||||||
|
path=/org/a11y/atspi/accessible/root
|
||||||
|
interface=org.freedesktop.DBus.Properties
|
||||||
|
member=Set,
|
||||||
|
dbus (send)
|
||||||
|
bus=accessibility
|
||||||
|
path=/org/a11y/atspi/accessible/root
|
||||||
|
interface=org.a11y.atspi.Socket
|
||||||
|
member=Embed
|
||||||
|
peer=(name=org.a11y.atspi.Registry),
|
||||||
|
dbus (send)
|
||||||
|
bus=accessibility
|
||||||
|
path=/org/a11y/atspi/registry
|
||||||
|
interface=org.a11y.atspi.Registry
|
||||||
|
member=GetRegisteredEvents
|
||||||
|
peer=(name=org.a11y.atspi.Registry),
|
||||||
|
dbus (send)
|
||||||
|
bus=accessibility
|
||||||
|
path=/org/a11y/atspi/registry/deviceeventcontroller
|
||||||
|
interface=org.a11y.atspi.DeviceEventController
|
||||||
|
member={GetDeviceEventListeners,GetKeystrokeListeners}
|
||||||
|
peer=(name=org.a11y.atspi.Registry),
|
||||||
|
|
||||||
|
dbus (send)
|
||||||
|
bus={accessibility,session}
|
||||||
|
path=/org/freedesktop/DBus
|
||||||
|
interface=org.freedesktop.DBus
|
||||||
|
member={AddMatch,GetNameOwner,Hello,ReleaseName,RemoveMatch,RequestName,StartServiceByName}
|
||||||
|
peer=(name=org.freedesktop.DBus),
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
interface=org.freedesktop.DBus.Introspectable
|
||||||
|
path=/StatusNotifierWatcher
|
||||||
|
member=Introspect
|
||||||
|
peer=(name=org.kde.StatusNotifierWatcher),
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
interface=org.freedesktop.DBus.Properties
|
||||||
|
path=/StatusNotifierWatcher
|
||||||
|
member=Get
|
||||||
|
peer=(name=org.kde.StatusNotifierWatcher),
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
interface=org.freedesktop.DBus.Properties
|
||||||
|
path=/org/a11y/bus
|
||||||
|
member=Get
|
||||||
|
peer=(name=org.a11y.Bus),
|
||||||
|
dbus (send)
|
||||||
|
bus=system
|
||||||
|
interface=org.freedesktop.DBus.Properties
|
||||||
|
path=/org/freedesktop/hostname1
|
||||||
|
member=GetAll,
|
||||||
|
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
interface=org.freedesktop.Notifications
|
||||||
|
path=/org/freedesktop/Notifications
|
||||||
|
member={GetCapabilities,Notify},
|
||||||
|
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
path=/org/gtk/Private/RemoteVolumeMonitor
|
||||||
|
interface=org.gtk.Private.RemoteVolumeMonitor
|
||||||
|
member={IsSupported,List},
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
path=/org/gtk/vfs/Daemon
|
||||||
|
interface=org.gtk.vfs.Daemon
|
||||||
|
member={GetConnection,ListMonitorImplementations},
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
path=/org/gtk/vfs/mount/[1-9]*
|
||||||
|
interface=org.gtk.vfs.Mount
|
||||||
|
member={CreateFileMonitor,Enumerate,QueryInfo},
|
||||||
|
dbus (receive)
|
||||||
|
bus=session
|
||||||
|
path=/org/gtk/vfs/mounttracker
|
||||||
|
interface=org.gtk.vfs.MountTracker
|
||||||
|
member=Mounted,
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
path=/org/gtk/vfs/mounttracker
|
||||||
|
interface=org.gtk.vfs.MountTracker
|
||||||
|
member={ListMountableInfo,ListMounts2,LookupMount},
|
||||||
|
|
||||||
|
@{PROC}/sys/kernel/random/uuid r,
|
||||||
|
|
||||||
|
owner @{PROC}/@{pid}/mountinfo r,
|
||||||
|
owner @{PROC}/@{pid}/mounts r,
|
||||||
|
|
||||||
|
owner @{run}/user/@{uid}/gvfsd/socket-* rw,
|
||||||
|
|
||||||
|
@{etc_ro}/fstab r,
|
||||||
|
|
||||||
|
@{system_share_dirs}/hwdata/** r,
|
||||||
|
@{system_share_dirs}/lxqt/** r,
|
||||||
|
|
||||||
|
owner /tmp/tr_session_id_* rwk,
|
||||||
|
|
||||||
|
# allow a top-level directory listing
|
||||||
|
@{HOME}/ r,
|
||||||
|
|
||||||
|
owner @{HOME}/.cache/transmission/ w,
|
||||||
|
owner @{HOME}/.cache/transmission/** rw,
|
||||||
|
owner @{HOME}/.config/transmission/ w,
|
||||||
|
owner @{HOME}/.config/transmission/** rw,
|
||||||
|
|
||||||
|
owner @{HOME}/.config/lxqt/lxqt.conf r,
|
||||||
|
|
||||||
|
owner @{HOME}/@{XDG_DOWNLOAD_DIR}/ r,
|
||||||
|
owner @{HOME}/@{XDG_DOWNLOAD_DIR}/** rw,
|
||||||
|
|
||||||
|
# exclude these for now
|
||||||
|
deny /usr/share/thumbnailers/ r,
|
||||||
|
deny @{HOME}/.local/share/gvfs-metadata/** r,
|
||||||
|
deny @{HOME}/.config/lxqt/** rw,
|
||||||
|
|
||||||
|
include if exists <abstractions/transmission-common.d>
|
@@ -13,6 +13,8 @@
|
|||||||
|
|
||||||
# some services update wtmp, utmp, and lastlog with per-user
|
# some services update wtmp, utmp, and lastlog with per-user
|
||||||
# connection information
|
# connection information
|
||||||
|
/var/lib/wtmpdb/ r,
|
||||||
|
/var/lib/wtmpdb/wtmp.db{,-journal} rwlk,
|
||||||
/var/log/lastlog rwk,
|
/var/log/lastlog rwk,
|
||||||
/var/log/wtmp rwk,
|
/var/log/wtmp rwk,
|
||||||
/var/log/btmp rwk,
|
/var/log/btmp rwk,
|
||||||
|
12
profiles/apparmor.d/balena-etcher
Normal file
12
profiles/apparmor.d/balena-etcher
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# This profile allows everything and only exists to give the
|
||||||
|
# application a name instead of having the label "unconfined"
|
||||||
|
|
||||||
|
abi <abi/4.0>,
|
||||||
|
include <tunables/global>
|
||||||
|
|
||||||
|
profile balena-etcher /usr/lib/balena-etcher/balena-etcher flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/balena-etcher>
|
||||||
|
}
|
14
profiles/apparmor.d/chromium
Normal file
14
profiles/apparmor.d/chromium
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# This profile allows everything and only exists to give the
|
||||||
|
# application a name instead of having the label "unconfined"
|
||||||
|
|
||||||
|
abi <abi/4.0>,
|
||||||
|
include <tunables/global>
|
||||||
|
|
||||||
|
@{chromium} = {,ungoogled-}chromium{,-browser}
|
||||||
|
|
||||||
|
profile chromium /usr/lib/@{chromium}/@{chromium} flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/chromium>
|
||||||
|
}
|
@@ -4,7 +4,7 @@
|
|||||||
abi <abi/4.0>,
|
abi <abi/4.0>,
|
||||||
include <tunables/global>
|
include <tunables/global>
|
||||||
|
|
||||||
profile firefox /usr/lib/firefox{,-esr,-beta,-devedition,-nightly}/firefox{,-esr,-bin} flags=(unconfined) {
|
profile firefox /{usr/lib/firefox{,-esr,-beta,-devedition,-nightly},opt/firefox}/firefox{,-esr,-bin} flags=(unconfined) {
|
||||||
userns,
|
userns,
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
12
profiles/apparmor.d/foliate
Normal file
12
profiles/apparmor.d/foliate
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# This profile allows everything and only exists to give the
|
||||||
|
# application a name instead of having the label "unconfined"
|
||||||
|
|
||||||
|
abi <abi/4.0>,
|
||||||
|
include <tunables/global>
|
||||||
|
|
||||||
|
profile foliate /usr/bin/foliate flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/foliate>
|
||||||
|
}
|
@@ -36,6 +36,9 @@ profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) {
|
|||||||
@{run}/php*-fpm.pid rw,
|
@{run}/php*-fpm.pid rw,
|
||||||
@{run}/php{,-fpm}/php*-fpm.sock rwlk,
|
@{run}/php{,-fpm}/php*-fpm.sock rwlk,
|
||||||
|
|
||||||
|
# LP: #2061113
|
||||||
|
owner @{run}/systemd/notify w,
|
||||||
|
|
||||||
# to reload
|
# to reload
|
||||||
/usr/sbin/php-fpm* rix,
|
/usr/sbin/php-fpm* rix,
|
||||||
|
|
||||||
|
@@ -17,8 +17,13 @@ profile plasmashell /usr/bin/plasmashell {
|
|||||||
unix,
|
unix,
|
||||||
ptrace,
|
ptrace,
|
||||||
|
|
||||||
/usr/lib/x86_64-linux-gnu/qt5/libexec/QtWebEngineProcess cx -> &plasmashell//QtWebEngineProcess,
|
# allow executing QtWebEngineProcess with full permissions including userns (using profile stacking to avoid no_new_privs issues)
|
||||||
|
/usr/lib/x86_64-linux-gnu/qt[56]/libexec/QtWebEngineProcess cx -> &plasmashell//QtWebEngineProcess,
|
||||||
|
/usr/libexec/qt[56]/QtWebEngineProcess cx -> &plasmashell//QtWebEngineProcess,
|
||||||
|
|
||||||
|
# allow to execute all other programs under their own profile, or to run unconfined
|
||||||
/** pux,
|
/** pux,
|
||||||
|
|
||||||
/{,**} mrwlk,
|
/{,**} mrwlk,
|
||||||
|
|
||||||
profile QtWebEngineProcess {
|
profile QtWebEngineProcess {
|
||||||
|
@@ -4,7 +4,7 @@
|
|||||||
abi <abi/4.0>,
|
abi <abi/4.0>,
|
||||||
include <tunables/global>
|
include <tunables/global>
|
||||||
|
|
||||||
profile runc /usr/sbin/runc flags=(unconfined) {
|
profile runc /usr/{bin,sbin}/runc flags=(unconfined) {
|
||||||
userns,
|
userns,
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
@@ -16,12 +16,14 @@ include <tunables/global>
|
|||||||
profile samba-dcerpcd /usr/lib*/samba/{,samba/}samba-dcerpcd {
|
profile samba-dcerpcd /usr/lib*/samba/{,samba/}samba-dcerpcd {
|
||||||
include <abstractions/samba-rpcd>
|
include <abstractions/samba-rpcd>
|
||||||
|
|
||||||
|
capability sys_resource,
|
||||||
|
|
||||||
@{run}/{,samba/}samba-dcerpcd.pid rwk,
|
@{run}/{,samba/}samba-dcerpcd.pid rwk,
|
||||||
|
|
||||||
/usr/lib*/samba/{,samba/}samba-dcerpcd mr,
|
/usr/lib*/samba/{,samba/}samba-dcerpcd mr,
|
||||||
|
|
||||||
/usr/lib*/samba/ r,
|
/usr/lib*/samba/ r,
|
||||||
/usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg} Px -> samba-rpcd,
|
/usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg,witness} Px -> samba-rpcd,
|
||||||
/usr/lib*/samba/{,samba/}rpcd_classic Px -> samba-rpcd-classic,
|
/usr/lib*/samba/{,samba/}rpcd_classic Px -> samba-rpcd-classic,
|
||||||
/usr/lib*/samba/{,samba/}rpcd_spoolss Px -> samba-rpcd-spoolss,
|
/usr/lib*/samba/{,samba/}rpcd_spoolss Px -> samba-rpcd-spoolss,
|
||||||
|
|
||||||
|
@@ -13,10 +13,15 @@ abi <abi/4.0>,
|
|||||||
|
|
||||||
include <tunables/global>
|
include <tunables/global>
|
||||||
|
|
||||||
profile samba-rpcd /usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg} {
|
profile samba-rpcd /usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg,witness} {
|
||||||
include <abstractions/samba-rpcd>
|
include <abstractions/samba-rpcd>
|
||||||
/usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg} mr,
|
|
||||||
|
|
||||||
|
capability sys_resource,
|
||||||
|
|
||||||
|
/usr/lib*/samba/{,samba/}rpcd_{mdssvc,epmapper,rpcecho,fsrvp,lsad,winreg,witness} mr,
|
||||||
|
|
||||||
|
@{run}/samba/ncalrpc/np/lsarpc wr,
|
||||||
|
@{run}/samba/ncalrpc/np/mdssvc wr,
|
||||||
@{run}/samba/ncalrpc/np/winreg wr,
|
@{run}/samba/ncalrpc/np/winreg wr,
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
@@ -17,8 +17,18 @@ profile samba-rpcd-classic /usr/lib*/samba/{,samba/}rpcd_classic {
|
|||||||
include <abstractions/samba-rpcd>
|
include <abstractions/samba-rpcd>
|
||||||
include <abstractions/wutmp>
|
include <abstractions/wutmp>
|
||||||
|
|
||||||
|
capability sys_resource,
|
||||||
|
|
||||||
/usr/lib*/samba/{,samba/}rpcd_classic mr,
|
/usr/lib*/samba/{,samba/}rpcd_classic mr,
|
||||||
|
|
||||||
|
@{run}/samba/ncalrpc/np/srvsvc wr,
|
||||||
|
@{run}/samba/ncalrpc/np/winreg wr,
|
||||||
|
/dev/urandom rw,
|
||||||
|
|
||||||
|
/usr/lib*/samba/{,samba/}samba-dcerpcd Px -> samba-dcerpcd,
|
||||||
|
|
||||||
|
@{HOMEDIRS}/** lrwk,
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
include if exists <local/samba-rpcd-classic>
|
include if exists <local/samba-rpcd-classic>
|
||||||
}
|
}
|
||||||
|
76
profiles/apparmor.d/transmission
Normal file
76
profiles/apparmor.d/transmission
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
# vim:syntax=apparmor
|
||||||
|
# Author: Daniel Richard G. <skunk@iSKUNK.ORG>
|
||||||
|
|
||||||
|
abi <abi/4.0>,
|
||||||
|
|
||||||
|
include <tunables/global>
|
||||||
|
|
||||||
|
profile transmission-daemon /usr/bin/transmission-daemon flags=(complain) {
|
||||||
|
# Don't use abstractions/transmission-common here, as the
|
||||||
|
# access needed is narrower than the user applications
|
||||||
|
include <abstractions/base>
|
||||||
|
include <abstractions/nameservice>
|
||||||
|
include <abstractions/openssl>
|
||||||
|
|
||||||
|
network inet dgram,
|
||||||
|
network inet6 dgram,
|
||||||
|
network inet stream,
|
||||||
|
network inet6 stream,
|
||||||
|
|
||||||
|
owner @{PROC}/@{pid}/mounts r,
|
||||||
|
@{PROC}/sys/kernel/random/uuid r,
|
||||||
|
|
||||||
|
@{run}/systemd/notify w,
|
||||||
|
|
||||||
|
/etc/transmission-daemon/** r,
|
||||||
|
owner /etc/transmission-daemon/settings.json{,.tmp.*} rw,
|
||||||
|
|
||||||
|
owner /tmp/tr_session_id_* rwk,
|
||||||
|
|
||||||
|
/usr/share/transmission/web/** r,
|
||||||
|
|
||||||
|
owner /var/lib/transmission-daemon/.config/transmission-daemon/** rw,
|
||||||
|
owner /var/lib/transmission-daemon/downloads/** rw,
|
||||||
|
owner /var/lib/transmission-daemon/info/** rw,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/transmission>
|
||||||
|
include if exists <local/transmission-daemon>
|
||||||
|
}
|
||||||
|
|
||||||
|
profile transmission-cli /usr/bin/transmission-cli flags=(complain) {
|
||||||
|
include <abstractions/transmission-common>
|
||||||
|
include <abstractions/consoles>
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/transmission>
|
||||||
|
include if exists <local/transmission-cli>
|
||||||
|
}
|
||||||
|
|
||||||
|
profile transmission-gtk /usr/bin/transmission-gtk flags=(complain) {
|
||||||
|
include <abstractions/transmission-common>
|
||||||
|
include <abstractions/dbus-session-strict>
|
||||||
|
include <abstractions/dconf>
|
||||||
|
include <abstractions/gnome>
|
||||||
|
|
||||||
|
owner @{run}/user/*/dconf/user w,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/transmission>
|
||||||
|
include if exists <local/transmission-gtk>
|
||||||
|
}
|
||||||
|
|
||||||
|
profile transmission-qt /usr/bin/transmission-qt flags=(complain) {
|
||||||
|
include <abstractions/transmission-common>
|
||||||
|
include <abstractions/dbus-accessibility-strict>
|
||||||
|
include <abstractions/dbus-network-manager-strict>
|
||||||
|
include <abstractions/dbus-session-strict>
|
||||||
|
include <abstractions/fonts>
|
||||||
|
include <abstractions/X>
|
||||||
|
include <abstractions/qt5>
|
||||||
|
include <abstractions/qt5-settings-write>
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/transmission>
|
||||||
|
include if exists <local/transmission-qt>
|
||||||
|
}
|
@@ -8,6 +8,7 @@ profile nmbd /usr/{bin,sbin}/nmbd {
|
|||||||
include <abstractions/samba>
|
include <abstractions/samba>
|
||||||
|
|
||||||
capability net_bind_service,
|
capability net_bind_service,
|
||||||
|
capability sys_resource,
|
||||||
|
|
||||||
@{PROC}/sys/kernel/core_pattern r,
|
@{PROC}/sys/kernel/core_pattern r,
|
||||||
|
|
||||||
|
@@ -32,9 +32,6 @@ profile smbd /usr/{bin,sbin}/smbd {
|
|||||||
/etc/samba/* rwk,
|
/etc/samba/* rwk,
|
||||||
@{PROC}/@{pid}/mounts r,
|
@{PROC}/@{pid}/mounts r,
|
||||||
@{PROC}/sys/kernel/core_pattern r,
|
@{PROC}/sys/kernel/core_pattern r,
|
||||||
/usr/etc/environment r,
|
|
||||||
/usr/etc/security/limits.d/ r,
|
|
||||||
/usr/etc/security/limits.d/*.conf r,
|
|
||||||
/usr/lib*/samba/vfs/*.so mr,
|
/usr/lib*/samba/vfs/*.so mr,
|
||||||
/usr/lib*/samba/auth/*.so mr,
|
/usr/lib*/samba/auth/*.so mr,
|
||||||
/usr/lib*/samba/charset/*.so mr,
|
/usr/lib*/samba/charset/*.so mr,
|
||||||
|
12
profiles/apparmor.d/wike
Normal file
12
profiles/apparmor.d/wike
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# This profile allows everything and only exists to give the
|
||||||
|
# application a name instead of having the label "unconfined"
|
||||||
|
|
||||||
|
abi <abi/4.0>,
|
||||||
|
include <tunables/global>
|
||||||
|
|
||||||
|
profile wike /usr/bin/wike flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/wike>
|
||||||
|
}
|
68
profiles/apparmor/profiles/extras/bwrap-userns-restrict
Normal file
68
profiles/apparmor/profiles/extras/bwrap-userns-restrict
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# This profile allows almost everything and only exists to allow
|
||||||
|
# bwrap to work on a system with user namespace restrictions
|
||||||
|
# being enforced.
|
||||||
|
# bwrap is allowed access to user namespaces and capabilities
|
||||||
|
# within the user namespace, but its children do not have
|
||||||
|
# capabilities, blocking bwrap from being able to be used to
|
||||||
|
# arbitrarily by-pass the user namespace restrictions.
|
||||||
|
#
|
||||||
|
# Note: the bwrap child is stacked against the bwrap profile due to
|
||||||
|
# bwraps use of no-new-privs
|
||||||
|
|
||||||
|
# disabled by default as it can break some use cases on a system that
|
||||||
|
# doesn't have or has disable user namespace restrictions for unconfined
|
||||||
|
# use aa-enforce to enable it
|
||||||
|
|
||||||
|
abi <abi/4.0>,
|
||||||
|
|
||||||
|
include <tunables/global>
|
||||||
|
|
||||||
|
profile bwrap /usr/bin/bwrap flags=(attach_disconnected,mediate_deleted) {
|
||||||
|
allow capability,
|
||||||
|
# not allow all, to allow for pix stack
|
||||||
|
# sadly we have to allow m every where to allow children to work under
|
||||||
|
# stacking.
|
||||||
|
allow file rwlkm /{**,},
|
||||||
|
allow network,
|
||||||
|
allow unix,
|
||||||
|
allow ptrace,
|
||||||
|
allow signal,
|
||||||
|
allow mqueue,
|
||||||
|
allow io_uring,
|
||||||
|
allow userns,
|
||||||
|
allow mount,
|
||||||
|
allow umount,
|
||||||
|
allow pivot_root,
|
||||||
|
allow dbus,
|
||||||
|
allow px /** -> bwrap//&unpriv_bwrap,
|
||||||
|
|
||||||
|
# the local include should not be used without understanding the userns
|
||||||
|
# restriction.
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/bwrap-userns-restrict>
|
||||||
|
}
|
||||||
|
|
||||||
|
profile unpriv_bwrap flags=(attach_disconnected,mediate_deleted) {
|
||||||
|
# not allow all, to allow for pix stack
|
||||||
|
allow file rwlkm /{**,},
|
||||||
|
allow network,
|
||||||
|
allow unix,
|
||||||
|
allow ptrace,
|
||||||
|
allow signal,
|
||||||
|
allow mqueue,
|
||||||
|
allow io_uring,
|
||||||
|
allow userns,
|
||||||
|
allow mount,
|
||||||
|
allow umount,
|
||||||
|
allow pivot_root,
|
||||||
|
allow dbus,
|
||||||
|
|
||||||
|
allow pix /** -> &unpriv_bwrap,
|
||||||
|
|
||||||
|
audit deny capability,
|
||||||
|
|
||||||
|
# the local include should not be used without understanding the userns
|
||||||
|
# restriction.
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/unpriv_bwrap>
|
||||||
|
}
|
@@ -12,9 +12,9 @@
|
|||||||
|
|
||||||
abi <abi/4.0>,
|
abi <abi/4.0>,
|
||||||
|
|
||||||
#include <tunables/global>
|
include <tunables/global>
|
||||||
|
|
||||||
@{chromium} = chromium{,-browser}
|
@{chromium} = {,ungoogled-}chromium{,-browser}
|
||||||
|
|
||||||
# We need 'flags=(attach_disconnected)' in newer chromium versions
|
# We need 'flags=(attach_disconnected)' in newer chromium versions
|
||||||
profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconnected) {
|
profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconnected) {
|
||||||
@@ -22,10 +22,13 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
include <abstractions/cups-client>
|
include <abstractions/cups-client>
|
||||||
include <abstractions/dbus-session>
|
include <abstractions/dbus-session>
|
||||||
include <abstractions/dbus-strict>
|
include <abstractions/dbus-strict>
|
||||||
|
include <abstractions/fonts>
|
||||||
include <abstractions/gnome>
|
include <abstractions/gnome>
|
||||||
include <abstractions/ibus>
|
include <abstractions/ibus>
|
||||||
|
include <abstractions/mesa>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/user-tmp>
|
include <abstractions/user-tmp>
|
||||||
|
include <abstractions/vulkan>
|
||||||
|
|
||||||
# This include specifies which ubuntu-browsers.d abstractions to use. Eg, if
|
# This include specifies which ubuntu-browsers.d abstractions to use. Eg, if
|
||||||
# you want access to productivity applications, adjust the following file
|
# you want access to productivity applications, adjust the following file
|
||||||
@@ -57,14 +60,48 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
member={EnumerateDevices,GetDisplayDevice}
|
member={EnumerateDevices,GetDisplayDevice}
|
||||||
peer=(label=unconfined),
|
peer=(label=unconfined),
|
||||||
|
|
||||||
# ???
|
dbus (send)
|
||||||
deny dbus (send)
|
|
||||||
bus=system
|
bus=system
|
||||||
path=/org/freedesktop/hostname1
|
path=/org/freedesktop/hostname1
|
||||||
interface=org.freedesktop.DBus.Properties
|
interface=org.freedesktop.DBus.Properties
|
||||||
member=GetAll
|
member=GetAll
|
||||||
peer=(label=unconfined),
|
peer=(label=unconfined),
|
||||||
|
|
||||||
|
dbus (receive)
|
||||||
|
bus=system
|
||||||
|
path=/org/freedesktop/login1
|
||||||
|
interface=org.freedesktop.login1.Manager
|
||||||
|
member={SessionNew,SessionRemoved}
|
||||||
|
peer=(label=unconfined),
|
||||||
|
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
path=/org/freedesktop/DBus
|
||||||
|
interface=org.freedesktop.DBus
|
||||||
|
member={AddMatch,GetNameOwner,Hello,NameHasOwner,RemoveMatch,StartServiceByName}
|
||||||
|
peer=(name=org.freedesktop.DBus),
|
||||||
|
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
path=/org/freedesktop/portal/desktop
|
||||||
|
interface=org.freedesktop.DBus.Properties
|
||||||
|
member=Get
|
||||||
|
peer=(name=org.freedesktop.portal.Desktop),
|
||||||
|
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
path=/org/freedesktop/Notifications
|
||||||
|
interface=org.freedesktop.Notifications
|
||||||
|
member={GetCapabilities,GetServerInformation}
|
||||||
|
peer=(name=org.freedesktop.Notifications),
|
||||||
|
|
||||||
|
dbus (send)
|
||||||
|
bus=session
|
||||||
|
path=/org/gtk/vfs/mounttracker
|
||||||
|
interface=org.gtk.vfs.MountTracker
|
||||||
|
member=ListMountableInfo
|
||||||
|
peer=(label=unconfined),
|
||||||
|
|
||||||
# Networking
|
# Networking
|
||||||
network inet stream,
|
network inet stream,
|
||||||
network inet6 stream,
|
network inet6 stream,
|
||||||
@@ -72,30 +109,35 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
@{PROC}/@{pid}/net/ipv6_route r,
|
@{PROC}/@{pid}/net/ipv6_route r,
|
||||||
|
|
||||||
# Should maybe be in abstractions
|
# Should maybe be in abstractions
|
||||||
|
/etc/fstab r,
|
||||||
/etc/mime.types r,
|
/etc/mime.types r,
|
||||||
/etc/mailcap r,
|
/etc/mailcap r,
|
||||||
/etc/mtab r,
|
/etc/mtab r,
|
||||||
/etc/xdg/xubuntu/applications/defaults.list r,
|
/etc/xdg/xubuntu/applications/defaults.list r,
|
||||||
|
owner @{HOME}/.cache/thumbnails/** r,
|
||||||
owner @{HOME}/.local/share/applications/defaults.list r,
|
owner @{HOME}/.local/share/applications/defaults.list r,
|
||||||
owner @{HOME}/.local/share/applications/mimeinfo.cache r,
|
owner @{HOME}/.local/share/applications/mimeinfo.cache r,
|
||||||
/tmp/.X[0-9]*-lock r,
|
/tmp/.X[0-9]*-lock r,
|
||||||
|
|
||||||
@{PROC}/self/exe ixr,
|
@{PROC}/self/exe ixr,
|
||||||
@{PROC}/@{pid}/fd/ r,
|
|
||||||
@{PROC}/filesystems r,
|
@{PROC}/filesystems r,
|
||||||
|
@{PROC}/pressure/{cpu,io,memory} r,
|
||||||
@{PROC}/vmstat r,
|
@{PROC}/vmstat r,
|
||||||
@{PROC}/ r,
|
@{PROC}/ r,
|
||||||
@{PROC}/@{pid}/task/@{tid}/stat r,
|
owner @{PROC}/@{pid}/task/@{tid}/stat r,
|
||||||
|
owner @{PROC}/@{pid}/clear_refs w,
|
||||||
owner @{PROC}/@{pid}/cmdline r,
|
owner @{PROC}/@{pid}/cmdline r,
|
||||||
owner @{PROC}/@{pid}/io r,
|
owner @{PROC}/@{pid}/io r,
|
||||||
|
owner @{PROC}/@{pid}/mountinfo r,
|
||||||
owner @{PROC}/@{pid}/setgroups w,
|
owner @{PROC}/@{pid}/setgroups w,
|
||||||
owner @{PROC}/@{pid}/{uid,gid}_map w,
|
owner @{PROC}/@{pid}/{uid,gid}_map w,
|
||||||
@{PROC}/@{pid}/smaps r,
|
owner @{PROC}/@{pid}/smaps r,
|
||||||
@{PROC}/@{pid}/stat r,
|
@{PROC}/@{pid}/stat r,
|
||||||
@{PROC}/@{pid}/statm r,
|
@{PROC}/@{pid}/statm r,
|
||||||
@{PROC}/@{pid}/status r,
|
owner @{PROC}/@{pid}/status r,
|
||||||
owner @{PROC}/@{pid}/task/@{tid}/status r,
|
owner @{PROC}/@{pid}/task/@{tid}/status r,
|
||||||
deny @{PROC}/@{pid}/oom_{,score_}adj w,
|
deny @{PROC}/@{pid}/oom_{,score_}adj w,
|
||||||
|
@{PROC}/sys/fs/inotify/max_user_watches r,
|
||||||
@{PROC}/sys/kernel/yama/ptrace_scope r,
|
@{PROC}/sys/kernel/yama/ptrace_scope r,
|
||||||
@{PROC}/sys/net/ipv4/tcp_fastopen r,
|
@{PROC}/sys/net/ipv4/tcp_fastopen r,
|
||||||
|
|
||||||
@@ -105,13 +147,24 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
/sys/devices/**/uevent r,
|
/sys/devices/**/uevent r,
|
||||||
/sys/devices/system/cpu/cpufreq/policy*/cpuinfo_max_freq r,
|
/sys/devices/system/cpu/cpufreq/policy*/cpuinfo_max_freq r,
|
||||||
/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_max_freq r,
|
/sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_max_freq r,
|
||||||
|
/sys/devices/system/cpu/kernel_max r,
|
||||||
|
/sys/devices/system/cpu/possible r,
|
||||||
|
/sys/devices/system/cpu/present r,
|
||||||
/sys/devices/system/node/node*/meminfo r,
|
/sys/devices/system/node/node*/meminfo r,
|
||||||
|
/sys/devices/pci[0-9]*/**/bConfigurationValue r,
|
||||||
|
/sys/devices/pci[0-9]*/**/boot_vga r,
|
||||||
|
/sys/devices/pci[0-9]*/**/busnum r,
|
||||||
/sys/devices/pci[0-9]*/**/class r,
|
/sys/devices/pci[0-9]*/**/class r,
|
||||||
/sys/devices/pci[0-9]*/**/config r,
|
/sys/devices/pci[0-9]*/**/config r,
|
||||||
|
/sys/devices/pci[0-9]*/**/descriptors r,
|
||||||
/sys/devices/pci[0-9]*/**/device r,
|
/sys/devices/pci[0-9]*/**/device r,
|
||||||
|
/sys/devices/pci[0-9]*/**/devnum r,
|
||||||
/sys/devices/pci[0-9]*/**/irq r,
|
/sys/devices/pci[0-9]*/**/irq r,
|
||||||
|
/sys/devices/pci[0-9]*/**/manufacturer r,
|
||||||
|
/sys/devices/pci[0-9]*/**/product r,
|
||||||
/sys/devices/pci[0-9]*/**/resource r,
|
/sys/devices/pci[0-9]*/**/resource r,
|
||||||
/sys/devices/pci[0-9]*/**/revision r,
|
/sys/devices/pci[0-9]*/**/revision r,
|
||||||
|
/sys/devices/pci[0-9]*/**/serial r,
|
||||||
/sys/devices/pci[0-9]*/**/subsystem_device r,
|
/sys/devices/pci[0-9]*/**/subsystem_device r,
|
||||||
/sys/devices/pci[0-9]*/**/subsystem_vendor r,
|
/sys/devices/pci[0-9]*/**/subsystem_vendor r,
|
||||||
/sys/devices/pci[0-9]*/**/vendor r,
|
/sys/devices/pci[0-9]*/**/vendor r,
|
||||||
@@ -122,6 +175,7 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
/sys/devices/virtual/tty/tty*/active r,
|
/sys/devices/virtual/tty/tty*/active r,
|
||||||
# This is requested, but doesn't seem to actually be needed so deny for now
|
# This is requested, but doesn't seem to actually be needed so deny for now
|
||||||
deny /run/udev/data/** r,
|
deny /run/udev/data/** r,
|
||||||
|
deny /sys/devices/virtual/dmi/id/* r,
|
||||||
|
|
||||||
# Needed for the crash reporter
|
# Needed for the crash reporter
|
||||||
owner @{PROC}/@{pid}/auxv r,
|
owner @{PROC}/@{pid}/auxv r,
|
||||||
@@ -132,13 +186,13 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
/usr/share/fonts/**/*.pfb m,
|
/usr/share/fonts/**/*.pfb m,
|
||||||
/usr/share/mime/mime.cache m,
|
/usr/share/mime/mime.cache m,
|
||||||
/usr/share/icons/**/*.cache m,
|
/usr/share/icons/**/*.cache m,
|
||||||
owner /{dev,run}/shm/pulse-shm* m,
|
owner /{dev,run,var/run}/shm/pulse-shm* m,
|
||||||
owner @{HOME}/.local/share/mime/mime.cache m,
|
owner @{HOME}/.local/share/mime/mime.cache m,
|
||||||
owner /tmp/** m,
|
owner /tmp/** m,
|
||||||
|
|
||||||
@{PROC}/sys/kernel/shmmax r,
|
@{PROC}/sys/kernel/shmmax r,
|
||||||
owner /{dev,run}/shm/{,.}org.chromium.* mrw,
|
owner /{dev,run,var/run}/shm/{,.}org.chromium.* mrw,
|
||||||
owner /{,var/}run/shm/shmfd-* mrw,
|
owner /{dev,run,var/run}/shm/shmfd-* mrw,
|
||||||
|
|
||||||
/usr/lib/@{chromium}/*.pak mr,
|
/usr/lib/@{chromium}/*.pak mr,
|
||||||
/usr/lib/@{chromium}/locales/* mr,
|
/usr/lib/@{chromium}/locales/* mr,
|
||||||
@@ -149,8 +203,8 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
|
|
||||||
# Allow ptracing ourselves and our helpers
|
# Allow ptracing ourselves and our helpers
|
||||||
ptrace (trace) peer=@{profile_name},
|
ptrace (trace) peer=@{profile_name},
|
||||||
ptrace (trace) peer=@{profile_name}//xdgsettings,
|
ptrace (read, trace) peer=@{profile_name}//xdgsettings,
|
||||||
ptrace (trace) peer=lsb_release,
|
ptrace (read, trace) peer=lsb_release,
|
||||||
|
|
||||||
# Make browsing directories work
|
# Make browsing directories work
|
||||||
/ r,
|
/ r,
|
||||||
@@ -183,10 +237,9 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
/etc/firefox/profile/bookmarks.html r,
|
/etc/firefox/profile/bookmarks.html r,
|
||||||
owner @{HOME}/.mozilla/** k,
|
owner @{HOME}/.mozilla/** k,
|
||||||
|
|
||||||
# Chromium Policies
|
|
||||||
/etc/@{chromium}/policies/** r,
|
|
||||||
|
|
||||||
# Chromium configuration
|
# Chromium configuration
|
||||||
|
/etc/@{chromium}/** r,
|
||||||
|
# Note: "~/.pki/{,nssdb/} w" is denied by private-files abstraction
|
||||||
owner @{HOME}/.pki/nssdb/* rwk,
|
owner @{HOME}/.pki/nssdb/* rwk,
|
||||||
owner @{HOME}/.cache/chromium/ rw,
|
owner @{HOME}/.cache/chromium/ rw,
|
||||||
owner @{HOME}/.cache/chromium/** rw,
|
owner @{HOME}/.cache/chromium/** rw,
|
||||||
@@ -197,12 +250,18 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
owner @{HOME}/.config/chromium/Dictionaries/*.bdic mr,
|
owner @{HOME}/.config/chromium/Dictionaries/*.bdic mr,
|
||||||
owner @{HOME}/.config/chromium/**/Dictionaries/*.bdic mr,
|
owner @{HOME}/.config/chromium/**/Dictionaries/*.bdic mr,
|
||||||
|
|
||||||
# Allow transitions to ourself and our sandbox
|
# Widevine CDM plugin
|
||||||
|
owner @{HOME}/.config/chromium/WidevineCdm/*/_platform_specific/*/libwidevinecdm.so mr,
|
||||||
|
|
||||||
|
# Allow transitions to ourself, our sandbox, and crash handler
|
||||||
/usr/lib/@{chromium}/@{chromium} ix,
|
/usr/lib/@{chromium}/@{chromium} ix,
|
||||||
/usr/lib/@{chromium}/chrome-sandbox cx -> sandbox,
|
/usr/lib/@{chromium}/chrome-sandbox cx -> sandbox,
|
||||||
|
/usr/lib/@{chromium}/chrome_crashpad_handler Cxr -> crashpad_handler,
|
||||||
|
|
||||||
# Allow communicating with sandbox
|
# Allow communicating with sandbox and crash handler
|
||||||
unix (receive, send) peer=(label=@{profile_name}//sandbox),
|
unix (receive, send) peer=(label=@{profile_name}//sandbox),
|
||||||
|
unix (receive, send) peer=(label=@{profile_name}//crashpad_handler),
|
||||||
|
signal (receive) set=(cont) peer=@{profile_name}//crashpad_handler,
|
||||||
|
|
||||||
/{usr/,}bin/ps Uxr,
|
/{usr/,}bin/ps Uxr,
|
||||||
/usr/lib/@{chromium}/xdg-settings Cxr -> xdgsettings,
|
/usr/lib/@{chromium}/xdg-settings Cxr -> xdgsettings,
|
||||||
@@ -210,10 +269,13 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
/usr/bin/lsb_release Pxr -> lsb_release,
|
/usr/bin/lsb_release Pxr -> lsb_release,
|
||||||
|
|
||||||
# GSettings
|
# GSettings
|
||||||
owner /{,var/}run/user/*/dconf/ rw,
|
owner @{run}/user/[0-9]*/dconf/ rw,
|
||||||
owner /{,var/}run/user/*/dconf/user rw,
|
owner @{run}/user/[0-9]*/dconf/user rw,
|
||||||
owner @{HOME}/.config/dconf/user r,
|
owner @{HOME}/.config/dconf/user r,
|
||||||
|
|
||||||
|
# GVfs
|
||||||
|
owner @{run}/user/[0-9]*/gvfsd/socket-* rw,
|
||||||
|
|
||||||
# Magnet links
|
# Magnet links
|
||||||
/usr/bin/gio ixr,
|
/usr/bin/gio ixr,
|
||||||
|
|
||||||
@@ -230,7 +292,7 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
/etc/ld.so.cache r,
|
/etc/ld.so.cache r,
|
||||||
/etc/xdg/** r,
|
/etc/xdg/** r,
|
||||||
/usr/bin/xdg-settings r,
|
/usr/bin/xdg-settings r,
|
||||||
/{usr/,}lib{,32,64}/@{chromium}/xdg-settings r,
|
/usr/lib/@{chromium}/xdg-settings r,
|
||||||
/usr/share/applications/*.desktop r,
|
/usr/share/applications/*.desktop r,
|
||||||
/usr/share/applications/*.list r,
|
/usr/share/applications/*.list r,
|
||||||
|
|
||||||
@@ -266,6 +328,8 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
/{usr/,}lib/@{multiarch}/libpthread-*.so* mr,
|
/{usr/,}lib/@{multiarch}/libpthread-*.so* mr,
|
||||||
/{usr/,}lib{,32,64}/libatomic.so* mr,
|
/{usr/,}lib{,32,64}/libatomic.so* mr,
|
||||||
/{usr/,}lib/@{multiarch}/libatomic.so* mr,
|
/{usr/,}lib/@{multiarch}/libatomic.so* mr,
|
||||||
|
/{usr/,}lib{,32,64}/libc.so.* mr,
|
||||||
|
/{usr/,}lib/@{multiarch}/libc.so.* mr,
|
||||||
/{usr/,}lib{,32,64}/libc-*.so* mr,
|
/{usr/,}lib{,32,64}/libc-*.so* mr,
|
||||||
/{usr/,}lib/@{multiarch}/libc-*.so* mr,
|
/{usr/,}lib/@{multiarch}/libc-*.so* mr,
|
||||||
/{usr/,}lib{,32,64}/libdl-*.so* mr,
|
/{usr/,}lib{,32,64}/libdl-*.so* mr,
|
||||||
@@ -326,6 +390,32 @@ profile chromium_browser /usr/lib/@{chromium}/@{chromium} flags=(attach_disconne
|
|||||||
owner /tmp/** rw,
|
owner /tmp/** rw,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
profile crashpad_handler {
|
||||||
|
include <abstractions/base>
|
||||||
|
|
||||||
|
capability sys_ptrace,
|
||||||
|
|
||||||
|
ptrace (read, trace) peer=chromium_browser,
|
||||||
|
|
||||||
|
signal (send) set=(cont) peer=chromium_browser,
|
||||||
|
|
||||||
|
unix (receive, send) peer=(label=chromium_browser),
|
||||||
|
|
||||||
|
/usr/lib/@{chromium}/chrome_crashpad_handler ixr,
|
||||||
|
|
||||||
|
/sys/devices/system/cpu/cpufreq/policy[0-9]*/scaling_{cur,max}_freq r,
|
||||||
|
|
||||||
|
@{PROC}/sys/kernel/yama/ptrace_scope r,
|
||||||
|
|
||||||
|
owner @{PROC}/@{pid}/fd/ r,
|
||||||
|
owner @{PROC}/@{pid}/mem r,
|
||||||
|
owner @{PROC}/@{pid}/stat r,
|
||||||
|
owner @{PROC}/@{pid}/task/ r,
|
||||||
|
owner @{PROC}/@{pid}/task/@{tid}/comm r,
|
||||||
|
|
||||||
|
owner @{HOME}/.config/chromium/Crash?Reports/** rwk,
|
||||||
|
}
|
||||||
|
|
||||||
# Site-specific additions and overrides. See local/README for details.
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
include if exists <local/chromium_browser>
|
include if exists <local/chromium_browser>
|
||||||
}
|
}
|
||||||
|
@@ -28,6 +28,7 @@ profile firefox @{MOZ_LIBDIR}/@{MOZ_APP_NAME}{,*[^s][^h]} {
|
|||||||
include <abstractions/dbus-strict>
|
include <abstractions/dbus-strict>
|
||||||
include <abstractions/dbus-session-strict>
|
include <abstractions/dbus-session-strict>
|
||||||
include <abstractions/dconf>
|
include <abstractions/dconf>
|
||||||
|
include <abstractions/fcitx>
|
||||||
include <abstractions/fonts>
|
include <abstractions/fonts>
|
||||||
include <abstractions/gnome>
|
include <abstractions/gnome>
|
||||||
include <abstractions/ibus>
|
include <abstractions/ibus>
|
||||||
@@ -139,7 +140,7 @@ profile firefox @{MOZ_LIBDIR}/@{MOZ_APP_NAME}{,*[^s][^h]} {
|
|||||||
interface=org.gtk.gio.DesktopAppInfo
|
interface=org.gtk.gio.DesktopAppInfo
|
||||||
member=Launched,
|
member=Launched,
|
||||||
|
|
||||||
/etc/timezone r,
|
/etc/{,writable/}timezone r,
|
||||||
/etc/wildmidi/wildmidi.cfg r,
|
/etc/wildmidi/wildmidi.cfg r,
|
||||||
|
|
||||||
# firefox specific
|
# firefox specific
|
||||||
@@ -241,7 +242,7 @@ profile firefox @{MOZ_LIBDIR}/@{MOZ_APP_NAME}{,*[^s][^h]} {
|
|||||||
owner @{HOME}/.gnome2/firefox* rwk,
|
owner @{HOME}/.gnome2/firefox* rwk,
|
||||||
owner @{HOME}/.cache/mozilla/{,@{MOZ_APP_NAME}/} rw,
|
owner @{HOME}/.cache/mozilla/{,@{MOZ_APP_NAME}/} rw,
|
||||||
owner @{HOME}/.cache/mozilla/@{MOZ_APP_NAME}/** rw,
|
owner @{HOME}/.cache/mozilla/@{MOZ_APP_NAME}/** rw,
|
||||||
owner @{HOME}/.cache/mozilla/@{MOZ_APP_NAME}/**/*.sqlite k,
|
owner @{HOME}/.cache/mozilla/@{MOZ_APP_NAME}/**/*.sqlite{,-shm} k,
|
||||||
owner @{HOME}/.config/gtk-3.0/bookmarks r,
|
owner @{HOME}/.config/gtk-3.0/bookmarks r,
|
||||||
owner @{HOME}/.config/dconf/user w,
|
owner @{HOME}/.config/dconf/user w,
|
||||||
owner @{run}/user/[0-9]*/dconf/ w,
|
owner @{run}/user/[0-9]*/dconf/ w,
|
||||||
@@ -416,14 +417,17 @@ profile firefox @{MOZ_LIBDIR}/@{MOZ_APP_NAME}{,*[^s][^h]} {
|
|||||||
bus=system
|
bus=system
|
||||||
path=/org/freedesktop/UPower
|
path=/org/freedesktop/UPower
|
||||||
interface=org.freedesktop.UPower
|
interface=org.freedesktop.UPower
|
||||||
member=EnumerateDevices
|
member=EnumerateDevices,
|
||||||
peer=(name=org.freedesktop.UPower),
|
dbus (send)
|
||||||
|
bus=system
|
||||||
|
path=/org/freedesktop/UPower
|
||||||
|
interface=org.freedesktop.DBus.Properties
|
||||||
|
member=GetAll,
|
||||||
dbus (send)
|
dbus (send)
|
||||||
bus=system
|
bus=system
|
||||||
path=/org/freedesktop/UPower/devices/*
|
path=/org/freedesktop/UPower/devices/*
|
||||||
interface=org.freedesktop.DBus.Properties
|
interface=org.freedesktop.DBus.Properties
|
||||||
member=GetAll
|
member=GetAll,
|
||||||
peer=(name=org.freedesktop.UPower),
|
|
||||||
|
|
||||||
# File browser
|
# File browser
|
||||||
dbus (send)
|
dbus (send)
|
||||||
|
65
profiles/apparmor/profiles/extras/unshare-userns-restrict
Normal file
65
profiles/apparmor/profiles/extras/unshare-userns-restrict
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# This profile allows almost everything and only exists to allow
|
||||||
|
# unshare to work on a system with user namespace restrictions
|
||||||
|
# being enforced.
|
||||||
|
# unshare is allowed access to user namespaces and capabilities
|
||||||
|
# within the user namespace, but its children do not have
|
||||||
|
# capabilities, blocking unshare from being able to be used to
|
||||||
|
# arbitrarily by-pass the user namespace restrictions.
|
||||||
|
# We restrict x mapping of any code that is unknown while unshare
|
||||||
|
# has privilige within the namespace. To help ensure unshare can't
|
||||||
|
# be used to attack the kernel.
|
||||||
|
#
|
||||||
|
# disabled by default as it can break some use cases on a system that
|
||||||
|
# doesn't have or has disable user namespace restrictions for unconfined
|
||||||
|
# use aa-enforce to enable it
|
||||||
|
|
||||||
|
abi <abi/4.0>,
|
||||||
|
|
||||||
|
include <tunables/global>
|
||||||
|
|
||||||
|
profile unshare /usr/bin/unshare flags=(attach_disconnected) {
|
||||||
|
# not allow all, to allow for cix transition
|
||||||
|
# and to limit executable mapping to just unshare
|
||||||
|
allow capability,
|
||||||
|
allow file rwlk /{**,},
|
||||||
|
allow network,
|
||||||
|
allow unix,
|
||||||
|
allow ptrace,
|
||||||
|
allow signal,
|
||||||
|
allow mqueue,
|
||||||
|
allow io_uring,
|
||||||
|
allow userns,
|
||||||
|
allow mount,
|
||||||
|
allow umount,
|
||||||
|
allow pivot_root,
|
||||||
|
allow dbus,
|
||||||
|
audit allow cx /** -> unpriv,
|
||||||
|
|
||||||
|
allow file m /usr/lib/@{multiarch}/libc.so.6,
|
||||||
|
allow file m /usr/bin/unshare,
|
||||||
|
|
||||||
|
# the local include should not be used without understanding the userns
|
||||||
|
# restriction.
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/unshare-userns-restrict>
|
||||||
|
|
||||||
|
profile unpriv flags=(attach_disconnected) {
|
||||||
|
# not allow all, to allow for pix stack
|
||||||
|
allow file rwlkm /{**,},
|
||||||
|
allow network,
|
||||||
|
allow unix,
|
||||||
|
allow ptrace,
|
||||||
|
allow signal,
|
||||||
|
allow mqueue,
|
||||||
|
allow io_uring,
|
||||||
|
allow userns,
|
||||||
|
allow mount,
|
||||||
|
allow umount,
|
||||||
|
allow pivot_root,
|
||||||
|
allow dbus,
|
||||||
|
|
||||||
|
allow pix /** -> &unshare//unpriv,
|
||||||
|
|
||||||
|
audit deny capability,
|
||||||
|
}
|
||||||
|
}
|
@@ -50,6 +50,15 @@ include <tunables/global>
|
|||||||
# needed when /proc is mounted with hidepid>=1
|
# needed when /proc is mounted with hidepid>=1
|
||||||
ptrace (read,trace) peer="unconfined",
|
ptrace (read,trace) peer="unconfined",
|
||||||
|
|
||||||
|
unix (bind) type=stream addr="@*/bus/sshd/system",
|
||||||
|
|
||||||
|
dbus (send)
|
||||||
|
bus=system
|
||||||
|
path=/org/freedesktop/login1
|
||||||
|
interface=org.freedesktop.login1.Manager
|
||||||
|
member=CreateSessionWithPIDFD
|
||||||
|
peer=(label=unconfined),
|
||||||
|
|
||||||
/dev/ptmx rw,
|
/dev/ptmx rw,
|
||||||
/dev/pts/[0-9]* rw,
|
/dev/pts/[0-9]* rw,
|
||||||
/dev/urandom r,
|
/dev/urandom r,
|
||||||
|
@@ -111,8 +111,8 @@ SRC=access.c \
|
|||||||
mount.c \
|
mount.c \
|
||||||
move_mount.c \
|
move_mount.c \
|
||||||
named_pipe.c \
|
named_pipe.c \
|
||||||
net_finegrained_rcv.c \
|
net_inet_rcv.c \
|
||||||
net_finegrained_snd.c \
|
net_inet_snd.c \
|
||||||
net_raw.c \
|
net_raw.c \
|
||||||
open.c \
|
open.c \
|
||||||
openat.c \
|
openat.c \
|
||||||
@@ -364,10 +364,10 @@ unix_fd_client: unix_fd_client.c unix_fd_common.o
|
|||||||
attach_disconnected: attach_disconnected.c unix_fd_common.o
|
attach_disconnected: attach_disconnected.c unix_fd_common.o
|
||||||
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS}
|
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS}
|
||||||
|
|
||||||
userns: userns.c userns.h
|
userns: userns.c pipe_helper.h
|
||||||
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS}
|
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS}
|
||||||
|
|
||||||
userns_setns: userns_setns.c userns.h
|
userns_setns: userns_setns.c pipe_helper.h
|
||||||
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS}
|
${CC} ${CFLAGS} ${LDFLAGS} $^ -o $@ ${LDLIBS}
|
||||||
|
|
||||||
mount: mount.c
|
mount: mount.c
|
||||||
|
@@ -79,3 +79,16 @@ runchecktest "complain (--namespace=${ns})" pass "$aa_exec -n $ns -p $test" "$te
|
|||||||
|
|
||||||
genprofile_aa_exec "$test" 0
|
genprofile_aa_exec "$test" 0
|
||||||
runchecktest "negative test: bad ns (--namespace=${ns}XXX)" fail "$aa_exec -n ${ns}XXX -p $test" "$test (enforce)"
|
runchecktest "negative test: bad ns (--namespace=${ns}XXX)" fail "$aa_exec -n ${ns}XXX -p $test" "$test (enforce)"
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
genprofile --stdin <<EOF
|
||||||
|
$test {
|
||||||
|
all,
|
||||||
|
}
|
||||||
|
|
||||||
|
:${ns}:${test} {
|
||||||
|
all,
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
runchecktest "allow all" pass "$aa_exec -p $test" "$test (enforce)"
|
||||||
|
fi
|
||||||
|
@@ -28,7 +28,14 @@ wxperm=wix
|
|||||||
touch $file
|
touch $file
|
||||||
chmod 777 $file # full perms so discretionary access checks succeed
|
chmod 777 $file # full perms so discretionary access checks succeed
|
||||||
|
|
||||||
# PASS TEST
|
# PASS TEST
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
genprofile "all"
|
||||||
|
runchecktest "ACCESS allow all r (rwx)" pass $file r
|
||||||
|
runchecktest "ACCESS allow all rx (rwx)" pass $file rx
|
||||||
|
runchecktest "ACCESS allow all rwx (rwx)" pass $file rwx
|
||||||
|
fi
|
||||||
|
|
||||||
genprofile $file:$rwxperm
|
genprofile $file:$rwxperm
|
||||||
runchecktest "ACCESS file r (rwx)" pass $file r
|
runchecktest "ACCESS file r (rwx)" pass $file r
|
||||||
runchecktest "ACCESS file rx (rwx)" pass $file rx
|
runchecktest "ACCESS file rx (rwx)" pass $file rx
|
||||||
|
@@ -23,12 +23,13 @@ settest unix_fd_server
|
|||||||
disk_img=$tmpdir/disk_img
|
disk_img=$tmpdir/disk_img
|
||||||
new_root=$tmpdir/new_root/
|
new_root=$tmpdir/new_root/
|
||||||
put_old=${new_root}put_old/
|
put_old=${new_root}put_old/
|
||||||
root_was_shared="no"
|
|
||||||
fstype="ext2"
|
fstype="ext2"
|
||||||
file=$tmpdir/file
|
file=$tmpdir/file
|
||||||
socket=$tmpdir/unix_fd_test
|
socket=$tmpdir/unix_fd_test
|
||||||
att_dis_client=$pwd/attach_disconnected
|
att_dis_client=$pwd/attach_disconnected
|
||||||
|
|
||||||
|
. $bin/mount.inc
|
||||||
|
|
||||||
attach_disconnected_cleanup() {
|
attach_disconnected_cleanup() {
|
||||||
if [ ! -z "$loop_device" ]; then
|
if [ ! -z "$loop_device" ]; then
|
||||||
losetup -d $loop_device
|
losetup -d $loop_device
|
||||||
@@ -39,10 +40,7 @@ attach_disconnected_cleanup() {
|
|||||||
umount "$new_root"
|
umount "$new_root"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$root_was_shared" = "yes" ] ; then
|
prop_cleanup
|
||||||
[ -n "$VERBOSE" ] && echo 'notice: re-mounting / as shared'
|
|
||||||
mount --make-shared /
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
do_onexit="attach_disconnected_cleanup"
|
do_onexit="attach_disconnected_cleanup"
|
||||||
|
|
||||||
@@ -50,24 +48,6 @@ if [ ! -b /dev/loop0 ] ; then
|
|||||||
modprobe loop
|
modprobe loop
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# systemd mounts / and everything under it MS_SHARED. This breaks
|
|
||||||
# pivot_root entirely, so attempt to detect it, and remount /
|
|
||||||
# MS_PRIVATE temporarily.
|
|
||||||
FINDMNT=/bin/findmnt
|
|
||||||
if [ -x "${FINDMNT}" ] && ${FINDMNT} -no PROPAGATION / > /dev/null 2>&1 ; then
|
|
||||||
if [ "$(${FINDMNT} -no PROPAGATION /)" = "shared" ] ; then
|
|
||||||
root_was_shared="yes"
|
|
||||||
fi
|
|
||||||
elif [ "$(ps hp1 -ocomm)" = "systemd" ] ; then
|
|
||||||
# no findmnt or findmnt doesn't know the PROPAGATION column,
|
|
||||||
# but init is systemd so assume rootfs is shared
|
|
||||||
root_was_shared="yes"
|
|
||||||
fi
|
|
||||||
if [ "${root_was_shared}" = "yes" ] ; then
|
|
||||||
[ -n "$VERBOSE" ] && echo 'notice: re-mounting / as private'
|
|
||||||
mount --make-private /
|
|
||||||
fi
|
|
||||||
|
|
||||||
dd if=/dev/zero of="$disk_img" bs=1024 count=512 2> /dev/null
|
dd if=/dev/zero of="$disk_img" bs=1024 count=512 2> /dev/null
|
||||||
/sbin/mkfs -t "$fstype" -F "$disk_img" > /dev/null 2> /dev/null
|
/sbin/mkfs -t "$fstype" -F "$disk_img" > /dev/null 2> /dev/null
|
||||||
# mounting will be done by the test binary
|
# mounting will be done by the test binary
|
||||||
@@ -105,6 +85,15 @@ do_test "attach_disconnected" pass $file $att_dis_client $socket $loop_device $n
|
|||||||
|
|
||||||
# TODO: adding attach_disconnected.path to a replaced unconfined
|
# TODO: adding attach_disconnected.path to a replaced unconfined
|
||||||
|
|
||||||
|
# ALLOW ALL does not include attach_disconnected
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
genprofile "all" flag:attach_disconnected -- image=$att_dis_client "all"
|
||||||
|
do_test "attach_disconnected allow all" pass $file $att_dis_client $socket $loop_device $new_root $put_old
|
||||||
|
|
||||||
|
genprofile "all" -- image=$att_dis_client "all"
|
||||||
|
do_test "attach_disconnected allow all no flag" fail $file $att_dis_client $socket $loop_device $new_root $put_old
|
||||||
|
fi
|
||||||
|
|
||||||
genprofile $file_perm unix:create $socket_perm $att_dis_client:px -- image=$att_dis_client $file_perm unix:create $socket_perm $create_dir $cap "pivot_root:ALL" "mount:ALL" flag:attach_disconnected
|
genprofile $file_perm unix:create $socket_perm $att_dis_client:px -- image=$att_dis_client $file_perm unix:create $socket_perm $create_dir $cap "pivot_root:ALL" "mount:ALL" flag:attach_disconnected
|
||||||
|
|
||||||
do_test "attach_disconnected" pass $file $att_dis_client $socket $loop_device $new_root $put_old
|
do_test "attach_disconnected" pass $file $att_dis_client $socket $loop_device $new_root $put_old
|
||||||
|
@@ -45,6 +45,11 @@ run_tests()
|
|||||||
|
|
||||||
# Make sure we're okay when confined with appropriate permissions
|
# Make sure we're okay when confined with appropriate permissions
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
gendbusprofile "all,"
|
||||||
|
runchecktest "eavesdrop (allow all)" pass $args
|
||||||
|
fi
|
||||||
|
|
||||||
gendbusprofile "dbus,"
|
gendbusprofile "dbus,"
|
||||||
runchecktest "eavesdrop (dbus allowed)" pass $args
|
runchecktest "eavesdrop (dbus allowed)" pass $args
|
||||||
|
|
||||||
|
@@ -60,6 +60,12 @@ run_tests()
|
|||||||
|
|
||||||
# Make sure send is allowed when confined with appropriate permissions
|
# Make sure send is allowed when confined with appropriate permissions
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
message_gendbusprofile "all,"
|
||||||
|
runtestfg "message (allow all)" pass $confined_args
|
||||||
|
checktestfg "compare_logs $unconfined_log eq $confined_log"
|
||||||
|
fi
|
||||||
|
|
||||||
message_gendbusprofile "dbus,"
|
message_gendbusprofile "dbus,"
|
||||||
runtestfg "message (dbus allowed)" pass $confined_args
|
runtestfg "message (dbus allowed)" pass $confined_args
|
||||||
checktestfg "compare_logs $unconfined_log eq $confined_log"
|
checktestfg "compare_logs $unconfined_log eq $confined_log"
|
||||||
|
@@ -92,6 +92,14 @@ run_tests()
|
|||||||
|
|
||||||
# Make sure we're okay when confined with appropriate permissions
|
# Make sure we're okay when confined with appropriate permissions
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
service_gendbusprofile "all,"
|
||||||
|
service_runtestbg "service (allow all)" pass $unconfined_log
|
||||||
|
sendmethod
|
||||||
|
sendsignal
|
||||||
|
service_checktestbg "compare_logs $unconfined_log eq $confined_log"
|
||||||
|
fi
|
||||||
|
|
||||||
service_gendbusprofile "dbus,"
|
service_gendbusprofile "dbus,"
|
||||||
service_runtestbg "service (dbus allowed)" pass $unconfined_log
|
service_runtestbg "service (dbus allowed)" pass $unconfined_log
|
||||||
sendmethod
|
sendmethod
|
||||||
|
@@ -80,6 +80,14 @@ run_tests()
|
|||||||
sendmethodreturn
|
sendmethodreturn
|
||||||
ur_checktestbg
|
ur_checktestbg
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
# All perms are granted so the logs should be equal
|
||||||
|
ur_gendbusprofile "all,"
|
||||||
|
ur_runtestbg "unrequested_reply (method_return, dbus allowed)" pass $confined_log
|
||||||
|
sendmethodreturn
|
||||||
|
ur_checktestbg "compare_logs $unconfined_log eq $confined_log"
|
||||||
|
fi
|
||||||
|
|
||||||
# All dbus perms are granted so the logs should be equal
|
# All dbus perms are granted so the logs should be equal
|
||||||
ur_gendbusprofile "dbus,"
|
ur_gendbusprofile "dbus,"
|
||||||
ur_runtestbg "unrequested_reply (method_return, dbus allowed)" pass $confined_log
|
ur_runtestbg "unrequested_reply (method_return, dbus allowed)" pass $confined_log
|
||||||
|
@@ -85,6 +85,32 @@ runchecktest "ENVIRON (shell script): confined/complain & sensitive env" pass ${
|
|||||||
# TEST environment filtering still works on setuid apps
|
# TEST environment filtering still works on setuid apps
|
||||||
removeprofile
|
removeprofile
|
||||||
|
|
||||||
|
tmpfs_dir=${tmpdir}/tmpfs_dir
|
||||||
|
remove_mnt() {
|
||||||
|
mountpoint -q "$tmpfs_dir"
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
umount "$tmpfs_dir"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
do_onexit="remove_mnt"
|
||||||
|
|
||||||
|
# setuid apps mounted in a fs with "nosuid" option do not honor those
|
||||||
|
# bits during execution, so run the test in a mounted tmpdir without nosuid
|
||||||
|
FINDMNT=/bin/findmnt
|
||||||
|
if [ -x "${FINDMNT}" ] && ${FINDMNT} -no TARGET,OPTIONS -T $tmpdir > /dev/null 2>&1 ; then
|
||||||
|
output="$(${FINDMNT} -no TARGET,OPTIONS -T $tmpdir)"
|
||||||
|
target="$(echo $output | cut -d' ' -f1)"
|
||||||
|
options="$(echo $output | cut -d' ' -f2)"
|
||||||
|
case "$options" in
|
||||||
|
*nosuid* )
|
||||||
|
echo " $target is mounted with nosuid, creating a new mountpoint..."
|
||||||
|
setuid_helper=${tmpfs_dir}/env_check
|
||||||
|
mkdir ${tmpfs_dir}
|
||||||
|
mount -t tmpfs tmpfs ${tmpfs_dir}
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
cp $helper ${setuid_helper}
|
cp $helper ${setuid_helper}
|
||||||
chown nobody ${setuid_helper}
|
chown nobody ${setuid_helper}
|
||||||
chmod u+s ${setuid_helper}
|
chmod u+s ${setuid_helper}
|
||||||
|
@@ -55,6 +55,11 @@ do_tests "no perms" fail fail
|
|||||||
genprofile $required_perms "qual=deny:io_uring"
|
genprofile $required_perms "qual=deny:io_uring"
|
||||||
do_tests "deny perms" fail fail
|
do_tests "deny perms" fail fail
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
genprofile "all"
|
||||||
|
do_tests "allow all" pass pass
|
||||||
|
fi
|
||||||
|
|
||||||
genprofile $required_perms "io_uring"
|
genprofile $required_perms "io_uring"
|
||||||
do_tests "generic perms" pass pass
|
do_tests "generic perms" pass pass
|
||||||
|
|
||||||
|
@@ -114,6 +114,7 @@ static void usage(char *prog_name)
|
|||||||
fprintf(stderr, "Options are:\n");
|
fprintf(stderr, "Options are:\n");
|
||||||
fprintf(stderr, "-o flags sent to the mount syscall\n");
|
fprintf(stderr, "-o flags sent to the mount syscall\n");
|
||||||
fprintf(stderr, "-d data sent to the mount syscall\n");
|
fprintf(stderr, "-d data sent to the mount syscall\n");
|
||||||
|
fprintf(stderr, "-t type of synthetic filesystem (e.g. proc) for mount syscall\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,12 +122,13 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
char *options = NULL;
|
char *options = NULL;
|
||||||
char *data = NULL;
|
char *data = NULL;
|
||||||
|
char *type = NULL;
|
||||||
int index;
|
int index;
|
||||||
int c;
|
int c;
|
||||||
char *op, *source, *target, *token;
|
char *op, *source, *target, *token;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
|
|
||||||
while ((c = getopt (argc, argv, "o:d:h")) != -1) {
|
while ((c = getopt (argc, argv, "o:d:t:h")) != -1) {
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 'o':
|
case 'o':
|
||||||
@@ -135,6 +137,9 @@ int main(int argc, char *argv[])
|
|||||||
case 'd':
|
case 'd':
|
||||||
data = optarg;
|
data = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
type = optarg;
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
break;
|
break;
|
||||||
@@ -162,10 +167,18 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(op, "mount") == 0) {
|
if (strcmp(op, "mount") == 0) {
|
||||||
if (mount(source, target, "ext2", flags, data) == -1) {
|
if (!type) {
|
||||||
fprintf(stderr, "FAIL: mount %s on %s failed - %s\n",
|
if (mount(source, target, "ext2", flags, data) == -1) {
|
||||||
source, target, strerror(errno));
|
fprintf(stderr, "FAIL: mount %s on %s failed - %s\n",
|
||||||
return errno;
|
source, target, strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (mount(source, target, type, flags, data) == -1) {
|
||||||
|
fprintf(stderr, "FAIL: mount %s on %s failed - %s\n",
|
||||||
|
source, target, strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (strcmp(op, "umount") == 0) {
|
} else if (strcmp(op, "umount") == 0) {
|
||||||
if (umount(target) == -1) {
|
if (umount(target) == -1) {
|
||||||
|
30
tests/regression/apparmor/mount.inc
Normal file
30
tests/regression/apparmor/mount.inc
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
root_was_shared="no"
|
||||||
|
root="/"
|
||||||
|
|
||||||
|
# systemd mounts / and everything under it MS_SHARED. This breaks
|
||||||
|
# pivot_root and mount "move" operations entirely, so attempt to
|
||||||
|
# detect from which mount point the test is running from, and remount
|
||||||
|
# it MS_PRIVATE temporarily.
|
||||||
|
FINDMNT=/bin/findmnt
|
||||||
|
if [ -x "${FINDMNT}" ] && ${FINDMNT} -no TARGET,PROPAGATION -T $tmpdir > /dev/null 2>&1 ; then
|
||||||
|
output="$(${FINDMNT} -no TARGET,PROPAGATION -T $tmpdir)"
|
||||||
|
root="$(echo $output | cut -d' ' -f1)"
|
||||||
|
if [ "$(echo $output | cut -d' ' -f2)" == "shared" ] ; then
|
||||||
|
root_was_shared="yes"
|
||||||
|
fi
|
||||||
|
elif [ "$(ps hp1 -ocomm)" = "systemd" ] ; then
|
||||||
|
# no findmnt or findmnt doesn't know the PROPAGATION column,
|
||||||
|
# but init is systemd so assume rootfs is shared
|
||||||
|
root_was_shared="yes"
|
||||||
|
fi
|
||||||
|
if [ "${root_was_shared}" = "yes" ] ; then
|
||||||
|
[ -n "$VERBOSE" ] && echo "notice: re-mounting $root as private"
|
||||||
|
mount --make-private $root
|
||||||
|
fi
|
||||||
|
|
||||||
|
prop_cleanup() {
|
||||||
|
if [ "${root_was_shared}" = "yes" ] ; then
|
||||||
|
[ -n "$VERBOSE" ] && echo "notice: re-mounting $root as shared"
|
||||||
|
mount --make-shared $root
|
||||||
|
fi
|
||||||
|
}
|
@@ -32,7 +32,8 @@ mount_point2=$tmpdir/mountpoint2
|
|||||||
mount_bad=$tmpdir/mountbad
|
mount_bad=$tmpdir/mountbad
|
||||||
loop_device="unset"
|
loop_device="unset"
|
||||||
fstype="ext2"
|
fstype="ext2"
|
||||||
root_was_shared="no"
|
|
||||||
|
. $bin/mount.inc
|
||||||
|
|
||||||
setup_mnt() {
|
setup_mnt() {
|
||||||
/bin/mount -n -t${fstype} ${loop_device} ${mount_point}
|
/bin/mount -n -t${fstype} ${loop_device} ${mount_point}
|
||||||
@@ -59,9 +60,7 @@ mount_cleanup() {
|
|||||||
then
|
then
|
||||||
/sbin/losetup -d ${loop_device} &> /dev/null
|
/sbin/losetup -d ${loop_device} &> /dev/null
|
||||||
fi
|
fi
|
||||||
if [ "${root_was_shared}" = "yes" ] ; then
|
prop_cleanup
|
||||||
mount --make-shared /
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
do_onexit="mount_cleanup"
|
do_onexit="mount_cleanup"
|
||||||
|
|
||||||
@@ -81,23 +80,6 @@ fi
|
|||||||
loop_device=$(losetup -f) || fatalerror 'Unable to find a free loop device'
|
loop_device=$(losetup -f) || fatalerror 'Unable to find a free loop device'
|
||||||
/sbin/losetup "$loop_device" ${mount_file} > /dev/null 2> /dev/null
|
/sbin/losetup "$loop_device" ${mount_file} > /dev/null 2> /dev/null
|
||||||
|
|
||||||
# systemd mounts / and everything under it MS_SHARED which does
|
|
||||||
# not work with "move", so attempt to detect it, and remount /
|
|
||||||
# MS_PRIVATE temporarily. snippet from pivot_root.sh
|
|
||||||
FINDMNT=/bin/findmnt
|
|
||||||
if [ -x "${FINDMNT}" ] && ${FINDMNT} -no PROPAGATION / > /dev/null 2>&1 ; then
|
|
||||||
if [ "$(${FINDMNT} -no PROPAGATION /)" == "shared" ] ; then
|
|
||||||
root_was_shared="yes"
|
|
||||||
fi
|
|
||||||
elif [ "$(ps hp1 -ocomm)" = "systemd" ] ; then
|
|
||||||
# no findmnt or findmnt doesn't know the PROPAGATION column,
|
|
||||||
# but init is systemd so assume rootfs is shared
|
|
||||||
root_was_shared="yes"
|
|
||||||
fi
|
|
||||||
if [ "${root_was_shared}" = "yes" ] ; then
|
|
||||||
mount --make-private /
|
|
||||||
fi
|
|
||||||
|
|
||||||
options=(
|
options=(
|
||||||
# default and non-default options
|
# default and non-default options
|
||||||
"rw,ro"
|
"rw,ro"
|
||||||
@@ -424,6 +406,34 @@ fsmount_tests() {
|
|||||||
fsmount_test " fsmount deny att_dis" "qual=deny:" "flag:attach_disconnected" ${should_fail}
|
fsmount_test " fsmount deny att_dis" "qual=deny:" "flag:attach_disconnected" ${should_fail}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
all_rule() {
|
||||||
|
if [ "$(parser_supports 'all,')" != "true" ]; then
|
||||||
|
echo " not supported by parser - skipping allow all,"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
settest mount
|
||||||
|
genprofile "all"
|
||||||
|
|
||||||
|
runchecktest "MOUNT (confined allow all)" pass mount ${loop_device} ${mount_point}
|
||||||
|
|
||||||
|
runchecktest "UMOUNT (confined allow all)" pass umount ${loop_device} ${mount_point}
|
||||||
|
|
||||||
|
runchecktest "MOUNT (confined allow all remount setup)" pass mount ${loop_device} ${mount_point}
|
||||||
|
runchecktest "MOUNT (confined allow all remount)" pass mount ${loop_device} ${mount_point} -o remount
|
||||||
|
remove_mnt
|
||||||
|
|
||||||
|
settest move_mount
|
||||||
|
genprofile "all"
|
||||||
|
|
||||||
|
runchecktest "MOVE_MOUNT (confined fsmount: allow all)" pass fsmount ${loop_device} ${mount_point} ${fstype}
|
||||||
|
remove_mnt
|
||||||
|
|
||||||
|
mount ${loop_device} ${mnt_source}
|
||||||
|
runchecktest "MOVE_MOUNT (confined open_tree: allow all)" pass open_tree ${mount_point2} ${mount_point} ${fstype}
|
||||||
|
remove_mnt
|
||||||
|
}
|
||||||
|
|
||||||
# TEST 1. Make sure can mount and umount unconfined
|
# TEST 1. Make sure can mount and umount unconfined
|
||||||
runchecktest "MOUNT (unconfined)" pass mount ${loop_device} ${mount_point}
|
runchecktest "MOUNT (unconfined)" pass mount ${loop_device} ${mount_point}
|
||||||
remove_mnt
|
remove_mnt
|
||||||
@@ -547,6 +557,12 @@ else
|
|||||||
runchecktest "UMOUNT (confined cap umount:ALL)" pass umount ${loop_device} ${mount_point}
|
runchecktest "UMOUNT (confined cap umount:ALL)" pass umount ${loop_device} ${mount_point}
|
||||||
remove_mnt
|
remove_mnt
|
||||||
|
|
||||||
|
# https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1597017
|
||||||
|
# CVE-2016-1585
|
||||||
|
genprofile cap:sys_admin "mount:options=(rw,make-slave) -> **"
|
||||||
|
runchecktest "MOUNT (confined cap mount -> mntpnt, CVE-2016-1585)" fail mount -t proc proc ${mount_point}
|
||||||
|
remove_mnt
|
||||||
|
|
||||||
# MR:https://gitlab.com/apparmor/apparmor/-/merge_requests/1054
|
# MR:https://gitlab.com/apparmor/apparmor/-/merge_requests/1054
|
||||||
# https://bugs.launchpad.net/apparmor/+bug/2023814
|
# https://bugs.launchpad.net/apparmor/+bug/2023814
|
||||||
# https://bugzilla.opensuse.org/show_bug.cgi?id=1211989
|
# https://bugzilla.opensuse.org/show_bug.cgi?id=1211989
|
||||||
@@ -563,6 +579,8 @@ else
|
|||||||
fsmount_tests tmpfs ${mount_point} tmpfs
|
fsmount_tests tmpfs ${mount_point} tmpfs
|
||||||
fsmount_tests ${loop_device} ${mount_point} ${fstype}
|
fsmount_tests ${loop_device} ${mount_point} ${fstype}
|
||||||
open_tree_tests ${mount_point2} ${mount_point} ${fstype}
|
open_tree_tests ${mount_point2} ${mount_point} ${fstype}
|
||||||
|
|
||||||
|
all_rule
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#need tests for chroot
|
#need tests for chroot
|
||||||
|
@@ -6,9 +6,9 @@
|
|||||||
#published by the Free Software Foundation, version 2 of the
|
#published by the Free Software Foundation, version 2 of the
|
||||||
#License.
|
#License.
|
||||||
|
|
||||||
#=NAME posix_mq
|
#=NAME net_inet
|
||||||
#=DESCRIPTION
|
#=DESCRIPTION
|
||||||
# This test verifies if mediation of posix message queues is working
|
# This test verifies if finegrained inet mediation is working
|
||||||
#=END
|
#=END
|
||||||
|
|
||||||
pwd=`dirname $0`
|
pwd=`dirname $0`
|
||||||
@@ -18,13 +18,13 @@ bin=$pwd
|
|||||||
|
|
||||||
. $bin/prologue.inc
|
. $bin/prologue.inc
|
||||||
|
|
||||||
#requires_kernel_features network_v8/finegrained
|
requires_kernel_features network_v8/af_inet
|
||||||
requires_parser_support "network ip=::1,"
|
requires_parser_support "network ip=::1,"
|
||||||
|
|
||||||
settest net_finegrained_rcv
|
settest net_inet_rcv
|
||||||
|
|
||||||
sender="$bin/net_finegrained_snd"
|
sender="$bin/net_inet_snd"
|
||||||
receiver="$bin/net_finegrained_rcv"
|
receiver="$bin/net_inet_rcv"
|
||||||
|
|
||||||
# local ipv6 address generated according to https://www.rfc-editor.org/rfc/rfc4193.html
|
# local ipv6 address generated according to https://www.rfc-editor.org/rfc/rfc4193.html
|
||||||
#ipv6_subnet=fd74:1820:b03a:b361::/64
|
#ipv6_subnet=fd74:1820:b03a:b361::/64
|
||||||
@@ -47,7 +47,7 @@ do_onexit="cleanup"
|
|||||||
|
|
||||||
do_test()
|
do_test()
|
||||||
{
|
{
|
||||||
local desc="FINEGRAINED NETWORK ($1)"
|
local desc="NETWORK INET ($1)"
|
||||||
shift
|
shift
|
||||||
runchecktest "$desc" "$@"
|
runchecktest "$desc" "$@"
|
||||||
}
|
}
|
||||||
@@ -65,12 +65,11 @@ do_tests()
|
|||||||
protocol=$8
|
protocol=$8
|
||||||
generate_profile=$9
|
generate_profile=$9
|
||||||
|
|
||||||
settest net_finegrained_rcv
|
settest net_inet_rcv
|
||||||
$generate_profile
|
$generate_profile
|
||||||
do_test "$prefix - root" $expect_rcv --bind_ip $bind_ip --bind_port $bind_port --remote_ip $remote_ip --remote_port $remote_port --protocol $protocol --timeout 5 --sender $sender
|
do_test "$prefix - root" $expect_rcv --bind_ip $bind_ip --bind_port $bind_port --remote_ip $remote_ip --remote_port $remote_port --protocol $protocol --timeout 5 --sender $sender
|
||||||
|
|
||||||
|
settest -u "foo" net_inet_rcv
|
||||||
settest -u "foo" net_finegrained_rcv
|
|
||||||
$generate_profile
|
$generate_profile
|
||||||
do_test "$prefix - user" $expect_rcv --bind_ip $bind_ip --bind_port $bind_port --remote_ip $remote_ip --remote_port $remote_port --protocol $protocol --timeout 5 --sender $sender
|
do_test "$prefix - user" $expect_rcv --bind_ip $bind_ip --bind_port $bind_port --remote_ip $remote_ip --remote_port $remote_port --protocol $protocol --timeout 5 --sender $sender
|
||||||
|
|
||||||
@@ -97,9 +96,9 @@ do_tests "ipv4 udp no conds" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remot
|
|||||||
generate_profile="genprofile network $sender:px -- image=$sender network"
|
generate_profile="genprofile network $sender:px -- image=$sender network"
|
||||||
do_tests "ipv4 tcp no conds" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port tcp "$generate_profile"
|
do_tests "ipv4 tcp no conds" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port tcp "$generate_profile"
|
||||||
|
|
||||||
setsockopt_rules="network;(setopt,getopt);ip=0.0.0.0;port=0"
|
setsockopt_rules="network;(setopt,getopt);ip=0.0.0.0;port=0" # INADDR_ANY
|
||||||
rcv_rules="network;ip=$bind_ipv4;peer=(ip=anon)"
|
rcv_rules="network;ip=$bind_ipv4;peer=(ip=none)"
|
||||||
snd_rules="network;ip=$remote_ipv4;peer=(ip=anon)"
|
snd_rules="network;ip=$remote_ipv4;peer=(ip=none)"
|
||||||
|
|
||||||
generate_profile="genprofile network;ip=$bind_ipv4;port=$bind_port;peer=(ip=$remote_ipv4,port=$remote_port) $setsockopt_rules $rcv_rules $sender:px -- image=$sender network;ip=$remote_ipv4;port=$remote_port;peer=(ip=$bind_ipv4,port=$bind_port) $setsockopt_rules $snd_rules"
|
generate_profile="genprofile network;ip=$bind_ipv4;port=$bind_port;peer=(ip=$remote_ipv4,port=$remote_port) $setsockopt_rules $rcv_rules $sender:px -- image=$sender network;ip=$remote_ipv4;port=$remote_port;peer=(ip=$bind_ipv4,port=$bind_port) $setsockopt_rules $snd_rules"
|
||||||
do_tests "ipv4 udp generic perms" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port udp "$generate_profile"
|
do_tests "ipv4 udp generic perms" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port udp "$generate_profile"
|
||||||
@@ -126,9 +125,9 @@ do_tests "ipv6 udp no conds" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remot
|
|||||||
generate_profile="genprofile network $sender:px -- image=$sender network"
|
generate_profile="genprofile network $sender:px -- image=$sender network"
|
||||||
do_tests "ipv6 tcp no conds" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remote_port tcp "$generate_profile"
|
do_tests "ipv6 tcp no conds" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remote_port tcp "$generate_profile"
|
||||||
|
|
||||||
setsockopt_rules="network;(setopt,getopt);ip=::0;port=0"
|
setsockopt_rules="network;(setopt,getopt);ip=::0;port=0" # IN6ADDR_ANY_INIT
|
||||||
rcv_rules="network;ip=$bind_ipv6;peer=(ip=anon)"
|
rcv_rules="network;ip=$bind_ipv6;peer=(ip=none)"
|
||||||
snd_rules="network;ip=$remote_ipv6;peer=(ip=anon)"
|
snd_rules="network;ip=$remote_ipv6;peer=(ip=none)"
|
||||||
|
|
||||||
generate_profile="genprofile network;ip=$bind_ipv6;port=$bind_port;peer=(ip=$remote_ipv6,port=$remote_port) $setsockopt_rules $rcv_rules $sender:px -- image=$sender network;ip=$remote_ipv6;port=$remote_port;peer=(ip=$bind_ipv6,port=$bind_port) $setsockopt_rules $snd_rules"
|
generate_profile="genprofile network;ip=$bind_ipv6;port=$bind_port;peer=(ip=$remote_ipv6,port=$remote_port) $setsockopt_rules $rcv_rules $sender:px -- image=$sender network;ip=$remote_ipv6;port=$remote_port;peer=(ip=$bind_ipv6,port=$bind_port) $setsockopt_rules $snd_rules"
|
||||||
do_tests "ipv6 udp generic perms" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remote_port udp "$generate_profile"
|
do_tests "ipv6 udp generic perms" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remote_port udp "$generate_profile"
|
||||||
@@ -137,3 +136,16 @@ generate_profile="genprofile network;ip=$bind_ipv6;port=$bind_port;peer=(ip=$rem
|
|||||||
do_tests "ipv6 tcp generic perms" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remote_port tcp "$generate_profile"
|
do_tests "ipv6 tcp generic perms" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remote_port tcp "$generate_profile"
|
||||||
|
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
generate_profile="genprofile all -- image=$sender all"
|
||||||
|
do_tests "ipv4 udp allow all" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port udp "$generate_profile"
|
||||||
|
|
||||||
|
generate_profile="genprofile all -- image=$sender all"
|
||||||
|
do_tests "ipv4 tcp allow all" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port tcp "$generate_profile"
|
||||||
|
|
||||||
|
generate_profile="genprofile all -- image=$sender all"
|
||||||
|
do_tests "ipv6 udp allow all" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remote_port udp "$generate_profile"
|
||||||
|
|
||||||
|
generate_profile="genprofile all -- image=$sender all"
|
||||||
|
do_tests "ipv6 tcp allow all" pass pass $bind_ipv6 $bind_port $remote_ipv6 $remote_port tcp "$generate_profile"
|
||||||
|
fi
|
@@ -9,7 +9,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include "net_finegrained.h"
|
#include "net_inet.h"
|
||||||
|
|
||||||
|
enum protocol {
|
||||||
|
UDP,
|
||||||
|
TCP,
|
||||||
|
ICMP
|
||||||
|
};
|
||||||
|
|
||||||
struct connection_info {
|
struct connection_info {
|
||||||
char *bind_ip;
|
char *bind_ip;
|
||||||
@@ -17,17 +23,72 @@ struct connection_info {
|
|||||||
char *remote_ip;
|
char *remote_ip;
|
||||||
char *remote_port;
|
char *remote_port;
|
||||||
char *protocol;
|
char *protocol;
|
||||||
|
enum protocol prot;
|
||||||
int timeout;
|
int timeout;
|
||||||
} net_info;
|
} net_info;
|
||||||
|
|
||||||
|
int receive_bind()
|
||||||
int receive_udp()
|
|
||||||
{
|
{
|
||||||
|
|
||||||
int sock;
|
int sock;
|
||||||
char *buf;
|
|
||||||
struct sockaddr_in local;
|
struct sockaddr_in local;
|
||||||
struct sockaddr_in6 local6;
|
struct sockaddr_in6 local6;
|
||||||
|
|
||||||
|
struct ip_address bind_addr;
|
||||||
|
|
||||||
|
if (!parse_ip(net_info.bind_ip, net_info.bind_port, &bind_addr)) {
|
||||||
|
fprintf(stderr, "FAIL - could not parse bind ip address\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(net_info.prot) {
|
||||||
|
case UDP:
|
||||||
|
sock = socket(bind_addr.family, SOCK_DGRAM, 0);
|
||||||
|
break;
|
||||||
|
case TCP:
|
||||||
|
sock = socket(bind_addr.family, SOCK_STREAM, 0);
|
||||||
|
break;
|
||||||
|
case ICMP:
|
||||||
|
sock = socket(bind_addr.family, SOCK_DGRAM, IPPROTO_ICMP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sock < 0) {
|
||||||
|
perror("FAIL - Socket error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int enable = 1;
|
||||||
|
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &enable, sizeof(int)) < 0)
|
||||||
|
perror("FAIL - setsockopt(SO_REUSEADDR) failed");
|
||||||
|
|
||||||
|
if (bind_addr.family == AF_INET) {
|
||||||
|
local = convert_to_sockaddr_in(bind_addr);
|
||||||
|
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
|
||||||
|
perror("FAIL - Bind error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
local6 = convert_to_sockaddr_in6(bind_addr);
|
||||||
|
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0) {
|
||||||
|
perror("FAIL - Bind error: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (net_info.prot == TCP) {
|
||||||
|
if (listen(sock, 5) == -1) {
|
||||||
|
perror("FAIL - Could not listen: ");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
int receive_udp(int sock)
|
||||||
|
{
|
||||||
|
|
||||||
|
char *buf;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int select_return;
|
int select_return;
|
||||||
|
|
||||||
@@ -37,38 +98,6 @@ int receive_udp()
|
|||||||
buf = (char *) malloc(255);
|
buf = (char *) malloc(255);
|
||||||
memset(buf, '\0', 255);
|
memset(buf, '\0', 255);
|
||||||
|
|
||||||
struct ip_address bind_addr;
|
|
||||||
if (!parse_ip(net_info.bind_ip, net_info.bind_port, &bind_addr)) {
|
|
||||||
fprintf(stderr, "FAIL - could not parse bind ip address\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((sock = socket(bind_addr.family, SOCK_DGRAM, 0)) < 0) {
|
|
||||||
perror("FAIL - Socket error: ");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int enable = 1;
|
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &enable, sizeof(int)) < 0)
|
|
||||||
perror("FAIL - setsockopt(SO_REUSEADDR) failed");
|
|
||||||
|
|
||||||
if (bind_addr.family == AF_INET) {
|
|
||||||
local = convert_to_sockaddr_in(bind_addr);
|
|
||||||
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
|
|
||||||
{
|
|
||||||
perror("FAIL - Bind error: ");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
local6 = convert_to_sockaddr_in6(bind_addr);
|
|
||||||
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0)
|
|
||||||
{
|
|
||||||
printf("errno %d\n", errno);
|
|
||||||
perror("FAIL - Bind error: ");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&read_set);
|
FD_ZERO(&read_set);
|
||||||
FD_SET(sock, &read_set);
|
FD_SET(sock, &read_set);
|
||||||
FD_ZERO(&err_set);
|
FD_ZERO(&err_set);
|
||||||
@@ -77,39 +106,30 @@ int receive_udp()
|
|||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout);
|
select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout);
|
||||||
if (select_return < 0)
|
if (select_return < 0) {
|
||||||
{
|
|
||||||
perror("FAIL - Select error: ");
|
perror("FAIL - Select error: ");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
} else if (select_return == 0) {
|
||||||
|
printf("FAIL - select timeout\n");
|
||||||
|
} else if (select_return > 0 && FD_ISSET(sock, &read_set) && !FD_ISSET(sock, &err_set)) {
|
||||||
|
if (recvfrom(sock, buf, 255, 0, NULL, NULL) >= 1) {
|
||||||
if ((select_return > 0) && (FD_ISSET(sock, &read_set)) && (!FD_ISSET(sock, &err_set)))
|
|
||||||
{
|
|
||||||
|
|
||||||
if (recvfrom(sock, buf, 255, 0, (struct sockaddr *)0, (unsigned int *)0) >= 1)
|
|
||||||
{
|
|
||||||
//printf("MESSAGE: %s\n", buf);
|
//printf("MESSAGE: %s\n", buf);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("FAIL - recvfrom failed\n");
|
printf("FAIL - recvfrom failed\n");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
return(ret);
|
return(ret);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int receive_tcp()
|
int receive_tcp(int sock)
|
||||||
{
|
{
|
||||||
int sock, cli_sock;
|
int cli_sock;
|
||||||
char *buf;
|
char *buf;
|
||||||
struct sockaddr_in local;
|
|
||||||
struct sockaddr_in6 local6;
|
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int select_return;
|
int select_return;
|
||||||
|
|
||||||
@@ -119,44 +139,6 @@ int receive_tcp()
|
|||||||
buf = (char *) malloc(255);
|
buf = (char *) malloc(255);
|
||||||
memset(buf, '\0', 255);
|
memset(buf, '\0', 255);
|
||||||
|
|
||||||
struct ip_address bind_addr;
|
|
||||||
if (!parse_ip(net_info.bind_ip, net_info.bind_port, &bind_addr)) {
|
|
||||||
fprintf(stderr, "FAIL - could not parse bind ip address\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((sock = socket(bind_addr.family, SOCK_STREAM, 0)) < 0)
|
|
||||||
{
|
|
||||||
perror("FAIL - Socket error:");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int enable = 1;
|
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &enable, sizeof(int)) < 0)
|
|
||||||
perror("FAIL - setsockopt(SO_REUSEADDR) failed");
|
|
||||||
|
|
||||||
if (bind_addr.family == AF_INET) {
|
|
||||||
local = convert_to_sockaddr_in(bind_addr);
|
|
||||||
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
|
|
||||||
{
|
|
||||||
perror("FAIL - Bind error: ");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
local6 = convert_to_sockaddr_in6(bind_addr);
|
|
||||||
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0)
|
|
||||||
{
|
|
||||||
perror("FAIL - Bind error: ");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (listen(sock, 5) == -1)
|
|
||||||
{
|
|
||||||
perror("FAIL - Could not listen: ");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&read_set);
|
FD_ZERO(&read_set);
|
||||||
FD_SET(sock, &read_set);
|
FD_SET(sock, &read_set);
|
||||||
FD_ZERO(&err_set);
|
FD_ZERO(&err_set);
|
||||||
@@ -165,48 +147,33 @@ int receive_tcp()
|
|||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout);
|
select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout);
|
||||||
if (select_return < 0)
|
if (select_return < 0) {
|
||||||
{
|
|
||||||
perror("FAIL - Select failed: ");
|
perror("FAIL - Select failed: ");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
} else if (select_return == 0) {
|
||||||
|
printf("FAIL - select timeout\n");
|
||||||
if ((select_return > 0) && (FD_ISSET(sock, &read_set)) && (!FD_ISSET(sock, &err_set)))
|
} else if (select_return > 0 && FD_ISSET(sock, &read_set) && !FD_ISSET(sock, &err_set)) {
|
||||||
{
|
if ((cli_sock = accept(sock, NULL, NULL)) < 0) {
|
||||||
if ((cli_sock = accept(sock, NULL, NULL)) < 0)
|
|
||||||
{
|
|
||||||
perror("FAIL - Accept failed: ");
|
perror("FAIL - Accept failed: ");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
} else {
|
||||||
else
|
if (recv(cli_sock, buf, 255, 0) >= 1) {
|
||||||
{
|
|
||||||
if (recv(cli_sock, buf, 255, 0) >= 1)
|
|
||||||
{
|
|
||||||
//printf("MESSAGE: %s\n", buf);
|
//printf("MESSAGE: %s\n", buf);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
perror("FAIL - recv failure: ");
|
perror("FAIL - recv failure: ");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
perror("FAIL - There were select failures: ");
|
|
||||||
ret = -1;
|
|
||||||
}
|
|
||||||
free(buf);
|
free(buf);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
int receive_icmp()
|
int receive_icmp(int sock)
|
||||||
{
|
{
|
||||||
|
|
||||||
int sock;
|
|
||||||
char *buf;
|
char *buf;
|
||||||
struct sockaddr_in local;
|
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
int select_return;
|
int select_return;
|
||||||
|
|
||||||
@@ -215,25 +182,6 @@ int receive_icmp()
|
|||||||
|
|
||||||
buf = (char *) malloc(255);
|
buf = (char *) malloc(255);
|
||||||
memset(buf, '\0', 255);
|
memset(buf, '\0', 255);
|
||||||
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP)) < 0)
|
|
||||||
{
|
|
||||||
perror("FAIL - Socket error: ");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const int enable = 1;
|
|
||||||
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &enable, sizeof(int)) < 0)
|
|
||||||
perror("FAIL - setsockopt(SO_REUSEADDR) failed");
|
|
||||||
|
|
||||||
local.sin_family = AF_INET;
|
|
||||||
local.sin_port = htons(atoi(net_info.bind_port));
|
|
||||||
inet_aton(net_info.bind_ip, &local.sin_addr);
|
|
||||||
|
|
||||||
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
|
|
||||||
{
|
|
||||||
perror("FAIL - Bind error: ");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
FD_ZERO(&read_set);
|
FD_ZERO(&read_set);
|
||||||
FD_SET(sock, &read_set);
|
FD_SET(sock, &read_set);
|
||||||
@@ -243,28 +191,21 @@ int receive_icmp()
|
|||||||
timeout.tv_usec = 0;
|
timeout.tv_usec = 0;
|
||||||
|
|
||||||
select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout);
|
select_return = select(sock + 1, &read_set, NULL, &err_set, &timeout);
|
||||||
if (select_return < 0)
|
if (select_return < 0) {
|
||||||
{
|
|
||||||
perror("FAIL - Select error: ");
|
perror("FAIL - Select error: ");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
} else if (select_return == 0) {
|
||||||
|
printf("FAIL - select timeout\n");
|
||||||
|
} else if (select_return > 0 && FD_ISSET(sock, &read_set) && !FD_ISSET(sock, &err_set)) {
|
||||||
|
if (recvfrom(sock, buf, 255, 0, NULL, NULL) >= 1) {
|
||||||
if ((select_return > 0) && (FD_ISSET(sock, &read_set)) && (!FD_ISSET(sock, &err_set)))
|
|
||||||
{
|
|
||||||
|
|
||||||
if (recvfrom(sock, buf, 255, 0, (struct sockaddr *)0, (unsigned int *)0) >= 1)
|
|
||||||
{
|
|
||||||
//printf("MESSAGE: %s\n", buf);
|
//printf("MESSAGE: %s\n", buf);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
printf("FAIL - recvfrom failed\n");
|
printf("FAIL - recvfrom failed\n");
|
||||||
ret = -1;
|
ret = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
return(ret);
|
return(ret);
|
||||||
|
|
||||||
@@ -302,7 +243,7 @@ int main(int argc, char *argv[])
|
|||||||
{"protocol", required_argument, 0, 'p' },
|
{"protocol", required_argument, 0, 'p' },
|
||||||
{"timeout", required_argument, 0, 't' },
|
{"timeout", required_argument, 0, 't' },
|
||||||
{"sender", required_argument, 0, 's' },
|
{"sender", required_argument, 0, 's' },
|
||||||
{0, 0, 0, 0 }
|
{0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
while ((opt = getopt_long(argc, argv,"i:o:r:e:p:t:s:", long_options, 0)) != -1) {
|
while ((opt = getopt_long(argc, argv,"i:o:r:e:p:t:s:", long_options, 0)) != -1) {
|
||||||
@@ -321,6 +262,14 @@ int main(int argc, char *argv[])
|
|||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
net_info.protocol = optarg;
|
net_info.protocol = optarg;
|
||||||
|
if (strcmp(net_info.protocol, "udp") == 0)
|
||||||
|
net_info.prot = UDP;
|
||||||
|
else if (strcmp(net_info.protocol, "tcp") == 0)
|
||||||
|
net_info.prot = TCP;
|
||||||
|
else if (strcmp(net_info.protocol, "icmp") == 0)
|
||||||
|
net_info.prot = ICMP;
|
||||||
|
else
|
||||||
|
printf("FAIL - Unknown protocol.\n");
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
net_info.timeout = atoi(optarg);
|
net_info.timeout = atoi(optarg);
|
||||||
@@ -333,6 +282,13 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get the server to bind/listen, so the child has something
|
||||||
|
* to connect to if it wins the race. */
|
||||||
|
int sockfd = receive_bind();
|
||||||
|
if (sockfd == -1) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* exec the sender */
|
/* exec the sender */
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
@@ -357,22 +313,23 @@ int main(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(net_info.protocol, "udp") == 0)
|
switch(net_info.prot) {
|
||||||
ret = receive_udp(net_info);
|
case UDP:
|
||||||
else if (strcmp(net_info.protocol, "tcp") == 0)
|
ret = receive_udp(sockfd);
|
||||||
ret = receive_tcp(net_info);
|
break;
|
||||||
else if (strcmp(net_info.protocol, "icmp") == 0)
|
case TCP:
|
||||||
ret = receive_icmp(net_info);
|
ret = receive_tcp(sockfd);
|
||||||
else
|
break;
|
||||||
printf("FAIL - Unknown protocol.\n");
|
case ICMP:
|
||||||
|
ret = receive_icmp(sockfd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (ret == -1)
|
if (ret == -1) {
|
||||||
{
|
|
||||||
printf("FAIL - Receive message failed.\n");
|
printf("FAIL - Receive message failed.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("PASS\n");
|
printf("PASS\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@@ -12,7 +12,7 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "net_finegrained.h"
|
#include "net_inet.h"
|
||||||
|
|
||||||
struct connection_info {
|
struct connection_info {
|
||||||
char *bind_ip;
|
char *bind_ip;
|
||||||
@@ -40,8 +40,7 @@ int send_udp(char *message)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sock = socket(bind_addr.family, SOCK_DGRAM, 0)) < 0)
|
if ((sock = socket(bind_addr.family, SOCK_DGRAM, 0)) < 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Could not open socket: ");
|
perror("FAIL SND - Could not open socket: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
@@ -53,15 +52,13 @@ int send_udp(char *message)
|
|||||||
|
|
||||||
if (bind_addr.family == AF_INET) {
|
if (bind_addr.family == AF_INET) {
|
||||||
local = convert_to_sockaddr_in(bind_addr);
|
local = convert_to_sockaddr_in(bind_addr);
|
||||||
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
|
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Bind error: ");
|
perror("FAIL SND - Bind error: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
local6 = convert_to_sockaddr_in6(bind_addr);
|
local6 = convert_to_sockaddr_in6(bind_addr);
|
||||||
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0)
|
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Bind error: ");
|
perror("FAIL SND - Bind error: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
@@ -70,22 +67,19 @@ int send_udp(char *message)
|
|||||||
if (remote_addr.family == AF_INET) {
|
if (remote_addr.family == AF_INET) {
|
||||||
remote = convert_to_sockaddr_in(remote_addr);
|
remote = convert_to_sockaddr_in(remote_addr);
|
||||||
//printf("Sending \"%s\"\n", message);
|
//printf("Sending \"%s\"\n", message);
|
||||||
if (sendto(sock, message, strlen(message), 0, (struct sockaddr *) &remote, sizeof(remote)) <= 0)
|
if (sendto(sock, message, strlen(message), 0, (struct sockaddr *) &remote, sizeof(remote)) <= 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Send failed: ");
|
perror("FAIL SND - Send failed: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
remote6 = convert_to_sockaddr_in6(remote_addr);
|
remote6 = convert_to_sockaddr_in6(remote_addr);
|
||||||
//printf("Sending \"%s\"\n", message);
|
//printf("Sending \"%s\"\n", message);
|
||||||
if (sendto(sock, message, strlen(message), 0, (struct sockaddr *) &remote6, sizeof(remote6)) <= 0)
|
if (sendto(sock, message, strlen(message), 0, (struct sockaddr *) &remote6, sizeof(remote6)) <= 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Send failed: ");
|
perror("FAIL SND - Send failed: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
close(sock);
|
close(sock);
|
||||||
return(0);
|
return(0);
|
||||||
|
|
||||||
@@ -121,15 +115,13 @@ int send_tcp(char *message)
|
|||||||
|
|
||||||
if (bind_addr.family == AF_INET) {
|
if (bind_addr.family == AF_INET) {
|
||||||
local = convert_to_sockaddr_in(bind_addr);
|
local = convert_to_sockaddr_in(bind_addr);
|
||||||
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
|
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Bind error: ");
|
perror("FAIL SND - Bind error: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
local6 = convert_to_sockaddr_in6(bind_addr);
|
local6 = convert_to_sockaddr_in6(bind_addr);
|
||||||
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0)
|
if (bind(sock, (struct sockaddr *) &local6, sizeof(local6)) < 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Bind error: ");
|
perror("FAIL SND - Bind error: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
@@ -138,24 +130,21 @@ int send_tcp(char *message)
|
|||||||
if (remote_addr.family == AF_INET) {
|
if (remote_addr.family == AF_INET) {
|
||||||
remote = convert_to_sockaddr_in(remote_addr);
|
remote = convert_to_sockaddr_in(remote_addr);
|
||||||
//printf("Sending \"%s\"\n", message);
|
//printf("Sending \"%s\"\n", message);
|
||||||
if (connect(sock, (struct sockaddr *) &remote, sizeof(remote)) < 0)
|
if (connect(sock, (struct sockaddr *) &remote, sizeof(remote)) < 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Could not connect: ");
|
perror("FAIL SND - Could not connect: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
remote6 = convert_to_sockaddr_in6(remote_addr);
|
remote6 = convert_to_sockaddr_in6(remote_addr);
|
||||||
//printf("Sending \"%s\"\n", message);
|
//printf("Sending \"%s\"\n", message);
|
||||||
if (connect(sock, (struct sockaddr *) &remote6, sizeof(remote6)) < 0)
|
if (connect(sock, (struct sockaddr *) &remote6, sizeof(remote6)) < 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Could not connect: ");
|
perror("FAIL SND - Could not connect: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("Sending \"%s\"\n", message);
|
//printf("Sending \"%s\"\n", message);
|
||||||
if (send(sock, message, strlen(message), 0) <= 0)
|
if (send(sock, message, strlen(message), 0) <= 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Send failed: ");
|
perror("FAIL SND - Send failed: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
@@ -171,8 +160,7 @@ int send_icmp(char *message)
|
|||||||
char packetdata[sizeof(icmp_hdr) + 4];
|
char packetdata[sizeof(icmp_hdr) + 4];
|
||||||
|
|
||||||
|
|
||||||
if ((sock = socket(AF_INET | AF_INET6, SOCK_DGRAM, IPPROTO_ICMP)) < 0)
|
if ((sock = socket(AF_INET | AF_INET6, SOCK_DGRAM, IPPROTO_ICMP)) < 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Could not open socket: ");
|
perror("FAIL SND - Could not open socket: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
@@ -199,8 +187,7 @@ int send_icmp(char *message)
|
|||||||
memcpy(packetdata, &icmp_hdr, sizeof(icmp_hdr));
|
memcpy(packetdata, &icmp_hdr, sizeof(icmp_hdr));
|
||||||
memcpy(packetdata + sizeof(icmp_hdr), message, strlen(message));
|
memcpy(packetdata + sizeof(icmp_hdr), message, strlen(message));
|
||||||
|
|
||||||
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
|
if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Could not bind: ");
|
perror("FAIL SND - Could not bind: ");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
@@ -208,8 +195,7 @@ int send_icmp(char *message)
|
|||||||
//printf("Sending \"%s\"\n", message);
|
//printf("Sending \"%s\"\n", message);
|
||||||
|
|
||||||
// Send the packet
|
// Send the packet
|
||||||
if(sendto(sock, packetdata, sizeof(packetdata), 0, (struct sockaddr*) &remote, sizeof(remote)) < 0)
|
if(sendto(sock, packetdata, sizeof(packetdata), 0, (struct sockaddr*) &remote, sizeof(remote)) < 0) {
|
||||||
{
|
|
||||||
perror("FAIL SND - Send failed: ");
|
perror("FAIL SND - Send failed: ");
|
||||||
close(sock);
|
close(sock);
|
||||||
return(-1);
|
return(-1);
|
||||||
@@ -231,8 +217,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
int send_ret;
|
int send_ret;
|
||||||
|
|
||||||
if (argc < 6)
|
if (argc < 6) {
|
||||||
{
|
|
||||||
printf("Usage: %s bind_ip bind_port remote_ip remote_port proto\n", argv[0]);
|
printf("Usage: %s bind_ip bind_port remote_ip remote_port proto\n", argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -253,8 +238,7 @@ int main(int argc, char *argv[])
|
|||||||
else
|
else
|
||||||
printf("FAIL SND - Unknown protocol.\n");
|
printf("FAIL SND - Unknown protocol.\n");
|
||||||
|
|
||||||
if (send_ret == -1)
|
if (send_ret == -1) {
|
||||||
{
|
|
||||||
printf("FAIL SND - Send message failed.\n");
|
printf("FAIL SND - Send message failed.\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
@@ -29,3 +29,7 @@ runchecktest "RAW SOCKET (no cap)" fail
|
|||||||
genprofile cap:net_raw network:
|
genprofile cap:net_raw network:
|
||||||
runchecktest "RAW SOCKET (cap net_raw)" pass
|
runchecktest "RAW SOCKET (cap net_raw)" pass
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
genprofile "all"
|
||||||
|
runchecktest "RAW SOCKET (allow all)" pass
|
||||||
|
fi
|
||||||
|
@@ -25,7 +25,8 @@ put_old=${new_root}put_old/
|
|||||||
bad=$tmpdir/BAD/
|
bad=$tmpdir/BAD/
|
||||||
proc=$new_root/proc
|
proc=$new_root/proc
|
||||||
fstype="ext2"
|
fstype="ext2"
|
||||||
root_was_shared="no"
|
|
||||||
|
. $bin/mount.inc
|
||||||
|
|
||||||
pivot_root_cleanup() {
|
pivot_root_cleanup() {
|
||||||
mountpoint -q "$proc"
|
mountpoint -q "$proc"
|
||||||
@@ -38,10 +39,7 @@ pivot_root_cleanup() {
|
|||||||
umount "$new_root"
|
umount "$new_root"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "${root_was_shared}" = "yes" ] ; then
|
prop_cleanup
|
||||||
[ -n "$VERBOSE" ] && echo 'notice: re-mounting / as shared'
|
|
||||||
mount --make-shared /
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
do_onexit="pivot_root_cleanup"
|
do_onexit="pivot_root_cleanup"
|
||||||
|
|
||||||
@@ -50,24 +48,6 @@ if [ ! -b /dev/loop0 ] ; then
|
|||||||
modprobe loop
|
modprobe loop
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# systemd mounts / and everything under it MS_SHARED. This breaks
|
|
||||||
# pivot_root entirely, so attempt to detect it, and remount /
|
|
||||||
# MS_PRIVATE temporarily.
|
|
||||||
FINDMNT=/bin/findmnt
|
|
||||||
if [ -x "${FINDMNT}" ] && ${FINDMNT} -no PROPAGATION / > /dev/null 2>&1 ; then
|
|
||||||
if [ "$(${FINDMNT} -no PROPAGATION /)" = "shared" ] ; then
|
|
||||||
root_was_shared="yes"
|
|
||||||
fi
|
|
||||||
elif [ "$(ps hp1 -ocomm)" = "systemd" ] ; then
|
|
||||||
# no findmnt or findmnt doesn't know the PROPAGATION column,
|
|
||||||
# but init is systemd so assume rootfs is shared
|
|
||||||
root_was_shared="yes"
|
|
||||||
fi
|
|
||||||
if [ "${root_was_shared}" = "yes" ] ; then
|
|
||||||
[ -n "$VERBOSE" ] && echo 'notice: re-mounting / as private'
|
|
||||||
mount --make-private /
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create disk image since pivot_root doesn't allow old root and new root to be
|
# Create disk image since pivot_root doesn't allow old root and new root to be
|
||||||
# on the same filesystem
|
# on the same filesystem
|
||||||
dd if=/dev/zero of="$disk_img" bs=1024 count=512 2> /dev/null
|
dd if=/dev/zero of="$disk_img" bs=1024 count=512 2> /dev/null
|
||||||
@@ -120,6 +100,11 @@ if [ "$(kernel_features mount)" != "true" -o "$(parser_supports 'mount,')" != "t
|
|||||||
exit
|
exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
genprofile "all"
|
||||||
|
do_test "allow all rule" pass "$put_old" "$new_root" "$test"
|
||||||
|
fi
|
||||||
|
|
||||||
# Ensure failure when no pivot_root perms are granted
|
# Ensure failure when no pivot_root perms are granted
|
||||||
genprofile $cur $cap
|
genprofile $cur $cap
|
||||||
do_test "cap only" fail "$put_old" "$new_root" "$test"
|
do_test "cap only" fail "$put_old" "$new_root" "$test"
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#define QNAME "/testmq"
|
#define QNAME "/testmq"
|
||||||
#define SHM_PATH "/unnamedsemtest"
|
#define SHM_PATH "/unnamedsemtest"
|
||||||
#define SEM_PATH "/namedsemtest"
|
#define SEM_PATH "/namedsemtest"
|
||||||
|
#define PIPENAME "/tmp/mqueuepipe";
|
||||||
#define OBJ_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
#define OBJ_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)
|
||||||
|
|
||||||
#define BUF_SIZE 1024
|
#define BUF_SIZE 1024
|
||||||
|
@@ -27,6 +27,7 @@ sender="$bin/posix_mq_snd"
|
|||||||
receiver="$bin/posix_mq_rcv"
|
receiver="$bin/posix_mq_rcv"
|
||||||
queuename="/queuename"
|
queuename="/queuename"
|
||||||
queuename2="/queuename2"
|
queuename2="/queuename2"
|
||||||
|
pipe="/tmp/mqueuepipe"
|
||||||
|
|
||||||
user="foo"
|
user="foo"
|
||||||
adduser --gecos "First Last,RoomNumber,WorkPhone,HomePhone" --no-create-home --disabled-password $user >/dev/null
|
adduser --gecos "First Last,RoomNumber,WorkPhone,HomePhone" --no-create-home --disabled-password $user >/dev/null
|
||||||
@@ -41,6 +42,7 @@ cleanup()
|
|||||||
{
|
{
|
||||||
rm -f /dev/mqueue/$queuename
|
rm -f /dev/mqueue/$queuename
|
||||||
rm -f /dev/mqueue/$queuename2
|
rm -f /dev/mqueue/$queuename2
|
||||||
|
rm -f $pipe
|
||||||
deluser foo >/dev/null
|
deluser foo >/dev/null
|
||||||
}
|
}
|
||||||
do_onexit="cleanup"
|
do_onexit="cleanup"
|
||||||
@@ -66,7 +68,7 @@ do_tests()
|
|||||||
do_test "$prefix" "$expect_send" $sender "$expect_recv" -c $sender -k $queuename "${rest_args[@]}"
|
do_test "$prefix" "$expect_send" $sender "$expect_recv" -c $sender -k $queuename "${rest_args[@]}"
|
||||||
|
|
||||||
# notify requires netlink permissions
|
# notify requires netlink permissions
|
||||||
do_test "$prefix : mq_notify" "$expect_send" $sender "$expect_recv" -c $sender -k $queuename -n mq_notify "${rest_args[@]}"
|
do_test "$prefix : mq_notify" "$expect_send" $sender "$expect_recv" -c $sender -k $queuename -n mq_notify -p $pipe "${rest_args[@]}"
|
||||||
|
|
||||||
do_test "$prefix : select" "$expect_open" -c $sender -k $queuename -n select "${rest_args[@]}"
|
do_test "$prefix : select" "$expect_open" -c $sender -k $queuename -n select "${rest_args[@]}"
|
||||||
|
|
||||||
@@ -86,13 +88,17 @@ for username in "root" "$userid" ; do
|
|||||||
do_tests "unconfined $username" pass pass pass pass $usercmd
|
do_tests "unconfined $username" pass pass pass pass $usercmd
|
||||||
|
|
||||||
# No mqueue perms
|
# No mqueue perms
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "$sender:px" -- image=$sender
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "$sender:px" "$pipe:rw" -- image=$sender "$pipe:rw"
|
||||||
do_tests "confined $username - no perms" fail fail fail fail $usercmd
|
do_tests "confined $username - no perms" fail fail fail fail $usercmd
|
||||||
|
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "deny:mqueue" "$sender:px" -- image=$sender "deny mqueue"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "deny:mqueue" "$sender:px" "$pipe:rw" -- image=$sender "deny mqueue" "$pipe:rw"
|
||||||
do_tests "confined $username - deny perms" fail fail fail fail $usercmd
|
do_tests "confined $username - deny perms" fail fail fail fail $usercmd
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
genprofile "all" -- image=$sender "all"
|
||||||
|
do_tests "confined $username - allow all" pass pass pass pass $usercmd
|
||||||
|
fi
|
||||||
|
|
||||||
# generic mqueue
|
# generic mqueue
|
||||||
# 2 Potential failures caused by missing other x permission in path
|
# 2 Potential failures caused by missing other x permission in path
|
||||||
@@ -102,46 +108,46 @@ for username in "root" "$userid" ; do
|
|||||||
# apparmor when doing "root" username tests
|
# apparmor when doing "root" username tests
|
||||||
# * if doing the $userid set of tests and you see
|
# * if doing the $userid set of tests and you see
|
||||||
# Permission denied in the test output
|
# Permission denied in the test output
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:px" -- image=$sender "mqueue"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:px" "$pipe:rw" -- image=$sender "mqueue" "$pipe:rw"
|
||||||
do_tests "confined $username - mqueue" pass pass pass pass $usercmd
|
do_tests "confined $username - mqueue" pass pass pass pass $usercmd
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:type=posix" "$sender:px" -- image=$sender "mqueue:type=posix"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:type=posix" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:type=posix" "$pipe:rw"
|
||||||
do_tests "confined $username - mqueue type=posix" pass pass pass pass $usercmd
|
do_tests "confined $username - mqueue type=posix" pass pass pass pass $usercmd
|
||||||
|
|
||||||
# queue name
|
# queue name
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" -- image=$sender "mqueue:$queuename"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:$queuename" "$pipe:rw"
|
||||||
do_tests "confined $username - mqueue /name 1" pass pass pass pass $usercmd
|
do_tests "confined $username - mqueue /name 1" pass pass pass pass $usercmd
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:px" -- image=$sender "mqueue:$queuename"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:$queuename" "$pipe:rw"
|
||||||
do_tests "confined $username - mqueue /name 2" pass pass pass pass $usercmd
|
do_tests "confined $username - mqueue /name 2" pass pass pass pass $usercmd
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" -- image=$sender "mqueue"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" "$pipe:rw" -- image=$sender "mqueue" "$pipe:rw"
|
||||||
do_tests "confined $username - mqueue /name 3" pass pass pass pass $usercmd
|
do_tests "confined $username - mqueue /name 3" pass pass pass pass $usercmd
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" -- image=$sender "mqueue:$queuename2"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:$queuename" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:$queuename2" "$pipe:rw"
|
||||||
do_tests "confined $username - mqueue /name 4" fail fail fail fail $usercmd -t 1
|
do_tests "confined $username - mqueue /name 4" fail fail fail fail $usercmd -t 1
|
||||||
|
|
||||||
|
|
||||||
# specific permissions
|
# specific permissions
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr,setattr)" "$sender:px" -- image=$sender "mqueue:write"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
|
||||||
do_tests "confined $username - specific 1" pass pass pass pass $usercmd
|
do_tests "confined $username - specific 1" pass pass pass pass $usercmd
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(read,delete,getattr,setattr)" "$sender:px" -- image=$sender "mqueue:write"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(read,delete,getattr,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
|
||||||
do_tests "confined $username - specific 2" fail fail fail fail $usercmd -t 1
|
do_tests "confined $username - specific 2" fail fail fail fail $usercmd -t 1
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,delete,getattr,setattr)" "$sender:px" -- image=$sender "mqueue:write"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,delete,getattr,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
|
||||||
do_tests "confined $username - specific 3" fail fail fail fail $usercmd -t 1
|
do_tests "confined $username - specific 3" fail fail fail fail $usercmd -t 1
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,getattr,setattr)" "$sender:px" -- image=$sender "mqueue:write"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,getattr,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
|
||||||
do_tests "confined $username - specific 4" fail fail fail fail $usercmd -t 1
|
do_tests "confined $username - specific 4" fail fail fail fail $usercmd -t 1
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,setattr)" "$sender:px" -- image=$sender "mqueue:write"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
|
||||||
do_tests "confined $username - specific 5" pass pass pass pass $usercmd
|
do_tests "confined $username - specific 5" pass pass pass pass $usercmd
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr)" "$sender:px" -- image=$sender "mqueue:write"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:write" "$pipe:rw"
|
||||||
do_tests "confined $username - specific 6" pass pass pass pass $usercmd
|
do_tests "confined $username - specific 6" pass pass pass pass $usercmd
|
||||||
|
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr,setattr)" "$sender:px" -- image=$sender "mqueue:read"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete,getattr,setattr)" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:read" "$pipe:rw"
|
||||||
do_tests "confined $username - specific 7" fail fail fail fail $usercmd -t 1
|
do_tests "confined $username - specific 7" fail fail fail fail $usercmd -t 1
|
||||||
|
|
||||||
# unconfined receiver
|
# unconfined receiver
|
||||||
@@ -150,17 +156,17 @@ for username in "root" "$userid" ; do
|
|||||||
|
|
||||||
|
|
||||||
# unconfined sender
|
# unconfined sender
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:ux"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue" "$sender:ux" "$pipe:rw"
|
||||||
do_tests "confined receiver $username - unconfined sender" pass pass pass pass $usercmd
|
do_tests "confined receiver $username - unconfined sender" pass pass pass pass $usercmd
|
||||||
|
|
||||||
|
|
||||||
# queue label
|
# queue label
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:label=$receiver" "$sender:px" -- image=$sender "mqueue:label=$receiver"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:label=$receiver" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:label=$receiver" "$pipe:rw"
|
||||||
do_tests "confined $username - mqueue label 1" xpass xpass xpass xpass $usercmd
|
do_tests "confined $username - mqueue label 1" xpass xpass xpass xpass $usercmd
|
||||||
|
|
||||||
|
|
||||||
# queue name and label
|
# queue name and label
|
||||||
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete):type=posix:label=$receiver:$queuename" "$sender:px" -- image=$sender "mqueue:(open,write):type=posix:label=$receiver:$queuename"
|
genprofile "qual=deny:cap:sys_resource" "cap:setuid" "cap:fowner" "network:netlink" "mqueue:(create,read,delete):type=posix:label=$receiver:$queuename" "$sender:px" "$pipe:rw" -- image=$sender "mqueue:(open,write):type=posix:label=$receiver:$queuename" "$pipe:rw"
|
||||||
do_tests "confined $username - mqueue label 2" xpass xpass xpass xpass $usercmd
|
do_tests "confined $username - mqueue label 2" xpass xpass xpass xpass $usercmd
|
||||||
|
|
||||||
# ensure we are cleaned up for next pass
|
# ensure we are cleaned up for next pass
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
#include <mqueue.h>
|
#include <mqueue.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -6,9 +7,11 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
#include "posix_mq.h"
|
#include "posix_mq.h"
|
||||||
|
#include "pipe_helper.h"
|
||||||
|
|
||||||
int timeout = 5; //seconds
|
int timeout = 5; //seconds
|
||||||
char *queuename = QNAME;
|
char *queuename = QNAME;
|
||||||
|
char *pipepath = PIPENAME;
|
||||||
|
|
||||||
enum notify_options {
|
enum notify_options {
|
||||||
DO_NOT_NOTIFY,
|
DO_NOT_NOTIFY,
|
||||||
@@ -18,10 +21,13 @@ enum notify_options {
|
|||||||
EPOLL
|
EPOLL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum notify_options notify = DO_NOT_NOTIFY;
|
||||||
|
|
||||||
int receive_message(mqd_t mqd, char needs_timeout) {
|
int receive_message(mqd_t mqd, char needs_timeout) {
|
||||||
ssize_t nbytes;
|
ssize_t nbytes;
|
||||||
struct mq_attr attr;
|
struct mq_attr attr;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
|
int ret = EXIT_FAILURE;
|
||||||
|
|
||||||
if (mq_getattr(mqd, &attr) == -1) {
|
if (mq_getattr(mqd, &attr) == -1) {
|
||||||
perror("FAIL - could not mq_getattr");
|
perror("FAIL - could not mq_getattr");
|
||||||
@@ -62,20 +68,24 @@ int receive_message(mqd_t mqd, char needs_timeout) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("PASS\n");
|
printf("PASS\n");
|
||||||
|
ret = EXIT_SUCCESS;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
if (mq_close(mqd) == (mqd_t) -1) {
|
if (mq_close(mqd) == (mqd_t) -1) {
|
||||||
perror("FAIL - could not close mq");
|
perror("FAIL - could not close mq");
|
||||||
exit(EXIT_FAILURE);
|
ret = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
if (mq_unlink(queuename) == (mqd_t) -1) {
|
if (mq_unlink(queuename) == (mqd_t) -1) {
|
||||||
perror("FAIL - could unlink mq");
|
perror("FAIL - could not unlink mq");
|
||||||
exit(EXIT_FAILURE);
|
ret = EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
if (notify == MQ_NOTIFY && unlink(pipepath) == -1) {
|
||||||
exit(EXIT_SUCCESS);
|
perror("FAIL - could not remove pipe");
|
||||||
|
ret = EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
exit(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_signal(union sigval sv) {
|
static void handle_signal(union sigval sv) {
|
||||||
@@ -96,6 +106,7 @@ static void usage(char *prog_name, char *msg)
|
|||||||
fprintf(stderr, "-c path of the client binary\n");
|
fprintf(stderr, "-c path of the client binary\n");
|
||||||
fprintf(stderr, "-u run test as specified UID\n");
|
fprintf(stderr, "-u run test as specified UID\n");
|
||||||
fprintf(stderr, "-t timeout in seconds\n");
|
fprintf(stderr, "-t timeout in seconds\n");
|
||||||
|
fprintf(stderr, "-p named pipe path. used by mq_notify\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,9 +119,15 @@ void receive_mq_notify(mqd_t mqd)
|
|||||||
sev.sigev_value.sival_ptr = &mqd;
|
sev.sigev_value.sival_ptr = &mqd;
|
||||||
|
|
||||||
if (mq_notify(mqd, &sev) == -1) {
|
if (mq_notify(mqd, &sev) == -1) {
|
||||||
perror(" FAIL - could not mq_notify");
|
perror("FAIL - could not mq_notify");
|
||||||
exit(EXIT_FAILURE);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (write_to_pipe(pipepath) == -1) { // let sender know mq_notify is ready
|
||||||
|
fprintf(stderr, "FAIL - could not write to pipe\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
sleep(timeout);
|
sleep(timeout);
|
||||||
fprintf(stderr, "FAIL - could not mq_notify: Connection timed out\n");
|
fprintf(stderr, "FAIL - could not mq_notify: Connection timed out\n");
|
||||||
}
|
}
|
||||||
@@ -127,7 +144,7 @@ void receive_select(mqd_t mqd)
|
|||||||
|
|
||||||
if (select(mqd + 1, &read_fds, NULL, NULL, &tv) == -1) {
|
if (select(mqd + 1, &read_fds, NULL, NULL, &tv) == -1) {
|
||||||
perror("FAIL - could not select");
|
perror("FAIL - could not select");
|
||||||
exit(EXIT_FAILURE);
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (FD_ISSET(mqd, &read_fds))
|
if (FD_ISSET(mqd, &read_fds))
|
||||||
receive_message(mqd, 0);
|
receive_message(mqd, 0);
|
||||||
@@ -142,7 +159,7 @@ void receive_poll(mqd_t mqd)
|
|||||||
|
|
||||||
if (poll(fds, 1, timeout * 1000) == -1) {
|
if (poll(fds, 1, timeout * 1000) == -1) {
|
||||||
perror("FAIL - could not poll");
|
perror("FAIL - could not poll");
|
||||||
exit(EXIT_FAILURE);
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (fds[0].revents & POLLIN)
|
if (fds[0].revents & POLLIN)
|
||||||
receive_message(mqd, 0);
|
receive_message(mqd, 0);
|
||||||
@@ -154,7 +171,7 @@ void receive_epoll(mqd_t mqd)
|
|||||||
int epfd = epoll_create(1);
|
int epfd = epoll_create(1);
|
||||||
if (epfd == -1) {
|
if (epfd == -1) {
|
||||||
perror("FAIL - could not create epoll");
|
perror("FAIL - could not create epoll");
|
||||||
exit(EXIT_FAILURE);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct epoll_event ev, rev[1];
|
struct epoll_event ev, rev[1];
|
||||||
@@ -162,12 +179,12 @@ void receive_epoll(mqd_t mqd)
|
|||||||
ev.data.fd = mqd;
|
ev.data.fd = mqd;
|
||||||
if (epoll_ctl(epfd, EPOLL_CTL_ADD, mqd, &ev) == -1) {
|
if (epoll_ctl(epfd, EPOLL_CTL_ADD, mqd, &ev) == -1) {
|
||||||
perror("FAIL - could not add mqd to epoll");
|
perror("FAIL - could not add mqd to epoll");
|
||||||
exit(EXIT_FAILURE);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (epoll_wait(epfd, rev, 1, timeout * 1000) == -1) {
|
if (epoll_wait(epfd, rev, 1, timeout * 1000) == -1) {
|
||||||
perror("FAIL - could not epoll_wait");
|
perror("FAIL - could not epoll_wait");
|
||||||
exit(EXIT_FAILURE);
|
return;
|
||||||
} else {
|
} else {
|
||||||
if (rev[0].data.fd == mqd && rev[0].events & EPOLLIN)
|
if (rev[0].data.fd == mqd && rev[0].events & EPOLLIN)
|
||||||
receive_message(mqd, 0);
|
receive_message(mqd, 0);
|
||||||
@@ -198,17 +215,17 @@ void receive(enum notify_options notify, mqd_t mqd)
|
|||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int opt = 0;
|
int opt = 0;
|
||||||
enum notify_options notify = DO_NOT_NOTIFY;
|
|
||||||
mqd_t mqd;
|
mqd_t mqd;
|
||||||
char *client = NULL;
|
char *client = NULL;
|
||||||
int uid;
|
int uid;
|
||||||
|
int pipefd;
|
||||||
struct mq_attr attr;
|
struct mq_attr attr;
|
||||||
attr.mq_flags = 0;
|
attr.mq_flags = 0;
|
||||||
attr.mq_maxmsg = 10;
|
attr.mq_maxmsg = 10;
|
||||||
attr.mq_msgsize = BUF_SIZE;
|
attr.mq_msgsize = BUF_SIZE;
|
||||||
attr.mq_curmsgs = 0;
|
attr.mq_curmsgs = 0;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "n:k:c:u:t:")) != -1) {
|
while ((opt = getopt(argc, argv, "n:k:c:u:t:p:")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 'n':
|
case 'n':
|
||||||
if (strcmp(optarg, "mq_notify") == 0)
|
if (strcmp(optarg, "mq_notify") == 0)
|
||||||
@@ -258,6 +275,9 @@ int main(int argc, char *argv[])
|
|||||||
case 't':
|
case 't':
|
||||||
timeout = atoi(optarg);
|
timeout = atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'p':
|
||||||
|
pipepath = optarg;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
usage(argv[0], "Unrecognized option\n");
|
usage(argv[0], "Unrecognized option\n");
|
||||||
}
|
}
|
||||||
@@ -269,11 +289,24 @@ int main(int argc, char *argv[])
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (notify == MQ_NOTIFY) {
|
||||||
|
if (mkfifo(pipepath, 0666) == -1) {
|
||||||
|
perror("FAIL - could not mkfifo");
|
||||||
|
goto nopipeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
pipefd = open_read_pipe(pipepath);
|
||||||
|
if (pipefd == -1) {
|
||||||
|
fprintf(stderr, "FAIL - couldn't open pipe\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* exec the client */
|
/* exec the client */
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
perror("FAIL - could not fork");
|
perror("FAIL - could not fork");
|
||||||
exit(EXIT_FAILURE);
|
goto out;
|
||||||
} else if (!pid) {
|
} else if (!pid) {
|
||||||
if (client == NULL) {
|
if (client == NULL) {
|
||||||
usage(argv[0], "client not specified");
|
usage(argv[0], "client not specified");
|
||||||
@@ -282,25 +315,30 @@ int main(int argc, char *argv[])
|
|||||||
* in case the client will be manually executed
|
* in case the client will be manually executed
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
execl(client, client, queuename, NULL);
|
if (notify == MQ_NOTIFY) {
|
||||||
printf("FAIL %d - execlp %s %s- %m\n", getuid(), client, queuename);
|
char strpipefd[12];
|
||||||
|
sprintf(strpipefd, "%d", pipefd);
|
||||||
|
execl(client, client, queuename, strpipefd, NULL);
|
||||||
|
printf("FAIL %d - execlp %s %s %s- %m\n", getuid(), client, queuename, strpipefd);
|
||||||
|
} else {
|
||||||
|
execl(client, client, queuename, NULL);
|
||||||
|
printf("FAIL %d - execlp %s %s- %m\n", getuid(), client, queuename);
|
||||||
|
}
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
receive(notify, mqd);
|
receive(notify, mqd);
|
||||||
|
|
||||||
/* when the notification fails because of timeout, it ends up here
|
/* when the notification fails because of timeout, it ends up here
|
||||||
* so, clean up the mqueue
|
* so, clean up the mqueue and exit_failure
|
||||||
*/
|
*/
|
||||||
|
out:
|
||||||
if (mq_close(mqd) == (mqd_t) -1) {
|
if (notify == MQ_NOTIFY && unlink(pipepath) == -1)
|
||||||
|
perror("FAIL - could not remove pipe");
|
||||||
|
nopipeout:
|
||||||
|
if (mq_close(mqd) == (mqd_t) -1)
|
||||||
perror("FAIL - could not close mq");
|
perror("FAIL - could not close mq");
|
||||||
exit(EXIT_FAILURE);
|
if (mq_unlink(queuename) == (mqd_t) -1)
|
||||||
}
|
|
||||||
if (mq_unlink(queuename) == (mqd_t) -1) {
|
|
||||||
perror("FAIL - could unlink mq");
|
perror("FAIL - could unlink mq");
|
||||||
exit(EXIT_FAILURE);
|
return EXIT_FAILURE;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
@@ -1,16 +1,27 @@
|
|||||||
|
#define _GNU_SOURCE
|
||||||
#include <mqueue.h>
|
#include <mqueue.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "posix_mq.h"
|
#include "posix_mq.h"
|
||||||
|
#include "pipe_helper.h"
|
||||||
|
|
||||||
int main(int argc, char * argv[])
|
int main(int argc, char * argv[])
|
||||||
{
|
{
|
||||||
mqd_t mqd;
|
mqd_t mqd;
|
||||||
char *queuename = QNAME;
|
char *queuename = QNAME;
|
||||||
|
int pipefd;
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
queuename = argv[1];
|
queuename = argv[1];
|
||||||
}
|
}
|
||||||
|
if (argc > 2) {
|
||||||
|
pipefd = atoi(argv[2]);
|
||||||
|
if (read_from_pipe(pipefd) == -1) { // wait for receiver to mq_notify
|
||||||
|
fprintf(stderr, "FAIL - could not read from pipe\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mqd = mq_open(queuename, O_WRONLY);
|
mqd = mq_open(queuename, O_WRONLY);
|
||||||
if (mqd == (mqd_t) -1) {
|
if (mqd == (mqd_t) -1) {
|
||||||
perror("FAIL sender - could not open mq");
|
perror("FAIL sender - could not open mq");
|
||||||
|
@@ -235,6 +235,15 @@ runchecktest "test 12p2 -hc" fail -h -c -n 100 $helper
|
|||||||
runchecktest "test 12p2 -h prog" fail -h -n 100 $helper ${bin_true}
|
runchecktest "test 12p2 -h prog" fail -h -n 100 $helper ${bin_true}
|
||||||
runchecktest "test 12p2 -hc prog" fail -h -c -n 100 $helper ${bin_true}
|
runchecktest "test 12p2 -hc prog" fail -h -c -n 100 $helper ${bin_true}
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
genprofile "all"
|
||||||
|
runchecktest "test allow all" pass -n 100 ${bin_true}
|
||||||
|
runchecktest "test allow all -c" pass -c -n 100 ${bin_true}
|
||||||
|
runchecktest "test allow all -h" pass -h -n 100 $helper
|
||||||
|
runchecktest "test allow all -hc" pass -h -c -n 100 $helper
|
||||||
|
runchecktest "test allow all -h prog" pass -h -n 100 $helper ${bin_true}
|
||||||
|
runchecktest "test allow all -hc prog" pass -h -c -n 100 $helper ${bin_true}
|
||||||
|
fi
|
||||||
|
|
||||||
#ptraced confined app traced by profile can px
|
#ptraced confined app traced by profile can px
|
||||||
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix
|
genprofile ${bin_true}:rpx $helper:rix signal:ALL ptrace:peer=$test ptrace:peer=${bin_true} -- image=${bin_true} ${bin_true}:rix
|
||||||
|
@@ -27,16 +27,38 @@ bin=$pwd
|
|||||||
## A. SWAP
|
## A. SWAP
|
||||||
##
|
##
|
||||||
|
|
||||||
# check if we can run the test at all
|
swap_file=$tmpdir/swapfile
|
||||||
|
|
||||||
|
# check if we can run the test in tmpdir
|
||||||
fstype=$(stat -f --format '%T' "${tmpdir}")
|
fstype=$(stat -f --format '%T' "${tmpdir}")
|
||||||
if [ "${fstype}" = "tmpfs" ] ; then
|
if [ "${fstype}" = "tmpfs" ] ; then
|
||||||
echo "ERROR: tmpdir '${tmpdir}' is of type tmpfs; can't mount a swapfile on it" 1>&2
|
# create a mountpoint not tmpfs
|
||||||
echo "ERROR: skipping swap tests" 1>&2
|
mount_file=$tmpdir/mountfile
|
||||||
num_testfailures=1
|
mount_point=$tmpdir/mountpoint
|
||||||
exit
|
fstype="ext2"
|
||||||
|
dd if=/dev/zero of=${mount_file} bs=1024 count=900 2> /dev/null
|
||||||
|
/sbin/mkfs -t${fstype} -F ${mount_file} > /dev/null 2> /dev/null
|
||||||
|
/bin/mkdir ${mount_point}
|
||||||
|
|
||||||
|
loop_device=$(losetup -f) || fatalerror 'Unable to find a free loop device'
|
||||||
|
/sbin/losetup "$loop_device" ${mount_file} > /dev/null 2> /dev/null
|
||||||
|
|
||||||
|
/bin/mount -n -t${fstype} ${loop_device} ${mount_point}
|
||||||
|
|
||||||
|
swap_file=$mount_point/swapfile
|
||||||
fi
|
fi
|
||||||
|
|
||||||
swap_file=$tmpdir/swapfile
|
remove_mnt() {
|
||||||
|
mountpoint -q "${mount_point}"
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
/bin/umount -t${fstype} ${mount_point}
|
||||||
|
fi
|
||||||
|
if [ -n "$loop_device" ]
|
||||||
|
then
|
||||||
|
/sbin/losetup -d ${loop_device} &> /dev/null
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
do_onexit="remove_mnt"
|
||||||
|
|
||||||
# ppc64el wants this to be larger than 640KiB
|
# ppc64el wants this to be larger than 640KiB
|
||||||
# arm/small machines want this as small as possible
|
# arm/small machines want this as small as possible
|
||||||
|
@@ -35,6 +35,12 @@ runchecktest "TCP (no apparmor)" pass $port
|
|||||||
genprofile
|
genprofile
|
||||||
runchecktest "TCP (accept, connect) no network rules" fail $port
|
runchecktest "TCP (accept, connect) no network rules" fail $port
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
# PASS TEST - allow all
|
||||||
|
genprofile "all"
|
||||||
|
runchecktest "TCP (allow all)" pass $port
|
||||||
|
fi
|
||||||
|
|
||||||
# PASS TEST - allow tcp
|
# PASS TEST - allow tcp
|
||||||
genprofile network:tcp
|
genprofile network:tcp
|
||||||
runchecktest "TCP (accept, connect) allow tcp" pass $port
|
runchecktest "TCP (accept, connect) allow tcp" pass $port
|
||||||
|
@@ -71,6 +71,11 @@ do_test()
|
|||||||
|
|
||||||
desc+=" confined $test_prog"
|
desc+=" confined $test_prog"
|
||||||
|
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
$genprof "all"
|
||||||
|
runchecktest "$desc (allow all)" pass $args
|
||||||
|
fi
|
||||||
|
|
||||||
$genprof "unix:ALL"
|
$genprof "unix:ALL"
|
||||||
runchecktest "$desc (implicit perms)" pass $args
|
runchecktest "$desc (implicit perms)" pass $args
|
||||||
|
|
||||||
|
@@ -23,7 +23,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
#include "userns.h"
|
#include "pipe_helper.h"
|
||||||
|
|
||||||
static void usage(char *pname)
|
static void usage(char *pname)
|
||||||
{
|
{
|
||||||
|
@@ -101,6 +101,11 @@ fi
|
|||||||
# confined tests should have the same results if apparmor_restrict_unprivileged_userns is enabled or not
|
# confined tests should have the same results if apparmor_restrict_unprivileged_userns is enabled or not
|
||||||
run_confined_tests()
|
run_confined_tests()
|
||||||
{
|
{
|
||||||
|
if [ "$(parser_supports 'all,')" = "true" ]; then
|
||||||
|
generate_profile="genprofile all"
|
||||||
|
do_test "confined allow all $1" pass pass pass pass "$generate_profile"
|
||||||
|
fi
|
||||||
|
|
||||||
generate_profile="genprofile userns"
|
generate_profile="genprofile userns"
|
||||||
do_test "confined all perms $1" pass pass fail fail "$generate_profile"
|
do_test "confined all perms $1" pass pass fail fail "$generate_profile"
|
||||||
|
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "userns.h"
|
#include "pipe_helper.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
@@ -131,7 +131,7 @@ def notify_about_new_entries(logfile, filters, wait=0):
|
|||||||
debug_logger.info(format_event(event, logfile))
|
debug_logger.info(format_event(event, logfile))
|
||||||
yield (format_event(event, logfile))
|
yield (format_event(event, logfile))
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
sys.exit(_("ERROR: Cannot read {}. Please check permissions.".format(logfile)))
|
sys.exit(_("ERROR: Cannot read {}. Please check permissions.").format(logfile))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(_('Notification emitter started in the background'))
|
print(_('Notification emitter started in the background'))
|
||||||
|
@@ -89,9 +89,9 @@ LOADED_PROFILES=$("$PARSER" -N $PROFILE_DIRS) || {
|
|||||||
echo "$LOADED_PROFILES" | awk '
|
echo "$LOADED_PROFILES" | awk '
|
||||||
BEGIN {
|
BEGIN {
|
||||||
while (getline < "'${PROFILES}'" ) {
|
while (getline < "'${PROFILES}'" ) {
|
||||||
str = sub(/ \((enforce|complain)\)$/, "", $0);
|
sub(/ \((enforce|complain|unconfined)\)$/, "", $0);
|
||||||
if (match($0, /^libvirt-[0-9a-f\-]+$/) == 0)
|
if (match($0, /^libvirt-[0-9a-f\-]+$/) == 0)
|
||||||
arr[$str] = $str
|
arr[$0] = $0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -603,8 +603,8 @@ def autodep(bin_name, pname=''):
|
|||||||
|
|
||||||
active_profiles.add_profile(file, pname, attachment)
|
active_profiles.add_profile(file, pname, attachment)
|
||||||
|
|
||||||
if os.path.isfile(profile_dir + '/abi/3.0'):
|
if os.path.isfile(profile_dir + '/abi/4.0'):
|
||||||
active_profiles.add_abi(file, AbiRule('abi/3.0', False, True))
|
active_profiles.add_abi(file, AbiRule('abi/4.0', False, True))
|
||||||
if os.path.isfile(profile_dir + '/tunables/global'):
|
if os.path.isfile(profile_dir + '/tunables/global'):
|
||||||
active_profiles.add_inc_ie(file, IncludeRule('tunables/global', False, True))
|
active_profiles.add_inc_ie(file, IncludeRule('tunables/global', False, True))
|
||||||
write_profile_ui_feedback(pname)
|
write_profile_ui_feedback(pname)
|
||||||
@@ -833,9 +833,12 @@ def ask_exec(hashlog):
|
|||||||
raise AppArmorBug(
|
raise AppArmorBug(
|
||||||
'exec permissions requested for directory %s (profile %s). This should not happen - please open a bugreport!' % (exec_target, full_profile))
|
'exec permissions requested for directory %s (profile %s). This should not happen - please open a bugreport!' % (exec_target, full_profile))
|
||||||
|
|
||||||
if not aa[profile].get(hat):
|
if not aa.get(profile):
|
||||||
continue # ignore log entries for non-existing profiles
|
continue # ignore log entries for non-existing profiles
|
||||||
|
|
||||||
|
if not aa[profile].get(hat):
|
||||||
|
continue # ignore log entries for non-existing hats
|
||||||
|
|
||||||
exec_event = FileRule(exec_target, None, FileRule.ANY_EXEC, FileRule.ALL, owner=False, log_event=True)
|
exec_event = FileRule(exec_target, None, FileRule.ANY_EXEC, FileRule.ALL, owner=False, log_event=True)
|
||||||
if is_known_rule(aa[profile][hat], 'file', exec_event):
|
if is_known_rule(aa[profile][hat], 'file', exec_event):
|
||||||
continue
|
continue
|
||||||
@@ -1797,6 +1800,9 @@ def read_profiles(ui_msg=False, skip_profiles=()):
|
|||||||
if os.path.isfile(full_file):
|
if os.path.isfile(full_file):
|
||||||
if is_skippable_file(file):
|
if is_skippable_file(file):
|
||||||
continue
|
continue
|
||||||
|
elif os.path.exists(f'{profile_dir}/disable/{file}'):
|
||||||
|
aaui.UI_Info("skipping disabled profile %s" % file)
|
||||||
|
continue
|
||||||
elif file in skip_profiles:
|
elif file in skip_profiles:
|
||||||
aaui.UI_Info("skipping profile %s" % full_file)
|
aaui.UI_Info("skipping profile %s" % full_file)
|
||||||
continue
|
continue
|
||||||
|
@@ -212,7 +212,7 @@ class ReadLog:
|
|||||||
self.hashlog[aamode][full_profile]['io_uring'][e['denied_mask']][e['peer_profile']] = True
|
self.hashlog[aamode][full_profile]['io_uring'][e['denied_mask']][e['peer_profile']] = True
|
||||||
return
|
return
|
||||||
|
|
||||||
elif e['class'] and e['class'] == 'mount':
|
elif e['class'] and e['class'] == 'mount' or e['operation'] == 'mount':
|
||||||
if e['flags'] != None:
|
if e['flags'] != None:
|
||||||
e['flags'] = ('=', e['flags'])
|
e['flags'] = ('=', e['flags'])
|
||||||
if e['fs_type'] != None:
|
if e['fs_type'] != None:
|
||||||
|
@@ -51,7 +51,7 @@ class BaseRule(metaclass=ABCMeta):
|
|||||||
# Set only in the parse() class method
|
# Set only in the parse() class method
|
||||||
self.raw_rule = None
|
self.raw_rule = None
|
||||||
|
|
||||||
def _aare_or_all(self, rulepart, partname, is_path, log_event):
|
def _aare_or_all(self, rulepart, partname, is_path, log_event, empty_ok=False):
|
||||||
"""checks rulepart and returns
|
"""checks rulepart and returns
|
||||||
- (AARE, False) if rulepart is a (non-empty) string
|
- (AARE, False) if rulepart is a (non-empty) string
|
||||||
- (None, True) if rulepart is all_obj (typically *Rule.ALL)
|
- (None, True) if rulepart is all_obj (typically *Rule.ALL)
|
||||||
@@ -67,7 +67,7 @@ class BaseRule(metaclass=ABCMeta):
|
|||||||
if rulepart == self.ALL:
|
if rulepart == self.ALL:
|
||||||
return None, True
|
return None, True
|
||||||
elif isinstance(rulepart, str):
|
elif isinstance(rulepart, str):
|
||||||
if not rulepart.strip():
|
if not rulepart.strip() and not empty_ok:
|
||||||
raise AppArmorBug(
|
raise AppArmorBug(
|
||||||
'Passed empty %(partname)s to %(classname)s: %(rulepart)s'
|
'Passed empty %(partname)s to %(classname)s: %(rulepart)s'
|
||||||
% {'partname': partname, 'classname': self.__class__.__name__, 'rulepart': str(rulepart)})
|
% {'partname': partname, 'classname': self.__class__.__name__, 'rulepart': str(rulepart)})
|
||||||
|
@@ -15,7 +15,7 @@ import re
|
|||||||
|
|
||||||
from apparmor.common import AppArmorBug, AppArmorException
|
from apparmor.common import AppArmorBug, AppArmorException
|
||||||
|
|
||||||
from apparmor.regex import RE_PROFILE_MOUNT, RE_PROFILE_PATH_OR_VAR, strip_parenthesis
|
from apparmor.regex import RE_PROFILE_MOUNT, strip_parenthesis, strip_quotes
|
||||||
from apparmor.rule import AARE
|
from apparmor.rule import AARE
|
||||||
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers, logprof_value_or_all, check_and_split_list
|
from apparmor.rule import BaseRule, BaseRuleset, parse_modifiers, logprof_value_or_all, check_and_split_list
|
||||||
|
|
||||||
@@ -23,32 +23,22 @@ from apparmor.translations import init_translation
|
|||||||
|
|
||||||
_ = init_translation()
|
_ = init_translation()
|
||||||
|
|
||||||
# TODO :
|
# TODO : Apparmor remount logs are displayed as mount (with remount flag). Profiles generated with aa-genprof are therefore mount rules. It could be interesting to make them remount rules.
|
||||||
# - match correctly AARE on every field
|
|
||||||
# - Find the actual list of supported filesystems. This one comes from /proc/filesystems. We also blindly accept fuse.*
|
|
||||||
# - Support path that begin by { (e.g. {,/usr}/lib/...) This syntax is not a valid AARE but is used by usr.lib.snapd.snap-confine.real in Ubuntu and will currently raise an error in genprof if these lines are not modified.
|
|
||||||
# - Apparmor remount logs are displayed as mount (with remount flag). Profiles generated with aa-genprof are therefore mount rules. It could be interesting to make them remount rules.
|
|
||||||
|
|
||||||
valid_fs = [
|
flags_bind_mount = {'B', 'bind', 'R', 'rbind'}
|
||||||
'sysfs', 'tmpfs', 'bdevfs', 'procfs', 'cgroup', 'cgroup2', 'cpuset', 'devtmpfs', 'configfs', 'debugfs', 'tracefs',
|
flags_change_propagation = {
|
||||||
'securityfs', 'sockfs', 'bpf', 'npipefs', 'ramfs', 'hugetlbfs', 'devpts', 'ext3', 'ext2', 'ext4', 'squashfs',
|
'remount', 'unbindable', 'shared', 'private', 'slave', 'runbindable', 'rshared', 'rprivate', 'rslave',
|
||||||
'vfat', 'ecryptfs', 'fuseblk', 'fuse', 'fusectl', 'efivarfs', 'mqueue', 'store', 'autofs', 'binfmt_misc', 'overlay',
|
'make-unbindable', 'make-shared', 'make-private', 'make-slave', 'make-runbindable', 'make-rshared', 'make-rprivate',
|
||||||
'none', 'bdev', 'proc', 'pipefs', 'pstore', 'btrfs', 'xfs', '9p', 'resctrl', 'zfs', 'iso9660', 'udf', 'ntfs3',
|
'make-rslave'
|
||||||
'nfs', 'cifs',
|
}
|
||||||
]
|
# keep in sync with parser/mount.cc mnt_opts_table!
|
||||||
|
flags_keywords = list(flags_bind_mount) + list(flags_change_propagation) + [
|
||||||
flags_keywords = [
|
'ro', 'r', 'read-only', 'rw', 'w', 'suid', 'nosuid', 'dev', 'nodev', 'exec', 'noexec', 'sync', 'async', 'mand',
|
||||||
# keep in sync with parser/mount.cc mnt_opts_table!
|
'nomand', 'dirsync', 'symfollow', 'nosymfollow', 'atime', 'noatime', 'diratime', 'nodiratime', 'move', 'M',
|
||||||
'ro', 'r', 'read-only', 'rw', 'w', 'suid', 'nosuid', 'dev', 'nodev', 'exec', 'noexec', 'sync', 'async', 'remount',
|
'verbose', 'silent', 'loud', 'acl', 'noacl', 'relatime', 'norelatime', 'iversion', 'noiversion', 'strictatime',
|
||||||
'mand', 'nomand', 'dirsync', 'symfollow', 'nosymfollow', 'atime', 'noatime', 'diratime', 'nodiratime', 'bind', 'B',
|
'nostrictatime', 'lazytime', 'nolazytime', 'user', 'nouser', '([A-Za-z0-9])',
|
||||||
'move', 'M', 'rbind', 'R', 'verbose', 'silent', 'loud', 'acl', 'noacl', 'unbindable', 'make-unbindable', 'runbindable',
|
|
||||||
'make-runbindable', 'private', 'make-private', 'rprivate', 'make-rprivate', 'slave', 'make-slave', 'rslave', 'make-rslave',
|
|
||||||
'shared', 'make-shared', 'rshared', 'make-rshared', 'relatime', 'norelatime', 'iversion', 'noiversion', 'strictatime',
|
|
||||||
'nostrictatime', 'lazytime', 'nolazytime', 'user', 'nouser',
|
|
||||||
'([A-Za-z0-9])',
|
|
||||||
]
|
]
|
||||||
join_valid_flags = '|'.join(flags_keywords)
|
join_valid_flags = '|'.join(flags_keywords)
|
||||||
join_valid_fs = '|'.join(valid_fs)
|
|
||||||
|
|
||||||
sep = r'\s*[\s,]\s*'
|
sep = r'\s*[\s,]\s*'
|
||||||
|
|
||||||
@@ -72,9 +62,13 @@ mount_condition_pattern = rf'({fs_type_pattern})?\s*({option_pattern})?'
|
|||||||
# - A filesystem : sysfs (sudo mount -t tmpfs tmpfs /tmp/bar)
|
# - A filesystem : sysfs (sudo mount -t tmpfs tmpfs /tmp/bar)
|
||||||
# - Any label : mntlabel (sudo mount -t tmpfs mntlabel /tmp/bar)
|
# - Any label : mntlabel (sudo mount -t tmpfs mntlabel /tmp/bar)
|
||||||
# Thus we cannot use directly RE_PROFILE_PATH_OR_VAR
|
# Thus we cannot use directly RE_PROFILE_PATH_OR_VAR
|
||||||
|
# Destination can also be
|
||||||
|
# - A path : /foo
|
||||||
|
# - A globbed Path : **
|
||||||
|
|
||||||
source_fileglob_pattern = r'(\s*(?P<source_file>([/{]\S*|"[/{][^"]*"|@{\S+}\S*|"@{\S+}[^"]*")|\w+))'
|
glob_pattern = r'(\s*(?P<%s>(([/{]|\*\*)\S*|"([/{]|\*\*)[^"]*"|@{\S+}\S*|"@{\S+}[^"]*"|"")|\w+))'
|
||||||
dest_fileglob_pattern = r'(\s*' + RE_PROFILE_PATH_OR_VAR % 'dest_file' + r')'
|
source_fileglob_pattern = glob_pattern % 'source_file'
|
||||||
|
dest_fileglob_pattern = glob_pattern % 'dest_file'
|
||||||
|
|
||||||
RE_MOUNT_DETAILS = re.compile(r'^\s*' + mount_condition_pattern + rf'(\s+{source_fileglob_pattern})?' + rf'(\s+->\s+{dest_fileglob_pattern})?\s*' + r'$')
|
RE_MOUNT_DETAILS = re.compile(r'^\s*' + mount_condition_pattern + rf'(\s+{source_fileglob_pattern})?' + rf'(\s+->\s+{dest_fileglob_pattern})?\s*' + r'$')
|
||||||
RE_UMOUNT_DETAILS = re.compile(r'^\s*' + mount_condition_pattern + rf'(\s+{dest_fileglob_pattern})?\s*' + r'$')
|
RE_UMOUNT_DETAILS = re.compile(r'^\s*' + mount_condition_pattern + rf'(\s+{dest_fileglob_pattern})?\s*' + r'$')
|
||||||
@@ -102,34 +96,26 @@ class MountRule(BaseRule):
|
|||||||
|
|
||||||
self.operation = operation
|
self.operation = operation
|
||||||
|
|
||||||
self.fstype, self.all_fstype, unknown_items = check_and_split_list(fstype[1] if fstype != self.ALL else fstype, valid_fs, self.ALL, type(self).__name__, 'fstype')
|
if fstype == self.ALL or fstype[1] == self.ALL:
|
||||||
|
self.all_fstype = True
|
||||||
if unknown_items:
|
self.fstype = None
|
||||||
for it in unknown_items:
|
self.is_fstype_equal = None
|
||||||
|
else:
|
||||||
# Several filesystems use fuse internally and are referred as fuse.<software_name> (e.g. fuse.jmtpfs, fuse.s3fs, fuse.obexfs).
|
self.all_fstype = False
|
||||||
# Since this list seems to evolve too fast for a fixed list to work in practice, we just accept fuse.*
|
for it in fstype[1]:
|
||||||
# See https://github.com/libfuse/libfuse/wiki/Filesystems and, https://doc.ubuntu-fr.org/fuse
|
l, unused = parse_aare(it, 0, 'fstype')
|
||||||
if it.startswith('fuse.') and len(it) > 5:
|
if l != len(it):
|
||||||
continue
|
raise AppArmorException(f'Invalid aare : {it}')
|
||||||
|
self.fstype = fstype[1]
|
||||||
it = AARE(it, is_path=False)
|
self.is_fstype_equal = fstype[0]
|
||||||
found = False
|
|
||||||
for fs in valid_fs:
|
|
||||||
if self._is_covered_aare(it, self.all_fstype, AARE(fs, False), self.all_fstype, 'fstype'):
|
|
||||||
found = True
|
|
||||||
break
|
|
||||||
if not found:
|
|
||||||
raise AppArmorException(_('Passed unknown fstype keyword to %s: %s') % (type(self).__name__, ' '.join(unknown_items)))
|
|
||||||
|
|
||||||
self.is_fstype_equal = fstype[0] if not self.all_fstype else None
|
|
||||||
|
|
||||||
self.options, self.all_options, unknown_items = check_and_split_list(options[1] if options != self.ALL else options, flags_keywords, self.ALL, type(self).__name__, 'options')
|
self.options, self.all_options, unknown_items = check_and_split_list(options[1] if options != self.ALL else options, flags_keywords, self.ALL, type(self).__name__, 'options')
|
||||||
if unknown_items:
|
if unknown_items:
|
||||||
raise AppArmorException(_('Passed unknown options keyword to %s: %s') % (type(self).__name__, ' '.join(unknown_items)))
|
raise AppArmorException(_('Passed unknown options keyword to %s: %s') % (type(self).__name__, ' '.join(unknown_items)))
|
||||||
self.is_options_equal = options[0] if not self.all_options else None
|
self.is_options_equal = options[0] if not self.all_options else None
|
||||||
|
|
||||||
self.source, self.all_source = self._aare_or_all(source, 'source', is_path=False, log_event=log_event)
|
self.source, self.all_source = self._aare_or_all(source, 'source', is_path=False, log_event=log_event, empty_ok=True)
|
||||||
|
self.dest, self.all_dest = self._aare_or_all(dest, 'dest', is_path=False, log_event=log_event)
|
||||||
|
|
||||||
if not self.all_fstype and self.is_fstype_equal not in ('=', 'in'):
|
if not self.all_fstype and self.is_fstype_equal not in ('=', 'in'):
|
||||||
raise AppArmorBug(f'Invalid is_fstype_equal : {self.is_fstype_equal}')
|
raise AppArmorBug(f'Invalid is_fstype_equal : {self.is_fstype_equal}')
|
||||||
@@ -138,11 +124,14 @@ class MountRule(BaseRule):
|
|||||||
if self.operation != 'mount' and not self.all_source:
|
if self.operation != 'mount' and not self.all_source:
|
||||||
raise AppArmorException(f'Operation {self.operation} cannot have a source')
|
raise AppArmorException(f'Operation {self.operation} cannot have a source')
|
||||||
|
|
||||||
flags_forbidden_with_source = {'remount', 'unbindable', 'shared', 'private', 'slave', 'runbindable', 'rshared', 'rprivate', 'rslave'}
|
if self.operation == 'mount' and not self.all_options and flags_change_propagation & self.options != set():
|
||||||
if self.operation == 'mount' and not self.all_source and not self.all_options and flags_forbidden_with_source & self.options != set():
|
if not (self.all_source or self.all_dest):
|
||||||
raise AppArmorException(f'Operation {flags_forbidden_with_source & self.options} cannot have a source. Source = {self.source}')
|
raise AppArmorException(f'Operation {flags_change_propagation & self.options} cannot specify a source. Source = {self.source}')
|
||||||
|
elif not self.all_fstype:
|
||||||
|
raise AppArmorException(f'Operation {flags_change_propagation & self.options} cannot specify a fstype. Fstype = {self.fstype}')
|
||||||
|
|
||||||
self.dest, self.all_dest = self._aare_or_all(dest, 'dest', is_path=True, log_event=log_event)
|
if self.operation == 'mount' and not self.all_options and flags_bind_mount & self.options != set() and not self.all_fstype:
|
||||||
|
raise AppArmorException(f'Bind mount rules cannot specify a fstype. Fstype = {self.fstype}')
|
||||||
|
|
||||||
self.can_glob = not self.all_source and not self.all_dest and not self.all_options
|
self.can_glob = not self.all_source and not self.all_dest and not self.all_options
|
||||||
|
|
||||||
@@ -169,7 +158,7 @@ class MountRule(BaseRule):
|
|||||||
|
|
||||||
if r['fstype'] is not None:
|
if r['fstype'] is not None:
|
||||||
is_fstype_equal = r['fstype_equals_or_in']
|
is_fstype_equal = r['fstype_equals_or_in']
|
||||||
fstype = strip_parenthesis(r['fstype']).replace(',', ' ').split()
|
fstype = parse_aare_list(strip_parenthesis(r['fstype']), 'fstype')
|
||||||
else:
|
else:
|
||||||
is_fstype_equal = None
|
is_fstype_equal = None
|
||||||
fstype = cls.ALL
|
fstype = cls.ALL
|
||||||
@@ -182,12 +171,12 @@ class MountRule(BaseRule):
|
|||||||
options = cls.ALL
|
options = cls.ALL
|
||||||
|
|
||||||
if operation == 'mount' and r['source_file'] is not None: # Umount cannot have a source
|
if operation == 'mount' and r['source_file'] is not None: # Umount cannot have a source
|
||||||
source = r['source_file']
|
source = strip_quotes(r['source_file'])
|
||||||
else:
|
else:
|
||||||
source = cls.ALL
|
source = cls.ALL
|
||||||
|
|
||||||
if r['dest_file'] is not None:
|
if r['dest_file'] is not None:
|
||||||
dest = r['dest_file']
|
dest = strip_quotes(r['dest_file'])
|
||||||
else:
|
else:
|
||||||
dest = cls.ALL
|
dest = cls.ALL
|
||||||
|
|
||||||
@@ -312,6 +301,38 @@ class MountRuleset(BaseRuleset):
|
|||||||
'''Class to handle and store a collection of Mount rules'''
|
'''Class to handle and store a collection of Mount rules'''
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def parse_aare(s, offset, param):
|
||||||
|
parsed = ''
|
||||||
|
brace_count = 0
|
||||||
|
for i, c in enumerate(s[offset:], start=offset):
|
||||||
|
if c in [' ', ',', '\t'] and brace_count == 0:
|
||||||
|
break
|
||||||
|
parsed += c
|
||||||
|
if c == '{':
|
||||||
|
brace_count += 1
|
||||||
|
elif c == '}':
|
||||||
|
brace_count -= 1
|
||||||
|
if brace_count < 0:
|
||||||
|
raise AppArmorException(f"Unmatched closing brace in {param}: {s[offset:]}")
|
||||||
|
offset = i
|
||||||
|
|
||||||
|
if brace_count != 0:
|
||||||
|
raise AppArmorException(f"Unmatched opening brace in {param}: {s[offset:]}")
|
||||||
|
|
||||||
|
return offset + 1, parsed
|
||||||
|
|
||||||
|
|
||||||
|
def parse_aare_list(s, param):
|
||||||
|
res = []
|
||||||
|
offset = 0
|
||||||
|
while offset <= len(s):
|
||||||
|
offset, part = parse_aare(s, offset, param)
|
||||||
|
if part.translate(' ,\t') != '':
|
||||||
|
res.append(part)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
def wrap_in_with_spaces(value):
|
def wrap_in_with_spaces(value):
|
||||||
''' wrap 'in' keyword in spaces, and leave everything else unchanged '''
|
''' wrap 'in' keyword in spaces, and leave everything else unchanged '''
|
||||||
|
|
||||||
|
@@ -35,7 +35,7 @@ RE_ACCESS_KEYWORDS = (joint_access_keyword + # one of the access_keyword or
|
|||||||
r'\(' + joint_access_keyword + '(' + r'(\s|,)+' + joint_access_keyword + ')*' + r'\)' # one or more access_keyword in (...)
|
r'\(' + joint_access_keyword + '(' + r'(\s|,)+' + joint_access_keyword + ')*' + r'\)' # one or more access_keyword in (...)
|
||||||
)
|
)
|
||||||
|
|
||||||
RE_MQUEUE_NAME = r'(?P<%s>(/\S+|\d*))' # / + string for posix, or digits for sys
|
RE_MQUEUE_NAME = r'(?P<%s>(/\S*|\d*))' # / + string for posix, or digits for sys
|
||||||
RE_MQUEUE_TYPE = r'(?P<%s>(sysv|posix))' # type can be sysv or posix
|
RE_MQUEUE_TYPE = r'(?P<%s>(sysv|posix))' # type can be sysv or posix
|
||||||
|
|
||||||
RE_MQUEUE_DETAILS = re.compile(
|
RE_MQUEUE_DETAILS = re.compile(
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user