aa-lint
This issue aims to discuss the creation of a linter for apparmor profiles.
Ideally, it should
- Be
apparmor.dcentric: enforce security and style rules defined by this project - Be generic enough to be usable on profile outside this project. Even when
apparmor.d's abstraction & tunable are not available.
We should provide a cli tool aa-lint that use an architecture similar to existing linter in python such as yamllint.
Rules set
Open discussion of the initial list of considered of convention, style, and security checks.
Convention
Most of them are already implemented by make check, and therefore are less of a priority
- apparmor.d header & license.
- Ensure indentation: 2 spaces.
- Ensure no trailing whitespaces.
- Ensure abi version is set on profile and abstraction.
- Ensure local include is set on abstractions, profiles and subprofile.
- Ensure local include is set of the last of the abstractions, profiles or subprofile.
- Ensure vim syntax is set.
- Ensure the profile is named:
profile <filename>. - Ensure only one profile has been defined by file.
Warning
-
Check for missing
abstractions/baseabstraction -
Check for missing variable.
- Ensure that all automatic search and replace form aa-log are in effect.
-
Check for missing directory mark (variable that are directories but that are not marked as it (no dirs suffix)).
- E.g.
@{HOME}instead of@{HOME}/. - Also valid for
@{MOUNTS},@{bin},@{lib},@{tmp}and all user directories (*_dirs,*_DIR).
- E.g.
-
Check for missing profile entrypoint:
@{exec_path} mr, -
Check for rule without effect. E.g. a rule already included in an abstraction, or in another more global rule in the profile.
- Detect rule included in abstraction
- Detect abstraction included in another abstraction
-
Check for lock permission on directory:
/path/to/dir/{,**} rwlk,as it is useless. -
Check for rules too restrictive that would break on
- E.g.
/usr/share/terminfo/x/*instead of/usr/share/terminfo/**,
- E.g.
Security
-
Check for dangerous abstraction used:
user-tmp: full access to/tmp/dbus-session,dbus-system,dbus-accessibility: full access to a dbus bus.
-
Check for deprecated abstraction
nameservice->nameservice-strictbash->shellX->X-strictdbus-accessibility-strict->bus-accessibilitydbus-session-strict->bus-sessiondbus-system-strict->bus-systemdbus-network-manager-strict->bus/org.freedesktop.NetworkManager
-
Check for rule too wide on shared directory:
- E.g.
/tmp/**,/var/tmp/**,@{tmp}/**,/etc/**,/dev/shm/**,@{run}/user/@{uid}/**
- E.g.
-
Check for unrestricted profile transition:
- Such as
@{bin}/** rPx,,@{lib}/** rPx,,rUx,orrux. - Needs to be ignored when it is done on purpose.
- Such as
-
Check for missing dbus peer label in dbus rules.
-
Check for unrestricted access to
@{HOME}- E.g.
@{HOME}/** rw,,
- E.g.
-
Check for mount rule too large (not restrictive enough):
- Mounting anything requires the
sys_admincap, access to the source and mountpoint directories and the required mount rule. If the mount rule is too large (such as allowing to mount /etc inrw),sys_adminis not restricted and is equivalent to full root access. - E.g.
mount,,umount,,mount -> /new/path/**,
- Mounting anything requires the
-
Check for the use of some dangerous capabilities:
- E.g.
mac_adminif not inapparmor_parser, orapparmor.systemd - This will require either: an in-line directive (similar do shellcheck) to disable the rule or, (better) a configuration file that manages the list of dangerous capabilities in profiles: https://github.com/SELinuxProject/refpolicy/blob/main/testing/sechecker.ini
- E.g.
Related work
Special thanks to @nobody43 for they work on it (#607)