mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-02 15:25:27 +00:00
Compare commits
87 Commits
v4.0.0-bet
...
v4.0.1
Author | SHA1 | Date | |
---|---|---|---|
|
b0eb95457b | ||
|
5ad4efec50 | ||
|
a635a86e1d | ||
|
c8e25e4689 | ||
|
68dd052873 | ||
|
4cef932170 | ||
|
8108a217a3 | ||
|
2284e99613 | ||
|
f763c44cd0 | ||
|
1d36e1f196 | ||
|
22ee6c19bc | ||
|
6198edb3d0 | ||
|
4d2a171466 | ||
|
e88cf3cd02 | ||
|
6f856dfee3 | ||
|
a6d8171bd6 | ||
|
26e7249f44 | ||
|
117d0cc444 | ||
|
1c7127d30d | ||
|
d111ddcc21 | ||
|
fa26623e6d | ||
|
451bb8b235 | ||
|
6e46631b6f | ||
|
f9527d2113 | ||
|
9dc2f48773 | ||
|
2fc80487f7 | ||
|
c87969b37c | ||
|
b68bb18860 | ||
|
c47789340a | ||
|
e23a3eeba5 | ||
|
d0fadc48cf | ||
|
aec3f3b22c | ||
|
101651c88f | ||
|
efc2ec5fdd | ||
|
b01b9895e7 | ||
|
a0a0c88d9e | ||
|
63676459c4 | ||
|
9ed04cb01e | ||
|
2a885872a3 | ||
|
989501428e | ||
|
25f21a0758 | ||
|
022af9c528 | ||
|
9a1838016c | ||
|
f4c19acfba | ||
|
dac9d08764 | ||
|
243162ca29 | ||
|
ae978c1953 | ||
|
d19db55a37 | ||
|
e3d381cf91 | ||
|
aa69d9adc9 | ||
|
3d1dedfa7e | ||
|
f27b1ef93a | ||
|
18d6a917f8 | ||
|
d1d39d176e | ||
|
2d654477f2 | ||
|
66dc2cc7d0 | ||
|
021c3248f9 | ||
|
353ba896d4 | ||
|
c13007f7fc | ||
|
88a420853e | ||
|
2db41acd1b | ||
|
a10d9044b8 | ||
|
b53441a689 | ||
|
7452f34279 | ||
|
aedb8a5b00 | ||
|
6695944c2c | ||
|
01090dcf1b | ||
|
3ea2bfec56 | ||
|
3d1a867c0a | ||
|
dfb02cbd93 | ||
|
90f056c1c6 | ||
|
0daf3e8c9b | ||
|
a86c1bd45a | ||
|
8f4073ecd9 | ||
|
440be71c12 | ||
|
8d21f01924 | ||
|
4e546291a5 | ||
|
8c026077d6 | ||
|
5e4c4a0cb3 | ||
|
9c27a7c435 | ||
|
a367c07437 | ||
|
2200013088 | ||
|
d5afc33c40 | ||
|
517e7c96c8 | ||
|
a7cd59819e | ||
|
e7f5ee3271 | ||
|
da75b1c8d8 |
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
|
||||||
|
@@ -67,10 +67,10 @@ to syslog.
|
|||||||
References
|
References
|
||||||
----------
|
----------
|
||||||
Project webpage:
|
Project webpage:
|
||||||
http://developer.novell.com/wiki/index.php/Novell_AppArmor
|
https://apparmor.net/
|
||||||
|
|
||||||
To provide feedback or ask questions please contact the
|
To provide feedback or ask questions please contact the
|
||||||
apparmor-dev@forge.novell.com mail list. This is the development list
|
apparmor@lists.ubuntu.com mail list. This is the development list
|
||||||
for the AppArmor team.
|
for the AppArmor team.
|
||||||
|
|
||||||
See also: change_hat(3), and the Linux-PAM online documentation at
|
See also: change_hat(3), and the Linux-PAM online documentation at
|
||||||
|
@@ -188,10 +188,9 @@ parent context.
|
|||||||
8. Feedback/Resources
|
8. Feedback/Resources
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
Project webpage:
|
||||||
|
https://apparmor.net/
|
||||||
|
|
||||||
To provide feedback or ask questions please contact the
|
To provide feedback or ask questions please contact the
|
||||||
apparmor-dev@forge.novell.com mail list. This is the development list for the
|
apparmor@lists.ubuntu.com mail list. This is the development list
|
||||||
AppArmor team.
|
for the AppArmor team.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -188,10 +188,9 @@ parent context.
|
|||||||
8. Feedback/Resources
|
8. Feedback/Resources
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
Project webpage:
|
||||||
|
https://apparmor.net/
|
||||||
|
|
||||||
To provide feedback or ask questions please contact the
|
To provide feedback or ask questions please contact the
|
||||||
apparmor-dev@forge.novell.com mail list. This is the development list for the
|
apparmor@lists.ubuntu.com mail list. This is the development list
|
||||||
AppArmor team.
|
for the AppArmor team.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1 +1 @@
|
|||||||
4.0.0~beta1
|
4.0.1
|
||||||
|
@@ -92,7 +92,8 @@ if test "$ac_cv_prog_cc_c99" = "no"; then
|
|||||||
AC_MSG_ERROR([C99 mode is required to build libapparmor])
|
AC_MSG_ERROR([C99 mode is required to build libapparmor])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
EXTRA_CFLAGS="-Wall $(EXTRA_WARNINGS) -fPIC"
|
m4_ifndef([AX_CHECK_COMPILE_FLAG], [AC_MSG_ERROR(['autoconf-archive' missing])])
|
||||||
|
EXTRA_CFLAGS="-Wall $EXTRA_WARNINGS -fPIC"
|
||||||
AX_CHECK_COMPILE_FLAG([-flto-partition=none], , , [-Werror])
|
AX_CHECK_COMPILE_FLAG([-flto-partition=none], , , [-Werror])
|
||||||
AS_VAR_IF([ax_cv_check_cflags__Werror__flto_partition_none], [yes],
|
AS_VAR_IF([ax_cv_check_cflags__Werror__flto_partition_none], [yes],
|
||||||
[EXTRA_CFLAGS="$EXTRA_CFLAGS -flto-partition=none"]
|
[EXTRA_CFLAGS="$EXTRA_CFLAGS -flto-partition=none"]
|
||||||
|
@@ -440,7 +440,6 @@ install-arch: $(INSTALLDEPS)
|
|||||||
install-indep: indep
|
install-indep: indep
|
||||||
install -m 755 -d $(INSTALL_CONFDIR)
|
install -m 755 -d $(INSTALL_CONFDIR)
|
||||||
install -m 644 parser.conf $(INSTALL_CONFDIR)
|
install -m 644 parser.conf $(INSTALL_CONFDIR)
|
||||||
install -m 755 -d ${DESTDIR}/var/lib/apparmor
|
|
||||||
install -m 755 -d $(APPARMOR_BIN_PREFIX)
|
install -m 755 -d $(APPARMOR_BIN_PREFIX)
|
||||||
install -m 755 rc.apparmor.functions $(APPARMOR_BIN_PREFIX)
|
install -m 755 rc.apparmor.functions $(APPARMOR_BIN_PREFIX)
|
||||||
install -m 755 profile-load $(APPARMOR_BIN_PREFIX)
|
install -m 755 profile-load $(APPARMOR_BIN_PREFIX)
|
||||||
|
@@ -29,8 +29,6 @@
|
|||||||
class all_rule: public prefix_rule_t {
|
class all_rule: public prefix_rule_t {
|
||||||
void move_conditionals(struct cond_entry *conds);
|
void move_conditionals(struct cond_entry *conds);
|
||||||
public:
|
public:
|
||||||
char *label;
|
|
||||||
|
|
||||||
all_rule(void): prefix_rule_t(RULE_TYPE_ALL) { }
|
all_rule(void): prefix_rule_t(RULE_TYPE_ALL) { }
|
||||||
|
|
||||||
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
virtual bool valid_prefix(const prefixes &p, const char *&error) {
|
||||||
|
@@ -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
|
||||||
@@ -2037,8 +2101,6 @@ An example AppArmor profile:
|
|||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
=item F</etc/init.d/boot.apparmor>
|
|
||||||
|
|
||||||
=item F</etc/apparmor.d/>
|
=item F</etc/apparmor.d/>
|
||||||
|
|
||||||
=back
|
=back
|
||||||
|
@@ -36,12 +36,11 @@ of resources. AppArmor's unique security model is to bind access control
|
|||||||
attributes to programs rather than to users.
|
attributes to programs rather than to users.
|
||||||
|
|
||||||
AppArmor confinement is provided via I<profiles> loaded into the kernel
|
AppArmor confinement is provided via I<profiles> loaded into the kernel
|
||||||
via apparmor_parser(8), typically through the F</etc/init.d/apparmor>
|
via apparmor_parser(8), typically through the F<apparmor.service>
|
||||||
SysV initscript, which is used like this:
|
systemd unit, which is used like this:
|
||||||
|
|
||||||
# /etc/init.d/apparmor start
|
# systemctl start apparmor
|
||||||
# /etc/init.d/apparmor stop
|
# systemctl reload apparmor
|
||||||
# /etc/init.d/apparmor restart
|
|
||||||
|
|
||||||
AppArmor can operate in two modes: I<enforcement>, and I<complain or learning>:
|
AppArmor can operate in two modes: I<enforcement>, and I<complain or learning>:
|
||||||
|
|
||||||
@@ -273,11 +272,9 @@ Else, if auditd is running, see auditd(8) and auditd.conf(5).
|
|||||||
|
|
||||||
=over 4
|
=over 4
|
||||||
|
|
||||||
=item F</etc/init.d/apparmor>
|
|
||||||
|
|
||||||
=item F</etc/apparmor.d/>
|
=item F</etc/apparmor.d/>
|
||||||
|
|
||||||
=item F</var/lib/apparmor/>
|
=item F</var/cache/apparmor/>
|
||||||
|
|
||||||
=item F</var/log/audit/audit.log>
|
=item F</var/log/audit/audit.log>
|
||||||
|
|
||||||
|
@@ -234,6 +234,7 @@ struct mnt_keyword_table {
|
|||||||
unsigned int clear;
|
unsigned int clear;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// keep in sync with utils/apparmor/rule/mount.py flags_keywords
|
||||||
static struct mnt_keyword_table mnt_opts_table[] = {
|
static struct mnt_keyword_table mnt_opts_table[] = {
|
||||||
{"ro", MS_RDONLY, 0},
|
{"ro", MS_RDONLY, 0},
|
||||||
{"r", MS_RDONLY, 0},
|
{"r", MS_RDONLY, 0},
|
||||||
|
@@ -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);
|
||||||
|
|
||||||
|
@@ -252,6 +252,19 @@ const char *net_find_af_name(unsigned int af)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char *net_find_protocol_name(unsigned int protocol)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(network_mappings) / sizeof(*network_mappings); i++) {
|
||||||
|
if (network_mappings[i].protocol == protocol) {
|
||||||
|
return network_mappings[i].protocol_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
const struct network_tuple *net_find_mapping(const struct network_tuple *map,
|
const struct network_tuple *net_find_mapping(const struct network_tuple *map,
|
||||||
const char *family,
|
const char *family,
|
||||||
const char *type,
|
const char *type,
|
||||||
@@ -331,8 +344,8 @@ bool parse_port_number(const char *port_entry, uint16_t *port) {
|
|||||||
char *eptr;
|
char *eptr;
|
||||||
unsigned long port_tmp = strtoul(port_entry, &eptr, 10);
|
unsigned long port_tmp = strtoul(port_entry, &eptr, 10);
|
||||||
|
|
||||||
if (port_tmp >= 0 && port_entry != eptr &&
|
if (port_entry != eptr && *eptr == '\0' &&
|
||||||
*eptr == '\0' && port_tmp <= UINT16_MAX) {
|
port_tmp <= UINT16_MAX) {
|
||||||
*port = port_tmp;
|
*port = port_tmp;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -347,6 +360,10 @@ 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, "none") == 0) {
|
||||||
|
entry.is_none = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
entry.is_ip = true;
|
entry.is_ip = true;
|
||||||
return parse_ip(entry.sip, &entry.ip);
|
return parse_ip(entry.sip, &entry.ip);
|
||||||
}
|
}
|
||||||
@@ -374,30 +391,45 @@ void network_rule::move_conditionals(struct cond_entry *conds, ip_conds &ip_cond
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void network_rule::set_netperm(unsigned int family, unsigned int type)
|
void network_rule::set_netperm(unsigned int family, unsigned int type, unsigned int protocol)
|
||||||
{
|
{
|
||||||
if (type > SOCK_PACKET) {
|
if (type > SOCK_PACKET) {
|
||||||
/* setting mask instead of a bit */
|
/* setting mask instead of a bit */
|
||||||
network_perms[family] |= type;
|
network_perms[family].first |= type;
|
||||||
} else
|
} else
|
||||||
network_perms[family] |= 1 << type;
|
network_perms[family].first |= 1 << type;
|
||||||
|
network_perms[family].second |= protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
network_rule::network_rule(perms_t perms_p, struct cond_entry *conds,
|
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)
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
@@ -412,29 +444,45 @@ network_rule::network_rule(perms_t perms_p, struct cond_entry *conds,
|
|||||||
network_rule::network_rule(perms_t perms_p, const char *family, const char *type,
|
network_rule::network_rule(perms_t perms_p, const char *family, const char *type,
|
||||||
const char *protocol, struct cond_entry *conds,
|
const char *protocol, struct cond_entry *conds,
|
||||||
struct cond_entry *peer_conds):
|
struct cond_entry *peer_conds):
|
||||||
dedup_perms_rule_t(AA_CLASS_NETV8)
|
dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL)
|
||||||
{
|
{
|
||||||
const struct network_tuple *mapping = NULL;
|
const struct network_tuple *mapping = NULL;
|
||||||
while ((mapping = net_find_mapping(mapping, family, type, protocol))) {
|
|
||||||
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
|
|
||||||
set_netperm(mapping->family, mapping->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == NULL && network_map.empty()) {
|
|
||||||
while ((mapping = net_find_mapping(mapping, type, family, protocol))) {
|
|
||||||
network_map[mapping->family].push_back({ mapping->family, mapping->type, mapping->protocol });
|
|
||||||
set_netperm(mapping->family, mapping->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (network_map.empty())
|
|
||||||
yyerror(_("Invalid network entry."));
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
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 });
|
||||||
|
set_netperm(mapping->family, mapping->type, mapping->protocol);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == NULL && network_map.empty()) {
|
||||||
|
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 });
|
||||||
|
set_netperm(mapping->family, mapping->type, mapping->protocol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (network_map.empty())
|
||||||
|
yyerror(_("Invalid network entry."));
|
||||||
|
|
||||||
if (perms_p) {
|
if (perms_p) {
|
||||||
perms = perms_p;
|
perms = perms_p;
|
||||||
if (perms & ~AA_VALID_NET_PERMS)
|
if (perms & ~AA_VALID_NET_PERMS)
|
||||||
@@ -447,10 +495,10 @@ network_rule::network_rule(perms_t perms_p, const char *family, const char *type
|
|||||||
}
|
}
|
||||||
|
|
||||||
network_rule::network_rule(perms_t perms_p, unsigned int family, unsigned int type):
|
network_rule::network_rule(perms_t perms_p, unsigned int family, unsigned int type):
|
||||||
dedup_perms_rule_t(AA_CLASS_NETV8)
|
dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL)
|
||||||
{
|
{
|
||||||
network_map[family].push_back({ family, type, 0xFFFFFFFF });
|
network_map[family].push_back({ family, type, 0xFFFFFFFF });
|
||||||
set_netperm(family, type);
|
set_netperm(family, type, 0xFFFFFFFF);
|
||||||
|
|
||||||
if (perms_p) {
|
if (perms_p) {
|
||||||
perms = perms_p;
|
perms = perms_p;
|
||||||
@@ -479,7 +527,8 @@ ostream &network_rule::dump(ostream &os)
|
|||||||
|
|
||||||
for (const auto& perm : network_perms) {
|
for (const auto& perm : network_perms) {
|
||||||
unsigned int family = perm.first;
|
unsigned int family = perm.first;
|
||||||
unsigned int type = perm.second;
|
unsigned int type = perm.second.first;
|
||||||
|
unsigned int protocol = perm.second.second;
|
||||||
|
|
||||||
const char *family_name = net_find_af_name(family);
|
const char *family_name = net_find_af_name(family);
|
||||||
if (family_name)
|
if (family_name)
|
||||||
@@ -507,6 +556,12 @@ ostream &network_rule::dump(ostream &os)
|
|||||||
os << " #" << std::hex << (type & mask);
|
os << " #" << std::hex << (type & mask);
|
||||||
|
|
||||||
printf(" }");
|
printf(" }");
|
||||||
|
|
||||||
|
const char *protocol_name = net_find_protocol_name(protocol);
|
||||||
|
if (protocol_name)
|
||||||
|
os << " " << protocol_name;
|
||||||
|
else
|
||||||
|
os << " #" << protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
os << ",\n";
|
os << ",\n";
|
||||||
@@ -531,14 +586,14 @@ std::string gen_ip_cond(const struct ip_address ip)
|
|||||||
int i;
|
int i;
|
||||||
if (ip.family == AF_INET) {
|
if (ip.family == AF_INET) {
|
||||||
/* add a byte containing the size of the following ip */
|
/* add a byte containing the size of the following ip */
|
||||||
oss << "\\x04";
|
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << IPV4_SIZE;
|
||||||
|
|
||||||
u8 *byte = (u8 *) &ip.address.address_v4; /* in network byte order */
|
u8 *byte = (u8 *) &ip.address.address_v4; /* in network byte order */
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << static_cast<unsigned int>(byte[i]);
|
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << static_cast<unsigned int>(byte[i]);
|
||||||
} else {
|
} else {
|
||||||
/* add a byte containing the size of the following ip */
|
/* add a byte containing the size of the following ip */
|
||||||
oss << "\\x10";
|
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << IPV6_SIZE;
|
||||||
for (i = 0; i < 16; ++i)
|
for (i = 0; i < 16; ++i)
|
||||||
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << static_cast<unsigned int>(ip.address.address_v6[i]);
|
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << static_cast<unsigned int>(ip.address.address_v6[i]);
|
||||||
}
|
}
|
||||||
@@ -557,48 +612,114 @@ std::string gen_port_cond(uint16_t port)
|
|||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void network_rule::gen_ip_conds(std::ostringstream &oss, ip_conds entry, bool is_peer, bool is_cmd)
|
std::list<std::ostringstream> gen_all_ip_options(std::ostringstream &oss) {
|
||||||
|
|
||||||
|
std::list<std::ostringstream> all_streams;
|
||||||
|
std::ostringstream none, ipv4, ipv6;
|
||||||
|
int i;
|
||||||
|
none << oss.str();
|
||||||
|
ipv4 << oss.str();
|
||||||
|
ipv6 << oss.str();
|
||||||
|
|
||||||
|
none << "\\x" << std::setfill('0') << std::setw(2) << std::hex << NONE_SIZE;
|
||||||
|
|
||||||
|
/* add a byte containing the size of the following ip */
|
||||||
|
ipv4 << "\\x" << std::setfill('0') << std::setw(2) << std::hex << IPV4_SIZE;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
ipv4 << ".";
|
||||||
|
|
||||||
|
/* add a byte containing the size of the following ip */
|
||||||
|
ipv6 << "\\x" << std::setfill('0') << std::setw(2) << std::hex << IPV6_SIZE;
|
||||||
|
for (i = 0; i < 16; ++i)
|
||||||
|
ipv6 << ".";
|
||||||
|
|
||||||
|
all_streams.push_back(std::move(none));
|
||||||
|
all_streams.push_back(std::move(ipv4));
|
||||||
|
all_streams.push_back(std::move(ipv6));
|
||||||
|
|
||||||
|
return all_streams;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::list<std::ostringstream> copy_streams_list(std::list<std::ostringstream> &streams)
|
||||||
{
|
{
|
||||||
/* encode protocol */
|
std::list<std::ostringstream> streams_copy;
|
||||||
if (!is_cmd) {
|
for (auto &oss : streams) {
|
||||||
if (entry.is_ip) {
|
std::ostringstream oss_copy(oss.str());
|
||||||
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ((entry.ip.family & 0xff00) >> 8);
|
streams_copy.push_back(std::move(oss_copy));
|
||||||
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (entry.ip.family & 0xff);
|
}
|
||||||
|
return streams_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool network_rule::gen_ip_conds(Profile &prof, std::list<std::ostringstream> &streams, ip_conds &entry, bool is_peer, bool is_cmd)
|
||||||
|
{
|
||||||
|
std::string buf;
|
||||||
|
perms_t cond_perms;
|
||||||
|
std::list<std::ostringstream> ip_streams;
|
||||||
|
|
||||||
|
for (auto &oss : streams) {
|
||||||
|
if (entry.is_port && !(entry.is_ip && entry.is_none)) {
|
||||||
|
/* encode port type (privileged - 1, remote - 2, unprivileged - 0) */
|
||||||
|
if (!is_peer && perms & AA_NET_BIND && entry.port < IPPORT_RESERVED)
|
||||||
|
oss << "\\x01";
|
||||||
|
else if (is_peer)
|
||||||
|
oss << "\\x02";
|
||||||
|
else
|
||||||
|
oss << "\\x00";
|
||||||
|
|
||||||
|
oss << gen_port_cond(entry.port);
|
||||||
} else {
|
} else {
|
||||||
oss << "..";
|
/* port type + port number */
|
||||||
|
oss << "...";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.is_port) {
|
ip_streams = std::move(streams);
|
||||||
/* encode port type (privileged - 1, remote - 2, unprivileged - 0) */
|
streams.clear();
|
||||||
if (!is_peer && perms & AA_NET_BIND && entry.port < IPPORT_RESERVED)
|
|
||||||
oss << "\\x01";
|
|
||||||
else if (is_peer)
|
|
||||||
oss << "\\x02";
|
|
||||||
else
|
|
||||||
oss << "\\x00";
|
|
||||||
|
|
||||||
oss << gen_port_cond(entry.port);
|
for (auto &oss : ip_streams) {
|
||||||
} else {
|
if (entry.is_ip) {
|
||||||
/* port type + port number */
|
oss << gen_ip_cond(entry.ip);
|
||||||
if (!is_cmd)
|
streams.push_back(std::move(oss));
|
||||||
oss << ".";
|
} else if (entry.is_none) {
|
||||||
oss << "..";
|
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << NONE_SIZE;
|
||||||
|
streams.push_back(std::move(oss));
|
||||||
|
} else {
|
||||||
|
streams.splice(streams.end(), gen_all_ip_options(oss));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.is_ip) {
|
cond_perms = map_perms(perms);
|
||||||
oss << gen_ip_cond(entry.ip);
|
if (!is_cmd && (label || is_peer))
|
||||||
} else {
|
cond_perms = (AA_CONT_MATCH << 1);
|
||||||
/* encode 0 to indicate there's no ip (ip size) */
|
|
||||||
oss << "\\x00";
|
|
||||||
}
|
|
||||||
|
|
||||||
oss << "\\-x01"; /* oob separator */
|
for (auto &oss : streams) {
|
||||||
oss << default_match_pattern; /* label - not used for now */
|
oss << "\\x00"; /* null transition */
|
||||||
oss << "\\x00"; /* null transition */
|
|
||||||
|
buf = oss.str();
|
||||||
|
/* AA_CONT_MATCH mapping (cond_perms) only applies to perms, not audit */
|
||||||
|
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, cond_perms,
|
||||||
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||||
|
parseopts))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (label || is_peer) {
|
||||||
|
if (!is_peer)
|
||||||
|
cond_perms = map_perms(perms);
|
||||||
|
|
||||||
|
oss << default_match_pattern; /* label - not used for now */
|
||||||
|
oss << "\\x00"; /* null transition */
|
||||||
|
|
||||||
|
buf = oss.str();
|
||||||
|
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, cond_perms,
|
||||||
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||||
|
parseopts))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mask) {
|
bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mask, unsigned int protocol) {
|
||||||
std::ostringstream buffer;
|
std::ostringstream buffer;
|
||||||
std::string buf;
|
std::string buf;
|
||||||
|
|
||||||
@@ -612,58 +733,96 @@ bool network_rule::gen_net_rule(Profile &prof, u16 family, unsigned int type_mas
|
|||||||
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (type_mask & 0xff);
|
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (type_mask & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!features_supports_inet) {
|
if (!features_supports_inet || (family != AF_INET && family != AF_INET6)) {
|
||||||
buf = buffer.str();
|
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(AA_VALID_NET_PERMS),
|
|
||||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(AA_VALID_NET_PERMS) : 0,
|
|
||||||
parseopts))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (perms & AA_PEER_NET_PERMS) {
|
|
||||||
gen_ip_conds(buffer, peer, true, false);
|
|
||||||
|
|
||||||
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_ADDR;
|
|
||||||
|
|
||||||
gen_ip_conds(buffer, local, false, true);
|
|
||||||
|
|
||||||
buf = buffer.str();
|
buf = buffer.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms),
|
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms),
|
||||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
return false;
|
return false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if ((perms & AA_NET_LISTEN) || (perms & AA_NET_OPT)) {
|
|
||||||
gen_ip_conds(buffer, local, false, false);
|
|
||||||
|
|
||||||
if (perms & AA_NET_LISTEN) {
|
buf = buffer.str();
|
||||||
std::ostringstream cmd_buffer;
|
/* create perms need to be generated excluding the rest of the perms */
|
||||||
cmd_buffer << buffer.str();
|
if (perms & AA_NET_CREATE) {
|
||||||
cmd_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_LISTEN;
|
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms & AA_NET_CREATE) | (AA_CONT_MATCH << 1),
|
||||||
/* length of queue allowed - not used for now */
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms & AA_NET_CREATE) : 0,
|
||||||
cmd_buffer << "..";
|
parseopts))
|
||||||
buf = cmd_buffer.str();
|
return false;
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms),
|
}
|
||||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
|
||||||
parseopts))
|
/* encode protocol */
|
||||||
return false;
|
if (protocol > 0xffff) {
|
||||||
|
buffer << "..";
|
||||||
|
} else {
|
||||||
|
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << ((protocol & 0xff00) >> 8);
|
||||||
|
buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << (protocol & 0xff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (perms & AA_PEER_NET_PERMS) {
|
||||||
|
std::list<std::ostringstream> streams;
|
||||||
|
std::ostringstream cmd_buffer;
|
||||||
|
|
||||||
|
cmd_buffer << buffer.str();
|
||||||
|
streams.push_back(std::move(cmd_buffer));
|
||||||
|
|
||||||
|
if (!gen_ip_conds(prof, streams, peer, true, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto &oss : streams) {
|
||||||
|
oss << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_ADDR;
|
||||||
}
|
}
|
||||||
if (perms & AA_NET_OPT) {
|
|
||||||
std::ostringstream cmd_buffer;
|
if (!gen_ip_conds(prof, streams, local, false, true))
|
||||||
cmd_buffer << buffer.str();
|
return false;
|
||||||
cmd_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_OPT;
|
}
|
||||||
/* level - not used for now */
|
|
||||||
cmd_buffer << "..";
|
std::list<std::ostringstream> streams;
|
||||||
/* socket mapping - not used for now */
|
std::ostringstream common_buffer;
|
||||||
cmd_buffer << "..";
|
|
||||||
buf = cmd_buffer.str();
|
common_buffer << buffer.str();
|
||||||
|
streams.push_back(std::move(common_buffer));
|
||||||
|
|
||||||
|
if (!gen_ip_conds(prof, streams, local, false, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (perms & AA_NET_LISTEN) {
|
||||||
|
std::list<std::ostringstream> cmd_streams;
|
||||||
|
cmd_streams = copy_streams_list(streams);
|
||||||
|
|
||||||
|
for (auto &cmd_buffer : streams) {
|
||||||
|
std::ostringstream listen_buffer;
|
||||||
|
listen_buffer << cmd_buffer.str();
|
||||||
|
listen_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_LISTEN;
|
||||||
|
/* length of queue allowed - not used for now */
|
||||||
|
listen_buffer << "..";
|
||||||
|
buf = listen_buffer.str();
|
||||||
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms),
|
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms),
|
||||||
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||||
parseopts))
|
parseopts))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (perms & AA_NET_OPT) {
|
||||||
|
std::list<std::ostringstream> cmd_streams;
|
||||||
|
cmd_streams = copy_streams_list(streams);
|
||||||
|
|
||||||
|
for (auto &cmd_buffer : streams) {
|
||||||
|
std::ostringstream opt_buffer;
|
||||||
|
opt_buffer << cmd_buffer.str();
|
||||||
|
opt_buffer << "\\x" << std::setfill('0') << std::setw(2) << std::hex << CMD_OPT;
|
||||||
|
/* level - not used for now */
|
||||||
|
opt_buffer << "..";
|
||||||
|
/* socket mapping - not used for now */
|
||||||
|
opt_buffer << "..";
|
||||||
|
buf = opt_buffer.str();
|
||||||
|
if (!prof.policy.rules->add_rule(buf.c_str(), rule_mode == RULE_DENY, map_perms(perms),
|
||||||
|
dedup_perms_rule_t::audit == AUDIT_FORCE ? map_perms(perms) : 0,
|
||||||
|
parseopts))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -679,17 +838,18 @@ int network_rule::gen_policy_re(Profile &prof)
|
|||||||
|
|
||||||
for (const auto& perm : network_perms) {
|
for (const auto& perm : network_perms) {
|
||||||
unsigned int family = perm.first;
|
unsigned int family = perm.first;
|
||||||
unsigned int type = perm.second;
|
unsigned int type = perm.second.first;
|
||||||
|
unsigned int protocol = perm.second.second;
|
||||||
|
|
||||||
if (type > 0xffff) {
|
if (type > 0xffff) {
|
||||||
if (!gen_net_rule(prof, family, type))
|
if (!gen_net_rule(prof, family, type, protocol))
|
||||||
goto fail;
|
goto fail;
|
||||||
} else {
|
} else {
|
||||||
int t;
|
int t;
|
||||||
/* generate rules for types that are set */
|
/* generate rules for types that are set */
|
||||||
for (t = 0; t < 16; t++) {
|
for (t = 0; t < 16; t++) {
|
||||||
if (type & (1 << t)) {
|
if (type & (1 << t)) {
|
||||||
if (!gen_net_rule(prof, family, t))
|
if (!gen_net_rule(prof, family, t, protocol))
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -760,13 +920,27 @@ void network_rule::update_compat_net(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cmp_network_map(std::unordered_map<unsigned int, perms_t> lhs,
|
static int cmp_ip_conds(ip_conds const &lhs, ip_conds const &rhs)
|
||||||
std::unordered_map<unsigned int, perms_t> rhs)
|
{
|
||||||
|
int res = null_strcmp(lhs.sip, rhs.sip);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
res = null_strcmp(lhs.sport, rhs.sport);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
return lhs.is_none - rhs.is_none;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmp_network_map(std::unordered_map<unsigned int, std::pair<unsigned int, unsigned int>> lhs,
|
||||||
|
std::unordered_map<unsigned int, std::pair<unsigned int, unsigned int>> rhs)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
size_t family_index;
|
size_t family_index;
|
||||||
for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) {
|
for (family_index = AF_UNSPEC; family_index < get_af_max(); family_index++) {
|
||||||
res = lhs[family_index] - rhs[family_index];
|
res = lhs[family_index].first - rhs[family_index].first;
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
res = lhs[family_index].second - rhs[family_index].second;
|
||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -779,5 +953,14 @@ int network_rule::cmp(rule_t const &rhs) const
|
|||||||
if (res)
|
if (res)
|
||||||
return res;
|
return res;
|
||||||
network_rule const &nrhs = rule_cast<network_rule const &>(rhs);
|
network_rule const &nrhs = rule_cast<network_rule const &>(rhs);
|
||||||
return cmp_network_map(network_perms, nrhs.network_perms);
|
res = cmp_network_map(network_perms, nrhs.network_perms);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
res = cmp_ip_conds(local, nrhs.local);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
res = cmp_ip_conds(peer, nrhs.peer);
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
return null_strcmp(label, nrhs.label);
|
||||||
};
|
};
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <list>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -79,6 +80,10 @@
|
|||||||
#define CMD_LISTEN 2
|
#define CMD_LISTEN 2
|
||||||
#define CMD_OPT 4
|
#define CMD_OPT 4
|
||||||
|
|
||||||
|
#define NONE_SIZE 0
|
||||||
|
#define IPV4_SIZE 1
|
||||||
|
#define IPV6_SIZE 2
|
||||||
|
|
||||||
struct network_tuple {
|
struct network_tuple {
|
||||||
const char *family_name;
|
const char *family_name;
|
||||||
unsigned int family;
|
unsigned int family;
|
||||||
@@ -127,6 +132,8 @@ public:
|
|||||||
uint16_t port;
|
uint16_t port;
|
||||||
struct ip_address ip;
|
struct ip_address ip;
|
||||||
|
|
||||||
|
bool is_none = false;
|
||||||
|
|
||||||
void free_conds() {
|
void free_conds() {
|
||||||
if (sip)
|
if (sip)
|
||||||
free(sip);
|
free(sip);
|
||||||
@@ -139,17 +146,18 @@ class network_rule: public dedup_perms_rule_t {
|
|||||||
void move_conditionals(struct cond_entry *conds, ip_conds &ip_cond);
|
void move_conditionals(struct cond_entry *conds, ip_conds &ip_cond);
|
||||||
public:
|
public:
|
||||||
std::unordered_map<unsigned int, std::vector<struct aa_network_entry>> network_map;
|
std::unordered_map<unsigned int, std::vector<struct aa_network_entry>> network_map;
|
||||||
std::unordered_map<unsigned int, perms_t> network_perms;
|
std::unordered_map<unsigned int, std::pair<unsigned int, unsigned int>> network_perms;
|
||||||
|
|
||||||
ip_conds peer;
|
ip_conds peer;
|
||||||
ip_conds local;
|
ip_conds local;
|
||||||
|
char *label;
|
||||||
|
|
||||||
bool has_local_conds(void) { return local.sip || local.sport; }
|
bool has_local_conds(void) { return local.sip || local.sport; }
|
||||||
bool has_peer_conds(void) { return peer.sip || peer.sport; }
|
bool has_peer_conds(void) { return peer.sip || peer.sport; }
|
||||||
/* empty constructor used only for the profile to access
|
/* empty constructor used only for the profile to access
|
||||||
* static elements to maintain compatibility with
|
* static elements to maintain compatibility with
|
||||||
* AA_CLASS_NET */
|
* AA_CLASS_NET */
|
||||||
network_rule(): dedup_perms_rule_t(AA_CLASS_NETV8) { }
|
network_rule(): dedup_perms_rule_t(AA_CLASS_NETV8), label(NULL) { }
|
||||||
network_rule(perms_t perms_p, struct cond_entry *conds,
|
network_rule(perms_t perms_p, struct cond_entry *conds,
|
||||||
struct cond_entry *peer_conds);
|
struct cond_entry *peer_conds);
|
||||||
network_rule(perms_t perms_p, const char *family, const char *type,
|
network_rule(perms_t perms_p, const char *family, const char *type,
|
||||||
@@ -178,9 +186,9 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
void gen_ip_conds(std::ostringstream &oss, ip_conds entry, bool is_peer, bool is_cmd);
|
bool gen_ip_conds(Profile &prof, std::list<std::ostringstream> &streams, ip_conds &entry, bool is_peer, bool is_cmd);
|
||||||
bool gen_net_rule(Profile &prof, u16 family, unsigned int type_mask);
|
bool gen_net_rule(Profile &prof, u16 family, unsigned int type_mask, unsigned int protocol);
|
||||||
void set_netperm(unsigned int family, unsigned int type);
|
void set_netperm(unsigned int family, unsigned int type, unsigned int protocol);
|
||||||
void update_compat_net(void);
|
void update_compat_net(void);
|
||||||
bool parse_address(ip_conds &entry);
|
bool parse_address(ip_conds &entry);
|
||||||
bool parse_port(ip_conds &entry);
|
bool parse_port(ip_conds &entry);
|
||||||
|
@@ -921,7 +921,7 @@ void set_supported_features()
|
|||||||
"network_v8");
|
"network_v8");
|
||||||
features_supports_inet = features_intersect(kernel_features,
|
features_supports_inet = features_intersect(kernel_features,
|
||||||
policy_features,
|
policy_features,
|
||||||
"network/af_inet");
|
"network_v8/af_inet");
|
||||||
features_supports_unix = features_intersect(kernel_features,
|
features_supports_unix = features_intersect(kernel_features,
|
||||||
policy_features,
|
policy_features,
|
||||||
"network/af_unix");
|
"network/af_unix");
|
||||||
|
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 -> **,
|
||||||
|
}
|
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),
|
||||||
|
|
||||||
|
}
|
@@ -31,6 +31,17 @@
|
|||||||
/{usr/,}lib/@{multiarch}/security/pam_*.so mr,
|
/{usr/,}lib/@{multiarch}/security/pam_*.so mr,
|
||||||
/{usr/,}lib/@{multiarch}/security/ r,
|
/{usr/,}lib/@{multiarch}/security/ r,
|
||||||
|
|
||||||
|
# pam_unix
|
||||||
|
owner /proc/@{pid}/loginuid r,
|
||||||
|
/{,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,
|
||||||
|
@@ -13,6 +13,9 @@
|
|||||||
|
|
||||||
abi <abi/4.0>,
|
abi <abi/4.0>,
|
||||||
|
|
||||||
|
# Global config of openssl
|
||||||
|
include <abstractions/openssl>
|
||||||
|
|
||||||
@{etc_ro}/gcrypt/hwf.deny r,
|
@{etc_ro}/gcrypt/hwf.deny r,
|
||||||
@{etc_ro}/gcrypt/random.conf r,
|
@{etc_ro}/gcrypt/random.conf r,
|
||||||
@{PROC}/sys/crypto/fips_enabled r,
|
@{PROC}/sys/crypto/fips_enabled r,
|
||||||
@@ -24,4 +27,8 @@
|
|||||||
/etc/crypto-policies/*/*.txt r,
|
/etc/crypto-policies/*/*.txt r,
|
||||||
/usr/share/crypto-policies/*/*.txt r,
|
/usr/share/crypto-policies/*/*.txt r,
|
||||||
|
|
||||||
|
# Global gnutls config
|
||||||
|
@{etc_ro}/gnutls/config r,
|
||||||
|
@{etc_ro}/gnutls/pkcs11.conf r,
|
||||||
|
|
||||||
include if exists <abstractions/crypto.d>
|
include if exists <abstractions/crypto.d>
|
||||||
|
@@ -50,7 +50,6 @@
|
|||||||
include <abstractions/kde-icon-cache-write>
|
include <abstractions/kde-icon-cache-write>
|
||||||
include <abstractions/kde>
|
include <abstractions/kde>
|
||||||
include <abstractions/nameservice> # for IceProcessMessages () from libICE.so (called by libQtCore.so)
|
include <abstractions/nameservice> # for IceProcessMessages () from libICE.so (called by libQtCore.so)
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/qt5>
|
include <abstractions/qt5>
|
||||||
include <abstractions/recent-documents-write>
|
include <abstractions/recent-documents-write>
|
||||||
include <abstractions/X>
|
include <abstractions/X>
|
||||||
|
@@ -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>
|
@@ -4,7 +4,7 @@
|
|||||||
abi <abi/4.0>,
|
abi <abi/4.0>,
|
||||||
include <tunables/global>
|
include <tunables/global>
|
||||||
|
|
||||||
profile firefox /usr/lib/firefox{,-esr}/firefox{,-esr} 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>
|
||||||
|
}
|
12
profiles/apparmor.d/geary
Normal file
12
profiles/apparmor.d/geary
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 geary /usr/bin/geary flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/geary>
|
||||||
|
}
|
12
profiles/apparmor.d/goldendict
Normal file
12
profiles/apparmor.d/goldendict
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 goldendict /usr/bin/goldendict flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/goldendict>
|
||||||
|
}
|
12
profiles/apparmor.d/kchmviewer
Normal file
12
profiles/apparmor.d/kchmviewer
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 kchmviewer /usr/bin/kchmviewer flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/kchmviewer>
|
||||||
|
}
|
12
profiles/apparmor.d/loupe
Normal file
12
profiles/apparmor.d/loupe
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 loupe /usr/bin/loupe flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/loupe>
|
||||||
|
}
|
12
profiles/apparmor.d/notepadqq
Normal file
12
profiles/apparmor.d/notepadqq
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 notepadqq /{{usr/bin,etc/alternatives}/notepadqq,usr/lib/notepadqq/notepadqq.sh} flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/notepadqq>
|
||||||
|
}
|
12
profiles/apparmor.d/pageedit
Normal file
12
profiles/apparmor.d/pageedit
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 pageedit /usr/bin/pageedit flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/pageedit>
|
||||||
|
}
|
@@ -11,8 +11,6 @@ profile php-fpm /usr/sbin/php-fpm* flags=(attach_disconnected) {
|
|||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
# common php files and support files that php needs
|
# common php files and support files that php needs
|
||||||
include <abstractions/php>
|
include <abstractions/php>
|
||||||
# read openssl configuration
|
|
||||||
include <abstractions/openssl>
|
|
||||||
# read the system certificates
|
# read the system certificates
|
||||||
include <abstractions/ssl_certs>
|
include <abstractions/ssl_certs>
|
||||||
|
|
||||||
|
12
profiles/apparmor.d/privacybrowser
Normal file
12
profiles/apparmor.d/privacybrowser
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 privacybrowser /usr/bin/privacybrowser flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/privacybrowser>
|
||||||
|
}
|
12
profiles/apparmor.d/qmapshack
Normal file
12
profiles/apparmor.d/qmapshack
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 qmapshack /usr/bin/qmapshack flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/qmapshack>
|
||||||
|
}
|
12
profiles/apparmor.d/qutebrowser
Normal file
12
profiles/apparmor.d/qutebrowser
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 qutebrowser /usr/bin/qutebrowser flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/qutebrowser>
|
||||||
|
}
|
12
profiles/apparmor.d/rssguard
Normal file
12
profiles/apparmor.d/rssguard
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 rssguard /usr/bin/rssguard flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/rssguard>
|
||||||
|
}
|
@@ -6,7 +6,6 @@ profile samba-bgqd /usr/lib*/samba/{,samba/}samba-bgqd {
|
|||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/cups-client>
|
include <abstractions/cups-client>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/samba>
|
include <abstractions/samba>
|
||||||
|
|
||||||
signal receive set=term peer=smbd,
|
signal receive set=term peer=smbd,
|
||||||
|
@@ -19,6 +19,8 @@ profile samba-rpcd-classic /usr/lib*/samba/{,samba/}rpcd_classic {
|
|||||||
|
|
||||||
/usr/lib*/samba/{,samba/}rpcd_classic mr,
|
/usr/lib*/samba/{,samba/}rpcd_classic mr,
|
||||||
|
|
||||||
|
@{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>
|
||||||
}
|
}
|
||||||
|
@@ -22,7 +22,6 @@ profile syslog-ng /{usr/,}{bin,sbin}/syslog-ng {
|
|||||||
include <abstractions/consoles>
|
include <abstractions/consoles>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/mysql>
|
include <abstractions/mysql>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/python>
|
include <abstractions/python>
|
||||||
include <abstractions/hosts_access>
|
include <abstractions/hosts_access>
|
||||||
|
|
||||||
|
13
profiles/apparmor.d/scide
Normal file
13
profiles/apparmor.d/scide
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# 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>
|
||||||
|
|
||||||
|
#supercollider-ide
|
||||||
|
profile scide /usr/bin/scide flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/scide>
|
||||||
|
}
|
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>
|
||||||
|
}
|
12
profiles/apparmor.d/tuxedo-control-center
Normal file
12
profiles/apparmor.d/tuxedo-control-center
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 tuxedo-control-center /opt/tuxedo-control-center/tuxedo-control-center flags=(unconfined) {
|
||||||
|
userns,
|
||||||
|
|
||||||
|
# Site-specific additions and overrides. See local/README for details.
|
||||||
|
include if exists <local/tuxedo-control-center>
|
||||||
|
}
|
35
profiles/apparmor.d/unix-chkpwd
Normal file
35
profiles/apparmor.d/unix-chkpwd
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# apparmor.d - Full set of apparmor profiles
|
||||||
|
# Copyright (C) 2019-2021 Mikhail Morfikov
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
|
||||||
|
# The apparmor.d project comes with several variables and abstractions
|
||||||
|
# that are not part of upstream AppArmor yet. Therefore this profile was
|
||||||
|
# adopted to use abstractions and variables that are available.
|
||||||
|
# Copyright (C) Christian Boltz 2024
|
||||||
|
|
||||||
|
abi <abi/4.0>,
|
||||||
|
|
||||||
|
include <tunables/global>
|
||||||
|
|
||||||
|
profile unix-chkpwd /{,usr/}{,s}bin/unix_chkpwd {
|
||||||
|
include <abstractions/base>
|
||||||
|
include <abstractions/nameservice>
|
||||||
|
|
||||||
|
# To write records to the kernel auditing log.
|
||||||
|
capability audit_write,
|
||||||
|
|
||||||
|
network netlink raw,
|
||||||
|
|
||||||
|
/{,usr/}{,s}bin/unix_chkpwd mr,
|
||||||
|
|
||||||
|
/etc/shadow r,
|
||||||
|
|
||||||
|
# systemd userdb, used in nspawn
|
||||||
|
/run/host/userdb/*.user r,
|
||||||
|
/run/host/userdb/*.user-privileged r,
|
||||||
|
|
||||||
|
# file_inherit
|
||||||
|
owner /dev/tty[0-9]* rw,
|
||||||
|
|
||||||
|
include if exists <local/unix-chkpwd>
|
||||||
|
}
|
@@ -19,7 +19,6 @@ profile dovecot-auth /usr/lib*/dovecot/auth {
|
|||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/mysql>
|
include <abstractions/mysql>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/wutmp>
|
include <abstractions/wutmp>
|
||||||
include <abstractions/dovecot-common>
|
include <abstractions/dovecot-common>
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@ profile dovecot-dict /usr/lib*/dovecot/dict {
|
|||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/mysql>
|
include <abstractions/mysql>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/dovecot-common>
|
include <abstractions/dovecot-common>
|
||||||
|
|
||||||
capability setuid,
|
capability setuid,
|
||||||
|
@@ -17,7 +17,6 @@ include <tunables/global>
|
|||||||
profile dovecot-imap-login /usr/lib*/dovecot/imap-login {
|
profile dovecot-imap-login /usr/lib*/dovecot/imap-login {
|
||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/dovecot-common>
|
include <abstractions/dovecot-common>
|
||||||
include <abstractions/openssl>
|
|
||||||
|
|
||||||
capability setuid,
|
capability setuid,
|
||||||
capability sys_chroot,
|
capability sys_chroot,
|
||||||
|
@@ -18,7 +18,6 @@ profile dovecot-lmtp /usr/lib*/dovecot/lmtp {
|
|||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/dovecot-common>
|
include <abstractions/dovecot-common>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/ssl_certs>
|
include <abstractions/ssl_certs>
|
||||||
include <abstractions/ssl_keys>
|
include <abstractions/ssl_keys>
|
||||||
|
|
||||||
|
@@ -19,7 +19,6 @@ include <tunables/global>
|
|||||||
profile dovecot-managesieve-login /usr/lib*/dovecot/managesieve-login {
|
profile dovecot-managesieve-login /usr/lib*/dovecot/managesieve-login {
|
||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/dovecot-common>
|
include <abstractions/dovecot-common>
|
||||||
include <abstractions/openssl>
|
|
||||||
|
|
||||||
capability setuid,
|
capability setuid,
|
||||||
capability sys_chroot,
|
capability sys_chroot,
|
||||||
|
@@ -17,7 +17,6 @@ include <tunables/global>
|
|||||||
profile dovecot-pop3-login /usr/lib*/dovecot/pop3-login {
|
profile dovecot-pop3-login /usr/lib*/dovecot/pop3-login {
|
||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/dovecot-common>
|
include <abstractions/dovecot-common>
|
||||||
include <abstractions/openssl>
|
|
||||||
|
|
||||||
capability setuid,
|
capability setuid,
|
||||||
capability sys_chroot,
|
capability sys_chroot,
|
||||||
|
@@ -16,7 +16,6 @@ include <tunables/ntpd>
|
|||||||
profile ntpd /usr/{bin,sbin}/{,open}ntpd flags=(attach_disconnected) {
|
profile ntpd /usr/{bin,sbin}/{,open}ntpd flags=(attach_disconnected) {
|
||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/ssl_certs>
|
include <abstractions/ssl_certs>
|
||||||
include <abstractions/xad>
|
include <abstractions/xad>
|
||||||
|
|
||||||
|
@@ -8,7 +8,6 @@ profile smbd /usr/{bin,sbin}/smbd {
|
|||||||
include <abstractions/consoles>
|
include <abstractions/consoles>
|
||||||
include <abstractions/cups-client>
|
include <abstractions/cups-client>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/samba>
|
include <abstractions/samba>
|
||||||
include <abstractions/user-tmp>
|
include <abstractions/user-tmp>
|
||||||
include <abstractions/wutmp>
|
include <abstractions/wutmp>
|
||||||
@@ -33,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,
|
||||||
@@ -50,7 +46,6 @@ profile smbd /usr/{bin,sbin}/smbd {
|
|||||||
/usr/share/samba/** r,
|
/usr/share/samba/** r,
|
||||||
/usr/{bin,sbin}/smbd mr,
|
/usr/{bin,sbin}/smbd mr,
|
||||||
/usr/{bin,sbin}/smbldap-useradd Px,
|
/usr/{bin,sbin}/smbldap-useradd Px,
|
||||||
/usr/sbin/unix_chkpwd Px,
|
|
||||||
/var/cache/samba/** rwk,
|
/var/cache/samba/** rwk,
|
||||||
/var/{cache,lib}/samba/printing/printers.tdb mrw,
|
/var/{cache,lib}/samba/printing/printers.tdb mrw,
|
||||||
/var/lib/nscd/netgroup r,
|
/var/lib/nscd/netgroup r,
|
||||||
@@ -63,8 +58,6 @@ profile smbd /usr/{bin,sbin}/smbd {
|
|||||||
@{run}/samba/ncalrpc/** rw,
|
@{run}/samba/ncalrpc/** rw,
|
||||||
/var/spool/samba/** rw,
|
/var/spool/samba/** rw,
|
||||||
|
|
||||||
owner /proc/@{pid}/loginuid r,
|
|
||||||
|
|
||||||
@{HOMEDIRS}/** lrwk,
|
@{HOMEDIRS}/** lrwk,
|
||||||
/var/lib/samba/usershares/{,**} lrwk,
|
/var/lib/samba/usershares/{,**} lrwk,
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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) {
|
||||||
|
# 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,7 +12,7 @@
|
|||||||
|
|
||||||
abi <abi/4.0>,
|
abi <abi/4.0>,
|
||||||
|
|
||||||
#include <tunables/global>
|
include <tunables/global>
|
||||||
|
|
||||||
@{chromium} = chromium{,-browser}
|
@{chromium} = chromium{,-browser}
|
||||||
|
|
||||||
@@ -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>
|
||||||
}
|
}
|
||||||
|
@@ -241,7 +241,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,
|
||||||
|
@@ -17,7 +17,6 @@ include <tunables/global>
|
|||||||
profile postfix-proxymap /usr/lib/postfix/{bin/,sbin/,}proxymap {
|
profile postfix-proxymap /usr/lib/postfix/{bin/,sbin/,}proxymap {
|
||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/postfix-common>
|
include <abstractions/postfix-common>
|
||||||
|
|
||||||
/etc/my.cnf r,
|
/etc/my.cnf r,
|
||||||
|
@@ -18,7 +18,6 @@ profile postfix-smtp /usr/lib/postfix/{bin/,sbin/,}smtp {
|
|||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/postfix-common>
|
include <abstractions/postfix-common>
|
||||||
include <abstractions/openssl>
|
|
||||||
|
|
||||||
capability dac_override,
|
capability dac_override,
|
||||||
capability dac_read_search,
|
capability dac_read_search,
|
||||||
|
@@ -18,7 +18,6 @@ profile postfix-smtpd /usr/lib/postfix/{bin/,sbin/,}smtpd {
|
|||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/postfix-common>
|
include <abstractions/postfix-common>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/ssl_certs>
|
include <abstractions/ssl_certs>
|
||||||
include <abstractions/ssl_keys>
|
include <abstractions/ssl_keys>
|
||||||
|
|
||||||
|
@@ -17,7 +17,6 @@ include <tunables/global>
|
|||||||
profile postfix-tlsmgr /usr/lib/postfix/{bin/,sbin/,}tlsmgr {
|
profile postfix-tlsmgr /usr/lib/postfix/{bin/,sbin/,}tlsmgr {
|
||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/postfix-common>
|
include <abstractions/postfix-common>
|
||||||
|
|
||||||
/usr/lib/postfix/{bin/,sbin/,}tlsmgr mrix,
|
/usr/lib/postfix/{bin/,sbin/,}tlsmgr mrix,
|
||||||
|
@@ -26,7 +26,6 @@ include <tunables/global>
|
|||||||
profile dhclient /{usr/,}sbin/dhclient {
|
profile dhclient /{usr/,}sbin/dhclient {
|
||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/bash>
|
include <abstractions/bash>
|
||||||
include <abstractions/openssl>
|
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
|
|
||||||
capability net_raw,
|
capability net_raw,
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
}
|
@@ -17,7 +17,6 @@ include <tunables/global>
|
|||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/consoles>
|
include <abstractions/consoles>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/openssl>
|
|
||||||
|
|
||||||
capability setgid,
|
capability setgid,
|
||||||
capability setuid,
|
capability setuid,
|
||||||
|
@@ -13,7 +13,6 @@ include <tunables/global>
|
|||||||
profile clamd /usr/sbin/clamd {
|
profile clamd /usr/sbin/clamd {
|
||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/openssl>
|
|
||||||
|
|
||||||
capability setgid,
|
capability setgid,
|
||||||
capability setuid,
|
capability setuid,
|
||||||
|
@@ -13,7 +13,6 @@ include <tunables/global>
|
|||||||
profile haproxy /usr/sbin/haproxy {
|
profile haproxy /usr/sbin/haproxy {
|
||||||
include <abstractions/base>
|
include <abstractions/base>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/openssl>
|
|
||||||
capability net_admin,
|
capability net_admin,
|
||||||
capability net_bind_service,
|
capability net_bind_service,
|
||||||
capability setgid,
|
capability setgid,
|
||||||
|
@@ -20,7 +20,6 @@ include <tunables/global>
|
|||||||
include <abstractions/kerberosclient>
|
include <abstractions/kerberosclient>
|
||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/perl>
|
include <abstractions/perl>
|
||||||
include <abstractions/openssl>
|
|
||||||
|
|
||||||
capability kill,
|
capability kill,
|
||||||
capability net_bind_service,
|
capability net_bind_service,
|
||||||
|
@@ -17,7 +17,6 @@ include <tunables/global>
|
|||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/authentication>
|
include <abstractions/authentication>
|
||||||
include <abstractions/user-mail>
|
include <abstractions/user-mail>
|
||||||
include <abstractions/openssl>
|
|
||||||
|
|
||||||
/dev/urandom r,
|
/dev/urandom r,
|
||||||
/tmp/* rwl,
|
/tmp/* rwl,
|
||||||
|
@@ -17,7 +17,6 @@ include <tunables/global>
|
|||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/authentication>
|
include <abstractions/authentication>
|
||||||
include <abstractions/user-mail>
|
include <abstractions/user-mail>
|
||||||
include <abstractions/openssl>
|
|
||||||
|
|
||||||
/dev/urandom r ,
|
/dev/urandom r ,
|
||||||
/tmp/.* rwl ,
|
/tmp/.* rwl ,
|
||||||
|
@@ -17,7 +17,6 @@ include <tunables/global>
|
|||||||
include <abstractions/nameservice>
|
include <abstractions/nameservice>
|
||||||
include <abstractions/authentication>
|
include <abstractions/authentication>
|
||||||
include <abstractions/user-mail>
|
include <abstractions/user-mail>
|
||||||
include <abstractions/openssl>
|
|
||||||
|
|
||||||
/dev/urandom r ,
|
/dev/urandom r ,
|
||||||
/tmp/.* rwl ,
|
/tmp/.* rwl ,
|
||||||
|
@@ -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,
|
||||||
|
12
profiles/apparmor/wike
Normal file
12
profiles/apparmor/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>
|
||||||
|
}
|
@@ -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
|
||||||
|
@@ -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) {
|
||||||
|
@@ -547,6 +547,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
|
||||||
|
@@ -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,16 +96,20 @@ 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"
|
||||||
|
|
||||||
generate_profile="genprofile network;ip=$bind_ipv4;port=$bind_port;peer=(ip=$remote_ipv4,port=$remote_port) $sender:px -- image=$sender network;ip=$remote_ipv4;port=$remote_port;peer=(ip=$bind_ipv4,port=$bind_port)"
|
setsockopt_rules="network;(setopt,getopt);ip=0.0.0.0;port=0" # INADDR_ANY
|
||||||
|
rcv_rules="network;ip=$bind_ipv4;peer=(ip=anon)"
|
||||||
|
snd_rules="network;ip=$remote_ipv4;peer=(ip=anon)"
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
generate_profile="genprofile network;ip=$bind_ipv4;port=$bind_port;peer=(ip=$remote_ipv4,port=$remote_port) $sender:px -- image=$sender network;ip=$remote_ipv4;port=$remote_port;peer=(ip=$bind_ipv4,port=$bind_port)"
|
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 tcp generic perms" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port tcp "$generate_profile"
|
do_tests "ipv4 tcp generic perms" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port tcp "$generate_profile"
|
||||||
|
|
||||||
generate_profile="genprofile network;(connect,receive,send);ip=$bind_ipv4;port=$bind_port;peer=(ip=$remote_ipv4,port=$remote_port) $sender:px -- image=$sender network;ip=$remote_ipv4;port=$remote_port;peer=(ip=$bind_ipv4,port=$bind_port)"
|
generate_profile="genprofile network;(connect,receive,send);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 specific perms" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port udp "$generate_profile"
|
do_tests "ipv4 udp specific perms" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port udp "$generate_profile"
|
||||||
|
|
||||||
generate_profile="genprofile network;(connect,receive,send);ip=$bind_ipv4;port=$bind_port;peer=(ip=$remote_ipv4,port=$remote_port) $sender:px -- image=$sender network;ip=$remote_ipv4;port=$remote_port;peer=(ip=$bind_ipv4,port=$bind_port)"
|
generate_profile="genprofile network;(connect,receive,send);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 tcp specific perms" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port tcp "$generate_profile"
|
do_tests "ipv4 tcp specific perms" pass pass $bind_ipv4 $bind_port $remote_ipv4 $remote_port tcp "$generate_profile"
|
||||||
|
|
||||||
removeprofile
|
removeprofile
|
||||||
@@ -122,10 +125,12 @@ 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"
|
||||||
|
|
||||||
generate_profile="genprofile network;ip=$bind_ipv6;port=$bind_port;peer=(ip=$remote_ipv6,port=$remote_port) $sender:px -- image=$sender network;ip=$remote_ipv6;port=$remote_port;peer=(ip=$bind_ipv6,port=$bind_port)"
|
setsockopt_rules="network;(setopt,getopt);ip=::0;port=0" # IN6ADDR_ANY_INIT
|
||||||
|
rcv_rules="network;ip=$bind_ipv6;peer=(ip=anon)"
|
||||||
|
snd_rules="network;ip=$remote_ipv6;peer=(ip=anon)"
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
generate_profile="genprofile network;ip=$bind_ipv6;port=$bind_port;peer=(ip=$remote_ipv6,port=$remote_port) $sender:px -- image=$sender network;ip=$remote_ipv6;port=$remote_port;peer=(ip=$bind_ipv6,port=$bind_port)"
|
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 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"
|
||||||
|
|
||||||
|
|
@@ -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);
|
||||||
}
|
}
|
@@ -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,11 +88,11 @@ 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
|
||||||
|
|
||||||
|
|
||||||
@@ -102,46 +104,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 +152,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");
|
||||||
|
@@ -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)
|
||||||
{
|
{
|
||||||
|
@@ -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[])
|
||||||
{
|
{
|
||||||
|
@@ -39,7 +39,7 @@ from apparmor.profile_storage import ProfileStorage, add_or_remove_flag, ruletyp
|
|||||||
from apparmor.regex import (
|
from apparmor.regex import (
|
||||||
RE_HAS_COMMENT_SPLIT, RE_PROFILE_CHANGE_HAT, RE_PROFILE_CONDITIONAL,
|
RE_HAS_COMMENT_SPLIT, RE_PROFILE_CHANGE_HAT, RE_PROFILE_CONDITIONAL,
|
||||||
RE_PROFILE_CONDITIONAL_BOOLEAN, RE_PROFILE_CONDITIONAL_VARIABLE, RE_PROFILE_END,
|
RE_PROFILE_CONDITIONAL_BOOLEAN, RE_PROFILE_CONDITIONAL_VARIABLE, RE_PROFILE_END,
|
||||||
RE_PROFILE_HAT_DEF, RE_PROFILE_MOUNT, RE_PROFILE_PIVOT_ROOT, RE_PROFILE_START,
|
RE_PROFILE_HAT_DEF, RE_PROFILE_PIVOT_ROOT, RE_PROFILE_START,
|
||||||
RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, parse_profile_start_line, re_match_include)
|
RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, parse_profile_start_line, re_match_include)
|
||||||
from apparmor.rule.abi import AbiRule
|
from apparmor.rule.abi import AbiRule
|
||||||
from apparmor.rule.capability import CapabilityRule
|
from apparmor.rule.capability import CapabilityRule
|
||||||
@@ -1995,29 +1995,6 @@ def parse_profile_data(data, file, do_include, in_preamble):
|
|||||||
# Conditional Boolean defined
|
# Conditional Boolean defined
|
||||||
pass
|
pass
|
||||||
|
|
||||||
elif RE_PROFILE_MOUNT.search(line):
|
|
||||||
matches = RE_PROFILE_MOUNT.search(line).groups()
|
|
||||||
|
|
||||||
if not profile:
|
|
||||||
raise AppArmorException(_('Syntax Error: Unexpected mount entry found in file: %(file)s line: %(line)s')
|
|
||||||
% {'file': file, 'line': lineno + 1})
|
|
||||||
|
|
||||||
audit = False
|
|
||||||
if matches[0]:
|
|
||||||
audit = True
|
|
||||||
allow = 'allow'
|
|
||||||
if matches[1] and matches[1].strip() == 'deny':
|
|
||||||
allow = 'deny'
|
|
||||||
mount = matches[2]
|
|
||||||
|
|
||||||
mount_rule = parse_mount_rule(mount)
|
|
||||||
mount_rule.audit = audit
|
|
||||||
mount_rule.deny = (allow == 'deny')
|
|
||||||
|
|
||||||
mount_rules = profile_data[profname][allow].get('mount', [])
|
|
||||||
mount_rules.append(mount_rule)
|
|
||||||
profile_data[profname][allow]['mount'] = mount_rules
|
|
||||||
|
|
||||||
elif RE_PROFILE_PIVOT_ROOT.search(line):
|
elif RE_PROFILE_PIVOT_ROOT.search(line):
|
||||||
matches = RE_PROFILE_PIVOT_ROOT.search(line).groups()
|
matches = RE_PROFILE_PIVOT_ROOT.search(line).groups()
|
||||||
|
|
||||||
@@ -2202,11 +2179,6 @@ def split_to_merged(profile_data):
|
|||||||
return merged
|
return merged
|
||||||
|
|
||||||
|
|
||||||
def parse_mount_rule(line):
|
|
||||||
# XXX Do real parsing here
|
|
||||||
return aarules.Raw_Mount_Rule(line)
|
|
||||||
|
|
||||||
|
|
||||||
def parse_pivot_root_rule(line):
|
def parse_pivot_root_rule(line):
|
||||||
# XXX Do real parsing here
|
# XXX Do real parsing here
|
||||||
return aarules.Raw_Pivot_Root_Rule(line)
|
return aarules.Raw_Pivot_Root_Rule(line)
|
||||||
|
@@ -15,8 +15,8 @@ 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
|
||||||
#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
|
||||||
|
|
||||||
from apparmor.translations import init_translation
|
from apparmor.translations import init_translation
|
||||||
@@ -25,7 +25,7 @@ _ = init_translation()
|
|||||||
|
|
||||||
# TODO :
|
# TODO :
|
||||||
# - match correctly AARE on every field
|
# - match correctly AARE on every field
|
||||||
# - Find the actual list of supported filesystems. This one comes from /proc/filesystems
|
# - 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.
|
# - 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.
|
# - 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.
|
||||||
|
|
||||||
@@ -33,40 +33,56 @@ valid_fs = [
|
|||||||
'sysfs', 'tmpfs', 'bdevfs', 'procfs', 'cgroup', 'cgroup2', 'cpuset', 'devtmpfs', 'configfs', 'debugfs', 'tracefs',
|
'sysfs', 'tmpfs', 'bdevfs', 'procfs', 'cgroup', 'cgroup2', 'cpuset', 'devtmpfs', 'configfs', 'debugfs', 'tracefs',
|
||||||
'securityfs', 'sockfs', 'bpf', 'npipefs', 'ramfs', 'hugetlbfs', 'devpts', 'ext3', 'ext2', 'ext4', 'squashfs',
|
'securityfs', 'sockfs', 'bpf', 'npipefs', 'ramfs', 'hugetlbfs', 'devpts', 'ext3', 'ext2', 'ext4', 'squashfs',
|
||||||
'vfat', 'ecryptfs', 'fuseblk', 'fuse', 'fusectl', 'efivarfs', 'mqueue', 'store', 'autofs', 'binfmt_misc', 'overlay',
|
'vfat', 'ecryptfs', 'fuseblk', 'fuse', 'fusectl', 'efivarfs', 'mqueue', 'store', 'autofs', 'binfmt_misc', 'overlay',
|
||||||
'none', 'bdev', 'proc', 'pipefs', 'pstore', 'brtfs', 'xfs',
|
'none', 'bdev', 'proc', 'pipefs', 'pstore', 'btrfs', 'xfs', '9p', 'resctrl', 'zfs', 'iso9660', 'udf', 'ntfs3',
|
||||||
|
'nfs', 'cifs', 'overlayfs', 'aufs', 'rpc_pipefs', 'msdos', 'nfs4',
|
||||||
]
|
]
|
||||||
|
|
||||||
flags_keywords = [
|
flags_keywords = [
|
||||||
'ro', 'rw', 'nosuid', 'suid', 'nodev', 'dev', 'noexec', 'exec', 'sync', 'async', 'remount', 'mand', 'nomand',
|
# keep in sync with parser/mount.cc mnt_opts_table!
|
||||||
'dirsync', 'noatime', 'atime', 'nodiratime', 'diratime', 'bind', 'rbind', 'move', 'verbose', 'silent', 'loud',
|
'ro', 'r', 'read-only', 'rw', 'w', 'suid', 'nosuid', 'dev', 'nodev', 'exec', 'noexec', 'sync', 'async', 'remount',
|
||||||
'acl', 'noacl', 'unbindable', 'runbindable', 'private', 'rprivate', 'slave', 'rslave', 'shared', 'rshared',
|
'mand', 'nomand', 'dirsync', 'symfollow', 'nosymfollow', 'atime', 'noatime', 'diratime', 'nodiratime', 'bind', 'B',
|
||||||
'relatime', 'norelatime', 'iversion', 'noiversion', 'strictatime', 'nostrictatime', 'lazytime', 'nolazytime',
|
'move', 'M', 'rbind', 'R', 'verbose', 'silent', 'loud', 'acl', 'noacl', 'unbindable', 'make-unbindable', 'runbindable',
|
||||||
'nouser', 'user', 'symfollow', 'nosymfollow', '([A-Za-z0-9]|AARE)', # TODO: handle AARE
|
'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)
|
join_valid_fs = '|'.join(valid_fs)
|
||||||
|
|
||||||
sep = r"\s*[\s,]\s*"
|
sep = r'\s*[\s,]\s*'
|
||||||
|
|
||||||
fs_type_pattern = r"\b(?P<fstype_or_vfstype>fstype|vfstype)\b\s*(?P<fstype_equals_or_in>=|in)\s*"\
|
# We aim to be a bit more restrictive than \S+ used in regex.py
|
||||||
r"(?P<fstype>\(\s*(" + join_valid_fs + ")(" + sep + "(" + join_valid_fs + "))*\s*\)|"\
|
FS_AARE = r'([][".*@{}\w^-]+)'
|
||||||
r"\{\s*(" + join_valid_fs + ")(" + sep + "(" + join_valid_fs + r"))*\s*\}|(\s*" + join_valid_fs + "))"\
|
|
||||||
|
fs_type_pattern = r'\b(?P<fstype_or_vfstype>fstype|vfstype)\b\s*(?P<fstype_equals_or_in>=|in)\s*'\
|
||||||
|
r'(?P<fstype>\(\s*(' + FS_AARE + r')(' + sep + r'(' + FS_AARE + r'))*\s*\)|'\
|
||||||
|
r'\{\s*(' + FS_AARE + r')(' + sep + r'(' + FS_AARE + r'))*\s*\}|(\s*' + FS_AARE + r'))'\
|
||||||
|
|
||||||
|
|
||||||
option_pattern = r"\s*(\boption(s?)\b\s*(?P<options_equals_or_in>=|in)\s*"\
|
option_pattern = r'\s*(\boption(s?)\b\s*(?P<options_equals_or_in>=|in)\s*'\
|
||||||
r"(?P<options>\(\s*(" + join_valid_flags + ")(" + sep + "(" + join_valid_flags + r"))*\s*\)|" \
|
r'(?P<options>\(\s*(' + join_valid_flags + r')(' + sep + r'(' + join_valid_flags + r'))*\s*\)|' \
|
||||||
"(\s*" + join_valid_flags + ")"\
|
r'(\s*' + join_valid_flags + r')'\
|
||||||
"))?"
|
r'))?'
|
||||||
mount_condition_pattern = rf"({fs_type_pattern})?\s*({option_pattern})?"
|
mount_condition_pattern = rf'({fs_type_pattern})?\s*({option_pattern})?'
|
||||||
|
|
||||||
# Source can either be
|
# Source can either be
|
||||||
# - A path : /foo
|
# - A path : /foo
|
||||||
|
# - A globbed Path : {,/usr}/lib{,32,64,x32}/modules/
|
||||||
# - 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)
|
||||||
source_fileglob_pattern = r"(\s*" + (RE_PROFILE_PATH_OR_VAR % "source_file")[:-1] + "|" + r"\w+" + "))"
|
# Thus we cannot use directly RE_PROFILE_PATH_OR_VAR
|
||||||
dest_fileglob_pattern = r"(\s*" + RE_PROFILE_PATH_OR_VAR % "dest_file" + ')'
|
# Destination can also be
|
||||||
|
# - A path : /foo
|
||||||
|
# - A globbed Path : **
|
||||||
|
|
||||||
|
glob_pattern = r'(\s*(?P<%s>(([/{]|\*\*)\S*|"([/{]|\*\*)[^"]*"|@{\S+}\S*|"@{\S+}[^"]*")|\w+))'
|
||||||
|
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_UMOUNT_DETAILS = re.compile(r'^\s*' + mount_condition_pattern + rf'(\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*" +"$")
|
|
||||||
RE_UMOUNT_DETAILS = re.compile(r"^\s*" + mount_condition_pattern + rf"(\s+{dest_fileglob_pattern})?\s*" +"$")
|
|
||||||
|
|
||||||
class MountRule(BaseRule):
|
class MountRule(BaseRule):
|
||||||
'''Class to handle and store a single mount rule'''
|
'''Class to handle and store a single mount rule'''
|
||||||
@@ -91,22 +107,37 @@ 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')
|
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 unknown_items:
|
||||||
|
for it in unknown_items:
|
||||||
|
|
||||||
|
# Several filesystems use fuse internally and are referred as fuse.<software_name> (e.g. fuse.jmtpfs, fuse.s3fs, fuse.obexfs).
|
||||||
|
# Since this list seems to evolve too fast for a fixed list to work in practice, we just accept fuse.*
|
||||||
|
# See https://github.com/libfuse/libfuse/wiki/Filesystems and, https://doc.ubuntu-fr.org/fuse
|
||||||
|
if it.startswith('fuse.') and len(it) > 5:
|
||||||
|
continue
|
||||||
|
|
||||||
|
it = AARE(it, is_path=False)
|
||||||
|
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.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:
|
||||||
|
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
|
||||||
|
|
||||||
if source != self.ALL and source[0].isalpha():
|
self.source, self.all_source = self._aare_or_all(source, 'source', is_path=False, log_event=log_event)
|
||||||
self.source = source
|
|
||||||
self.all_source = False
|
|
||||||
self.source_is_path = False
|
|
||||||
else:
|
|
||||||
self.source_is_path = True
|
|
||||||
self.source, self.all_source = self._aare_or_all(source, 'source', is_path=self.source_is_path, log_event=log_event)
|
|
||||||
|
|
||||||
if not self.all_fstype and self.is_fstype_equal != "=" and self.is_fstype_equal != "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}')
|
||||||
if not self.all_options and self.is_options_equal != "=" and self.is_options_equal != "in":
|
if not self.all_options and self.is_options_equal not in ('=', 'in'):
|
||||||
raise AppArmorBug(f'Invalid is_options_equal : {self.is_options_equal}')
|
raise AppArmorBug(f'Invalid is_options_equal : {self.is_options_equal}')
|
||||||
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')
|
||||||
@@ -115,11 +146,10 @@ class MountRule(BaseRule):
|
|||||||
if self.operation == 'mount' and not self.all_source and not self.all_options and flags_forbidden_with_source & 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():
|
||||||
raise AppArmorException(f'Operation {flags_forbidden_with_source & self.options} cannot have a source. Source = {self.source}')
|
raise AppArmorException(f'Operation {flags_forbidden_with_source & self.options} cannot have a source. Source = {self.source}')
|
||||||
|
|
||||||
self.dest, self.all_dest = self._aare_or_all(dest, 'dest', is_path=True, log_event=log_event)
|
self.dest, self.all_dest = self._aare_or_all(dest, 'dest', is_path=False, log_event=log_event)
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _create_instance(cls, raw_rule, matches):
|
def _create_instance(cls, raw_rule, matches):
|
||||||
'''parse raw_rule and return instance of this class'''
|
'''parse raw_rule and return instance of this class'''
|
||||||
@@ -132,7 +162,7 @@ class MountRule(BaseRule):
|
|||||||
if matches.group('details'):
|
if matches.group('details'):
|
||||||
rule_details = matches.group('details')
|
rule_details = matches.group('details')
|
||||||
|
|
||||||
if operation == "mount":
|
if operation == 'mount':
|
||||||
parsed = RE_MOUNT_DETAILS.search(rule_details)
|
parsed = RE_MOUNT_DETAILS.search(rule_details)
|
||||||
else:
|
else:
|
||||||
parsed = RE_UMOUNT_DETAILS.search(rule_details)
|
parsed = RE_UMOUNT_DETAILS.search(rule_details)
|
||||||
@@ -152,7 +182,7 @@ class MountRule(BaseRule):
|
|||||||
is_options_equal = r['options_equals_or_in']
|
is_options_equal = r['options_equals_or_in']
|
||||||
options = strip_parenthesis(r['options']).replace(',', ' ').split()
|
options = strip_parenthesis(r['options']).replace(',', ' ').split()
|
||||||
else:
|
else:
|
||||||
is_options_equal =None
|
is_options_equal = None
|
||||||
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
|
||||||
@@ -168,38 +198,42 @@ class MountRule(BaseRule):
|
|||||||
else:
|
else:
|
||||||
is_fstype_equal = None
|
is_fstype_equal = None
|
||||||
is_options_equal = None
|
is_options_equal = None
|
||||||
fstype = cls.ALL
|
fstype = cls.ALL
|
||||||
options = cls.ALL
|
options = cls.ALL
|
||||||
source = cls.ALL
|
source = cls.ALL
|
||||||
dest = cls.ALL
|
dest = cls.ALL
|
||||||
|
|
||||||
return cls(operation=operation, fstype=(is_fstype_equal, fstype), options=(is_options_equal, options), source=source, dest=dest, audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment)
|
return cls(operation=operation, fstype=(is_fstype_equal, fstype), options=(is_options_equal, options), source=source, dest=dest, audit=audit, deny=deny, allow_keyword=allow_keyword, comment=comment)
|
||||||
|
|
||||||
def get_clean(self, depth=0):
|
def get_clean(self, depth=0):
|
||||||
space = ' ' * depth
|
space = ' ' * depth
|
||||||
|
|
||||||
fstype = ' fstype%s(%s)' % (self.is_fstype_equal, ', '.join(sorted(self.fstype))) if not self.all_fstype else ''
|
fstype = ' fstype%s(%s)' % (wrap_in_with_spaces(self.is_fstype_equal), ', '.join(sorted(self.fstype))) if not self.all_fstype else ''
|
||||||
options = ' options%s(%s)' % (self.is_options_equal, ', '.join(sorted(self.options))) if not self.all_options else ''
|
options = ' options%s(%s)' % (wrap_in_with_spaces(self.is_options_equal), ', '.join(sorted(self.options))) if not self.all_options else ''
|
||||||
|
|
||||||
|
source = ''
|
||||||
|
dest = ''
|
||||||
|
|
||||||
if self.operation == 'mount':
|
if self.operation == 'mount':
|
||||||
return ('%s%s%s%s%s%s%s,%s' % ( self.modifiers_str(),
|
if not self.all_source:
|
||||||
space,
|
source = ' ' + str(self.source.regex)
|
||||||
self.operation,
|
|
||||||
fstype,
|
if not self.all_dest:
|
||||||
options,
|
dest = ' -> ' + str(self.dest.regex)
|
||||||
" " + str(self.source.regex) if not self.all_source else '',
|
|
||||||
" -> " + str(self.dest.regex) if not self.all_dest else '',
|
|
||||||
self.comment,
|
|
||||||
))
|
|
||||||
else:
|
else:
|
||||||
return ('%s%s%s%s%s%s,%s' % ( self.modifiers_str(),
|
if not self.all_dest:
|
||||||
space,
|
dest = ' ' + str(self.dest.regex)
|
||||||
self.operation,
|
|
||||||
fstype,
|
return ('%s%s%s%s%s%s%s,%s' % (self.modifiers_str(),
|
||||||
options,
|
space,
|
||||||
" " + str(self.dest.regex) if not self.all_dest else '',
|
self.operation,
|
||||||
self.comment,
|
fstype,
|
||||||
))
|
options,
|
||||||
|
source,
|
||||||
|
dest,
|
||||||
|
self.comment,
|
||||||
|
))
|
||||||
|
|
||||||
def _is_covered_localvars(self, other_rule):
|
def _is_covered_localvars(self, other_rule):
|
||||||
if self.operation != other_rule.operation:
|
if self.operation != other_rule.operation:
|
||||||
@@ -208,16 +242,18 @@ class MountRule(BaseRule):
|
|||||||
return False
|
return False
|
||||||
if self.is_options_equal != other_rule.is_options_equal:
|
if self.is_options_equal != other_rule.is_options_equal:
|
||||||
return False
|
return False
|
||||||
if not self._is_covered_list(self.fstype, self.all_fstype, other_rule.fstype, other_rule.all_fstype, 'fstype'):
|
|
||||||
return False
|
for o_it in other_rule.fstype or []:
|
||||||
|
found = False
|
||||||
|
for s_it in self.fstype or []:
|
||||||
|
if self._is_covered_aare(AARE(s_it, False), self.all_fstype, AARE(o_it, False), other_rule.all_fstype, 'fstype'):
|
||||||
|
found = True
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
return False
|
||||||
if not self._is_covered_list(self.options, self.all_options, other_rule.options, other_rule.all_options, 'options'):
|
if not self._is_covered_list(self.options, self.all_options, other_rule.options, other_rule.all_options, 'options'):
|
||||||
return False
|
return False
|
||||||
if not self.source_is_path and not other_rule.source_is_path:
|
if not self._is_covered_aare(self.source, self.all_source, other_rule.source, other_rule.all_source, 'source'):
|
||||||
if self.source != other_rule.source:
|
|
||||||
return False
|
|
||||||
elif self.source_is_path != other_rule.source_is_path:
|
|
||||||
return False
|
|
||||||
elif not self._is_covered_aare(self.source, self.all_source, other_rule.source, other_rule.all_source, 'source'):
|
|
||||||
return False
|
return False
|
||||||
if not self._is_covered_aare(self.dest, self.all_dest, other_rule.dest, other_rule.all_dest, 'dest'):
|
if not self._is_covered_aare(self.dest, self.all_dest, other_rule.dest, other_rule.all_dest, 'dest'):
|
||||||
return False
|
return False
|
||||||
@@ -233,12 +269,7 @@ class MountRule(BaseRule):
|
|||||||
return False
|
return False
|
||||||
if self.fstype != rule_obj.fstype or self.options != rule_obj.options:
|
if self.fstype != rule_obj.fstype or self.options != rule_obj.options:
|
||||||
return False
|
return False
|
||||||
if not self.source_is_path and not rule_obj.source_is_path:
|
if not self._is_equal_aare(self.source, self.all_source, rule_obj.source, rule_obj.all_source, 'source'):
|
||||||
if self.source != rule_obj.source:
|
|
||||||
return False
|
|
||||||
elif self.source_is_path != rule_obj.source_is_path:
|
|
||||||
return False
|
|
||||||
elif not self._is_equal_aare(self.source, self.all_source, rule_obj.source, rule_obj.all_source, 'source'):
|
|
||||||
return False
|
return False
|
||||||
if not self._is_equal_aare(self.dest, self.all_dest, rule_obj.dest, rule_obj.all_dest, 'dest'):
|
if not self._is_equal_aare(self.dest, self.all_dest, rule_obj.dest, rule_obj.all_dest, 'dest'):
|
||||||
return False
|
return False
|
||||||
@@ -256,8 +287,8 @@ class MountRule(BaseRule):
|
|||||||
elif not self.all_source and type(self.source) is not str:
|
elif not self.all_source and type(self.source) is not str:
|
||||||
self.source = self.source.glob_path()
|
self.source = self.source.glob_path()
|
||||||
if self.source.is_equal('/**/'):
|
if self.source.is_equal('/**/'):
|
||||||
self.all_source= True
|
self.all_source = True
|
||||||
self.source=self.ALL
|
self.source = self.ALL
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.options = self.ALL
|
self.options = self.ALL
|
||||||
@@ -273,15 +304,22 @@ class MountRule(BaseRule):
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
_('Operation'), operation,
|
_('Operation'), operation,
|
||||||
_('Fstype'), (self.is_fstype_equal, fstype) if fstype != 'ALL' else fstype ,
|
_('Fstype'), (self.is_fstype_equal, fstype) if fstype != 'ALL' else fstype,
|
||||||
_('Options'), (self.is_options_equal, options) if options != 'ALL' else options ,
|
_('Options'), (self.is_options_equal, options) if options != 'ALL' else options,
|
||||||
_('Source'), source,
|
_('Source'), source,
|
||||||
_('Destination'), dest,
|
_('Destination'), dest,
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class MountRuleset(BaseRuleset):
|
class MountRuleset(BaseRuleset):
|
||||||
'''Class to handle and store a collection of Mount rules'''
|
'''Class to handle and store a collection of Mount rules'''
|
||||||
|
|
||||||
|
|
||||||
|
def wrap_in_with_spaces(value):
|
||||||
|
''' wrap 'in' keyword in spaces, and leave everything else unchanged '''
|
||||||
|
|
||||||
|
if value == 'in':
|
||||||
|
value = ' in '
|
||||||
|
|
||||||
|
return value
|
||||||
|
@@ -140,7 +140,8 @@ Feb 4 13:40:38 XPS-13-9370 kernel: [128552.880347] audit: type=1400 audit({epoc
|
|||||||
if 'SUDO_USER' in os.environ:
|
if 'SUDO_USER' in os.environ:
|
||||||
username = os.environ.get('SUDO_USER')
|
username = os.environ.get('SUDO_USER')
|
||||||
|
|
||||||
return_code, output = cmd(['last', '-1', username, '--time-format', 'iso'])
|
return_code, output = cmd(['last', username, '--time-format', 'iso'])
|
||||||
|
output = output.split('\n')[0] # the first line is enough
|
||||||
# example of output:
|
# example of output:
|
||||||
# ubuntu tty7 :0 2024-01-05T14:29:11-03:00 gone - no logout
|
# ubuntu tty7 :0 2024-01-05T14:29:11-03:00 gone - no logout
|
||||||
if output.startswith(username):
|
if output.startswith(username):
|
||||||
|
@@ -28,36 +28,38 @@ _ = init_translation()
|
|||||||
class MountTestParse(AATest):
|
class MountTestParse(AATest):
|
||||||
|
|
||||||
tests = (
|
tests = (
|
||||||
# Rule Operation Filesystem Options Source Destination Audit Deny Allow Comment
|
# Rule Operation Filesystem Options Source Destination Audit Deny Allow Comment
|
||||||
('mount fstype=bpf options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=',('bpf')), ('=',('rw')), "bpf", "/sys/fs/bpf/", False, False, False, '' )),
|
('mount -> **,', MountRule('mount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '**', False, False, False, '' )),
|
||||||
('mount fstype=bpf options=(rw) random_label -> /sys/fs/bpf/,', MountRule('mount', ('=',('bpf')), ('=',('rw')), "random_label", "/sys/fs/bpf/", False, False, False, '' )),
|
('mount options=(rw, shared) -> **,', MountRule('mount', MountRule.ALL, ('=', ('rw', 'shared')), MountRule.ALL, '**', False, False, False, '' )),
|
||||||
('mount,', MountRule('mount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
('mount fstype=bpf options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ('bpf')), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
|
||||||
('mount fstype=(ext3, ext4),', MountRule('mount', ('=',('ext3', 'ext4')), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
('mount fstype=fuse.obex* options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ('fuse.obex*')), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
|
||||||
('mount bpf,', MountRule('mount', MountRule.ALL, MountRule.ALL, "bpf", MountRule.ALL, False, False, False, '' )),
|
('mount fstype=fuse.* options=rw bpf -> /sys/fs/bpf/,', MountRule('mount', ('=', ('fuse.*')), ('=', ('rw')), 'bpf', '/sys/fs/bpf/', False, False, False, '' )),
|
||||||
('mount none,', MountRule('mount', MountRule.ALL, MountRule.ALL, "none", MountRule.ALL, False, False, False, '' )),
|
('mount fstype=bpf options=(rw) random_label -> /sys/fs/bpf/,', MountRule('mount', ('=', ("bpf")), ('=', ('rw')), 'random_label', '/sys/fs/bpf/', False, False, False, '' )),
|
||||||
('mount fstype=(ext3, ext4) options=(ro),', MountRule('mount', ('=',('ext3', 'ext4')), ('=',('ro')), MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
('mount,', MountRule('mount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
||||||
('mount @{mntpnt},', MountRule('mount', MountRule.ALL, MountRule.ALL, "@{mntpnt}", MountRule.ALL, False, False, False, '' )),
|
('mount fstype=(ext3, ext4),', MountRule('mount', ('=', ('ext3', 'ext4')), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
||||||
('mount /a,', MountRule('mount', MountRule.ALL, MountRule.ALL, "/a", MountRule.ALL, False, False, False, '' )),
|
('mount bpf,', MountRule('mount', MountRule.ALL, MountRule.ALL, 'bpf', MountRule.ALL, False, False, False, '' )),
|
||||||
('mount fstype=(ext3, ext4) /a -> /b,', MountRule('mount', ('=',('ext3', 'ext4')), MountRule.ALL, "/a", "/b", False, False, False, '' )),
|
('mount none,', MountRule('mount', MountRule.ALL, MountRule.ALL, 'none', MountRule.ALL, False, False, False, '' )),
|
||||||
('mount fstype=(ext3, ext4) options=(ro, rbind) /a -> /b,', MountRule('mount', ('=',('ext3', 'ext4')), ('=',('ro', 'rbind')), "/a", "/b", False, False, False, '' )),
|
('mount fstype=(ext3, ext4) options=(ro),', MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
||||||
('mount fstype=(ext3, ext4) options=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('=',('ext3', 'ext4')), ('=',('ro', 'rbind')), "/a", "/b", False, False, False, ' #cmt')),
|
('mount @{mntpnt},', MountRule('mount', MountRule.ALL, MountRule.ALL, '@{mntpnt}', MountRule.ALL, False, False, False, '' )),
|
||||||
('mount fstype=(ext3, ext4) options in (ro, rbind) /a -> /b,', MountRule('mount', ('=',('ext3', 'ext4')), ('in',('ro', 'rbind')), "/a", "/b", False, False, False, '' )),
|
('mount /a,', MountRule('mount', MountRule.ALL, MountRule.ALL, '/a', MountRule.ALL, False, False, False, '' )),
|
||||||
('mount fstype in (ext3, ext4) options=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('in',('ext3', 'ext4')),('=',('ro', 'rbind')), "/a", "/b", False, False, False, ' #cmt')),
|
('mount fstype=(ext3, ext4) /a -> /b,', MountRule('mount', ('=', ('ext3', 'ext4')), MountRule.ALL, '/a', '/b', False, False, False, '' )),
|
||||||
('mount fstype in (ext3, ext4) option in (ro, rbind) /a, #cmt', MountRule('mount', ('in',('ext3', 'ext4')),('in',('ro', 'rbind')), "/a", MountRule.ALL, False, False, False, ' #cmt')),
|
('mount fstype=(ext3, ext4) options=(ro, rbind) /a -> /b,', MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, '' )),
|
||||||
('mount fstype=(ext3, ext4) option=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('=',('ext3', 'ext4')), ('=', ('ro', 'rbind')), "/a", "/b", False, False, False, ' #cmt')),
|
('mount fstype=(ext3, ext4) options=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
|
||||||
('mount options=(rw, rbind) /usr/lib{,32,64,x32}/modules/ -> /tmp/snap.rootfs_*{,/usr}/lib/modules/,',
|
('mount fstype=(ext3, ext4) options in (ro, rbind) /a -> /b,', MountRule('mount', ('=', ('ext3', 'ext4')), ('in', ('ro', 'rbind')), '/a', '/b', False, False, False, '' )),
|
||||||
MountRule('mount', MountRule.ALL, ('=',('rw', 'rbind')), "/usr/lib{,32,64,x32}/modules/",
|
('mount fstype in (ext3, ext4) options=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('in', ('ext3', 'ext4')), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
|
||||||
"/tmp/snap.rootfs_*{,/usr}/lib/modules/",
|
('mount fstype in (ext3, ext4) option in (ro, rbind) /a, #cmt', MountRule('mount', ('in', ('ext3', 'ext4')), ('in', ('ro', 'rbind')), '/a', MountRule.ALL, False, False, False, ' #cmt')),
|
||||||
False, False, False, '' )),
|
('mount fstype=(ext3, ext4) option=(ro, rbind) /a -> /b, #cmt', MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro', 'rbind')), '/a', '/b', False, False, False, ' #cmt')),
|
||||||
('umount,', MountRule('umount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
('mount options=(rw, rbind) {,/usr}/lib{,32,64,x32}/modules/ -> /tmp/snap.rootfs_*{,/usr}/lib/modules/,',
|
||||||
('umount fstype=ext3,', MountRule('umount', ('=',('ext3')), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
MountRule('mount', MountRule.ALL, ('=', ('rw', 'rbind')), '{,/usr}/lib{,32,64,x32}/modules/',
|
||||||
('umount /a,', MountRule('umount', MountRule.ALL, MountRule.ALL, MountRule.ALL, "/a", False, False, False, '' )),
|
'/tmp/snap.rootfs_*{,/usr}/lib/modules/',
|
||||||
|
False, False, False, '' )),
|
||||||
('remount,', MountRule('remount',MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
('umount,', MountRule('umount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
||||||
('remount fstype=ext4,', MountRule('remount',('=',('ext4')), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
('umount fstype=ext3,', MountRule('umount', ('=', ('ext3')), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
||||||
('remount /b,', MountRule('remount',MountRule.ALL, MountRule.ALL, MountRule.ALL, "/b", False, False, False, '' )),
|
('umount /a,', MountRule('umount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '/a', False, False, False, '' )),
|
||||||
|
|
||||||
|
|
||||||
|
('remount,', MountRule('remount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
||||||
|
('remount fstype=ext4,', MountRule('remount', ('=', ('ext4')), MountRule.ALL, MountRule.ALL, MountRule.ALL, False, False, False, '' )),
|
||||||
|
('remount /b,', MountRule('remount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '/b', False, False, False, '' )),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _run_test(self, rawrule, expected):
|
def _run_test(self, rawrule, expected):
|
||||||
@@ -69,12 +71,12 @@ class MountTestParse(AATest):
|
|||||||
|
|
||||||
class MountTestParseInvalid(AATest):
|
class MountTestParseInvalid(AATest):
|
||||||
tests = (
|
tests = (
|
||||||
('mount fstype=,', AppArmorException),
|
('mount fstype=,', AppArmorException),
|
||||||
('mount fstype=(foo),', AppArmorException),
|
('mount fstype=(foo),', AppArmorException),
|
||||||
('mount fstype=(),', AppArmorException),
|
('mount fstype=(),', AppArmorException),
|
||||||
('mount options=(),', AppArmorException),
|
('mount options=(),', AppArmorException),
|
||||||
('mount option=(invalid),', AppArmorException),
|
('mount option=(invalid),', AppArmorException),
|
||||||
('mount option=(ext3ext4),',AppArmorException),
|
('mount option=(ext3ext4),', AppArmorException),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _run_test(self, rawrule, expected):
|
def _run_test(self, rawrule, expected):
|
||||||
@@ -88,60 +90,69 @@ class MountTestParseInvalid(AATest):
|
|||||||
|
|
||||||
def test_diff_non_mountrule(self):
|
def test_diff_non_mountrule(self):
|
||||||
exp = namedtuple('exp', ('audit', 'deny'))
|
exp = namedtuple('exp', ('audit', 'deny'))
|
||||||
obj = MountRule('mount',("=", '(ext4)'), MountRule.ALL, MountRule.ALL, MountRule.ALL)
|
obj = MountRule('mount', ('=', 'ext4'), MountRule.ALL, MountRule.ALL, MountRule.ALL)
|
||||||
with self.assertRaises(AppArmorBug):
|
with self.assertRaises(AppArmorBug):
|
||||||
obj.is_equal(exp(False, False), False)
|
obj.is_equal(exp(False, False), False)
|
||||||
|
|
||||||
def test_diff_invalid_fstype_equals_or_in(self):
|
def test_diff_invalid_fstype_equals_or_in(self):
|
||||||
with self.assertRaises(AppArmorBug):
|
with self.assertRaises(AppArmorBug):
|
||||||
MountRule('mount', ('ext3', '(ext4)'), MountRule.ALL, MountRule.ALL, MountRule.ALL) # fstype[0] should be '=' or 'in'
|
MountRule('mount', ('ext3', 'ext4'), MountRule.ALL, MountRule.ALL, MountRule.ALL) # fstype[0] should be '=' or 'in'
|
||||||
|
|
||||||
|
def test_diff_invalid_fstype_keyword(self):
|
||||||
|
with self.assertRaises(AppArmorException):
|
||||||
|
MountRule('mount', ('=', 'invalidfs'), MountRule.ALL, MountRule.ALL, MountRule.ALL) # fstype[0] should be '=' or 'in'
|
||||||
|
|
||||||
def test_diff_invalid_options_equals_or_in(self):
|
def test_diff_invalid_options_equals_or_in(self):
|
||||||
with self.assertRaises(AppArmorBug):
|
with self.assertRaises(AppArmorBug):
|
||||||
MountRule('mount', MountRule.ALL, ('rbind', '(rw)'), MountRule.ALL, MountRule.ALL) # fstype[0] should be '=' or 'in'
|
MountRule('mount', MountRule.ALL, ('rbind', 'rw'), MountRule.ALL, MountRule.ALL) # fstype[0] should be '=' or 'in'
|
||||||
|
|
||||||
|
def test_diff_invalid_options_keyword(self):
|
||||||
|
with self.assertRaises(AppArmorException):
|
||||||
|
MountRule('mount', MountRule.ALL, ('=', 'invalid'), MountRule.ALL, MountRule.ALL) # fstype[0] should be '=' or 'in'
|
||||||
|
|
||||||
def test_diff_fstype(self):
|
def test_diff_fstype(self):
|
||||||
obj1 = MountRule('mount',("=", '(ext4)'), MountRule.ALL, MountRule.ALL, MountRule.ALL)
|
obj1 = MountRule('mount', ('=', 'ext4'), MountRule.ALL, MountRule.ALL, MountRule.ALL)
|
||||||
obj2 = MountRule('mount',MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL)
|
obj2 = MountRule('mount', MountRule.ALL, MountRule.ALL, MountRule.ALL, MountRule.ALL)
|
||||||
self.assertFalse(obj1.is_equal(obj2, False))
|
self.assertFalse(obj1.is_equal(obj2, False))
|
||||||
|
|
||||||
def test_diff_source(self):
|
def test_diff_source(self):
|
||||||
obj1 = MountRule('mount',MountRule.ALL, MountRule.ALL, "/foo", MountRule.ALL)
|
obj1 = MountRule('mount', MountRule.ALL, MountRule.ALL, '/foo', MountRule.ALL)
|
||||||
obj2 = MountRule('mount',MountRule.ALL, MountRule.ALL, "/bar", MountRule.ALL)
|
obj2 = MountRule('mount', MountRule.ALL, MountRule.ALL, '/bar', MountRule.ALL)
|
||||||
self.assertFalse(obj1.is_equal(obj2, False))
|
self.assertFalse(obj1.is_equal(obj2, False))
|
||||||
|
|
||||||
def test_invalid_umount_with_source(self):
|
def test_invalid_umount_with_source(self):
|
||||||
with self.assertRaises(AppArmorException):
|
with self.assertRaises(AppArmorException):
|
||||||
MountRule('umount', MountRule.ALL, MountRule.ALL, "/foo", MountRule.ALL) # Umount and remount shall not have a source
|
MountRule('umount', MountRule.ALL, MountRule.ALL, '/foo', MountRule.ALL) # Umount and remount shall not have a source
|
||||||
|
|
||||||
def test_invalid_remount_with_source(self):
|
def test_invalid_remount_with_source(self):
|
||||||
with self.assertRaises(AppArmorException):
|
with self.assertRaises(AppArmorException):
|
||||||
MountRule('remount', MountRule.ALL, MountRule.ALL, "/foo", MountRule.ALL)
|
MountRule('remount', MountRule.ALL, MountRule.ALL, '/foo', MountRule.ALL)
|
||||||
|
|
||||||
|
|
||||||
class MountTestFilesystems(AATest):
|
class MountTestFilesystems(AATest):
|
||||||
def test_fs(self):
|
def test_fs(self):
|
||||||
with open("/proc/filesystems") as f:
|
with open('/proc/filesystems') as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
self.assertTrue(line.split()[-1] in valid_fs)
|
fs_name = line.split()[-1]
|
||||||
|
self.assertTrue(fs_name in valid_fs, '/proc/filesystems contains %s which is not listed in MountRule valid_fs' % fs_name)
|
||||||
|
|
||||||
|
|
||||||
class MountTestGlob(AATest):
|
class MountTestGlob(AATest):
|
||||||
def test_glob(self):
|
def test_glob(self):
|
||||||
globList = [(
|
globList = [(
|
||||||
"mount options=(bind, rw) /home/user/Downloads/ -> /mnt/a/,",
|
'mount options=(bind, rw) /home/user/Downloads/ -> /mnt/a/,',
|
||||||
"mount options=(bind, rw) /home/user/Downloads/,",
|
'mount options=(bind, rw) /home/user/Downloads/,',
|
||||||
"mount options=(bind, rw) /home/user/*/,",
|
'mount options=(bind, rw) /home/user/*/,',
|
||||||
"mount options=(bind, rw) /home/**/,",
|
'mount options=(bind, rw) /home/**/,',
|
||||||
"mount options=(bind, rw),",
|
'mount options=(bind, rw),',
|
||||||
"mount,",
|
'mount,',
|
||||||
"mount,",
|
'mount,',
|
||||||
)]
|
)]
|
||||||
for globs in globList:
|
for globs in globList:
|
||||||
for i in range(len(globs)-1):
|
for i in range(len(globs) - 1):
|
||||||
rule = MountRule.create_instance(globs[i])
|
rule = MountRule.create_instance(globs[i])
|
||||||
rule.glob()
|
rule.glob()
|
||||||
self.assertEqual(rule.get_clean(), globs[i+1])
|
self.assertEqual(rule.get_clean(), globs[i + 1])
|
||||||
|
|
||||||
|
|
||||||
class MountTestClean(AATest):
|
class MountTestClean(AATest):
|
||||||
@@ -152,7 +163,13 @@ class MountTestClean(AATest):
|
|||||||
(' mount fstype = ( sysfs , procfs ) , ', 'mount fstype=(procfs, sysfs),'),
|
(' mount fstype = ( sysfs , procfs ) , ', 'mount fstype=(procfs, sysfs),'),
|
||||||
(' mount options = ( rw ) , ', 'mount options=(rw),'),
|
(' mount options = ( rw ) , ', 'mount options=(rw),'),
|
||||||
(' mount options = ( rw , noatime ) , ', 'mount options=(noatime, rw),'),
|
(' mount options = ( rw , noatime ) , ', 'mount options=(noatime, rw),'),
|
||||||
|
(' mount fstype in ( sysfs ) , ', 'mount fstype in (sysfs),'),
|
||||||
|
(' mount fstype in ( sysfs , procfs ) , ', 'mount fstype in (procfs, sysfs),'),
|
||||||
|
(' mount options in ( rw ) , ', 'mount options in (rw),'),
|
||||||
|
(' mount options in ( rw , noatime ) , ', 'mount options in (noatime, rw),'),
|
||||||
|
(' umount , ', 'umount,'),
|
||||||
(' umount /foo , ', 'umount /foo,'),
|
(' umount /foo , ', 'umount /foo,'),
|
||||||
|
(' remount , ', 'remount,'),
|
||||||
(' remount /foo , ', 'remount /foo,'),
|
(' remount /foo , ', 'remount /foo,'),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -165,11 +182,12 @@ class MountTestClean(AATest):
|
|||||||
self.assertEqual(expected, clean, 'unexpected clean rule')
|
self.assertEqual(expected, clean, 'unexpected clean rule')
|
||||||
self.assertEqual(rawrule.strip(), raw, 'unexpected raw rule')
|
self.assertEqual(rawrule.strip(), raw, 'unexpected raw rule')
|
||||||
|
|
||||||
|
|
||||||
class MountLogprofHeaderTest(AATest):
|
class MountLogprofHeaderTest(AATest):
|
||||||
tests = (
|
tests = (
|
||||||
('mount,', [_('Operation'), _('mount'), _('Fstype'), _('ALL'), _('Options'), _('ALL'), _('Source'), _('ALL'), _('Destination'), _('ALL')]),
|
('mount,', [_('Operation'), _('mount'), _('Fstype'), _('ALL'), _('Options'), _('ALL'), _('Source'), _('ALL'), _('Destination'), _('ALL')]),
|
||||||
('mount options=(ro, nosuid) /a,', [_('Operation'), _('mount'), _('Fstype'), _('ALL'), _('Options'), ("=", _('nosuid ro')),_('Source'), _('/a'), _('Destination'), _('ALL')]),
|
('mount options=(ro, nosuid) /a,', [_('Operation'), _('mount'), _('Fstype'), _('ALL'), _('Options'), ('=', _('nosuid ro')), _('Source'), _('/a'), _('Destination'), _('ALL')]),
|
||||||
('mount fstype=(ext3, ext4) options=(ro, nosuid) /a -> /b,', [_('Operation'), _('mount'), _('Fstype'), ("=", _('ext3 ext4')),_('Options'), ("=", _('nosuid ro')),_('Source'), _('/a'), _('Destination'), _('/b')])
|
('mount fstype=(ext3, ext4) options=(ro, nosuid) /a -> /b,', [_('Operation'), _('mount'), _('Fstype'), ('=', _('ext3 ext4')), _('Options'), ('=', _('nosuid ro')), _('Source'), _('/a'), _('Destination'), _('/b')])
|
||||||
)
|
)
|
||||||
|
|
||||||
def _run_test(self, params, expected):
|
def _run_test(self, params, expected):
|
||||||
@@ -179,45 +197,59 @@ class MountLogprofHeaderTest(AATest):
|
|||||||
|
|
||||||
class MountIsCoveredTest(AATest):
|
class MountIsCoveredTest(AATest):
|
||||||
def test_is_covered(self):
|
def test_is_covered(self):
|
||||||
obj = MountRule("mount", ("=", ('ext3', 'ext4')), ("=", ('ro')), "/foo/b*", "/b*")
|
obj = MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/foo/b*', '/b*')
|
||||||
tests = [
|
tests = [
|
||||||
("mount", ("=", ('ext3', 'ext4')), ("=", ('ro')), "/foo/b", "/bar"),
|
('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/foo/b', '/bar'),
|
||||||
("mount", ("=", ('ext3', 'ext4')), ("=", ('ro')), "/foo/bar", "/b")
|
('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/foo/bar', '/b')
|
||||||
]
|
]
|
||||||
for test in tests:
|
for test in tests:
|
||||||
self.assertTrue(obj.is_covered(MountRule(*test)))
|
self.assertTrue(obj.is_covered(MountRule(*test)))
|
||||||
self.assertFalse(obj.is_equal(MountRule(*test)))
|
self.assertFalse(obj.is_equal(MountRule(*test)))
|
||||||
|
|
||||||
def test_is_covered_fs_source(self):
|
def test_is_covered_fs_source(self):
|
||||||
obj = MountRule("mount", ("=", ('ext3', 'ext4')), ("=", ('ro')), "tmpfs", MountRule.ALL)
|
obj = MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), 'tmpfs', MountRule.ALL)
|
||||||
self.assertTrue(obj.is_covered(MountRule("mount", ("=", ('ext3')), ("=", ('ro')), "tmpfs", MountRule.ALL)))
|
self.assertTrue(obj.is_covered(MountRule('mount', ('=', ('ext3')), ('=', ('ro')), 'tmpfs', MountRule.ALL)))
|
||||||
self.assertFalse(obj.is_equal(MountRule("mount", ("=", ('ext3')), ("=", ('ro')), "tmpfs", MountRule.ALL)))
|
self.assertFalse(obj.is_equal(MountRule('mount', ('=', ('ext3')), ('=', ('ro')), 'tmpfs', MountRule.ALL)))
|
||||||
|
|
||||||
|
def test_is_covered_regex(self):
|
||||||
|
obj = MountRule('mount', ('=', ('sys*', 'fuse.*')), ('=', ('ro')), 'tmpfs', MountRule.ALL)
|
||||||
|
tests = [
|
||||||
|
('mount', ('=', ('sysfs', 'fuse.s3fs')), ('=', ('ro')), 'tmpfs', MountRule.ALL),
|
||||||
|
('mount', ('=', ('sysfs', 'fuse.jmtpfs', 'fuse.s3fs', 'fuse.obexfs', 'fuse.obexautofs', 'fuse.fuseiso')), ('=', ('ro')), 'tmpfs', MountRule.ALL)
|
||||||
|
]
|
||||||
|
for test in tests:
|
||||||
|
self.assertTrue(obj.is_covered(MountRule(*test)))
|
||||||
|
self.assertFalse(obj.is_equal(MountRule(*test)))
|
||||||
|
|
||||||
def test_is_notcovered(self):
|
def test_is_notcovered(self):
|
||||||
obj = MountRule("mount", ("=", ('ext3', 'ext4')), ("=", ('ro')), "/foo/b*", "/b*")
|
obj = MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/foo/b*', '/b*')
|
||||||
tests = [
|
tests = [
|
||||||
("mount", ("in", ('ext3', 'ext4')), ("=", ('ro')), "/foo/bar", "/bar" ),
|
('mount', ('in', ('ext3', 'ext4')), ('=', ('ro')), '/foo/bar', '/bar' ),
|
||||||
("mount", ("=", ('procfs, ext4')), ("=", ('ro')), "/foo/bar", "/bar" ),
|
('mount', ('=', ('procfs', 'ext4')), ('=', ('ro')), '/foo/bar', '/bar' ),
|
||||||
("mount", ("=", ('ext3')), ("=", ('rw')), "/foo/bar", "/bar" ),
|
('mount', ('=', ('ext3')), ('=', ('rw')), '/foo/bar', '/bar' ),
|
||||||
("mount", ("=", ('ext3', 'ext4')), MountRule.ALL, "/foo/b*", "/bar" ),
|
('mount', ('=', ('ext3', 'ext4')), MountRule.ALL, '/foo/b*', '/bar' ),
|
||||||
("mount", MountRule.ALL, ("=", ('ro')), "/foo/b*", "/bar" ),
|
('mount', MountRule.ALL, ('=', ('ro')), '/foo/b*', '/bar' ),
|
||||||
("mount", ("=", ('ext3', 'ext4')), ("=", ('ro')), "/invalid/bar", "/bar" ),
|
('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/invalid/bar', '/bar' ),
|
||||||
("umount", MountRule.ALL, MountRule.ALL, MountRule.ALL, "/bar" ),
|
('umount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '/bar' ),
|
||||||
("remount", MountRule.ALL, MountRule.ALL, MountRule.ALL, "/bar" ),
|
('remount', MountRule.ALL, MountRule.ALL, MountRule.ALL, '/bar' ),
|
||||||
("mount", ("=", ('ext3', 'ext4')), ("=", ('ro')), "tmpfs", "/bar" ),
|
('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), 'tmpfs', '/bar' ),
|
||||||
("mount", ("=", ('ext3', 'ext4')), ("=", ('ro')), "/foo/b*", "/invalid" ),
|
('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), '/foo/b*', '/invalid'),
|
||||||
]
|
]
|
||||||
for test in tests:
|
for test in tests:
|
||||||
self.assertFalse(obj.is_covered(MountRule(*test)))
|
self.assertFalse(obj.is_covered(MountRule(*test)))
|
||||||
self.assertFalse(obj.is_equal(MountRule(*test)))
|
self.assertFalse(obj.is_equal(MountRule(*test)))
|
||||||
|
|
||||||
|
|
||||||
def test_is_not_covered_fs_source(self):
|
def test_is_not_covered_fs_source(self):
|
||||||
obj = MountRule("mount", ("=", ('ext3', 'ext4')), ("=", ('ro')), "tmpfs", MountRule.ALL)
|
obj = MountRule('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), 'tmpfs', MountRule.ALL)
|
||||||
test = ("mount", ("=", ('ext3', 'ext4')), ("=", ('ro')), "procfs", MountRule.ALL)
|
test = ('mount', ('=', ('ext3', 'ext4')), ('=', ('ro')), 'procfs', MountRule.ALL)
|
||||||
self.assertFalse(obj.is_covered(MountRule(*test)))
|
self.assertFalse(obj.is_covered(MountRule(*test)))
|
||||||
self.assertFalse(obj.is_equal(MountRule(*test)))
|
self.assertFalse(obj.is_equal(MountRule(*test)))
|
||||||
|
|
||||||
|
def test_is_not_covered_fs_options(self):
|
||||||
|
obj = MountRule('mount', MountRule.ALL, ('=', ('ro')), 'tmpfs', MountRule.ALL)
|
||||||
|
test = ('mount', MountRule.ALL, ('=', ('rw')), 'procfs', MountRule.ALL)
|
||||||
|
self.assertFalse(obj.is_covered(MountRule(*test)))
|
||||||
|
self.assertFalse(obj.is_equal(MountRule(*test)))
|
||||||
|
|
||||||
|
|
||||||
setup_all_loops(__name__)
|
setup_all_loops(__name__)
|
||||||
|
@@ -1,53 +0,0 @@
|
|||||||
#! /usr/bin/python3
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
# Copyright (C) 2014 Canonical Ltd.
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of version 2 of the GNU General Public
|
|
||||||
# License published by the Free Software Foundation.
|
|
||||||
#
|
|
||||||
# ------------------------------------------------------------------
|
|
||||||
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
import apparmor.aa as aa
|
|
||||||
from common_test import AAParseTest, setup_aa, setup_regex_tests
|
|
||||||
|
|
||||||
|
|
||||||
class BaseAAParseMountTest(AAParseTest):
|
|
||||||
def setUp(self):
|
|
||||||
self.parse_function = aa.parse_mount_rule
|
|
||||||
|
|
||||||
|
|
||||||
class AAParseMountTest(BaseAAParseMountTest):
|
|
||||||
tests = (
|
|
||||||
('mount,', 'mount base keyword rule'),
|
|
||||||
('mount -o ro,', 'mount ro rule'),
|
|
||||||
('mount -o rw /dev/sdb1 -> /mnt/external,', 'mount rw with mount point'),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AAParseRemountTest(BaseAAParseMountTest):
|
|
||||||
tests = (
|
|
||||||
('remount,', 'remount base keyword rule'),
|
|
||||||
('remount -o ro,', 'remount ro rule'),
|
|
||||||
('remount -o ro /,', 'remount ro with mountpoint'),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class AAParseUmountTest(BaseAAParseMountTest):
|
|
||||||
tests = (
|
|
||||||
('umount,', 'umount base keyword rule'),
|
|
||||||
('umount /mnt/external,', 'umount with mount point'),
|
|
||||||
('unmount,', 'unmount base keyword rule'),
|
|
||||||
('unmount /mnt/external,', 'unmount with mount point'),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
setup_aa(aa)
|
|
||||||
if __name__ == '__main__':
|
|
||||||
setup_regex_tests(AAParseMountTest)
|
|
||||||
setup_regex_tests(AAParseRemountTest)
|
|
||||||
setup_regex_tests(AAParseUmountTest)
|
|
||||||
unittest.main(verbosity=1)
|
|
@@ -85,6 +85,16 @@ exception_not_raised = (
|
|||||||
'mount/bad_1.sd',
|
'mount/bad_1.sd',
|
||||||
'mount/bad_2.sd',
|
'mount/bad_2.sd',
|
||||||
|
|
||||||
|
# not checked/detected: "make-*" mount opt and an invalid src
|
||||||
|
'mount/bad_opt_17.sd',
|
||||||
|
'mount/bad_opt_18.sd',
|
||||||
|
'mount/bad_opt_19.sd',
|
||||||
|
'mount/bad_opt_20.sd',
|
||||||
|
'mount/bad_opt_21.sd',
|
||||||
|
'mount/bad_opt_22.sd',
|
||||||
|
'mount/bad_opt_23.sd',
|
||||||
|
'mount/bad_opt_24.sd',
|
||||||
|
|
||||||
'profile/flags/flags_bad10.sd',
|
'profile/flags/flags_bad10.sd',
|
||||||
'profile/flags/flags_bad11.sd',
|
'profile/flags/flags_bad11.sd',
|
||||||
'profile/flags/flags_bad12.sd',
|
'profile/flags/flags_bad12.sd',
|
||||||
@@ -314,15 +324,8 @@ unknown_line = (
|
|||||||
'bare_include_tests/ok_85.sd',
|
'bare_include_tests/ok_85.sd',
|
||||||
'bare_include_tests/ok_86.sd',
|
'bare_include_tests/ok_86.sd',
|
||||||
|
|
||||||
# option = make-${valid-option} (e.g. make-private) is not supported
|
# mount with fstype using AARE
|
||||||
'mount/ok_opt_48.sd',
|
'mount/ok_12.sd',
|
||||||
'mount/ok_opt_49.sd',
|
|
||||||
'mount/ok_opt_50.sd',
|
|
||||||
'mount/ok_opt_51.sd',
|
|
||||||
'mount/ok_opt_52.sd',
|
|
||||||
'mount/ok_opt_53.sd',
|
|
||||||
'mount/ok_opt_54.sd',
|
|
||||||
'mount/ok_opt_55.sd',
|
|
||||||
|
|
||||||
# Mount with flags in {remount, [r]unbindable, [r]shared, [r]private, [r]slave} does not support a source
|
# Mount with flags in {remount, [r]unbindable, [r]shared, [r]private, [r]slave} does not support a source
|
||||||
'mount/ok_opt_68.sd',
|
'mount/ok_opt_68.sd',
|
||||||
@@ -334,15 +337,7 @@ unknown_line = (
|
|||||||
'mount/ok_opt_74.sd',
|
'mount/ok_opt_74.sd',
|
||||||
'mount/ok_opt_75.sd',
|
'mount/ok_opt_75.sd',
|
||||||
|
|
||||||
# option = make-${valid-option} (e.g. make-private) is not supported
|
# options=slave with /** src (first rule in the test causes exception)
|
||||||
'mount/ok_opt_76.sd',
|
|
||||||
'mount/ok_opt_77.sd',
|
|
||||||
'mount/ok_opt_78.sd',
|
|
||||||
'mount/ok_opt_79.sd',
|
|
||||||
'mount/ok_opt_80.sd',
|
|
||||||
'mount/ok_opt_81.sd',
|
|
||||||
'mount/ok_opt_82.sd',
|
|
||||||
'mount/ok_opt_83.sd',
|
|
||||||
'mount/ok_opt_84.sd',
|
'mount/ok_opt_84.sd',
|
||||||
|
|
||||||
# According to spec mount should be in the form fstype=... options=... and NOT in the form options=... fstype=...
|
# According to spec mount should be in the form fstype=... options=... and NOT in the form options=... fstype=...
|
||||||
@@ -351,8 +346,6 @@ unknown_line = (
|
|||||||
'mount/ok_opt_combo_1.sd',
|
'mount/ok_opt_combo_1.sd',
|
||||||
'mount/ok_opt_combo_4.sd',
|
'mount/ok_opt_combo_4.sd',
|
||||||
|
|
||||||
# Invalid keyword: read-only --> Should be ro
|
|
||||||
'mount/ok_opt_3.sd',
|
|
||||||
# Options should be comma separated
|
# Options should be comma separated
|
||||||
'mount/in_4.sd', # also order option then fstype is invalid
|
'mount/in_4.sd', # also order option then fstype is invalid
|
||||||
)
|
)
|
||||||
@@ -499,6 +492,7 @@ syntax_failure = (
|
|||||||
'network/network_ok_41.sd',
|
'network/network_ok_41.sd',
|
||||||
'network/network_ok_42.sd',
|
'network/network_ok_42.sd',
|
||||||
'network/network_ok_43.sd',
|
'network/network_ok_43.sd',
|
||||||
|
'network/network_ok_44.sd',
|
||||||
'network/perms/ok_accept_1.sd',
|
'network/perms/ok_accept_1.sd',
|
||||||
'network/perms/ok_accept_2.sd',
|
'network/perms/ok_accept_2.sd',
|
||||||
'network/perms/ok_attr_1.sd',
|
'network/perms/ok_attr_1.sd',
|
||||||
|
@@ -14,7 +14,7 @@ import unittest
|
|||||||
import apparmor.aa as aa
|
import apparmor.aa as aa
|
||||||
from apparmor.common import AppArmorBug, AppArmorException
|
from apparmor.common import AppArmorBug, AppArmorException
|
||||||
from apparmor.regex import (
|
from apparmor.regex import (
|
||||||
RE_PROFILE_CAP, RE_PROFILE_DBUS, RE_PROFILE_PTRACE, RE_PROFILE_SIGNAL,
|
RE_PROFILE_CAP, RE_PROFILE_DBUS, RE_PROFILE_MOUNT, RE_PROFILE_PTRACE, RE_PROFILE_SIGNAL,
|
||||||
RE_PROFILE_START, parse_profile_start_line, re_match_include,
|
RE_PROFILE_START, parse_profile_start_line, re_match_include,
|
||||||
re_match_include_parse, strip_parenthesis, strip_quotes)
|
re_match_include_parse, strip_parenthesis, strip_quotes)
|
||||||
from common_test import AATest, setup_aa, setup_all_loops
|
from common_test import AATest, setup_aa, setup_all_loops
|
||||||
@@ -248,7 +248,7 @@ class AARegexMount(AARegexTest):
|
|||||||
"""Tests for RE_PROFILE_MOUNT"""
|
"""Tests for RE_PROFILE_MOUNT"""
|
||||||
|
|
||||||
def AASetup(self):
|
def AASetup(self):
|
||||||
self.regex = aa.RE_PROFILE_MOUNT
|
self.regex = RE_PROFILE_MOUNT
|
||||||
|
|
||||||
tests = (
|
tests = (
|
||||||
(' mount,', (None, None, 'mount,', 'mount', None, None)),
|
(' mount,', (None, None, 'mount,', 'mount', None, None)),
|
||||||
|
Reference in New Issue
Block a user