mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-02 23:35:37 +00:00
Compare commits
53 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
99cb8cc7f1 | ||
|
7b47dee81e | ||
|
789309f419 | ||
|
e7488ebff1 | ||
|
498853ca6e | ||
|
e262991d18 | ||
|
90b8189547 | ||
|
34d1b5ddce | ||
|
9d09389290 | ||
|
b292de2ca0 | ||
|
e5daa5fa39 | ||
|
383bbd68d6 | ||
|
845507b8a1 | ||
|
6b2a8191a6 | ||
|
681fef917b | ||
|
b15f758490 | ||
|
c9e3e6e85a | ||
|
6920e3d717 | ||
|
ae595aea03 | ||
|
1251e0c143 | ||
|
b56fdec804 | ||
|
eacb977ebd | ||
|
29d287f94e | ||
|
9fd54008c4 | ||
|
0ffc0941a8 | ||
|
ed68e397aa | ||
|
c79607927d | ||
|
353ef34ca0 | ||
|
80a17a6106 | ||
|
44f2c6d2bc | ||
|
a7898cfe5b | ||
|
91b9b44f53 | ||
|
8fcfc27d56 | ||
|
791d40aa9d | ||
|
4ad98a8302 | ||
|
064541cb53 | ||
|
9618cc9a62 | ||
|
119522307f | ||
|
2a929f3f1c | ||
|
ec4de6e081 | ||
|
fde4f8a522 | ||
|
cad5d461ca | ||
|
922096a8be | ||
|
9d8340a8b3 | ||
|
1d8e388c93 | ||
|
28d5c335af | ||
|
8ea1054f50 | ||
|
36b699bcf6 | ||
|
0125d04924 | ||
|
ad169656bf | ||
|
0f7ccc49bb | ||
|
90e5294578 | ||
|
6d19a507ae |
@@ -88,7 +88,7 @@ libraries/libapparmor/swig/perl/MYMETA.yml
|
||||
libraries/libapparmor/swig/perl/blib
|
||||
libraries/libapparmor/swig/perl/libapparmor_wrap.c
|
||||
libraries/libapparmor/swig/perl/pm_to_blib
|
||||
libraries/libapparmor/swig/python/__init__.py
|
||||
libraries/libapparmor/swig/python/LibAppArmor.py
|
||||
libraries/libapparmor/swig/python/build/
|
||||
libraries/libapparmor/swig/python/libapparmor_wrap.c
|
||||
libraries/libapparmor/swig/python/Makefile
|
||||
|
@@ -65,7 +65,7 @@ provides the AAHatName and AADefaultHatName Apache configuration options.
|
||||
|
||||
AAHatName allows you to specify a hat to be used for a given Apache
|
||||
E<lt>DirectoryE<gt>, E<lt>DirectoryMatchE<gt>, E<lt>LocationE<gt> or
|
||||
E<lt>LocationMatchE<gt> directive (see the Apache documenation for more
|
||||
E<lt>LocationMatchE<gt> directive (see the Apache documentation for more
|
||||
details). Note that mod_apparmor behavior can become confused if
|
||||
E<lt>Directory*E<gt> and E<lt>Location*E<gt> directives are intermingled
|
||||
and it is recommended to use one type of directive. If the hat specified by
|
||||
|
@@ -1 +1 @@
|
||||
2.10.1
|
||||
2.10.2
|
||||
|
@@ -38,6 +38,6 @@ aclocal
|
||||
echo "Running autoconf"
|
||||
autoconf --force
|
||||
echo "Running libtoolize"
|
||||
libtoolize --automake -c
|
||||
libtoolize --automake -c --force
|
||||
echo "Running automake"
|
||||
automake -ac
|
||||
|
@@ -178,7 +178,7 @@ syslog_month Jan(uary)?|Feb(ruary)?|Mar(ch)?|Apr(il)?|May|Jun(e)?|Jul(y)?|Aug(
|
||||
hhmmss {digit}{2}{colon}{digit}{2}{colon}{digit}{2}
|
||||
timezone ({plus}|{minus}){digit}{2}{colon}{digit}{2}
|
||||
syslog_time {hhmmss}({period}{digits})?{timezone}?
|
||||
syslog_hostname [[:alnum:]_-]+
|
||||
syslog_hostname [[:alnum:]._-]+
|
||||
dmesg_timestamp \[[[:digit:] ]{5,}\.[[:digit:]]{6,}\]
|
||||
|
||||
%x single_quoted_string
|
||||
|
@@ -6,9 +6,8 @@ SUBDIRS = test
|
||||
|
||||
libapparmor_wrap.c: $(srcdir)/../SWIG/libapparmor.i
|
||||
$(SWIG) -python -I$(srcdir)/../../include -module LibAppArmor -o $@ $(srcdir)/../SWIG/libapparmor.i
|
||||
mv LibAppArmor.py __init__.py
|
||||
|
||||
MOSTLYCLEANFILES=libapparmor_wrap.c __init__.py
|
||||
MOSTLYCLEANFILES=libapparmor_wrap.c LibAppArmor.py
|
||||
|
||||
all-local: libapparmor_wrap.c setup.py
|
||||
if test ! -f libapparmor_wrap.c; then cp $(srcdir)/libapparmor_wrap.c . ; fi
|
||||
|
6
libraries/libapparmor/swig/python/__init__.py
Normal file
6
libraries/libapparmor/swig/python/__init__.py
Normal file
@@ -0,0 +1,6 @@
|
||||
import sys
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
from LibAppArmor.LibAppArmor import *
|
||||
else:
|
||||
from .LibAppArmor import *
|
@@ -0,0 +1 @@
|
||||
[103975.623545] audit: type=1400 audit(1481284511.494:2807): apparmor="DENIED" operation="change_onexec" info="no new privs" error=-1 namespace="root//lxd-tor_<var-lib-lxd>" profile="unconfined" name="system_tor" pid=18593 comm="(tor)" target="system_tor"
|
@@ -0,0 +1,15 @@
|
||||
START
|
||||
File: change_onexec_lp1648143.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1481284511.494:2807
|
||||
Operation: change_onexec
|
||||
Profile: unconfined
|
||||
Name: system_tor
|
||||
Command: (tor)
|
||||
Name2: system_tor
|
||||
Namespace: root//lxd-tor_<var-lib-lxd>
|
||||
Info: no new privs
|
||||
ErrorCode: 1
|
||||
PID: 18593
|
||||
Epoch: 1481284511
|
||||
Audit subid: 2807
|
1
libraries/libapparmor/testsuite/test_multi/file_chown.in
Normal file
1
libraries/libapparmor/testsuite/test_multi/file_chown.in
Normal file
@@ -0,0 +1 @@
|
||||
type=AVC msg=audit(1465133533.431:728): apparmor="DENIED" operation="chown" profile="/usr/sbin/cupsd" name="/run/cups/certs/" pid=8515 comm="cupsd" requested_mask="w" denied_mask="w" fsuid=0 ouid=4
|
15
libraries/libapparmor/testsuite/test_multi/file_chown.out
Normal file
15
libraries/libapparmor/testsuite/test_multi/file_chown.out
Normal file
@@ -0,0 +1,15 @@
|
||||
START
|
||||
File: file_chown.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1465133533.431:728
|
||||
Operation: chown
|
||||
Mask: w
|
||||
Denied Mask: w
|
||||
fsuid: 0
|
||||
ouid: 4
|
||||
Profile: /usr/sbin/cupsd
|
||||
Name: /run/cups/certs/
|
||||
Command: cupsd
|
||||
PID: 8515
|
||||
Epoch: 1465133533
|
||||
Audit subid: 728
|
@@ -0,0 +1 @@
|
||||
Oct 22 15:57:38 NR021AA kernel: [ 69.827705] audit: type=1400 audit(1445522258.769:1054): apparmor="DENIED" operation="file_inherit" profile="/usr/lib/NetworkManager/nm-dhcp-client.action" pid=2407 comm="nm-dhcp-client." lport=10580 family="inet6" sock_type="dgram" protocol=17
|
@@ -0,0 +1,14 @@
|
||||
START
|
||||
File: file_inherit_network_lp1509030.in
|
||||
Event type: AA_RECORD_DENIED
|
||||
Audit ID: 1445522258.769:1054
|
||||
Operation: file_inherit
|
||||
Profile: /usr/lib/NetworkManager/nm-dhcp-client.action
|
||||
Command: nm-dhcp-client.
|
||||
PID: 2407
|
||||
Network family: inet6
|
||||
Socket type: dgram
|
||||
Protocol: udp
|
||||
Local port: 10580
|
||||
Epoch: 1445522258
|
||||
Audit subid: 1054
|
@@ -0,0 +1 @@
|
||||
Jun 19 12:00:55 piorun kernel: [4475115.459952] audit: type=1400 audit(1434708055.676:19629): apparmor="ALLOWED" operation="file_perm" profile="/usr/sbin/apache2" pid=3512 comm="apache2" laddr=::ffff:192.168.236.159 lport=80 faddr=::ffff:192.168.103.80 fport=61985 family="inet6" sock_type="stream" protocol=6
|
@@ -0,0 +1,17 @@
|
||||
START
|
||||
File: file_perm_network_lp1466812.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1434708055.676:19629
|
||||
Operation: file_perm
|
||||
Profile: /usr/sbin/apache2
|
||||
Command: apache2
|
||||
PID: 3512
|
||||
Network family: inet6
|
||||
Socket type: stream
|
||||
Protocol: tcp
|
||||
Local addr: ::ffff:192.168.236.159
|
||||
Foreign addr: ::ffff:192.168.103.80
|
||||
Local port: 80
|
||||
Foreign port: 61985
|
||||
Epoch: 1434708055
|
||||
Audit subid: 19629
|
@@ -0,0 +1 @@
|
||||
type=AVC msg=audit(1463403689.381:267599): apparmor="ALLOWED" operation="file_perm" profile="/usr/sbin/apache2//www.xxxxxxxxxx.co.uk" pid=13215 comm="apache2" laddr=::ffff:192.168.1.100 lport=80 faddr=::ffff:192.168.1.100 fport=45658 family="inet6" sock_type="stream" protocol=6 requested_mask="send" denied_mask="send"
|
@@ -0,0 +1,19 @@
|
||||
START
|
||||
File: file_perm_network_receive_lp1577051.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1463403689.381:267599
|
||||
Operation: file_perm
|
||||
Mask: send
|
||||
Denied Mask: send
|
||||
Profile: /usr/sbin/apache2//www.xxxxxxxxxx.co.uk
|
||||
Command: apache2
|
||||
PID: 13215
|
||||
Network family: inet6
|
||||
Socket type: stream
|
||||
Protocol: tcp
|
||||
Local addr: ::ffff:192.168.1.100
|
||||
Foreign addr: ::ffff:192.168.1.100
|
||||
Local port: 80
|
||||
Foreign port: 45658
|
||||
Epoch: 1463403689
|
||||
Audit subid: 267599
|
@@ -0,0 +1 @@
|
||||
Apr 30 21:53:05 nova kernel: [24668.960760] audit: type=1400 audit(1462045985.636:2154): apparmor="ALLOWED" operation="file_perm" profile="/usr/local/apache-tomcat-8.0.33/bin/catalina.sh///usr/local/jdk1.8.0_92/bin/java" pid=12529 comm="java" laddr=::ffff:127.0.0.1 lport=8080 faddr=::ffff:127.0.0.1 fport=52308 family="inet6" sock_type="stream" protocol=6 requested_mask="receive" denied_mask="receive"
|
@@ -0,0 +1,19 @@
|
||||
START
|
||||
File: file_perm_network_receive_lp1582374.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1462045985.636:2154
|
||||
Operation: file_perm
|
||||
Mask: receive
|
||||
Denied Mask: receive
|
||||
Profile: /usr/local/apache-tomcat-8.0.33/bin/catalina.sh///usr/local/jdk1.8.0_92/bin/java
|
||||
Command: java
|
||||
PID: 12529
|
||||
Network family: inet6
|
||||
Socket type: stream
|
||||
Protocol: tcp
|
||||
Local addr: ::ffff:127.0.0.1
|
||||
Foreign addr: ::ffff:127.0.0.1
|
||||
Local port: 8080
|
||||
Foreign port: 52308
|
||||
Epoch: 1462045985
|
||||
Audit subid: 2154
|
@@ -0,0 +1 @@
|
||||
Sep 14 18:49:13 mfa-mia-74-app-rabbitmq-1.mia.ix.int kernel: [964718.247816] type=1400 audit(1442256553.643:40143): apparmor="ALLOWED" operation="open" profile="/opt/evoke/venv/bin/gunicorn" name="/opt/evoke/venv/lib/python2.7/warnings.pyc" pid=28943 comm="gunicorn" requested_mask="r" denied_mask="r" fsuid=1000 ouid=110
|
@@ -0,0 +1,15 @@
|
||||
START
|
||||
File: syslog_hostname_with_dot.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1442256553.643:40143
|
||||
Operation: open
|
||||
Mask: r
|
||||
Denied Mask: r
|
||||
fsuid: 1000
|
||||
ouid: 110
|
||||
Profile: /opt/evoke/venv/bin/gunicorn
|
||||
Name: /opt/evoke/venv/lib/python2.7/warnings.pyc
|
||||
Command: gunicorn
|
||||
PID: 28943
|
||||
Epoch: 1442256553
|
||||
Audit subid: 40143
|
@@ -0,0 +1 @@
|
||||
Jul 29 11:42:05 files kernel: [483212.877816] audit: type=1400 audit(1469785325.122:21021): apparmor="ALLOWED" operation="file_inherit" profile="/usr/bin/nginx-amplify-agent.py//null-/bin/dash" pid=18239 comm="sh" laddr=192.168.10.3 lport=50758 faddr=54.153.70.241 fport=443 family="inet" sock_type="stream" protocol=6 requested_mask="send receive" denied_mask="send receive"
|
@@ -0,0 +1,19 @@
|
||||
START
|
||||
File: testcase_network_send_receive.in
|
||||
Event type: AA_RECORD_ALLOWED
|
||||
Audit ID: 1469785325.122:21021
|
||||
Operation: file_inherit
|
||||
Mask: send receive
|
||||
Denied Mask: send receive
|
||||
Profile: /usr/bin/nginx-amplify-agent.py//null-/bin/dash
|
||||
Command: sh
|
||||
PID: 18239
|
||||
Network family: inet
|
||||
Socket type: stream
|
||||
Protocol: tcp
|
||||
Local addr: 192.168.10.3
|
||||
Foreign addr: 54.153.70.241
|
||||
Local port: 50758
|
||||
Foreign port: 443
|
||||
Epoch: 1469785325
|
||||
Audit subid: 21021
|
@@ -46,7 +46,13 @@ to the policy; this behaviour is modelled after cpp(1).
|
||||
|
||||
B<PROFILE FILE> = ( [ I<PREAMBLE> ] [ I<PROFILE> ] )*
|
||||
|
||||
B<PREAMBLE> = ( I<COMMENT> | I<VARIABLE ASSIGNMENT> | I<INCLUDE> )* (variable assignment must come before the profile)
|
||||
B<PREAMBLE> = ( I<COMMENT> | I<VARIABLE ASSIGNMENT> | I<ALIAS RULE> | I<INCLUDE> )* (variable assignment and alias rules must come before the profile)
|
||||
|
||||
B<VARIABLE ASSIGNMENT> = I<VARIABLE> ('=' | '+=') (space separated values)
|
||||
|
||||
B<VARIABLE> = '@{' I<ALPHA> [ ( I<ALPHANUMERIC> | '_' ) ... ] '}'
|
||||
|
||||
B<ALIAS RULE> = 'alias' I<ABS PATH> '-E<gt>' I<REWRITTEN ABS PATH> ','
|
||||
|
||||
B<INCLUDE> = '#include' ( I<ABS PATH> | I<MAGIC PATH> )
|
||||
|
||||
@@ -78,7 +84,7 @@ B<RULES> = [ ( I<LINE RULES> | I<COMMA RULES> ',' | I<BLOCK RULES> )
|
||||
|
||||
B<LINE RULES> = ( I<COMMENT> | I<INCLUDE> ) [ '\r' ] '\n'
|
||||
|
||||
B<COMMA RULES> = ( I<CAPABILITY RULE> | I<NETWORK RULE> | I<MOUNT RULE> | I<PIVOT ROOT RULE> | I<UNIX RULE> | I<FILE RULE> | I<LINK RULE> | I<CHANGE_PROFILE RULE> | I<RLIMIT RULE> | I<ALIAS RULE> | I<DBUS RULE> )
|
||||
B<COMMA RULES> = ( I<CAPABILITY RULE> | I<NETWORK RULE> | I<MOUNT RULE> | I<PIVOT ROOT RULE> | I<UNIX RULE> | I<FILE RULE> | I<LINK RULE> | I<CHANGE_PROFILE RULE> | I<RLIMIT RULE> | I<DBUS RULE> )
|
||||
|
||||
B<BLOCK RULES> = ( I<SUBPROFILE> | I<HAT> | I<QUALIFIER BLOCK> )
|
||||
|
||||
@@ -257,12 +263,6 @@ B<EXEC TARGET> = name (requires I<EXEC TRANSITION> specified)
|
||||
|
||||
B<LINK RULE> = I<QUALIFIERS> [ 'owner' ] 'link' [ 'subset' ] I<FILEGLOB> ( 'to' | '-E<gt>' ) I<FILEGLOB>
|
||||
|
||||
B<VARIABLE> = '@{' I<ALPHA> [ ( I<ALPHANUMERIC> | '_' ) ... ] '}'
|
||||
|
||||
B<VARIABLE ASSIGNMENT> = I<VARIABLE> ('=' | '+=') (space separated values)
|
||||
|
||||
B<ALIAS RULE> = I<ABS PATH> '-E<gt>' I<REWRITTEN ABS PATH>
|
||||
|
||||
B<ALPHA> = ('a', 'b', 'c', ... 'z', 'A', 'B', ... 'Z')
|
||||
|
||||
B<ALPHANUMERIC> = ('0', '1', '2', ... '9', 'a', 'b', 'c', ... 'z', 'A', 'B', ... 'Z')
|
||||
@@ -1234,7 +1234,8 @@ must be made before the start of the profile.
|
||||
|
||||
The parser will automatically expand variables to include all values
|
||||
that they have been assigned; it is an error to reference a variable
|
||||
without setting at least one value.
|
||||
without setting at least one value. You can use empty quotes ("") to
|
||||
explicitly add an empty value.
|
||||
|
||||
At the time of this writing, the following variables are defined in the
|
||||
provided AppArmor policy:
|
||||
|
@@ -288,7 +288,7 @@ it so that policy can't complete compilation due to size constraints
|
||||
take days or longer to compile).
|
||||
|
||||
Note: The parser is set to use a balanced default set of flags, that
|
||||
will result in resonable compression but not take excessive amounts
|
||||
will result in reasonable compression but not take excessive amounts
|
||||
of time to complete.
|
||||
|
||||
Use --help=optimize to see a full list of which optimization flags are
|
||||
|
@@ -21,9 +21,10 @@
|
||||
owner /{,var/}run/lightdm/authority/[0-9]* r,
|
||||
owner /{,var/}run/lightdm/*/xauthority r,
|
||||
owner /{,var/}run/user/*/gdm/Xauthority r,
|
||||
owner /{,var/}run/user/*/X11/Xauthority r,
|
||||
|
||||
# the unix socket to use to connect to the display
|
||||
/tmp/.X11-unix/* w,
|
||||
/tmp/.X11-unix/* rw,
|
||||
unix (connect, receive, send)
|
||||
type=stream
|
||||
peer=(addr="@/tmp/.X11-unix/X[0-9]*"),
|
||||
|
@@ -47,6 +47,7 @@
|
||||
# ld.so.cache and ld are used to load shared libraries; they are best
|
||||
# available everywhere
|
||||
/etc/ld.so.cache mr,
|
||||
/etc/ld.so.preload r,
|
||||
/lib{,32,64}/ld{,32,64}-*.so mrix,
|
||||
/lib{,32,64}/**/ld{,32,64}-*.so mrix,
|
||||
/lib/@{multiarch}/ld{,32,64}-*.so mrix,
|
||||
|
@@ -17,6 +17,9 @@
|
||||
type=stream
|
||||
peer=(addr="@/tmp/dbus-*"),
|
||||
|
||||
# dbus with systemd and --enable-user-session
|
||||
owner /run/user/[0-9]*/bus rw,
|
||||
|
||||
dbus send
|
||||
bus=session
|
||||
path=/org/freedesktop/DBus
|
||||
|
@@ -15,12 +15,15 @@
|
||||
#include <abstractions/freedesktop.org>
|
||||
#include <abstractions/xdg-desktop>
|
||||
#include <abstractions/user-tmp>
|
||||
#include <abstractions/wayland>
|
||||
|
||||
# systemwide gtk defaults
|
||||
/etc/gnome/gtkrc* r,
|
||||
/etc/gtk/* r,
|
||||
/usr/lib{,32,64}/gtk/** mr,
|
||||
/usr/lib/@{multiarch}/gtk/** mr,
|
||||
/usr/lib{,32,64}/gtk-[0-9]*/** mr,
|
||||
/usr/lib/@{multiarch}/gtk-[0-9]*/** mr,
|
||||
/usr/share/themes/ r,
|
||||
/usr/share/themes/** r,
|
||||
|
||||
|
@@ -33,14 +33,10 @@
|
||||
/var/lib/sss/pipes/nss rw,
|
||||
|
||||
/etc/resolv.conf r,
|
||||
# on systems using resolvconf, /etc/resolv.conf is a symlink to
|
||||
# /{,var/}run/resolvconf/resolv.conf and a file sometimes referenced in
|
||||
# /etc/resolvconf/run/resolv.conf
|
||||
/{,var/}run/resolvconf/resolv.conf r,
|
||||
# On systems where /etc/resolv.conf is managed programmatically, it is
|
||||
# a symlink to /{,var/}run/(whatever program is managing it)/resolv.conf.
|
||||
/{,var/}run/{resolvconf,NetworkManager,systemd/resolve,connman}/resolv.conf r,
|
||||
/etc/resolvconf/run/resolv.conf r,
|
||||
# on systems using systemd's networkd, /etc/resolv.conf is a symlink to
|
||||
# /run/systemd/resolve/resolv.conf
|
||||
/{,var/}run/systemd/resolve/resolv.conf r,
|
||||
|
||||
/etc/samba/lmhosts r,
|
||||
/etc/services r,
|
||||
@@ -50,7 +46,7 @@
|
||||
# to vast speed increases when working with network-based lookups.
|
||||
/{,var/}run/.nscd_socket rw,
|
||||
/{,var/}run/nscd/socket rw,
|
||||
/{var/db,var/cache,var/run,run}/nscd/{passwd,group,services,hosts} r,
|
||||
/{var/db,var/cache,var/lib,var/run,run}/nscd/{passwd,group,services,hosts} r,
|
||||
# nscd renames and unlinks files in it's operation that clients will
|
||||
# have open
|
||||
/{,var/}run/nscd/db* rmix,
|
||||
|
36
profiles/apparmor.d/abstractions/php
Normal file
36
profiles/apparmor.d/abstractions/php
Normal file
@@ -0,0 +1,36 @@
|
||||
# vim:syntax=apparmor
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2009-2010 Canonical Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
# shared snippets for config files
|
||||
/etc/php{,5,7}/**/ r,
|
||||
/etc/php{,5,7}/**.ini r,
|
||||
|
||||
# Xlibs
|
||||
/usr/X11R6/lib{,32,64}/lib*.so* mr,
|
||||
# php extensions
|
||||
/usr/lib{64,}/php{,5,7}/*/*.so mr,
|
||||
|
||||
# php session mmap socket
|
||||
/var/lib/php{,5,7}/session_mm_* rwlk,
|
||||
# file based session handler
|
||||
/var/lib/php{,5,7}/sess_* rwlk,
|
||||
/var/lib/php{,5,7}/sessions/* rwlk,
|
||||
|
||||
# php libraries
|
||||
/usr/share/php{,5,7}/ r,
|
||||
/usr/share/php{,5,7}/** mr,
|
||||
|
||||
# MySQL extension
|
||||
/usr/share/mysql/** r,
|
||||
|
||||
# Zend opcache
|
||||
/tmp/.ZendSem.* rwlk,
|
@@ -1,35 +1,3 @@
|
||||
# vim:syntax=apparmor
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2006 Novell/SUSE
|
||||
# Copyright (C) 2009-2010 Canonical Ltd.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
# License published by the Free Software Foundation.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
#backwards compatibility include, actual abstraction moved from php5 to php
|
||||
|
||||
# shared snippets for config files
|
||||
/etc/php5/**/ r,
|
||||
/etc/php5/**.ini r,
|
||||
|
||||
# Xlibs
|
||||
/usr/X11R6/lib{,32,64}/lib*.so* mr,
|
||||
# php extensions
|
||||
/usr/lib{64,}/php5/*/*.so mr,
|
||||
|
||||
# php5 session mmap socket
|
||||
/var/lib/php5/session_mm_* rwlk,
|
||||
# file based session handler
|
||||
/var/lib/php5/sess_* rwlk,
|
||||
|
||||
# php libraries
|
||||
/usr/share/php{,5}/ r,
|
||||
/usr/share/php{,5}/** mr,
|
||||
|
||||
# MySQL extension
|
||||
/usr/share/mysql/** r,
|
||||
|
||||
# Zend opcache
|
||||
/tmp/.ZendSem.* rwlk,
|
||||
#include <abstractions/php>
|
||||
|
@@ -10,9 +10,11 @@
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
/etc/samba/* r,
|
||||
/usr/lib*/ldb/*.so mr,
|
||||
/usr/share/samba/*.dat r,
|
||||
/usr/share/samba/codepages/{lowcase,upcase,valid}.dat r,
|
||||
/var/cache/samba/ w,
|
||||
/var/cache/samba/lck/* rwk,
|
||||
/var/lib/samba/** rwk,
|
||||
/var/log/samba/cores/ rw,
|
||||
/var/log/samba/cores/** rw,
|
||||
|
14
profiles/apparmor.d/abstractions/wayland
Normal file
14
profiles/apparmor.d/abstractions/wayland
Normal file
@@ -0,0 +1,14 @@
|
||||
# vim:syntax=apparmor
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2016 intrigeri <intrigeri@boum.org>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
owner /var/run/user/*/weston-shared-* rw,
|
||||
owner /run/user/*/wayland-[0-9]* rw,
|
||||
owner /run/user/*/{mesa,mutter,sdl,weston,xwayland}-shared-* rw,
|
@@ -5,7 +5,7 @@
|
||||
#include <abstractions/apache2-common>
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
#include <abstractions/php5>
|
||||
#include <abstractions/php>
|
||||
#include <abstractions/python>
|
||||
|
||||
/{,usr/}bin/dash ixr,
|
||||
|
@@ -18,6 +18,7 @@
|
||||
capability net_raw,
|
||||
capability setuid,
|
||||
network inet raw,
|
||||
network inet6 raw,
|
||||
|
||||
/{,usr/}bin/ping mixr,
|
||||
/etc/modules.conf r,
|
||||
|
@@ -48,6 +48,7 @@ profile syslog-ng /{usr/,}sbin/syslog-ng {
|
||||
/{usr/,}sbin/syslog-ng mr,
|
||||
/sys/devices/system/cpu/online r,
|
||||
/usr/share/syslog-ng/** r,
|
||||
/var/lib/syslog-ng/syslog-ng-?????.qf rw,
|
||||
# chrooted applications
|
||||
@{CHROOT_BASE}/var/lib/*/dev/log w,
|
||||
@{CHROOT_BASE}/var/lib/syslog-ng/syslog-ng.persist* rw,
|
||||
|
@@ -38,7 +38,10 @@
|
||||
/var/tmp/smtp_* rw,
|
||||
|
||||
/{var/,}run/dovecot/auth-token-secret.dat{,.tmp} rw,
|
||||
/{var/,}run/dovecot/stats-user w,
|
||||
/{var/,}run/dovecot/stats-user rw,
|
||||
/{var/,}run/dovecot/anvil-auth-penalty rw,
|
||||
|
||||
/var/spool/postfix/private/auth w,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
#include <local/usr.lib.dovecot.auth>
|
||||
|
@@ -23,6 +23,7 @@
|
||||
/usr/bin/doveconf rix,
|
||||
/usr/lib/dovecot/config mr,
|
||||
/usr/lib/dovecot/managesieve Px,
|
||||
/usr/share/dovecot/** r,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
#include <local/usr.lib.dovecot.config>
|
||||
|
@@ -25,7 +25,14 @@
|
||||
@{DOVECOT_MAILSTORE}/** rwkl,
|
||||
|
||||
@{HOME} r, # ???
|
||||
/usr/lib/dovecot/imap mr,
|
||||
|
||||
/etc/dovecot/dovecot.conf r,
|
||||
/etc/dovecot/conf.d/ r,
|
||||
/etc/dovecot/conf.d/** r,
|
||||
|
||||
/usr/bin/doveconf rix,
|
||||
/usr/lib/dovecot/imap mrix,
|
||||
/usr/share/dovecot/** r,
|
||||
/{,var/}run/dovecot/auth-master rw,
|
||||
/{,var/}run/dovecot/mounts r,
|
||||
|
||||
|
@@ -25,6 +25,8 @@
|
||||
@{DOVECOT_MAILSTORE}/ rw,
|
||||
@{DOVECOT_MAILSTORE}/** rwkl,
|
||||
|
||||
@{HOME}/.dovecot.svbin r,
|
||||
|
||||
/proc/*/mounts r,
|
||||
/tmp/dovecot.lmtp.* rw,
|
||||
/usr/lib/dovecot/lmtp mr,
|
||||
|
@@ -11,7 +11,7 @@
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/lib/dovecot/log {
|
||||
/usr/lib/dovecot/log flags=(attach_disconnected) {
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/dovecot-common>
|
||||
|
||||
|
@@ -28,6 +28,7 @@
|
||||
capability net_bind_service,
|
||||
capability setuid,
|
||||
capability sys_chroot,
|
||||
capability sys_resource,
|
||||
|
||||
/etc/dovecot/** r,
|
||||
/etc/mtab r,
|
||||
|
@@ -20,6 +20,8 @@
|
||||
/var/{cache,lib}/samba/smb_tmp_krb5.* rw,
|
||||
/var/{cache,lib}/samba/sync.* rw,
|
||||
/var/{cache,lib}/samba/unexpected rw,
|
||||
/var/cache/samba/msg/ rw,
|
||||
/var/cache/samba/msg/* w,
|
||||
|
||||
/{,var/}run/samba/** rwk,
|
||||
|
||||
|
@@ -28,8 +28,10 @@
|
||||
/{,var/}run/nscd/ rw,
|
||||
/{,var/}run/nscd/db* rwl,
|
||||
/{,var/}run/nscd/socket wl,
|
||||
/{var/cache,var/run,run}/nscd/{passwd,group,services,hosts,netgroup} rw,
|
||||
/{var/cache,var/lib,var/run,run}/nscd/{passwd,group,services,hosts,netgroup} rw,
|
||||
/{,var/}run/{nscd/,}nscd.pid rwl,
|
||||
/var/lib/libvirt/dnsmasq/ r,
|
||||
/var/lib/libvirt/dnsmasq/*.status r,
|
||||
/var/log/nscd.log rw,
|
||||
@{PROC}/@{pid}/cmdline r,
|
||||
@{PROC}/@{pid}/fd/ r,
|
||||
|
@@ -27,6 +27,8 @@
|
||||
capability sys_time,
|
||||
capability sys_nice,
|
||||
|
||||
network unspec dgram,
|
||||
|
||||
/drift/ntp.drift rwl,
|
||||
/drift/ntp.drift.TEMP rwl,
|
||||
/etc/ntp.conf r,
|
||||
|
@@ -20,7 +20,8 @@
|
||||
network inet raw,
|
||||
network inet6 raw,
|
||||
|
||||
/usr/sbin/traceroute rmix,
|
||||
/usr/sbin/traceroute mrix,
|
||||
/usr/bin/traceroute.db mrix,
|
||||
@{PROC}/net/route r,
|
||||
|
||||
# Site-specific additions and overrides. See local/README for details.
|
||||
|
@@ -7,6 +7,7 @@
|
||||
|
||||
deny capability block_suspend,
|
||||
|
||||
capability dac_override,
|
||||
capability ipc_lock,
|
||||
capability setuid,
|
||||
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) Per Jessen <per@computer.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -14,9 +15,26 @@
|
||||
/usr/bin/mlmmj-bounce {
|
||||
#include <abstractions/base>
|
||||
|
||||
/usr/bin/mlmmj-bounce r,
|
||||
/usr/bin/mlmmj-bounce mr,
|
||||
/usr/bin/mlmmj-send Px,
|
||||
/usr/bin/mlmmj-maintd Px,
|
||||
/var/spool/mlmmj/*/subscribers.d/ r,
|
||||
/var/spool/mlmmj/*/subscribers.d/* r,
|
||||
/var/spool/mlmmj/*/subconf rwl, #
|
||||
/var/spool/mlmmj/*/subconf/* rwl,
|
||||
/var/spool/mlmmj/*/queue rwl, #
|
||||
/var/spool/mlmmj/*/queue/* rwl,
|
||||
/var/spool/mlmmj/*/bounce/ rwl,
|
||||
|
||||
/var/spool/mlmmj/*/nomailsubs.d/ r,
|
||||
/var/spool/mlmmj/*/nomailsubs.d/* r,
|
||||
/var/spool/mlmmj/*/digesters.d/ r,
|
||||
/var/spool/mlmmj/*/digesters.d/* r,
|
||||
|
||||
/var/spool/mlmmj/*/bounce/* rw,
|
||||
|
||||
/var/spool/mlmmj/*/unsubconf/* w,
|
||||
|
||||
/usr/share/mlmmj/text.skel/*/* r,
|
||||
/var/spool/mlmmj/*/control/* r,
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) Per Jessen <per@computer.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -16,21 +17,36 @@
|
||||
|
||||
capability setuid,
|
||||
|
||||
/usr/bin/mlmmj-maintd r,
|
||||
/usr/bin/mlmmj-maintd mr,
|
||||
/usr/bin/mlmmj-send Px,
|
||||
/usr/bin/mlmmj-bounce Px,
|
||||
/usr/bin/mlmmj-unsub Px,
|
||||
|
||||
/var/spool/mlmmj r,
|
||||
/var/spool/mlmmj/*/bounce r,
|
||||
/var/spool/mlmmj/ r,
|
||||
/var/spool/mlmmj/* r, #
|
||||
/var/spool/mlmmj/*/bounce/ r,
|
||||
/var/spool/mlmmj/*/bounce/* rw,
|
||||
/var/spool/mlmmj/*/index r,
|
||||
/var/spool/mlmmj/*/lastdigest rw,
|
||||
/var/spool/mlmmj/*/lastdigest rwk,
|
||||
/var/spool/mlmmj/*/maintdlog-* lrw,
|
||||
/var/spool/mlmmj/*/mlmmj-maintd.lastrun.log w,
|
||||
/var/spool/mlmmj/*/moderation r,
|
||||
/var/spool/mlmmj/*/moderation/ r,
|
||||
/var/spool/mlmmj/*/moderation/* w,
|
||||
/var/spool/mlmmj/*/archive/ r,
|
||||
/var/spool/mlmmj/*/archive/* r,
|
||||
/var/spool/mlmmj/*/control/ r,
|
||||
/var/spool/mlmmj/*/control/* r,
|
||||
/var/spool/mlmmj/*/queue r,
|
||||
/var/spool/mlmmj/*/queue/* rwl,
|
||||
/var/spool/mlmmj/*/requeue r,
|
||||
/var/spool/mlmmj/*/subconf r,
|
||||
/var/spool/mlmmj/*/unsubconf r,
|
||||
/var/spool/mlmmj/*/queue/ r,
|
||||
/var/spool/mlmmj/*/queue/** rwl,
|
||||
/var/spool/mlmmj/*/requeue/ r,
|
||||
/var/spool/mlmmj/*/requeue/* rw,
|
||||
/var/spool/mlmmj/*/requeue/*/ rw,
|
||||
/var/spool/mlmmj/*/subconf/ r,
|
||||
/var/spool/mlmmj/*/subconf/* rw,
|
||||
/var/spool/mlmmj/*/unsubconf/ r,
|
||||
/var/spool/mlmmj/*/unsubconf/* rw,
|
||||
|
||||
/usr/share/mlmmj/text.skel/*/digest r,
|
||||
/var/spool/mlmmj/*/mlmmj.operation.log rwk,
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) Per Jessen <per@computer.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -14,16 +15,32 @@
|
||||
/usr/bin/mlmmj-process {
|
||||
#include <abstractions/base>
|
||||
|
||||
/usr/bin/mlmmj-process r,
|
||||
/usr/bin/mlmmj-process mr,
|
||||
/usr/bin/mlmmj-send Px,
|
||||
/usr/bin/mlmmj-sub Px,
|
||||
/usr/bin/mlmmj-unsub Px,
|
||||
/usr/bin/mlmmj-bounce Px,
|
||||
# skeleton data
|
||||
/usr/share/mlmmj/text.skel/ r,
|
||||
/usr/share/mlmmj/text.skel/*/* r,
|
||||
|
||||
/var/spool/mlmmj/*/control/* r,
|
||||
/var/spool/mlmmj/*/text/* r,
|
||||
/var/spool/mlmmj/*/incoming/* rwl,
|
||||
/var/spool/mlmmj/*/queue/* rwl,
|
||||
/var/spool/mlmmj/*/queue/** rwl,
|
||||
/var/spool/mlmmj/*/subconf/* rwl,
|
||||
/var/spool/mlmmj/*/unsubconf/* rwl,
|
||||
/var/spool/mlmmj/*/mlmmj.operation.log rw,
|
||||
/var/spool/mlmmj/*/mlmmj.operation.log rwk,
|
||||
/var/spool/mlmmj/*/mlmmj.operation.log.rotated w,
|
||||
|
||||
/var/spool/mlmmj/*/nomailsubs.d/ r,
|
||||
/var/spool/mlmmj/*/nomailsubs.d/* r,
|
||||
/var/spool/mlmmj/*/subscribers.d/ r,
|
||||
/var/spool/mlmmj/*/subscribers.d/* r,
|
||||
/var/spool/mlmmj/*/digesters.d/ r,
|
||||
/var/spool/mlmmj/*/digesters.d/* r,
|
||||
|
||||
/var/spool/mlmmj/*/moderation/* rw,
|
||||
/etc/mlmmj/text/*/* r,
|
||||
|
||||
}
|
||||
|
22
profiles/apparmor/profiles/extras/usr.bin.mlmmj-receive
Normal file
22
profiles/apparmor/profiles/extras/usr.bin.mlmmj-receive
Normal file
@@ -0,0 +1,22 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) Per Jessen <per@computer.org>
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
# vim:syntax=apparmor
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/bin/mlmmj-receive {
|
||||
#include <abstractions/base>
|
||||
|
||||
/usr/bin/mlmmj-process Px,
|
||||
/usr/bin/mlmmj-receive mr,
|
||||
/var/spool/mlmmj/*/incoming/ rw,
|
||||
/var/spool/mlmmj/*/incoming/* rw,
|
||||
}
|
@@ -9,12 +9,17 @@
|
||||
# ------------------------------------------------------------------
|
||||
# vim:syntax=apparmor
|
||||
|
||||
|
||||
# mlmmj upstream renamed the (misspelled) mlmmj-recieve to mlmmj-receive,
|
||||
# so this profile is probably superfluous
|
||||
|
||||
|
||||
#include <tunables/global>
|
||||
|
||||
/usr/bin/mlmmj-recieve {
|
||||
#include <abstractions/base>
|
||||
|
||||
/usr/bin/mlmmj-process Px,
|
||||
/usr/bin/mlmmj-recieve r,
|
||||
/usr/bin/mlmmj-recieve mr,
|
||||
/var/spool/mlmmj/*/incoming/* w,
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) Per Jessen <per@computer.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -15,11 +16,16 @@
|
||||
#include <abstractions/base>
|
||||
#include <abstractions/nameservice>
|
||||
|
||||
/usr/bin/mlmmj-send r,
|
||||
/usr/bin/mlmmj-send mr,
|
||||
/var/spool/mlmmj/*/archive/* w,
|
||||
/var/spool/mlmmj/*/control/* r,
|
||||
/var/spool/mlmmj/*/index rw,
|
||||
/var/spool/mlmmj/*/queue/* lrw,
|
||||
/var/spool/mlmmj/*/subscribers.d r,
|
||||
/var/spool/mlmmj/*/index rwk,
|
||||
/var/spool/mlmmj/*/queue/* klrw,
|
||||
/var/spool/mlmmj/*/subscribers.d/ r,
|
||||
/var/spool/mlmmj/*/subscribers.d/* r,
|
||||
|
||||
/var/spool/mlmmj/*/digesters.d/ r,
|
||||
|
||||
/var/spool/mlmmj/*/moderation/* rwk,
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) Per Jessen <per@computer.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -17,12 +18,24 @@
|
||||
capability setuid,
|
||||
|
||||
/usr/bin/mlmmj-send Px,
|
||||
/usr/bin/mlmmj-sub r,
|
||||
/usr/bin/mlmmj-sub mr,
|
||||
/var/spool/mlmmj/*/control/ r,
|
||||
/var/spool/mlmmj/*/control/* r,
|
||||
/var/spool/mlmmj/*/queue/* w,
|
||||
/var/spool/mlmmj/*/subconf/* w,
|
||||
/var/spool/mlmmj/*/subscribers.d rw,
|
||||
/var/spool/mlmmj/*/subscribers.d/* rw,
|
||||
/var/spool/mlmmj/*/subscribers.d/.d.lock lw,
|
||||
/var/spool/mlmmj/*/queue/ rw,
|
||||
/var/spool/mlmmj/*/queue/* rw,
|
||||
/var/spool/mlmmj/*/subconf/ rw,
|
||||
/var/spool/mlmmj/*/subconf/* rw,
|
||||
/var/spool/mlmmj/*/subscribers.d/ rw,
|
||||
/var/spool/mlmmj/*/subscribers.d/* rwk,
|
||||
/var/spool/mlmmj/*/text/ r, #
|
||||
/var/spool/mlmmj/*/text/* r,
|
||||
|
||||
/usr/share/mlmmj/text.skel/*/* r,
|
||||
|
||||
/var/spool/mlmmj/*/nomailsubs.d/ rw,
|
||||
/var/spool/mlmmj/*/nomailsubs.d/* rwk,
|
||||
|
||||
/var/spool/mlmmj/*/digesters.d/ rw,
|
||||
/var/spool/mlmmj/*/digesters.d/* rwk,
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2002-2005 Novell/SUSE
|
||||
# Copyright (C) Per Jessen <per@computer.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -14,14 +15,27 @@
|
||||
/usr/bin/mlmmj-unsub {
|
||||
#include <abstractions/base>
|
||||
|
||||
/usr/bin/mlmmj-unsub r,
|
||||
/usr/bin/mlmmj-unsub mr,
|
||||
/usr/bin/mlmmj-send Px,
|
||||
/var/spool/mlmmj/*/control/ r,
|
||||
/var/spool/mlmmj/*/control/* r,
|
||||
/var/spool/mlmmj/*/text/ r,
|
||||
/var/spool/mlmmj/*/text/* r,
|
||||
/var/spool/mlmmj/*/subscribers.d r,
|
||||
/var/spool/mlmmj/*/subscribers.d/* r,
|
||||
|
||||
/var/spool/mlmmj/*/queue/ rwl,
|
||||
/var/spool/mlmmj/*/queue/* rwl,
|
||||
/var/spool/mlmmj/*/unsubconf/ rwl,
|
||||
/var/spool/mlmmj/*/unsubconf/* rwl,
|
||||
/var/spool/mlmmj/*/subscribers.d/* rwl,
|
||||
/var/spool/mlmmj/*/subscribers.d/ rw,
|
||||
/var/spool/mlmmj/*/subscribers.d/* rwk,
|
||||
|
||||
/var/spool/mlmmj/*/nomailsubs.d/ rw,
|
||||
/var/spool/mlmmj/*/nomailsubs.d/* rwk,
|
||||
|
||||
/var/spool/mlmmj/*/digesters.d/ rw,
|
||||
/var/spool/mlmmj/*/digesters.d/* rwk,
|
||||
|
||||
/usr/share/mlmmj/text.skel/*/* r,
|
||||
/etc/mlmmj/text/*/finish r,
|
||||
|
||||
}
|
||||
|
@@ -149,8 +149,7 @@ test_sysctl_proc()
|
||||
# generally we want to encourage kernels to disable it, but if it's
|
||||
# enabled we want to test against it
|
||||
settest syscall_sysctl
|
||||
res=$(${test} ro)
|
||||
if [ $? -ne 0 -a $res == "FAIL: sysctl read failed - Function not implemented" ] ; then
|
||||
if ! res="$(${test} ro 2>&1)" && [ "$res" = "FAIL: sysctl read failed - Function not implemented" ] ; then
|
||||
echo " WARNING: syscall sysctl not implemented, skipping tests ..."
|
||||
else
|
||||
test_syscall_sysctl
|
||||
|
@@ -41,6 +41,8 @@ B<aa-complain> is used to set the enforcement mode for one or more profiles to I
|
||||
In this mode security policy is not enforced but rather access violations
|
||||
are logged to the system log.
|
||||
|
||||
Note that 'deny' rules will be enforced even in complain mode.
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
If you find any bugs, please report them at
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#! /usr/bin/env python
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2014-2016 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -17,7 +18,7 @@ import re
|
||||
import os
|
||||
|
||||
import apparmor.aa
|
||||
from apparmor.aa import available_buttons, combine_name, delete_duplicates, is_known_rule, match_includes
|
||||
from apparmor.aa import available_buttons, combine_name, delete_duplicates, get_profile_filename, is_known_rule, match_includes
|
||||
import apparmor.aamode
|
||||
from apparmor.common import AppArmorException
|
||||
from apparmor.regex import re_match_include
|
||||
@@ -283,6 +284,9 @@ class Merge(object):
|
||||
if not sev_db:
|
||||
sev_db = apparmor.severity.Severity(apparmor.aa.CONFDIR + '/severity.db', _('unknown'))
|
||||
|
||||
sev_db.unload_variables()
|
||||
sev_db.load_variables(get_profile_filename(profile))
|
||||
|
||||
for hat in sorted(other.aa[profile].keys()):
|
||||
#Add the includes from the other profile to the user profile
|
||||
done = False
|
||||
|
@@ -43,13 +43,13 @@ pids = []
|
||||
if paranoid:
|
||||
pids = list(filter(lambda x: re.search(r"^\d+$", x), aa.get_subdirectories("/proc")))
|
||||
else:
|
||||
regex_tcp_udp = re.compile(r"^(tcp|udp)\s+\d+\s+\d+\s+\S+\:(\d+)\s+\S+\:(\*|\d+)\s+(LISTEN|\s+)\s+(\d+)\/(\S+)")
|
||||
regex_tcp_udp = re.compile(r"^(tcp|udp|raw)6?\s+\d+\s+\d+\s+\S+\:(\d+)\s+\S+\:(\*|\d+)\s+(LISTEN|\d+|\s+)\s+(\d+)\/(\S+)")
|
||||
import subprocess
|
||||
if sys.version_info < (3, 0):
|
||||
output = subprocess.check_output("LANG=C netstat -nlp", shell=True).split("\n")
|
||||
output = subprocess.check_output("LANG=C netstat -nlp46", shell=True).split("\n")
|
||||
else:
|
||||
#Python3 needs to translate a stream of bytes to string with specified encoding
|
||||
output = str(subprocess.check_output("LANG=C netstat -nlp", shell=True), encoding='utf8').split("\n")
|
||||
output = str(subprocess.check_output("LANG=C netstat -nlp46", shell=True), encoding='utf8').split("\n")
|
||||
|
||||
for line in output:
|
||||
match = regex_tcp_udp.search(line)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2014-2015 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2014-2016 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -364,9 +364,9 @@ def get_reqs(file):
|
||||
raise AppArmorException('Can\'t find ldd')
|
||||
|
||||
ret, ldd_out = get_output([ldd, file])
|
||||
if ret == 0:
|
||||
if ret == 0 or ret == 1:
|
||||
for line in ldd_out:
|
||||
if 'not a dynamic executable' in line:
|
||||
if 'not a dynamic executable' in line: # comes with ret == 1
|
||||
break
|
||||
if 'cannot read header' in line:
|
||||
break
|
||||
@@ -557,8 +557,11 @@ def get_profile(prof_name):
|
||||
inactive_profile[prof_name][prof_name].pop('filename')
|
||||
profile_hash[uname]['username'] = uname
|
||||
profile_hash[uname]['profile_type'] = 'INACTIVE_LOCAL'
|
||||
profile_hash[uname]['profile'] = serialize_profile(inactive_profile[prof_name], prof_name)
|
||||
profile_hash[uname]['profile'] = serialize_profile(inactive_profile[prof_name], prof_name, None)
|
||||
profile_hash[uname]['profile_data'] = inactive_profile
|
||||
|
||||
existing_profiles.pop(prof_name) # remove profile filename from list to force storing in /etc/apparmor.d/ instead of extra_profile_dir
|
||||
|
||||
# If no profiles in repo and no inactive profiles
|
||||
if not profile_hash.keys():
|
||||
return None
|
||||
@@ -579,18 +582,13 @@ def get_profile(prof_name):
|
||||
|
||||
q = aaui.PromptQuestion()
|
||||
q.headers = ['Profile', prof_name]
|
||||
q.functions = ['CMD_VIEW_PROFILE', 'CMD_USE_PROFILE', 'CMD_CREATE_PROFILE',
|
||||
'CMD_ABORT', 'CMD_FINISHED']
|
||||
q.functions = ['CMD_VIEW_PROFILE', 'CMD_USE_PROFILE', 'CMD_CREATE_PROFILE', 'CMD_ABORT']
|
||||
q.default = "CMD_VIEW_PROFILE"
|
||||
q.options = options
|
||||
q.selected = 0
|
||||
|
||||
ans = ''
|
||||
while 'CMD_USE_PROFILE' not in ans and 'CMD_CREATE_PROFILE' not in ans:
|
||||
if ans == 'CMD_FINISHED':
|
||||
save_profiles()
|
||||
return
|
||||
|
||||
ans, arg = q.promptUser()
|
||||
p = profile_hash[options[arg]]
|
||||
q.selected = options.index(options[arg])
|
||||
@@ -602,12 +600,13 @@ def get_profile(prof_name):
|
||||
'profile_type': p['profile_type']
|
||||
})
|
||||
ypath, yarg = GetDataFromYast()
|
||||
#else:
|
||||
# pager = get_pager()
|
||||
# proc = subprocess.Popen(pager, stdin=subprocess.PIPE)
|
||||
else:
|
||||
pager = get_pager()
|
||||
proc = subprocess.Popen(pager, stdin=subprocess.PIPE)
|
||||
# proc.communicate('Profile submitted by %s:\n\n%s\n\n' %
|
||||
# (options[arg], p['profile']))
|
||||
# proc.kill()
|
||||
proc.communicate(p['profile'].encode())
|
||||
proc.kill()
|
||||
elif ans == 'CMD_USE_PROFILE':
|
||||
if p['profile_type'] == 'INACTIVE_LOCAL':
|
||||
profile_data = p['profile_data']
|
||||
@@ -658,6 +657,7 @@ def autodep(bin_name, pname=''):
|
||||
if not profile_data:
|
||||
profile_data = create_new_profile(pname)
|
||||
file = get_profile_filename(pname)
|
||||
profile_data[pname][pname]['filename'] = None # will be stored in /etc/apparmor.d when saving, so it shouldn't carry the extra_profile_dir filename
|
||||
attach_profile_data(aa, profile_data)
|
||||
attach_profile_data(original_aa, profile_data)
|
||||
if os.path.isfile(profile_dir + '/tunables/global'):
|
||||
@@ -1095,7 +1095,7 @@ def handle_children(profile, hat, root):
|
||||
|
||||
seen_events += 1
|
||||
|
||||
ans = q.promptUser()
|
||||
ans = q.promptUser()[0]
|
||||
|
||||
if ans == 'CMD_FINISHED':
|
||||
save_profiles()
|
||||
@@ -1105,7 +1105,9 @@ def handle_children(profile, hat, root):
|
||||
|
||||
if ans == 'CMD_ADDHAT':
|
||||
hat = uhat
|
||||
aa[profile][hat] = profile_storage(profile, hat, 'handle_children addhat')
|
||||
aa[profile][hat]['flags'] = aa[profile][profile]['flags']
|
||||
changed[profile] = True
|
||||
elif ans == 'CMD_USEDEFAULT':
|
||||
hat = default_hat
|
||||
elif ans == 'CMD_DENY':
|
||||
@@ -1166,6 +1168,9 @@ def handle_children(profile, hat, root):
|
||||
prelog[aamode][profile][hat]['path'][path] = mode
|
||||
|
||||
if do_execute:
|
||||
if not aa[profile][hat]:
|
||||
continue # ignore log entries for non-existing profiles
|
||||
|
||||
if profile_known_exec(aa[profile][hat], 'exec', exec_target):
|
||||
continue
|
||||
|
||||
@@ -1590,6 +1595,10 @@ def ask_the_questions():
|
||||
UI_SelectUpdatedRepoProfile(profile, p)
|
||||
|
||||
found += 1
|
||||
|
||||
sev_db.unload_variables()
|
||||
sev_db.load_variables(get_profile_filename(profile))
|
||||
|
||||
# Sorted list of hats with the profile name coming first
|
||||
hats = list(filter(lambda key: key != profile, sorted(log_dict[aamode][profile].keys())))
|
||||
if log_dict[aamode][profile].get(profile, False):
|
||||
@@ -2305,7 +2314,7 @@ def save_profiles():
|
||||
reload_base(profile_name)
|
||||
|
||||
def get_pager():
|
||||
pass
|
||||
return 'less'
|
||||
|
||||
def generate_diff(oldprofile, newprofile):
|
||||
oldtemp = tempfile.NamedTemporaryFile('w')
|
||||
@@ -2504,7 +2513,7 @@ def read_inactive_profiles():
|
||||
except:
|
||||
fatal_error(_("Can't read AppArmor profiles in %s") % extra_profile_dir)
|
||||
|
||||
for file in os.listdir(profile_dir):
|
||||
for file in os.listdir(extra_profile_dir):
|
||||
if os.path.isfile(extra_profile_dir + '/' + file):
|
||||
if is_skippable_file(file):
|
||||
continue
|
||||
|
@@ -245,11 +245,12 @@ def user_perm(prof_dir):
|
||||
return False
|
||||
return True
|
||||
|
||||
if sys.version_info[0] > 2:
|
||||
unicode = str # python 3 dropped the unicode type. To keep type_is_str() simple (and pyflakes3 happy), re-create it as alias of str.
|
||||
|
||||
def type_is_str(var):
|
||||
''' returns True if the given variable is a str (or unicode string when using python 2)'''
|
||||
if type(var) == str:
|
||||
return True
|
||||
elif sys.version_info[0] < 3 and type(var) == unicode: # python 2 sometimes uses the 'unicode' type
|
||||
if type(var) in [str, unicode]: # python 2 sometimes uses the 'unicode' type
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# ----------------------------------------------------------------------
|
||||
# Copyright (C) 2013 Kshitij Gupta <kgupta8592@gmail.com>
|
||||
# Copyright (C) 2015 Christian Boltz <apparmor@cboltz.de>
|
||||
# Copyright (C) 2015-2016 Christian Boltz <apparmor@cboltz.de>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of version 2 of the GNU General Public
|
||||
@@ -43,25 +43,6 @@ class ReadLog:
|
||||
# used to pre-filter log lines so that we hand over only relevant lines to LibAppArmor parsing
|
||||
RE_LOG_ALL = re.compile('(' + '|'.join(RE_log_parts) + ')')
|
||||
|
||||
|
||||
# Used by netdomain to identify the operation types
|
||||
# New socket names
|
||||
OPERATION_TYPES = {'create': 'net',
|
||||
'post_create': 'net',
|
||||
'bind': 'net',
|
||||
'connect': 'net',
|
||||
'listen': 'net',
|
||||
'accept': 'net',
|
||||
'sendmsg': 'net',
|
||||
'recvmsg': 'net',
|
||||
'getsockname': 'net',
|
||||
'getpeername': 'net',
|
||||
'getsockopt': 'net',
|
||||
'setsockopt': 'net',
|
||||
'socket_create': 'net',
|
||||
'sock_shutdown': 'net'
|
||||
}
|
||||
|
||||
def __init__(self, pid, filename, existing_profiles, profile_dir, log):
|
||||
self.filename = filename
|
||||
self.profile_dir = profile_dir
|
||||
@@ -133,10 +114,10 @@ class ReadLog:
|
||||
ev['denied_mask'] = event.denied_mask
|
||||
ev['request_mask'] = event.requested_mask
|
||||
ev['magic_token'] = event.magic_token
|
||||
if ev['operation'] and self.op_type(ev['operation']) == 'net':
|
||||
ev['family'] = event.net_family
|
||||
ev['protocol'] = event.net_protocol
|
||||
ev['sock_type'] = event.net_sock_type
|
||||
ev['family'] = event.net_family
|
||||
ev['protocol'] = event.net_protocol
|
||||
ev['sock_type'] = event.net_sock_type
|
||||
|
||||
LibAppArmor.free_record(event)
|
||||
|
||||
if not ev['time']:
|
||||
@@ -277,18 +258,7 @@ class ReadLog:
|
||||
else:
|
||||
self.debug_logger.debug('parse_event_for_tree: dropped exec event in %s' % e['profile'])
|
||||
|
||||
elif ( e['operation'].startswith('file_') or e['operation'].startswith('inode_') or
|
||||
e['operation'] in ['open', 'truncate', 'mkdir', 'mknod', 'chmod', 'rename_src',
|
||||
'rename_dest', 'unlink', 'rmdir', 'symlink_create', 'link',
|
||||
'sysctl', 'getattr', 'setattr', 'xattr'] ):
|
||||
|
||||
# for some kernel-side reason, we get file-related log events without request_mask, see
|
||||
# https://bugs.launchpad.net/apparmor/+bug/1466812/, https://bugs.launchpad.net/apparmor/+bug/1509030 and https://bugs.launchpad.net/apparmor/+bug/1540562
|
||||
# request_mask can also be '', see https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1525119
|
||||
if not e['request_mask']:
|
||||
self.debug_logger.debug('UNHANDLED (missing request_mask): %s' % e)
|
||||
return None
|
||||
|
||||
elif self.op_type(e) == 'file':
|
||||
# Map c (create) and d (delete) to w (logging is more detailed than the profile language)
|
||||
rmask = e['request_mask']
|
||||
rmask = rmask.replace('c', 'w')
|
||||
@@ -347,7 +317,7 @@ class ReadLog:
|
||||
# self.log += [arrayref]
|
||||
# self.pid[child] = arrayref
|
||||
|
||||
elif self.op_type(e['operation']) == 'net':
|
||||
elif self.op_type(e) == 'net':
|
||||
return(e['pid'], e['parent'], 'netdomain',
|
||||
[profile, hat, prog, aamode, e['family'], e['sock_type'], e['protocol']])
|
||||
elif e['operation'] == 'change_hat':
|
||||
@@ -398,10 +368,57 @@ class ReadLog:
|
||||
self.logmark = ''
|
||||
return self.log
|
||||
|
||||
def op_type(self, operation):
|
||||
# operation types that can be network or file operations
|
||||
# (used by op_type() which checks some event details to decide)
|
||||
OP_TYPE_FILE_OR_NET = {
|
||||
# Note: op_type() also uses some startswith() checks which are not listed here!
|
||||
'create',
|
||||
'post_create',
|
||||
'bind',
|
||||
'connect',
|
||||
'listen',
|
||||
'accept',
|
||||
'sendmsg',
|
||||
'recvmsg',
|
||||
'getsockname',
|
||||
'getpeername',
|
||||
'getsockopt',
|
||||
'setsockopt',
|
||||
'socket_create',
|
||||
'sock_shutdown',
|
||||
'open',
|
||||
'truncate',
|
||||
'mkdir',
|
||||
'mknod',
|
||||
'chmod',
|
||||
'chown',
|
||||
'rename_src',
|
||||
'rename_dest',
|
||||
'unlink',
|
||||
'rmdir',
|
||||
'symlink_create',
|
||||
'link',
|
||||
'sysctl',
|
||||
'getattr',
|
||||
'setattr',
|
||||
'xattr',
|
||||
}
|
||||
|
||||
def op_type(self, event):
|
||||
"""Returns the operation type if known, unkown otherwise"""
|
||||
operation_type = self.OPERATION_TYPES.get(operation, 'unknown')
|
||||
return operation_type
|
||||
|
||||
if ( event['operation'].startswith('file_') or event['operation'].startswith('inode_') or event['operation'] in self.OP_TYPE_FILE_OR_NET ):
|
||||
# file or network event?
|
||||
if event['family'] and event['protocol'] and event['sock_type']:
|
||||
# 'unix' events also use keywords like 'connect', but protocol is 0 and should therefore be filtered out
|
||||
return 'net'
|
||||
elif event['denied_mask']:
|
||||
return 'file'
|
||||
else:
|
||||
raise AppArmorException('unknown file or network event type')
|
||||
|
||||
else:
|
||||
return 'unknown'
|
||||
|
||||
def profile_exists(self, program):
|
||||
"""Returns True if profile exists, False otherwise"""
|
||||
|
@@ -312,10 +312,13 @@ class BaseRuleset(object):
|
||||
|
||||
# delete rules that are covered by include files
|
||||
if include_rules:
|
||||
for rule in self.rules:
|
||||
if include_rules.is_covered(rule, True, True):
|
||||
self.delete(rule)
|
||||
oldrules = self.rules
|
||||
self.rules = []
|
||||
for rule in oldrules:
|
||||
if include_rules.is_covered(rule, True, False):
|
||||
deleted += 1
|
||||
else:
|
||||
self.rules.append(rule)
|
||||
|
||||
# de-duplicate rules inside the profile
|
||||
deleted += self.delete_in_profile_duplicates()
|
||||
|
@@ -27,7 +27,7 @@ _ = init_translation()
|
||||
network_domain_keywords = [ 'unspec', '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', 'can', 'tipc', 'bluetooth', 'iucv', 'rxrpc', 'isdn', 'phonet',
|
||||
'ieee802154', 'caif', 'alg', 'nfc', 'vsock', 'mpls', 'ib' ]
|
||||
'ieee802154', 'caif', 'alg', 'nfc', 'vsock', 'mpls', 'ib', 'kcm' ]
|
||||
|
||||
network_type_keywords = ['stream', 'dgram', 'seqpacket', 'rdm', 'raw', 'packet']
|
||||
network_protocol_keywords = ['tcp', 'udp', 'icmp']
|
||||
|
@@ -249,7 +249,6 @@ CMDS = {'CMD_ALLOW': _('(A)llow'),
|
||||
'CMD_EXEC_IX_ON': _('(X) ix On'),
|
||||
'CMD_EXEC_IX_OFF': _('(X) ix Off'),
|
||||
'CMD_SAVE': _('(S)ave Changes'),
|
||||
'CMD_CONTINUE': _('(C)ontinue Profiling'),
|
||||
'CMD_NEW': _('(N)ew'),
|
||||
'CMD_GLOB': _('(G)lob'),
|
||||
'CMD_GLOBEXT': _('Glob with (E)xtension'),
|
||||
@@ -278,7 +277,6 @@ CMDS = {'CMD_ALLOW': _('(A)llow'),
|
||||
'CMD_NET_FAMILY': _('Allow Network Fa(m)ily'),
|
||||
'CMD_OVERWRITE': _('(O)verwrite Profile'),
|
||||
'CMD_KEEP': _('(K)eep Profile'),
|
||||
'CMD_CONTINUE': _('(C)ontinue'),
|
||||
'CMD_IGNORE_ENTRY': _('(I)gnore')
|
||||
}
|
||||
|
||||
|
@@ -118,7 +118,10 @@ class CapabilityTest(AATest):
|
||||
'task': 0,
|
||||
'attr': None,
|
||||
'name2': None,
|
||||
'name': 'net_raw'
|
||||
'name': 'net_raw',
|
||||
'family': None,
|
||||
'protocol': None,
|
||||
'sock_type': None,
|
||||
})
|
||||
|
||||
obj = CapabilityRule(parsed_event['name'], log_event=parsed_event)
|
||||
@@ -817,7 +820,6 @@ class CapabilityDeleteTest(AATest):
|
||||
inc.add(CapabilityRule.parse(rule))
|
||||
|
||||
expected_raw = [
|
||||
' allow capability sys_admin,', # XXX huh? should be deleted!
|
||||
' deny capability chgrp, # example comment',
|
||||
'',
|
||||
]
|
||||
@@ -825,11 +827,9 @@ class CapabilityDeleteTest(AATest):
|
||||
expected_clean = [
|
||||
' deny capability chgrp, # example comment',
|
||||
'',
|
||||
' allow capability sys_admin,', # XXX huh? should be deleted!
|
||||
'',
|
||||
]
|
||||
|
||||
self.assertEqual(self.ruleset.delete_duplicates(inc), 1)
|
||||
self.assertEqual(self.ruleset.delete_duplicates(inc), 2)
|
||||
self.assertEqual(expected_raw, self.ruleset.get_raw(1))
|
||||
self.assertEqual(expected_clean, self.ruleset.get_clean(1))
|
||||
|
||||
|
@@ -85,7 +85,7 @@ class ChangeProfileTestParseInvalid(ChangeProfileTest):
|
||||
ChangeProfileRule.parse(rawrule)
|
||||
|
||||
class ChangeProfileTestParseFromLog(ChangeProfileTest):
|
||||
def test_net_from_log(self):
|
||||
def test_change_profile_from_log(self):
|
||||
parser = ReadLog('', '', '', '', '')
|
||||
|
||||
event = 'type=AVC msg=audit(1428699242.551:386): apparmor="DENIED" operation="change_profile" profile="/foo/changeprofile" pid=3459 comm="changeprofile" target="/foo/rename"'
|
||||
@@ -99,7 +99,6 @@ class ChangeProfileTestParseFromLog(ChangeProfileTest):
|
||||
'request_mask': None,
|
||||
'denied_mask': None,
|
||||
'error_code': 0,
|
||||
#'family': 'inet',
|
||||
'magic_token': 0,
|
||||
'parent': 0,
|
||||
'profile': '/foo/changeprofile',
|
||||
@@ -114,6 +113,9 @@ class ChangeProfileTestParseFromLog(ChangeProfileTest):
|
||||
'attr': None,
|
||||
'name2': '/foo/rename', # target
|
||||
'name': None,
|
||||
'family': None,
|
||||
'protocol': None,
|
||||
'sock_type': None,
|
||||
})
|
||||
|
||||
obj = ChangeProfileRule(ChangeProfileRule.ALL, parsed_event['name2'], log_event=parsed_event)
|
||||
|
@@ -84,7 +84,10 @@ class TestParseEvent(unittest.TestCase):
|
||||
'request_mask': 'r',
|
||||
'resource': 'Failed name lookup - disconnected path',
|
||||
'task': 0,
|
||||
'time': 1424425690
|
||||
'time': 1424425690,
|
||||
'family': None,
|
||||
'protocol': None,
|
||||
'sock_type': None,
|
||||
})
|
||||
|
||||
self.assertIsNotNone(ReadLog.RE_LOG_ALL.search(event))
|
||||
|
Reference in New Issue
Block a user