2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-09-01 14:55:10 +00:00

Compare commits

...

176 Commits

Author SHA1 Message Date
John Johansen
3ee4f9c75f Merge severity.py: bump test coverage to 100%
... by adding some new tests, and by marking two lines as "pragma: no branch" because I didn't find a testcase that doesn't let them continue with the next line.

Finally, remove severity.py from the "not 100% covered" list in test/Makefile.

Also run severity tests with the official severity.db instead of the slightly outdated copy in test/.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/737
Acked-by: John Johansen <john.johansen@canonical.com>
2021-04-14 21:23:35 +00:00
Christian Boltz
a07515bdd4 Run severity tests with official severity.db
... instead of the slightly outdated copy in test/
2021-04-14 21:37:53 +02:00
Christian Boltz
d9cb8df696 severity.py: bump test coverage to 100%
... by adding some new tests, and by marking two lines as "pragma: no
branch" because I didn't find a testcase that doesn't let them continue
with the next line.

Finally, remove severity.py from the "not 100% covered" list in
test/Makefile.
2021-04-14 21:37:01 +02:00
Steve Beattie
94b7704e56 utils: ProfileStorage - add tests with invalid type
Add tests with invalid type to ensure error handling works as expected.

Merge branch 'cboltz/cboltz-profile-storage-tests'

[Fixed conflict with prior change to utils/test/test-profile-storage.py]
Acked-by: Steve Beattie <steve@nxnw.org>
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/735
2021-04-11 16:54:43 -07:00
Steve Beattie
d270b2c3d0 utils: move and rename write_header() to ProfileStorage.get_header()
Merge branch 'cboltz-move-write_header' into 'master'

As a preparation, change change_profile_flags() to use ProfileStorage,
and replace some regex usage with startswith() to make the code easier
to read and (probably) more performant.

See the individual commits for details.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/734
Acked-by: Steve Beattie <steve@nxnw.org>
2021-04-11 22:36:59 +00:00
Christian Boltz
38c63026a4 ProfileStorage: add tests with invalid type
... to ensure error handling works as expected.
2021-04-11 21:54:36 +02:00
Christian Boltz
6a170ddaa1 Move and rename write_header() to ProfileStorage.get_header()
Also adjust the calling code to use get_header() instead of
write_header().

Finally, move the tests to test-profile-storage.py and do a few
adjustments needed by the change. Part of these adjustments is to hand
over empty params with the correct type instead of just "None".
2021-04-11 15:05:12 +02:00
Christian Boltz
4ef975fb97 change_profile_flags(): use ProfileStorage
... instead of a dict faking it.
2021-04-11 15:03:41 +02:00
Christian Boltz
9494238eec write_header(): replace regex with startswith()
... to make the code easier to read and (probably) more performant.
2021-04-11 15:03:34 +02:00
John Johansen
edf52a7531 Merge read_profile(): use actual profile name
... instead of profile_data\[profile\]\[profile\]\['name'\] which is not always correct.

Note: setting 'name' will be fixed in a later commit/MR, but don't hold your breath for it ;-)

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/733
Acked-by: John Johansen <john.johansen@canonical.com>
2021-04-08 06:53:25 +00:00
John Johansen
09dfbb97e5 Merge logparser: don't return empty AUDIT section
AUDIT events get skipped when parsing the log (they are not relevant for updating a profile), therefore stop returning an always-empty AUDIT section when reading the log.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/731
Acked-by: John Johansen <john.johansen@canonical.com>
2021-04-08 06:50:06 +00:00
Christian Boltz
f9078c4b01 read_profile(): use actual profile name
... instead of profile_data[profile][profile]['name'] which is not
always correct.

Note: setting 'name' will be fixed in a later commit, but don't hold
your breath for it ;-)
2021-04-04 14:04:48 +02:00
Steve Beattie
eb1328f18a utils: ask_conflict_mode: drop superfluous parameters
Merge branch 'cboltz-ask-conflict-mode' into 'master'
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/732
Acked-by: Steve Beattie <steve@nxnw.org>
2021-04-02 21:58:09 +00:00
Christian Boltz
f931daa771 ask_conflict_mode: drop superfluous parameters
profile and hat are not needed by this function.
2021-04-02 17:58:41 +02:00
Christian Boltz
9aa70ab710 logparser: don't return empty AUDIT section
AUDIT events get skipped when parsing the log (they are not relevant for
updating a profile), therefore stop returning an always-empty AUDIT
section when reading the log.
2021-04-02 17:37:23 +02:00
John Johansen
c734839551 profiles: dhclient: allow setting task comm name
dhclient wants to set its thread names to functional names for
introspection purposes. Eg.

$ pstree -at 3395
dhclient ens3
  ├─{isc-socket}
  ├─{isc-timer}
  └─{isc-worker0000}

When denied this can result in dhclient breaking and failing to obtain
IPv4 addresses.

Fixes: https://bugs.launchpad.net/ubuntu/+source/isc-dhcp/+bug/1918410
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2021-03-30 17:16:50 -07:00
John Johansen
c32c970d00 Merge look up python-config using AC_PATH_TOOL
Doing so adds the $ac_tool_prefix during cross compilation and will end up using the correct, architecture-dependent python-config.

This is the second and last upstreamable change from https://bugs.debian.org/984582. It looks a little simpler here, because apparmor evolved upstream compared to the Debian version. Fortunately, it got a lot simpler in the process.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/729
Acked-by: John Johansen <john.johansen@canonical.com>
2021-03-20 10:00:25 +00:00
Helmut Grohne
af4800f3b8 look up python-config using AC_PATH_TOOL
Doing so adds the $ac_tool_prefix during cross compilation and will end
up using the correct, architecture-dependent python-config.

Link: https://bugs.debian.org/984582
2021-03-20 09:42:16 +00:00
John Johansen
f17143b5c3 Merge Do not abuse AC_CHECK_FILE
AC_CHECK_FILE is meant to check for host files and therefore fails hard during cross compilation unless one supplies a cached check result. Here we want to know about the presence of a build system file though, so AC_CHECK_FILE is the wrong tool.

This is part of https://bugs.debian.org/984582.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/728
Acked-by: John Johansen <john.johansen@canonical.com>
2021-03-20 08:18:07 +00:00
Helmut Grohne
60e6847e85 Do not abuse AC_CHECK_FILE
AC_CHECK_FILE is meant to check for host files and therefore fails hard during cross compilation unless one supplies a cached check result. Here we want to know about the presence of a build system file though, so AC_CHECK_FILE is the wrong tool.
2021-03-20 05:41:48 +00:00
John Johansen
277677daf3 profiles: dhcpd: add rule for port_range
The following AppArmor denial errors are shown on startup:

Oct 25 00:52:00 xxx kernel: [  556.231990] audit: type=1400 audit(1603601520.710:32): apparmor="DENIED" operation="open" profile="/usr/sbin/dhcpd" name="/proc/sys/net/ipv4/ip_local_port_range" pid=1982 comm="dhcpd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

Oct 25 00:52:00 xxx kernel: [  556.232257] audit: type=1400 audit(1603601520.710:33): apparmor="DENIED" operation="open" profile="/usr/sbin/dhcpd" name="/proc/sys/net/ipv4/ip_local_port_range" pid=1982 comm="dhcpd" requested_mask="r" denied_mask="r" fsuid=0 ouid=0

Fixes: https://bugs.launchpad.net/bugs/1901373
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/726
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
2021-03-15 23:56:19 -07:00
John Johansen
4101d74de6 man: apparmor.7 add info about complain mode and kernel parameters
Add additional info about complain mode, its behavior, how to enable
it and add warnings about its use.

In addition add info on how to set kernel parameters on boot for
the various options that are covered.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/722
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2021-03-15 15:24:43 -07:00
Mikhail Morfikov
5ad5dd0bcb abstractions: Fix wayland abstraction for compositors based on wlroots
Apparmor provides the wayland abstraction, but it looks like it misses
some rules. For instance, there are many wayland compositors which are
based on wlroots, and it looks like that when you try to use such
compositor, all GUI apps executed in the graphical environment can't
work properly (they don't event start). They all want the following
rule:

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/143
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/725
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-15 05:54:39 -07:00
John Johansen
2852e1ecdf parser: fix filter slashes for link targets
The parser is failing to properly filter the slashes in the link name
after variable expansion. Causing match failures when multiple slashes
occur.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/153
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/723
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
2021-03-15 00:45:58 -07:00
Mikhail Morfikov
d4e0a94511 abstractions: Add missing rule in wutmp abstraction
Currently the wutmp abstraction has the following rules:
  /var/log/lastlog  rwk,
  /var/log/wtmp     wk,
  @{run}/utmp       rwk,

According to what I see in my apparmor profiles, just a few apps want
to interact with the files listed above, especially with the
/var/log/wtmp . But when the apps do this, they sometimes want the
read access to this file. An example could be the last command. Is
there any reason for not having the r in the rule?  The second thing
is the file /var/log/btmp (which isn't included in the
abstracion). Whenever I see an app, which wants to access the
/var/log/wtmp file, it also tries to interact with the /var/log/btmp
file, for instance lightdm/sddm or su . Most of the time they need
just wk permissions, but sometimes apps need also r on this file, an
example could be the lastb command, which is just a link to last.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/152
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/724
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-14 11:50:43 -07:00
John Johansen
fe477af62a libapparmor: alphasort directory traversals
Directory traversal does not have a guaranteed walk order which can
cause ordering problems on profile loads when explicit dependencies
are missing.

Combined with MR:703 this provides a userspace work around for issue
147.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/147
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/706
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
2021-03-14 07:22:59 -07:00
John Johansen
855dbd4ac8 parser: fix rule downgrade for unix rules
Rule downgrades are used to provide some confinement when a feature
is only partially supported by the kernel.

  Eg. On a kernel that doesn't support fine grained af_unix mediation
      but does support network mediation.

        unix (connect, receive, send)
              type=stream
              peer=(addr="@/tmp/.ICE-unix/[0-9]*"),

      will be downgraded to

        network unix type=stream,

Which while more permissive still provides some mediation while
allowing the appication to still function. However making the rule
a deny rule result in tightening the profile.

  Eg.
        deny unix (connect, receive, send)
              type=stream
              peer=(addr="@/tmp/.ICE-unix/[0-9]*"),

      will be downgraded to

        deny network unix type=stream,

and that deny rule will take priority over any allow rule. Which means
that if the profile also had unix allow rules they will get blocked by
the downgraded deny rule, because deny rules have a higher priority,
and the application will break. Even worse there is no way to add the
functionality back to the profile without deleting the offending deny
rule.

To fix this we drop deny rules that can't be downgraded in a way that
won't break the application.

Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1180766
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/700
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-03-14 07:16:24 -07:00
John Johansen
3f51877220 Merge Improve and simplify profile parsing in the tools
This is done by introducing a match_line_against_rule_classes() function to get of repeating code in parse_profile_data().

A side effect is a better separation of preamble and profile data, which needed changes at several places - especially include rules in the preamble were funny\[tm\].

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/719
Acked-by: John Johansen <john.johansen@canonical.com>
2021-03-14 11:59:36 +00:00
Christian Boltz
aaad284d8d Handle include rules in match_line_against_rule_classes()
This needed several changes because so far data for all includes was
stored in include[]. However, preamble data for everything else gets
stored in active_profiles (and with this commit, preamble includes also
get stored in active_profiles).

The needed changes to store preamble includes in active_profiles are:

* include_list_recursive(): add and honor in_preamble flag

* add this flag at several places calling include_list_recursive() for
  a preamble

* parse_profile_data(): call active_profiles.init_file() for all files.
  Before, empty/comment-only files weren't (indirectly) added to
  active_profiles because none of the add_$ruletype functions was
  called, which could lead to KeyErrors for comment-only preamble include
  files (prevented by the now-obsolete and removed check in
  get_all_merged_variables()).
2021-03-08 01:15:12 +01:00
Christian Boltz
3448127ca6 Also parse preamble rules with match_line_against_rule_classes()
For this, we have to hand over in_preamble, and to do a slightly
different handling for preamble and profile rules.

For adding preamble rules to ProfileList, add a add_rule() function that
accepts the rule type as parameter. This is easier than using one of the
add_$type functions depending on the rule type.

With this change, match_line_against_rule_classes() handles nearly all
rule types that have a *Rule class, with the exception of include rules
which need some additional work.
2021-03-07 21:33:36 +01:00
Christian Boltz
accc380326 Add in_preamble parameter to profile loading/parsing functions
in_preamble keeps track of the current parsing position.

It's True while parsing the preamble of a profile file, and when loading
an include file that is included in the preamble (typically tunables/*).

While inside a profile or parsing abstractions/*, it is False.

This commit only hands the information around and keeps in_preamble
updated, but it doesn't really get used yet.

Also adjust the tests to hand over the additional parameter to
parse_profile_data().
2021-03-07 21:33:36 +01:00
Christian Boltz
d442620102 Add match_line_against_rule_classes()
... to handle parsing of lines that are managed with a *Rule

This needs 'ruletypes' to also know about *Rule, not only about
*Ruleset.

Also switch over handling of most rules that live inside a profile from
parse_profile() to match_line_against_rule_classes() to make
parse_profile() more readable.

Exceptions are:
- include and abi, which can also exist in the preamble
- file rules, because they'd need to be handled later (after variable
  definitions)
2021-03-07 21:33:36 +01:00
John Johansen
089b266c03 Merge Use parse() instead of _parse() in LogprofHeaderTest
The \*LogprofHeaderTest accidently used the private `_parse()` insteaf of the official `parse()`.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/718
Acked-by: John Johansen <john.johansen@canonical.com>
2021-03-07 17:43:46 +00:00
John Johansen
55a7c89117 Merge update postfix profiles
Update postfix profiles:

* cleanup postfix profiles - /etc/postfix/\*.db is covered by abstractions/postfix-common
* postfix: allow access to \*.lmdb files in addition to \*.db files. (openSUSE Tumbleweed now uses the lmdb format by default.)
* postfix-flush and -showq: add permissions needed with latest postfix as seen on openSUSE Tumbleweed

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/717
Acked-by: John Johansen <john.johansen@canonical.com>
2021-03-07 17:28:47 +00:00
Christian Boltz
4c77f7193b Use parse() instead of _parse() in LogprofHeaderTest
The *LogprofHeaderTest accidently used the private _parse() insteaf of
the official parse().
2021-03-07 18:28:27 +01:00
John Johansen
c2718e2677 Merge Improve AARE documentation in apparmor.d manpage
... as discussed on the mailinglist

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/715
Acked-by: John Johansen <john.johansen@canonical.com>
2021-03-07 17:25:36 +00:00
John Johansen
447ce37b47 Merge loadincludes(): only load tunables and abstractions
Also split out parts of the function into loadincludes_dir() to keep the code readable.

Note: This change might affect the list of includes proposed by aa-logprof.

Also drop is_skippable_dir()

Since loadincludes() now only loads a specified list of subdirectories, we no longer need a directory blacklist.

The only possibly remaining part are .git subdirectories (for example tunables/.git or abstractions/.git). Since it's very unlikely that someone would have only a subdirectory of /etc/apparmor.d/ in git, drop that check.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/714
Acked-by: John Johansen <john.johansen@canonical.com>
2021-03-07 17:22:35 +00:00
Christian Boltz
08719eebc1 postfix-flush and -showq: add permissions needed with latest postfix
... as seen on openSUSE Tumbleweed
2021-03-07 14:33:59 +01:00
Christian Boltz
a07f30e25d postfix: allow access to *.lmdb files
... in addition to *.db files.

openSUSE Tumbleweed now uses the lmdb format by default.
2021-03-07 14:33:49 +01:00
Christian Boltz
32bd2bcec3 cleanup postfix profiles
/etc/postfix/*.db is covered by abstractions/postfix-common
2021-03-07 14:33:37 +01:00
Christian Boltz
cc2d71023b Improve AARE documentation in apparmor.d manpage
... as discussed on the mailinglist
2021-03-01 19:40:50 +01:00
Christian Boltz
d0693b09b5 Drop is_skippable_dir()
Since loadincludes() now only loads a specified list of subdirectories,
we no longer need a directory blacklist.

The only possibly remaining part are .git subdirectories (for example
tunables/.git or abstractions/.git). Since it's very unlikely that
someone would have only a subdirectory of /etc/apparmor.d/ in git, drop
that check.
2021-02-25 13:08:22 +01:00
Christian Boltz
bb5ca91e7e loadincludes(): only load tunables and abstractions
Also split out parts of the function into loadincludes_dir() to keep the
code readable.

Note: This change might affect the list of includes proposed by
aa-logprof.
2021-02-25 12:59:12 +01:00
Christian Boltz
0f21ca6173 Merge branch 'cboltz-parse-profile-start' into 'master'
split off parse_profile_start_to_storage() from parse_profile_data()

See merge request apparmor/apparmor!710

Acked-by: Steve Beattie <steve.beattie@canonical.com>
2021-02-25 11:20:52 +00:00
Christian Boltz
0f1d5fdba4 Merge branch 'cboltz-preamble-ruletypes' into 'master'
profile_list: add preamble_ruletypes

See merge request apparmor/apparmor!708

Acked-by: Steve Beattie <steve.beattie@canonical.com>
2021-02-25 11:20:04 +00:00
John Johansen
d5de9692ab Merge parser: replace dynamic_cast with is_type method
The dynamic_cast operator is slow as it needs to look at RTTI information and even does some string comparisons, especially in deep hierarchies. Profiling with callgrind showed that dynamic_cast can eat a huge portion of the running time, as it takes most of the time that is spent in the simplify_tree() function. For some complex profiles, the number of calls to dynamic_cast can be in the range of millions.

This commit replaces the use of dynamic_cast in the Node hierarchy with a method called is_type(), which returns true if the pointer can be casted to the specified type. It works by looking at an Node object field that is an integer with bits set for each type up in the hierarchy. Therefore, dynamic_cast is replaced by a simple bits operation.

In my tests, for complex profiles the improvement in speed even made running apparmor_parser with "-O no-expr-simplify" slower that when simplifying, apparently because the smaller trees obtained after the expression simplification require less calls to DFA::update_state_transitions(), and that compensates the now significantly slower time spent in simplify_tree(). This opens the door to maybe avoid "-O no-expr-simplify" in the snapd daemon, thus allowing faster run-time checks in the kernel.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/711
Acked-by: John Johansen <john.johansen@canonical.com>
2021-02-17 03:44:23 +00:00
John Johansen
b6fbe10d11 parser: fix build issue with REALLOCARRAY check
On some systems the build of the parser is spitting out

cc: fatal error: no input files
compilation terminated.

This is being caused by the REALLOCARRAY checkfailing due to cpp trying
to check for both input and output files and not correctly falling
back to stdin/stdout if infile and outfile aren't specified.

Fix this by being explicit that infile and outfile are supposed to
use stdin and stdout.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/712
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2021-02-16 04:50:34 -08:00
Alfonso Sánchez-Beato
5aab543a3b parser: replace dynamic_cast with is_type method
The dynamic_cast operator is slow as it needs to look at RTTI
information and even does some string comparisons, especially in deep
hierarchies like the one for Node. Profiling with callgrind showed
that dynamic_cast can eat a huge portion of the running time, as it
takes most of the time that is spent in the simplify_tree()
function. For some complex profiles, the number of calls to
dynamic_cast can be in the range of millions.

This commit replaces the use of dynamic_cast in the Node hierarchy
with a method called is_type(), which returns true if the pointer can
be casted to the specified type. It works by looking at a Node object
field that is an integer with bits set for each type up in the
hierarchy. Therefore, dynamic_cast is replaced by a simple bits
operation.

This change can reduce the compilation times for some profiles more
that 50%, especially in arm/arm64 arch. This opens the door to maybe
avoid "-O no-expr-simplify" in the snapd daemon, as now that option
would make the compilation slower in almost all cases.

This is the example profile used in some of my tests, with this change
the run-time is around 1/3 of what it was before on an x86 laptop:

profile "test" (attach_disconnected,mediate_deleted) {
dbus send
    bus={fcitx,session}
    path=/inputcontext_[0-9]*
    interface=org.fcitx.Fcitx.InputContext
    member="{Close,Destroy,Enable}IC"
    peer=(label=unconfined),
dbus send
    bus={fcitx,session}
    path=/inputcontext_[0-9]*
    interface=org.fcitx.Fcitx.InputContext
    member=Reset
    peer=(label=unconfined),
dbus receive
    bus=fcitx
    peer=(label=unconfined),
dbus receive
    bus=session
    interface=org.fcitx.Fcitx.*
    peer=(label=unconfined),
dbus send
    bus={fcitx,session}
    path=/inputcontext_[0-9]*
    interface=org.fcitx.Fcitx.InputContext
    member="Focus{In,Out}"
    peer=(label=unconfined),
dbus send
    bus={fcitx,session}
    path=/inputcontext_[0-9]*
    interface=org.fcitx.Fcitx.InputContext
    member="{CommitPreedit,Set*}"
    peer=(label=unconfined),
dbus send
    bus={fcitx,session}
    path=/inputcontext_[0-9]*
    interface=org.fcitx.Fcitx.InputContext
    member="{MouseEvent,ProcessKeyEvent}"
    peer=(label=unconfined),
dbus send
    bus={fcitx,session}
    path=/inputcontext_[0-9]*
    interface=org.freedesktop.DBus.Properties
    member=GetAll
    peer=(label=unconfined),
dbus (send)
    bus=session
    path=/org/a11y/bus
    interface=org.a11y.Bus
    member=GetAddress
    peer=(label=unconfined),
dbus (send)
    bus=session
    path=/org/a11y/bus
    interface=org.freedesktop.DBus.Properties
    member=Get{,All}
    peer=(label=unconfined),
dbus (receive, send)
    bus=accessibility
    path=/org/a11y/atspi/**
    peer=(label=unconfined),
dbus (send)
    bus=system
    path=/org/freedesktop/Accounts
    interface=org.freedesktop.DBus.Introspectable
    member=Introspect
    peer=(label=unconfined),
dbus (send)
    bus=system
    path=/org/freedesktop/Accounts
    interface=org.freedesktop.Accounts
    member=FindUserById
    peer=(label=unconfined),
dbus (receive, send)
    bus=system
    path=/org/freedesktop/Accounts/User[0-9]*
    interface=org.freedesktop.DBus.Properties
    member={Get,PropertiesChanged}
    peer=(label=unconfined),
dbus (send)
    bus=session
    interface=org.gtk.Actions
    member=Changed
    peer=(name=org.freedesktop.DBus, label=unconfined),
dbus (receive)
    bus=session
    interface=org.gtk.Actions
    member={Activate,DescribeAll,SetState}
    peer=(label=unconfined),
dbus (receive)
    bus=session
    interface=org.gtk.Menus
    member={Start,End}
    peer=(label=unconfined),
dbus (send)
    bus=session
    interface=org.gtk.Menus
    member=Changed
    peer=(name=org.freedesktop.DBus, label=unconfined),
dbus (send)
    bus=session
    path="/com/ubuntu/MenuRegistrar"
    interface="com.ubuntu.MenuRegistrar"
    member="{Register,Unregister}{App,Surface}Menu"
    peer=(label=unconfined),
}
2021-02-16 10:23:10 +01:00
Christian Boltz
f7a365f89f Simplify handling of in_contained_hat
in_contained_hat is needed to know if we are already in a profile or
not. (Simply checking if we are in a hat doesn't work, because something
like "profile foo//bar" will set profile and hat at once, and later
(wrongfully) expect another "}".

However, the way how this variable was set became too complicated.

To simplify the code, set in_contained_hat directly in
parse_profile_data() RE_PROFILE_START instead of returning it via
parse_profile_start() and parse_profile_start_to_storage()

Since this change removes a return value from two functions, also adjust
the tests accordingly.
2021-02-14 23:08:38 +01:00
Christian Boltz
7cfda2772d split off parse_profile_start_to_storage() from parse_profile_data()
parse_profile_start_to_storage() converts the result of
parse_profile_start() into a ProfileStorage object.

No functional change, but parse_profile_data() becomes more readable.

Also extend tests to cover parse_profile_start_to_storage().
2021-02-14 23:08:30 +01:00
John Johansen
3a87b33af7 Merge Rewrite parse_profile_start() tests to use tests[] array
No functional changes, just more readable.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/709
Acked-by: John Johansen <john.johansen@canonical.com>
2021-02-14 21:53:13 +00:00
Christian Boltz
7e5c02e3d4 Rewrite parse_profile_start() tests to use tests[] array
No functional changes, just more readable.
2021-02-14 19:26:40 +01:00
Christian Boltz
33f2b3692b Un-hardcode rule list in ProfileList delete_preamble_duplicates()
Note that before this change, boolean variable definitions were not
checked in delete_preamble_duplicates().
2021-02-14 18:26:24 +01:00
Christian Boltz
718fa5b9da profile_list: add preamble_ruletypes
... instead of keeping the list in ProfileList init_file()
2021-02-14 18:26:18 +01:00
Rose Kunkel
ee5303c8a0 Fix nscd conflict with systemd-homed
My main user account is managed by systemd-homed. When I enable
AppArmor and have nscd running, I get inconsistent behavior with my
user account - sometimes I can't log in, sometimes I can log in but
not use sudo, etc.

This is the output of getent passwd:
  $ getent passwd
  root0:0::/root:/usr/bin/zsh
  bin1:1::/:/sbin/nologin
  daemon2:2::/:/sbin/nologin
  mail8:12::/var/spool/mail:/sbin/nologin
  ftp14:11::/srv/ftp:/sbin/nologin
  http33:33::/srv/http:/sbin/nologin
  nobody65534:65534:Nobody:/:/sbin/nologin
  dbus81:81:System Message Bus:/:/sbin/nologin
  [...]
  rose1000:1000:Rose Kunkel:/home/rose:/usr/bin/zsh

But getent passwd rose and getent passwd 1000 both return no output.
Stopping nscd.service fixes these problems. Checking the apparmor
logs, I noticed that nscd was denied access to
/etc/machine-id. Allowing access to that file seems to have fixed the
issue.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/707
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/145
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-02-11 22:53:07 -08:00
Seth Arnold
656f2103ed profiles: firefox Add support for widevine DRM
Ubuntu 18.04, Firefox 60.0.1+build2-0ubuntu0.18.04.1

Running firefix, then going to netflix.com and attempting to play a
movie. The widevinecdm plugin crashes, the following is found in
syslog:

Jun 15 19:13:22 xplt kernel: [301351.553043] audit: type=1400 audit(1529046802.585:246): apparmor="DENIED" operation="file_mmap" profile="/usr/lib/firefox/firefox{,*[^s][^h]}" name="/home/xav/.mozilla/firefox/wiavokxk.default-1510977878171/gmp-widevinecdm/1.4.8.1008/libwidevinecdm.so" pid=16118 comm="plugin-containe" requested_mask="m" denied_mask="m" fsuid=1000 ouid=1000
Jun 15 19:13:22 xplt kernel: [301351.553236] audit: type=1400 audit(1529046802.585:247): apparmor="DENIED" operation="ptrace" profile="/usr/lib/firefox/firefox{,*[^s][^h]}" pid=24714 comm="firefox" requested_mask="trace" denied_mask="trace" peer="/usr/lib/firefox/firefox{,*[^s][^h]}"
Jun 15 19:13:22 xplt kernel: [301351.553259] plugin-containe[16118]: segfault at 0 ip 00007fcdfdaa76af sp 00007ffc1ff03e28 error 6 in libxul.so[7fcdfb77a000+6111000]
Jun 15 19:13:22 xplt snmpd[2334]: error on subcontainer 'ia_addr' insert
...

Fixes: https://bugs.launchpad.net/ubuntu/+source/firefox/+bug/1777070
Reported-by: Xav Paice <xav.paice@canonical.com>
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/684
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
2021-02-11 19:38:57 -08:00
John Johansen
681c976550 parser: fixup "fix --jobs so jobs scaling is applied correctly"
65ba20b955 provides a fix for job
scaling but during a merge conflict part of the patch got dropped.
This is the missing portion of the patch that was approved as part
of MR703

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/703
Signed-off-by: John Johansen <john.johansen@canonical.com>
2021-02-10 19:24:43 -08:00
John Johansen
65ba20b955 parser: fix --jobs so job scaling is applied correctly
job scaling allows the parser to resample the number of cpus available
and increase the number of jobs that can be launched if cpu available
increases.

Unfortunately job scaling was being applied even when a fixed number
of jobs was specified. So
  --jobs=2

doesn't actually clamp the compile at 2 jobs.

Instead job scaling should only be applied when --jobs=auto or when
jobs are set to a multiple of the cpus.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/703
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
2021-02-10 19:06:26 -08:00
John Johansen
136502acd9 parser: enable the parser to do some rough tuning based on memory and cpu
The parsers default settings can OOM smaller special use systems
when building or loading policy. Use basic memory info and cpus to
tune the parser for lower resource environments.

Currently this just sets the jobs parameters if the default values
haven't been modified by user config or parameters. But in the
future this could add cache control and compile parameters.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/702
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
2021-02-10 18:51:39 -08:00
John Johansen
d50262cf2c parser: fix warning for rule not enforced
If af_unix rules are not supported but network rules are and
--warn=rule-downgraded is not set then the parser will incorrectly
output warning when the rule is actually being downgraded.

  Warning from profile test-profile (./prof): extended network unix socket rules not enforced

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/699
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/144
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
2021-02-10 18:48:28 -08:00
John Johansen
a83f5d7a85 Merge Update profile usr.sbin.ntpd and abstractions/ssl_certs
* abstractions/ssl_certs
  * On Arch Linux certificates are extracted to `/etc/ca-certificates/` by the [update-ca-trust](https://github.com/archlinux/svntogit-packages/blob/packages/ca-certificates/trunk/update-ca-trust) script.
  * `/etc/libressl/` is used by Arch Linux's [libressl](https://archlinux.org/packages/community/x86_64/libressl/) package.
* usr.sbin.ntpd:
  * Add `abstractions/ssl_certs`. OpenNTPD requires access to CA certificates when using the HTTPS constraint feature.

PR: https://gitlab.com/apparmor/apparmor/-/merge_requests/698
Acked-by: John Johansen <john.johansen@canonical.com>
2021-02-08 11:17:38 +00:00
John Johansen
1bd0d8f2ff Merge Add make coverage-regression
... to find regressions or improvements in the python code coverage.

`make coverage-regression` will error out if a file looses its 100% coverage, or if a file improved to 100% coverage.

Other coverage changes (for example 45% -> 47%) will be ignored.

PR: https://gitlab.com/apparmor/apparmor/-/merge_requests/697
Acked-by: John Johansen <john.johansen@canonical.com>
2021-02-08 11:13:56 +00:00
Steve Beattie
15e897cad0 profiles: add new deny path for kwallet (used in KDE 5)
Acked-by: Steve Beattie <steve@nxnw.org>
Merge branch 'cboltz-kwallet-path' into 'master'
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/704
2021-02-08 05:55:31 +00:00
Steve Beattie
0ee0b9a9e8 parser: drop unused extern int debug_cache
The external reference definitions appear to have been overlooked
in `(f5c4927c) parser: convert remaining pwarn() to flag controlled warns`

Acked-by: Steve Beattie <steve@nxnw.org>
Merge branch 'cboltz-unused-debug-cache' into 'master'
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/705
2021-02-07 22:49:32 +00:00
Christian Boltz
7bd1f48799 drop unused extern int debug_cache
Reported by arekmx on IRC.
2021-02-07 16:02:20 +01:00
Christian Boltz
f1c53e125f add new path for kwallet (used in KDE 5)
Reported on IRC by finalspacevoid
2021-02-07 14:19:46 +01:00
nl6720
c5ef2d2f9e usr.sbin.ntpd: add abstractions/ssl_certs
openntpd requires access to CA certificates when using the HTTPS constraint feature.
2021-01-28 08:50:25 +02:00
nl6720
63bcad086f abstractions/ssl_certs: add /etc/ca-certificates/ and /etc/libressl/
- On Arch Linux certificates are extracted to /etc/ca-certificates/ by the update-ca-trust script.
- /etc/libressl/ is used by Arch Linux's libressl package.
- Combine rules to reduce number of lines.
2021-01-28 08:50:25 +02:00
John Johansen
cb65ab92d0 Merge fix setting proc_attr_base
There is currently a case in which proc_attr_base won't get set when asprintf is able to generate the path, but the file doesn't exist, it will exit proc_attr_base_init_once() without proc_attr_base having been set as the fall-through if/else logic will get bypassed when asprintf is successful.

Without this fix, various commands like aa-status will not properly display which processes have an apparmor profile enforced because it proc_attr_base will always be NULL and therefore the proc attr path won't be able to be generated.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/701
Acked-by: John Johansen <john.johansen@canonical.com>
2021-01-22 20:46:01 +00:00
Aaron U'Ren
cc113f4820 fix setting proc_attr_base
There is currently a case in which proc_attr_base won't get set when
asprintf is able to generate the path, but the file doesn't exist, it
will exit proc_attr_base_init_once() without proc_attr_base having been
set as the fall-through if/else logic will get bypassed when asprintf is
successful.
2021-01-22 11:01:13 -06:00
Christian Boltz
e38be7b14f enable utils coverage-regression checks in CI
This also needs installing python3-coverage in the test environment.
2021-01-11 13:51:54 +01:00
Christian Boltz
69c6ac3073 Add make coverage-regression
... to find regressions or improvements in the python code coverage.

`make coverage-regression` will error out if a file looses its 100%
coverage, or if a file improved to 100% coverage.

Other coverage changes (for example 45% -> 47%) will be ignored.
2021-01-10 20:53:44 +01:00
John Johansen
d86b7acd31 Merge Enable minitools tests
To get them running in the CI,

* call them with `--configdir ./`
* skip testing `aa-unconfined` if securityfs is not available

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/696
Acked-by: John Johansen <john.johansen@canonical.com>
2021-01-10 11:43:18 +00:00
John Johansen
7e02f254a3 Merge add re_match_include_parse() test with invalid rule name
... to increase test coverity of regex.py to 100%.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/695
Acked-by: John Johansen <john.johansen@canonical.com>
2021-01-10 11:38:57 +00:00
John Johansen
cc28ebaab4 Merge Add missing test for ProfileList add_alias()
... to ensure that it errors out if a wrong parameter type is given.

This also increases the test coverage of ProfileList to 100%.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/694
Acked-by: John Johansen <john.johansen@canonical.com>
2021-01-10 11:35:03 +00:00
John Johansen
ca344a3601 Merge Add and use BooleanRule and BooleanRuleset classes to handle boolean variable definitions
Add the BooleanRule and BooleanRuleset classes, add handling of boolean variable definitions in ProfileList and adjust `parse_profile_data()` to use BooleanRule. As usual, add tests for the added code.

See the individual commits for the details.

Note that this MR is also a bugfix - the previous code in (3.0 and master) saved boolean variables at a wrong place, and they were silently lost when writing the profile.
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/693
Acked-by: John Johansen <john.johansen@canonical.com>
2021-01-10 11:33:01 +00:00
John Johansen
d7ce5f0d2e Merge branch 'cboltz-comment-fix' into 'master'
Fix comment in split_name() tests

See merge request apparmor/apparmor!692
2021-01-10 11:24:32 +00:00
Christian Boltz
2e6bdc0b64 skip testing aa-unconfined if securityfs is not available 2020-12-25 21:24:42 +01:00
Christian Boltz
8d422ff66e Test minitools with --configdir ./ 2020-12-25 21:07:18 +01:00
Christian Boltz
70bbc321db Enable minitools tests in 'make check`
... by renaming them to test-*.py
2020-12-25 20:50:44 +01:00
Christian Boltz
c3d3203a60 add re_match_include_parse() test with invalid rule name
... to increase test coverity of regex.py to 100%.
2020-12-25 19:57:20 +01:00
Christian Boltz
32b11c0375 Add missing test for ProfileList add_alias()
... to ensure that it errors out if a wrong parameter type is given.

This also increases the test coverage of ProfileList to 100%.
2020-12-25 18:48:27 +01:00
Christian Boltz
f7e6f795c3 parse_profile_data(): Use BooleanRule
... and save rules at the right place (ProfileList) where they actually
get written when writing the profile.

This is also a bugfix - the previous code saved boolean variables at a
wrong place, and they were silently lost when writing the profile.

Extend cleanprof_test.{in,out} to ensure that this doesn't break again.

Also remove boolean_bad_[2-4] from the test-parser-simple-tests.py
exception_not_raised list because these test profiles now get correctly
detected as invalid.
2020-12-25 18:03:41 +01:00
Christian Boltz
a108934091 ProfileList: add handling of boolean variable definitions
This means adding the add_boolean() function and handling boolean
variables in get_clean() and get_raw().

Also add some tests to cover the added code.
2020-12-25 18:03:38 +01:00
Christian Boltz
3f11eebc17 Add BooleanRule and BooleanRuleset
These two classes are meant to handle the definition of boolean rules
like `$foo = true`.

Also extend RE_PROFILE_BOOLEAN to provide named matches.

As usual, add tests for the new classes.
2020-12-25 18:03:33 +01:00
Christian Boltz
2cbd0d94be Fix comment in split_name() tests 2020-12-25 13:24:42 +01:00
John Johansen
20234d240e Merge apparmor.vim: add support for abi rules
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/690
Acked-by: John Johansen <john.johansen@canonical.com>
2020-12-11 22:52:39 +00:00
zt1024
c43bdf2e8b parser: don't abort profile compile if the kernel is missing caps/mask
3.0 added the ability to extract and use the kernels cap mask
to augment its internal capability list as a stop gap measure to
support new capabilities.

Unfortunately not all kernel export the cap/mask and this is causing
the policy compile to fail. If the kernel doesn't export a cp/mask
just use the internal list.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/140
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/691
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-12-11 04:01:40 -08:00
John Johansen
c2d105f81b Merge Honor global LDFLAGS when building python library
libraries/libapparmor/swig/python/Makefile.am: Add global LDFLAGS when building the python library. When only applying the custom PYTHON_LDFLAGS (which are in fact `python-config --ldflags`) distributions are unable to build the library with e.g. full RELRO.

Closes #129
PR: https://gitlab.com/apparmor/apparmor/-/merge_requests/689
Acked-by: John Johansen <john.johansen@canonical.com>
2020-12-11 11:04:48 +00:00
Christian Boltz
c421fcd38a apparmor.vim: add support for abi rules 2020-12-09 22:44:33 +01:00
David Runge
b646bbf21b Honor global LDFLAGS when building python library
libraries/libapparmor/swig/python/Makefile.am:
Add global LDFLAGS when building the python library.
When only applying the custom PYTHON_LDFLAGS (which are in fact
`python-config --ldflags`) distributions are unable to build the library
with e.g. full RELRO.

Fixes #129
Related to #138
2020-12-08 10:28:53 +01:00
John Johansen
6e5dba4f49 libapparmor: Sync library version bump done for the 3.0.1 release
Keep library version bump in sync so that dev does not fall behind
3.0.x

Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-12-02 04:16:28 -08:00
John Johansen
d26da6c42f libapparmor: fix failure in procattr accesses due to domain change
libapparmor on startup does detection of whether the new stacking
proc interfaces are available and then store a var for which interface
should be used. This avoids libapparmor needing to detect which interface
to use on each proc based api call.

Unfortunately if the domain is changed on the task via change_hat or
change_profile and the proc interface is used after the domain change
it is possible that access to the interface will be denied by policy.
This is not a problem in and of it self except policy may have been
created assuming the old interface.

Fix this by adding a fallback that tries the old interface if we
are using the new interface by default and the failure was due to
an EACCES denial (policy based).

Also refactor the code a bit so this retry is isolated to one function
instead of adding it in two places.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/131
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/681
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
2020-12-01 20:33:53 -08:00
Steve Beattie
4a7b029246 Merge branch 'codespell-fixes' into 'master'
treewide: spelling fixes identified partially by codespell

See merge request apparmor/apparmor!687
2020-12-01 20:57:34 +00:00
Steve Beattie
8782f53593 parser: spelling fixes in aare_rules.c
Adjust function and variable names to spell separator correctly. Kept
as a distinct change in case someone wants to cherrypick other fixes.

Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/687
2020-12-01 12:47:26 -08:00
Steve Beattie
05547ac8f6 treewide: spelling fix in logprof.conf and profile comments
Kept separate from other fixes because conf file changes can cause
problems for packagers.

Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/687
2020-12-01 12:47:23 -08:00
Steve Beattie
8b708d3b45 treewide: spelling/typo fixes in code strings
Fix spelling errors in code strings. Some strings are translatable.
This fixes are potentially user visible.

Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/687
2020-12-01 12:47:18 -08:00
Steve Beattie
461d9c2294 treewide: spelling/typo fixes in comments and docs
With the exception of the documentation fixes, these should all be
invisible to users.

Signed-off-by: Steve Beattie <steve.beattie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/687
2020-12-01 12:47:11 -08:00
John Johansen
7c88f02d6a aa-notify: don't crash if the logfile is not present due to rotation
If aa-notify races file rotation it may crash with a trace back to
the log file being removed before the new one is moved into place.

    Traceback (most recent call last):
       File "/usr/sbin/aa-notify", line 570, in <module>
         main()
       File "/usr/sbin/aa-notify", line 533, in main
          for message in notify_about_new_entries(logfile, args.wait):
       File "/usr/sbin/aa-notify", line 145, in notify_about_new_entries
         for event in follow_apparmor_events(logfile, wait):
       File "/usr/sbin/aa-notify", line 236, in follow_apparmor_events
         if os.stat(logfile).st_ino != log_inode:
    FileNotFoundError: [Errno 2] No such file or directory: '/var/log/audit/audit.log'

If we hit this situation sleep and then retry opening the logfile.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/130
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/688
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2020-11-30 05:19:28 -08:00
John Johansen
e0ef309542 Merge create_new_profile(): check if abstractions exist
... instead of blindly adding them to the profile, and later crash (and/or cause parser errors) because they don't exist.

Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1178527
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/683
Acked-by: John Johansen <john.johansen@canonical.com>
2020-11-28 13:19:13 +00:00
John Johansen
44aa30cf2a Merge aa-autodep: load abstractions on start
So far, aa-autodep "accidently" loaded the abstractions when parsing the existing profiles. Obviously, this only worked if there is at least one profile in the active or extra profile directory.

Without any existing profiles, aa-autodep crashed with KeyError: '/tmp/apparmor.d/abstractions/base'

Prevent this crash by explicitely loading the abstractions on start.

Fixes: https://bugzilla.opensuse.org/show_bug.cgi?id=1178527
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/682
Acked-by: John Johansen <john.johansen@canonical.com>
2020-11-28 13:10:18 +00:00
John Johansen
e5733d726d Merge Convert gen-xtrans from perl to python
The generated files are exactly the same, but the code is a bit more readable.

Additional differences:

* added test_gen_list() to verify the result of gen_list()
* null_target has a non-empty value to avoid that it gets skipped in loops as empty value
* invert_save has an additional entry for ''
* copyright header added (based on git log of gen-xtrans.pl)

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/673
Acked-by: John Johansen <john.johansen@canonical.com>
2020-11-28 13:06:17 +00:00
John Johansen
0af37358e6 Merge Add --configdir to all aa-* utils
Since this option is mostly meant for testing, it will not show up in `--help`.

`aa-notify` was the only tool that honored the `__AA_CONFDIR` env variable. Drop it in favor of the `--configdir` option.

Note: Since we now pass `confdir=` to `init_aa()` (in most cases `None`), setting the default needs to be moved inside the function.

Also use `--configdir` in the tests.

See the individual commits for details.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/670
Acked-by: John Johansen <john.johansen@canonical.com>
2020-11-28 13:02:06 +00:00
John Johansen
af0f16a3bf Merge abstractions/X: Allow (only) reading X compose cache
... (/var/cache/libx11/compose/\*), and deny any write attempts

Reported by darix, https://git.nordisch.org/darix/apparmor-profiles-nordisch/-/blob/master/apparmor.d/teams

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/685
Acked-by: John Johansen <john.johansen@canonical.com>
2020-11-17 10:05:01 +00:00
Christian Boltz
78bd811e2a abstractions/X: Allow (only) reading X compose cache
... (/var/cache/libx11/compose/*), and deny any write attempts

Reported by darix,
https://git.nordisch.org/darix/apparmor-profiles-nordisch/-/blob/master/apparmor.d/teams
2020-11-16 20:42:00 +01:00
Christian Boltz
dfd7c245cd create_new_profile(): check if abstractions exist
... instead of blindly adding them to the profile, and later crash
(and/or cause parser errors) because they don't exist.

References: https://bugzilla.opensuse.org/show_bug.cgi?id=1178527#c1 [1]
2020-11-08 15:26:51 +01:00
Christian Boltz
f6b3de7116 aa-autodep: load abstractions on start
So far, aa-autodep "accidently" loaded the abstractions when parsing the
existing profiles. Obviously, this only worked if there is at least one
profile in the active or extra profile directory.

Without any existing profiles, aa-autodep crashed with
KeyError: '/tmp/apparmor.d/abstractions/base'

Prevent this crash by explicitely loading the abstractions on start.

References: https://bugzilla.opensuse.org/show_bug.cgi?id=1178527#c1 [1]
2020-11-08 14:41:33 +01:00
John Johansen
c29357a294 Merge Fix invalid Pux (should be PUx) permissions in dhclient-script
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/676
Acked-by: John Johansen <john.johansen@canonical.com>
2020-11-01 09:43:28 +00:00
John Johansen
e57174589c Merge Fix hotkey conflict in utils de.po and id.po
This is needed to catch conflicts between uppercase and lowercase hotkeys of the same letter, as seen with `(B)enannt` and `A(b)lehnen` in the german utils translations.

Also fix conflicting hotkeys in utils de.po, id.po and sv.po.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/675
Acked-by: John Johansen <john.johansen@canonical.com>
2020-11-01 09:25:18 +00:00
Christian Boltz
7cf54f2cd8 Fix hotkey conflict in utils de.po, id.po and sv.po 2020-10-31 21:59:32 +01:00
Christian Boltz
d08d1a00a3 Fix invalid Pux (should be PUx) permissions in dhclient-script 2020-10-31 20:52:30 +01:00
Christian Boltz
07bd11390e Check hotkey conflicts case-insensitive
This is needed to catch conflicts between uppercase and lowercase
hotkeys of the same letter, as seen with `(B)enannt` and `A(b)lehnen` in
the german utils translations.
2020-10-31 20:21:29 +01:00
Christian Boltz
f3a816d6a5 use aa-notify --configdir in test-aa-notify.py 2020-10-29 21:24:15 +01:00
Christian Boltz
87eec0d62d use aa-logprof --configdir ../utils in profile testsuite
(except if USE_SYSTEM is given)

This also needs an additional parser path in utils/test/logprof.conf,
which then needs an update in test-config.py.
2020-10-29 21:24:15 +01:00
Christian Boltz
ab6e9b2de2 Add --configdir to all aa-* utils
Since this option is mostly meant for testing, it will not show up in
--help.

aa-notify was the only tool that honored the __AA_CONFDIR env variable.
It still does if --configdir is not given.

Note: Since we now pass confdir= to init_aa() (in most cases None),
setting the default needs to be moved inside the function.
2020-10-29 21:24:15 +01:00
John Johansen
53d812cfd2 Merge Update dovecot for SIGKILL and dh.pem denials
Running dovecot on Debian 10 (buster) produced these denials:

```
type=AVC msg=audit(1601314853.031:9327): apparmor="DENIED"
operation="signal" profile="dovecot" pid=21223 comm="dovecot"
requested_mask="send" denied_mask="send" signal=kill
peer="/usr/lib/dovecot/auth"

type=AVC msg=audit(1601315453.655:9369): apparmor="DENIED"
operation="signal" profile="dovecot" pid=21223 comm="dovecot"
requested_mask="send" denied_mask="send" signal=kill
peer="/usr/lib/dovecot/pop3"

type=AVC msg=audit(1602939754.145:101362): apparmor="DENIED"
operation="signal" profile="dovecot" pid=31632 comm="dovecot"
requested_mask="send" denied_mask="send" signal=kill
peer="/usr/lib/dovecot/pop3-login"
```

And:

```
type=AVC msg=audit(1603647096.369:24514): apparmor="DENIED"
operation="open" profile="dovecot" name="/usr/share/dovecot/dh.pem"
pid=28774 comm="doveconf" requested_mask="r" denied_mask="r" fsuid=0
ouid=0
```

These are fixed in respective comits.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/671
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-26 22:14:50 +00:00
Christian Boltz
6b96a9badc Convert gen-xtrans from perl to python
The generated files are exactly the same, but the code is a bit more
readable.

Additional differences:
- added test_gen_list() to verify the result of gen_list()
- null_target has a non-empty value to avoid that it gets skipped in
  loops as empty value
- invert_save has an additional entry for ''
- copyright header added (based on git log of gen-xtrans.pl)
2020-10-26 00:28:16 +01:00
Vincas Dargis
9d8e111abe dovecot: allow reading dh.pem
Dovecot is hit with this denial on Debian 10 (buster):
```
type=AVC msg=audit(1603647096.369:24514): apparmor="DENIED"
operation="open" profile="dovecot" name="/usr/share/dovecot/dh.pem"
pid=28774 comm="doveconf" requested_mask="r" denied_mask="r" fsuid=0
ouid=0
```

This results in fatal error:

```
Oct 25 19:31:36 dovecot[28774]: doveconf: Fatal: Error in configuration
file /etc/dovecot/conf.d/10-ssl.conf line 50: ssl_dh: Can't open file
/usr/share/dovecot/dh.pem: Permission denied
```

Add rule to allow reading dh.pem.
2020-10-25 19:30:10 +02:00
Vincas Dargis
2f9d172c64 dovecot: allow kill signal
Dovecot might try to kill related processes:

```
type=AVC msg=audit(1601314853.031:9327): apparmor="DENIED"
operation="signal" profile="dovecot" pid=21223 comm="dovecot"
requested_mask="send" denied_mask="send" signal=kill
peer="/usr/lib/dovecot/auth"

type=AVC msg=audit(1601315453.655:9369): apparmor="DENIED"
operation="signal" profile="dovecot" pid=21223 comm="dovecot"
requested_mask="send" denied_mask="send" signal=kill
peer="/usr/lib/dovecot/pop3"

type=AVC msg=audit(1602939754.145:101362): apparmor="DENIED"
operation="signal" profile="dovecot" pid=31632 comm="dovecot"
requested_mask="send" denied_mask="send" signal=kill
peer="/usr/lib/dovecot/pop3-login"
```
This discovered on low-power high-load machine (last resort timeout
handling?).

Update signal rule to allow SIGKILL.
2020-10-25 19:12:42 +02:00
John Johansen
11d3218519 Merge Fix typos
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/669
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-25 12:01:27 +00:00
intrigeri
d6e18b0db8 Fix typos
Spotted by Lintian.
2020-10-25 11:54:56 +00:00
intrigeri
0da70b173c apparmor_xattrs.7: fix whatis entry
Spotted by Lintian (bad-whatis-entry).
2020-10-25 11:54:47 +00:00
John Johansen
0cb35fda84 Merge profiles/apparmor.d/abstractions/X: make x11 socket writable again
Unfortunately in apparmor sockets need `rw` access. Currently x11 can only work if abstract socket is available and used instead so those restrictions won't trigger.

partially reverts c7b8368216

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/664
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-25 11:32:06 +00:00
John Johansen
24855edd11 Merge Add Fontmatrix to abstractions/fonts
[Fontmatrix](https://github.com/fontmatrix/fontmatrix) [adds \~/.Fontmatrix/Activated to fonts.conf](https://github.com/fontmatrix/fontmatrix/blob/75552e2/src/typotek.cpp#L1081-L1088). This causes programs which use [Fontconfig](https://gitlab.freedesktop.org/fontconfig/fontconfig) (directly or indirectly through libraries such as [Pango](https://pango.gnome.org/)) to include that directory in their font search path, which causes errors such as:

```
audit: type=1400 audit(1602678958.525:53): apparmor="DENIED" operation="open" profile="fr.emersion.Mako" name="/home/username/.Fontmatrix/Activated/.uuid" pid=48553 comm="mako" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
audit: type=1400 audit(1602678958.525:54): apparmor="DENIED" operation="open" profile="fr.emersion.Mako" name="/home/username/.Fontmatrix/Activated/" pid=48553 comm="mako" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
```

if the program does not explicitly include this directory in its AppArmor profile. As with other common font locations, add `~/.Fontmatrix/Activated` to the fonts abstraction for read-only access.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/657
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-25 11:24:58 +00:00
John Johansen
32d748ab0f Merge add Dovecot and other mail related profiles
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/644
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-25 11:22:24 +00:00
John Johansen
1961bb7719 Merge Adjust to support brave in ubuntu abstractions
See Bug-Ubuntu: https://launchpad.net/bugs/1889699

Fixes: https://launchpad.net/bugs/1889699
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/667
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-25 11:13:43 +00:00
John Johansen
3ff07adda5 Merge Adjust ubuntu-integration to use abstractions/exo-open
see Bug-Ubuntu: https://launchpad.net/bugs/1891338

Fixes: https://launchpad.net/bugs/1891338
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/666
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-25 11:11:39 +00:00
Christian Boltz
dbb1b900b8 Merge branch 'adjust-for-new-ICEauthority-path-in-run' into 'master'
Adjust for new ICEauthority path in /run

Bug-Ubuntu: https://launchpad.net/bugs/1881357

See merge request apparmor/apparmor!668


Acked-by: Christian Boltz <apparmor@cboltz.de> for 3.0 and master
2020-10-25 10:16:26 +00:00
Jamie Strandboge
1abe101734 Adjust for new ICEauthority path in /run
Bug-Ubuntu: https://launchpad.net/bugs/1881357
2020-10-25 09:56:34 +00:00
Francois Marier
9b30f9306d Adjust to support brave in ubuntu abstractions
Bug-Ubuntu: https://launchpad.net/bugs/1889699
2020-10-25 09:53:44 +00:00
Jamie Strandboge
9ff0bbb69e Adjust ubuntu-integration to use abstractions/exo-open
Bug-Ubuntu: https://launchpad.net/bugs/1891338
2020-10-25 09:48:25 +00:00
John Johansen
6039d1580a Merge abstractions: mesa - tightens cache location and add fallback
This tightens the cache location in @{HOME}/.cache and also adds the tmp fallback location.

Currently there are the following entries in the mesa abstraction:

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/91
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/652
Acked-by: Christian Boltz <apparmor@cboltz.de>
2020-10-25 09:14:40 +00:00
John Johansen
cfc57c08e6 Merge profiles: nscd: service fails with apparmor 3.0.0-2 on Arch Linux
After a recent upgrade of apparmor on Arch Linux the nscd systemd service fails to start. Arch Linux has /var/db/nscd and that path is missing from the profile AFAICT.

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/124
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/651
Acked-by: Christian Boltz <apparmor@cboltz.de>
2020-10-25 09:08:06 +00:00
Erick555
81867f9424 profiles/apparmor.d/abstractions/X: make x11 socket writable again
Unfortunately in apparmor sockets need rw access. Currently x11 can only work if abstract socket is available and used instead so those restrictions won't trigger. This partially reverts c7b8368216
2020-10-23 12:22:10 +00:00
John Johansen
15dc06248c utils: fix make -C profiles check-logprof fails
On arch
  make -C profiles check-logprof

fails with
  *** Checking profiles from ./apparmor.d against logprof

  ERROR: Can't find AppArmor profiles in /etc/apparmor.d
  make: *** [Makefile:113: check-logprof] Error 1
  make: Leaving directory '/build/apparmor/src/apparmor-2.13.3/profiles'

because /etc/apparmor.d/ is not available in the build environment
and aa-logprofs --dir argument, is not being passed to init_aa()
but used to update profiles_dir after the fact.

Fix this by passing profiledir as an argument to init_aa()

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/36
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/663
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2020-10-22 14:56:09 -07:00
John Johansen
8ea7630b6d aa-notify: Stop aa-notify from exit after 100s of polling
When run with the -p flag, aa-notify works fine for 100 seconds and then it exits.
I suspect that the issue arises from the following check on line 259 in utils/aa-notify
if debug_logger.debug_level <= 10 and int(time.time()) - start_time > 100:
    debug_logger.debug('Debug mode detected: aborting notification emitter after 100 seconds.')
    sys.exit(0)
together with line 301 in utils/apparmor/common.py which initializes debug_logger.debug_level to logging.DEBUG which has the numerical value 10.
A simple solution might be to just remove the check as I'm not quit sure why one would want aa-notify to exit when run in debug mode in the first place.
Alternatively, one could check against debug_logger.debugging (initialized to False) or change the initialization of debug_logger.debug_level to something else, but I don't know how that would affect other consumers of utils/apparmor/common.py.

For now just add dbugger_logger.debugging as an additional check as the
reason for timing out after 100s during debugging are unclear.

Suggested-by: vicvbcun
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/126
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/660
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Otto Kekäläinen <otto@kekalainen.net>
2020-10-21 16:59:28 -07:00
John Johansen
43eb54d13c utils: split linting with PYFLAKES into a separate target.
This a step towards addressing the linting of the utils causing
problems in a build vs dev environment. See
  https://gitlab.com/apparmor/apparmor/-/issues/121

Split off linting with PYFLAKES into its own target as a step towards
making the running of the lint checks as a configuration option.

https://gitlab.com/apparmor/apparmor/-/merge_requests/662
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2020-10-21 16:55:41 -07:00
John Johansen
38c611ed31 Merge Revert "Merge dnsmasq: Permit access to /proc/self/fd/"
This reverts merge request !628. My reason for this proposal is that commit 88c142c6 already provided this change, something I must have missed when I opened the initial merge request. This resulted in duplicate entries in the profile, something that is also potentially confusing to users or other contributors.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/659
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-19 22:22:23 +00:00
FallenWarrior2k
e0b20a4d2f Revert "Merge dnsmasq: Permit access to /proc/self/fd/"
This reverts merge request !628
2020-10-19 20:29:43 +00:00
John Johansen
89fc65592b Merge Add CAP_CHECKPOINT_RESTORE to severity.db
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/656
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-15 09:48:42 +00:00
Kevin Locke
17cb8f0418 Add Fontmatrix to abstractions/fonts
[Fontmatrix] [adds ~/.Fontmatrix/Activated to fonts.conf].  This causes
programs which use [Fontconfig] (directly or indirectly through
libraries such as [pango]) to include that directory in their font
search path, which causes errors such as:

    audit: type=1400 audit(1602678958.525:53): apparmor="DENIED" operation="open" profile="fr.emersion.Mako" name="/home/username/.Fontmatrix/Activated/.uuid" pid=48553 comm="mako" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000
    audit: type=1400 audit(1602678958.525:54): apparmor="DENIED" operation="open" profile="fr.emersion.Mako" name="/home/username/.Fontmatrix/Activated/" pid=48553 comm="mako" requested_mask="r" denied_mask="r" fsuid=1000 ouid=1000

if the program does not explicitly include this directory in its
AppArmor profile.  As with other common font locations, add
~/.Fontmatrix/Activated to the fonts abstraction for read-only access.

[Fontconfig]: https://gitlab.freedesktop.org/fontconfig/fontconfig
[Fontmatrix]: https://github.com/fontmatrix/fontmatrix
[Pango]: https://pango.gnome.org/
[adds ~/.Fontmatrix/Activated to fonts.conf]: https://github.com/fontmatrix/fontmatrix/blob/75552e2/src/typotek.cpp#L1081-L1088

Signed-off-by: Kevin Locke <kevin@kevinlocke.name>
2020-10-14 19:45:23 -06:00
Christian Boltz
2c2dbdc3a3 Add CAP_CHECKPOINT_RESTORE to severity.db 2020-10-14 14:01:55 +02:00
John Johansen
4a226637f5 translations: update generated pot files
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-10-14 03:56:38 -07:00
John Johansen
644a473971 parser: Add support for CAP_CHECKPOINT_RESTORE
Linux 5.9 added CAP_CHECKPOINT_RESTORE add it to the set of supported
capabilities.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/654
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2020-10-13 21:30:19 -07:00
John Johansen
71a51fcb18 Merge regression test: Fix regression tests when using in tree parser
When using the in tree parser we should not be using the system parser.conf file, as if the system apparmor is newer than the tree being tested the parser.conf file could contain options not understood by the in tree apparmor_parser.

Use --config-file to specify the default in tree parser.conf

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/653
Acked-by: Steve Beattie <steve.beattie@canonical.com>
2020-10-13 12:01:22 +00:00
John Johansen
1033e19171 regression tests: fix aa_policy_cache to use correct config file
The aa_policy_cache test is using the system parser.conf file even
when the tests are set to use source. This can lead to failures
if the system parser.conf contain options not understood by
the source parser.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/653
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-10-13 04:49:59 -07:00
John Johansen
5ac368bce7 regression test: Fix regression tests when using in tree parser
When using the in tree parser we should not be using the system
parser.conf file, as if the system apparmor is newer than the
tree being tested the parser.conf file could contain options not
understood by the in tree apparmor_parser.

Use --config-file to specify the default in tree parser.conf

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/653
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-10-13 04:48:15 -07:00
Mikhail Morfikov
5aa6db68e0 abstractions: mesa - tightens cache location and add fallback
This tightens the cache location in @{HOME}/.cache and also adds
the tmp fallback location.

Currently there are the following entries in the mesa abstraction:

Fixes: https://gitlab.com/apparmor/apparmor/-/issues/91
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-10-11 05:08:32 -07:00
glitsj16
821f9fe42d profiles: nscd: service fails with apparmor 3.0.0-2 on Arch Linux
After a recent upgrade of apparmor on Arch Linux the nscd systemd service fails to start. Arch Linux has /var/db/nscd and that path is missing from the profile AFAICT.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/651
Fixes: https://gitlab.com/apparmor/apparmor/-/issues/124
Signed-off-by: John Johansen <john.johansen@canonical.com>
2020-10-11 04:50:49 -07:00
John Johansen
40b7019d72 Merge Fix wording of some warnings
pwarn() prints "Warning" itsself, therefore it doesn't make sense to include/repeat that word in the actual warning text.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/650
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-11 11:34:29 +00:00
John Johansen
21060e802a parser: Fix warning message when complain mode is forced
when a profile is being forced to complain a variation of the
following message is displayed

  Warning from /etc/apparmor.d/usr.sbin.sssd (/etc/apparmor.d/usr.sbin.sssd line 54): Warning failed to create cache: usr.sbin.sssd

This is incorrect in that the parser doesn't even try to create the
cache, it just can't cache force complain profiles.

Output a warning message for this case that is correct.

Fixes: https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/1899218
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/649
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Steve Beattie <steve.beattie@canonical.com>
Acked-by: Christian Boltz <apparmor@cboltz.de>
2020-10-11 03:34:37 -07:00
Christian Boltz
01f5954b5c Fix wording of some warnings
pwarn() prints "Warning" itsself, therefore it doesn't make sense to
include/repeat that word in the actual warning text.
2020-10-11 12:22:23 +02:00
John Johansen
ec19ff9f72 parser: fix parser.conf commenting on pinning an abi
The comments describing the example rules to pin the abi are wrong.
The comments of the two example rules are swapped resulting in confusion.

While we are at it. Add a reference to the wiki doc on abi, and
how to disable abi warnings without pinning.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/648
Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
2020-10-09 13:25:49 -07:00
John Johansen
042a75a6a5 Merge Fix dhclient and dhclient-script profiles to work on debian buster
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/645
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-08 06:33:08 +00:00
John Johansen
05acf374b1 Merge aa_status: Fix build issue with musl
add limits.h

aa_status.c:269:22: error: 'PATH_MAX' undeclared (first use in this function); did you mean 'AF_MAX'? | 269 | real_exe = calloc(PATH_MAX + 1, sizeof(char));

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/647
Signed-off-by: Armin Kuster [akuster808@gmail.com](mailto:akuster808@gmail.com)
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-08 06:31:02 +00:00
Armin Kuster
0dbcbee700 parser/Makefile: dont force host cpp to detect reallocarray
In cross build environments, using the hosts cpp gives incorrect
detection of reallocarray. Change cpp to a variable.

fixes:
parser_misc.c: In function 'int capable_add_cap(const char*, int, unsigned int, capability_flags)':
| parser_misc.c:297:37: error: 'reallocarray' was not declared in this scope
|   297 |   tmp = (struct capability_table *) reallocarray(cap_table, sizeof(struct capability_table), cap_table_size+1);

Signed-off-by: Armin Kuster <akuster808@gmail.com>
2020-10-07 20:55:52 -07:00
Bernhard M. Wiedemann
bd1e22ad07 profiles: add pyzorsocket and razorsocket
Signed-off-by: Bernhard M. Wiedemann <bwiedemann@suse.de>
2020-10-07 20:26:01 +02:00
Bernhard M. Wiedemann
c343f052c0 profiles: add haproxy
Signed-off-by: Bernhard M. Wiedemann <bwiedemann@suse.de>
2020-10-07 20:26:01 +02:00
Bernhard M. Wiedemann
2eea414c68 profiles: add clamd
Signed-off-by: Bernhard M. Wiedemann <bwiedemann@suse.de>
2020-10-07 20:26:01 +02:00
Bernhard M. Wiedemann
8319bc5dc7 profiles: Add 3 more dovecot services
Signed-off-by: Bernhard M. Wiedemann <bwiedemann@suse.de>
2020-10-07 20:26:01 +02:00
Bernhard M. Wiedemann
286f071259 profile: Allow SSL access to freshclam
Signed-off-by: Bernhard M. Wiedemann <bwiedemann@suse.de>
2020-10-07 20:12:45 +02:00
Bernhard M. Wiedemann
6e908f28d6 profiles: Drop duplicate line
already covered by dovecot-common

Signed-off-by: Bernhard M. Wiedemann <bwiedemann@suse.de>
2020-10-07 20:12:45 +02:00
Armin Kuster
a2a0d14b9c aa_status: Fix build issue with musl
add limits.h

aa_status.c:269:22: error: 'PATH_MAX' undeclared (first use in this function); did you mean 'AF_MAX'?
|   269 |    real_exe = calloc(PATH_MAX + 1, sizeof(char));

Signed-off-by: Armin Kuster <akuster808@gmail.com>
2020-10-07 09:10:43 -07:00
Christian Boltz
17c55b3bf8 Merge branch 'master' into 'master'
apparmor: fix manpage order

See merge request apparmor/apparmor!646

Acked-by: Christian Boltz <apparmor@cboltz.de>
2020-10-07 15:48:28 +00:00
Armin Kuster
37b9028499 apparmor: fix manpage order
It trys to create a symlink before the man pages are installed.

 ln -sf aa-status.8 /(path}/apparmor/3.0-r0/image/usr/share/man/man8/apparmor_status.8
 | ln: failed to create symbolic link '{path}/apparmor/3.0-r0/image/usr/share/man/man8/apparmor_status.8': No such file or directory

...

install -d /{path}/apparmor/3.0-r0/image/usr/share/man/man8 ; install -m 644 aa-status.8 /{path}/apparmor/3.0-r0/image/usr/share/man/man8;

Signed-off-by: Armin Kuster <akuster808@gmail.com>
2020-10-07 06:30:33 -07:00
Anton Nesterov
9b70ef4fb7 Fix dhclient and dhclient-script profiles to work on debian buster 2020-10-06 19:51:07 +00:00
John Johansen
6e7d1b6baa Merge Skip test if it can not access /var/log/wtmp
utils/test/test-aa-notify.py: Change `AANotifyTest.test_entries_since_login()` to be decorated by a `skipUnless()` checking for existence of **/var/log/wtmp** (similar to `AANotifyTest.test_entries_since_login_verbose()`). The test otherwise fails trying to access /var/log/wtmp in environments where the file is not available.

Closes https://gitlab.com/apparmor/apparmor/-/issues/120
MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/641
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-05 00:01:22 +00:00
John Johansen
1909561150 Merge Test for full parser error messages, not parts
By using assertIn, we test if a given message is contained in the parser error message. This can (and actually does) hide errors if the error message changes outside the checked part.

Change the test to assertEqual to test the full error message, and add '\\n' to all expected error messages to make them still match.

Note: test_modefail() has an outdated error message which went unnoticed so far, and should cause the (updated) tests to fail.

I'll add another commit that adjusts the expected test_modefail() error message as soon as we have an official test failure.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/632
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-04 23:58:52 +00:00
Christian Boltz
3f752fac5f Ensure empty stderr if no errors are expected
... instead of not checking stderr if it's expected to be empty.
2020-10-04 19:51:54 +02:00
Christian Boltz
37552669d4 Test for full parser error messages, not parts
By using assertIn, we test if a given message is contained in the parser
error message. This can (and actually does) hide errors if the error
message changes outside the checked part.

Change the test to assertEqual to test the full error message, and add
'\n' to all expected error messages to make them still match.

Depending on the kernel version and patches, there can be an additional
message
    Cache read/write disabled: interface file missing. (Kernel needs AppArmor 2.4 compatibility patch.)
which will be ignored by the check.
2020-10-04 19:51:54 +02:00
John Johansen
e6e54dc9e7 Merge libapparmor: add missing include for socklen_t
While `include/sys/apparmor.h` makes use of `socklen_t`, it doesn't include the `<sys/socket.h>` header to make its declaration available. While this works on systems using glibc via transitive includes, it breaks compilation on musl libc.

Fix the issue by including the header.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/642
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-03 20:15:17 +00:00
John Johansen
4a89067c1a Merge Symbol visibility
This fixes two issues with symbol visibility that's exposed when linking `apparmor_parser`.

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/643
Acked-by: John Johansen <john.johansen@canonical.com>
2020-10-03 19:21:15 +00:00
Patrick Steinhardt
9a8fee6bf1 libapparmor: add _aa_asprintf to private symbols
While `_aa_asprintf` is supposed to be of private visibility, it's used
by apparmor_parser and thus required to be visible when linking. This
commit thus adds it to the list of private symbols to make it available
for linking in apparmor_parser.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
2020-10-03 21:08:41 +02:00
Patrick Steinhardt
c9255a0343 libapparmor: add aa_features_new_from_file to public symbols
With AppArmor release 3.0, a new function `aa_features_new_from_file`
was added, but not added to the list of public symbols. As a result,
it's not possible to make use of this function when linking against
libapparmor.so.

Fix the issue by adding it to the symbol map.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
2020-10-03 21:08:37 +02:00
Patrick Steinhardt
47263a3a74 libapparmor: add missing include for socklen_t
While `include/sys/apparmor.h` makes use of `socklen_t`, it doesn't
include the `<sys/socket.h>` header to make its declaration available.
While this works on systems using glibc via transitive includes, it
breaks compilation on musl libc.

Fix the issue by including the header.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
2020-10-03 20:42:51 +02:00
David Runge
e0200b1b16 Skip test if it can not access /var/log/wtmp
utils/test/test-aa-notify.py:
Change `AANotifyTest.test_entries_since_login()` to be decorated by a
`skipUnless()` checking for existence of **/var/log/wtmp** (similar to
`AANotifyTest.test_entries_since_login_verbose()`).
The test otherwise fails trying to access /var/log/wtmp in environments
where the file is not available.

Fixes #120
2020-10-02 23:58:53 +02:00
202 changed files with 2714 additions and 1652 deletions

View File

@@ -1,7 +1,7 @@
---
image: ubuntu:latest
before_script:
- export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool perl liblocale-gettext-perl pkg-config python-all-dev python3-all-dev pyflakes3 ruby-dev swig lsb-release python3-notify2 python3-psutil zlib1g-dev
- export DEBIAN_FRONTEND=noninteractive && apt-get update -qq && apt-get install --no-install-recommends -y build-essential apache2-dev autoconf automake bison dejagnu flex libpam-dev libtool perl liblocale-gettext-perl pkg-config python-all-dev python3-all-dev pyflakes3 ruby-dev swig lsb-release python3-coverage python3-notify2 python3-psutil zlib1g-dev
- lsb_release -a
- uname -a
@@ -42,6 +42,7 @@ test-all:
- make -C parser check
- make -C binutils check
- make -C utils check
- make -C utils/test coverage-regression
- make -C changehat/mod_apparmor check
- make -C profiles check-parser
- make -C profiles check-abstractions.d

View File

@@ -156,12 +156,12 @@ install-arch: arch
install -m 755 -d ${SBINDIR}
ln -sf aa-status ${SBINDIR}/apparmor_status
install -m 755 ${SBINTOOLS} ${SBINDIR}
ln -sf aa-status.8 ${DESTDIR}/${MANDIR}/man8/apparmor_status.8
.PHONY: install-indep
install-indep: indep
$(MAKE) -C po install NAME=${NAME} DESTDIR=${DESTDIR}
$(MAKE) install_manpages DESTDIR=${DESTDIR}
ln -sf aa-status.8 ${DESTDIR}/${MANDIR}/man8/apparmor_status.8
ifndef VERBOSE
.SILENT: clean

View File

@@ -83,7 +83,7 @@ if B<aa-enabled> doesn't have enough privileges to read the apparmor control fil
=item B<10>
AppArmor is enabled but does not have access to shared LSM interaces.
AppArmor is enabled but does not have access to shared LSM interfaces.
=item B<64>

View File

@@ -32,7 +32,7 @@ B<aa-features-abi> [OPTIONS] <SOURCE> [OUTPUT OPTIONS]
B<aa-features-abi> is used to extract a features abi and output to
either stdout or a specified file. A SOURCE_OPTION must be specified.
If an output option is not specified the features abi is writen to
If an output option is not specified the features abi is written to
stdout.
=head1 OPTIONS

View File

@@ -20,7 +20,7 @@ void print_help(const char *command)
{
printf(_("%s: [options]\n"
" options:\n"
" -x | --exclusive Shared interfaces must be availabe\n"
" -x | --exclusive Shared interfaces must be available\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"),
command);

View File

@@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

View File

@@ -0,0 +1,73 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Canonical Ltd
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
"POT-Creation-Date: 2020-10-14 03:52-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../aa_enabled.c:21
#, c-format
msgid ""
"%s: [options]\n"
" options:\n"
" -x | --exclusive Shared interfaces must be available\n"
" -q | --quiet Don't print out any messages\n"
" -h | --help Print help\n"
msgstr ""
#: ../aa_enabled.c:37
#, c-format
msgid "No - not available on this system.\n"
msgstr ""
#: ../aa_enabled.c:41
#, c-format
msgid "No - disabled at boot.\n"
msgstr ""
#: ../aa_enabled.c:45
#, c-format
msgid "Maybe - policy interface not available.\n"
msgstr ""
#: ../aa_enabled.c:50
#, c-format
msgid "Maybe - insufficient permissions to determine availability.\n"
msgstr ""
#: ../aa_enabled.c:54
#, c-format
msgid "Partially - public shared interfaces are not available.\n"
msgstr ""
#: ../aa_enabled.c:58
#, c-format
msgid "Error - %s\n"
msgstr ""
#: ../aa_enabled.c:73
#, c-format
msgid "unknown or incompatible options\n"
msgstr ""
#: ../aa_enabled.c:87
#, c-format
msgid "unknown option '%s'\n"
msgstr ""
#: ../aa_enabled.c:98
#, c-format
msgid "Yes\n"
msgstr ""

55
binutils/po/aa_exec.pot Normal file
View File

@@ -0,0 +1,55 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Canonical Ltd
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
"POT-Creation-Date: 2020-10-14 03:52-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../aa_exec.c:50
#, c-format
msgid ""
"USAGE: %s [OPTIONS] <prog> <args>\n"
"\n"
"Confine <prog> with the specified PROFILE.\n"
"\n"
"OPTIONS:\n"
" -p PROFILE, --profile=PROFILE\t\tPROFILE to confine <prog> with\n"
" -n NAMESPACE, --namespace=NAMESPACE\tNAMESPACE to confine <prog> in\n"
" -d, --debug\t\t\t\tshow messages with debugging information\n"
" -i, --immediate\t\t\tchange profile immediately instead of at exec\n"
" -v, --verbose\t\t\t\tshow messages with stats\n"
" -h, --help\t\t\t\tdisplay this help\n"
"\n"
msgstr ""
#: ../aa_exec.c:65
#, c-format
msgid "[%ld] aa-exec: ERROR: "
msgstr ""
#: ../aa_exec.c:76
#, c-format
msgid "[%ld] aa-exec: DEBUG: "
msgstr ""
#: ../aa_exec.c:89
#, c-format
msgid "[%ld] "
msgstr ""
#: ../aa_exec.c:107
#, c-format
msgid "[%ld] exec"
msgstr ""

View File

@@ -0,0 +1,51 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Canonical Ltd
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
"POT-Creation-Date: 2020-10-14 03:52-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../aa_features_abi.c:53
#, c-format
msgid ""
"USAGE: %s [OPTIONS] <SOURCE> [OUTPUT OPTIONS]\n"
"\n"
"Output AppArmor feature abi from SOURCE to OUTPUT\n"
"OPTIONS:\n"
" -d, --debug show messages with debugging information\n"
" -v, --verbose show messages with stats\n"
" -h, --help display this help\n"
"SOURCE:\n"
" -f F, --file=F load features abi from file F\n"
" -x, --extract extract features abi from the kernel\n"
"OUTPUT OPTIONS:\n"
" --stdout default, write features to stdout\n"
" -w F, --write=F write features abi to the file F instead of stdout\n"
"\n"
msgstr ""
#: ../aa_features_abi.c:73
#, c-format
msgid "%s: ERROR: "
msgstr ""
#: ../aa_features_abi.c:85
#, c-format
msgid "%s: DEBUG: "
msgstr ""
#: ../aa_features_abi.c:98
msgid "\n"
msgstr ""

View File

@@ -412,7 +412,7 @@ register_hooks(unused_ apr_pool_t *p)
module AP_MODULE_DECLARE_DATA apparmor_module = {
STANDARD20_MODULE_STUFF,
aa_create_dir_config, /* dir config creater */
aa_create_dir_config, /* dir config creator */
NULL, /* dir merger --- default is to override */
/* immunix_merge_dir_config, */ /* dir merger --- default is to override */
aa_create_srv_config, /* server config */

View File

@@ -66,8 +66,8 @@ under src/jni_src.
cp dist/libJNIChangeHat.so /usr/lib
[Note: you must ensure that the target directory is passed to tomcat via the
java.library.path propert. This can be accomplished by setting the JAVA_OPTS
enviroment variable, export JAVA_OPTS=-Djava.library.path, or set via the
java.library.path property. This can be accomplished by setting the JAVA_OPTS
environment variable, export JAVA_OPTS=-Djava.library.path, or set via the
env variable LD_LIBRARY_PATH to include this directory so that tomcat can
find this library at startup]
@@ -108,13 +108,13 @@ under src/jni_src.
Once the installation steps above have been started you are ready to begin
creating a profile for your application. The profile creation tool genprof will
guide you through generating a profile and its support for change_hat will
prompt you create discrete hats as requested byt the changeHatValve during
prompt you create discrete hats as requested by the changeHatValve during
tomcat execution.
1. Create a basic profile for the tomcat server.
- Run the command "genprof PATH_TO_CATALINA.SH"
- In a seperate window start tomcat and then stop tomcat
- In a separate window start tomcat and then stop tomcat
- In the genprof window press "S" to scan for events
- Answer the questions about the initial profile for tomcat
@@ -124,7 +124,7 @@ tomcat execution.
- Stop the tomcat server
- Deploy your WAR file or equivalent files under the container.
- execute "genprof PATH_TO_CATALINA.SH"
- In a seperate window start tomcat and then exercise your web application
- In a separate window start tomcat and then exercise your web application
- In the genprof window press "S" to scan for events
During the prompting you will be asked questions similar to:
@@ -180,7 +180,7 @@ all subsequent resource requests will be mediated in this hew hat (or security
context).
If you choose to use the default hat: genprof will mediate all resource
requests in the default hat for the duration of processing this request.
When the request processng is complete the valve will change_hat back to the
When the request processing is complete the valve will change_hat back to the
parent context.

View File

@@ -66,8 +66,8 @@ under src/jni_src.
cp dist/libJNIChangeHat.so /usr/lib
[Note: you must ensure that the target directory is passed to tomcat via the
java.library.path propert. This can be accomplished by setting the JAVA_OPTS
enviroment variable, export JAVA_OPTS=-Djava.library.path, or set via the
java.library.path property. This can be accomplished by setting the JAVA_OPTS
environment variable, export JAVA_OPTS=-Djava.library.path, or set via the
env variable LD_LIBRARY_PATH to include this directory so that tomcat can
find this library at startup]
@@ -108,13 +108,13 @@ under src/jni_src.
Once the installation steps above have been started you are ready to begin
creating a profile for your application. The profile creation tool genprof will
guide you through generating a profile and its support for change_hat will
prompt you create discrete hats as requested byt the changeHatValve during
prompt you create discrete hats as requested by the changeHatValve during
tomcat execution.
1. Create a basic profile for the tomcat server.
- Run the command "genprof PATH_TO_CATALINA.SH"
- In a seperate window start tomcat and then stop tomcat
- In a separate window start tomcat and then stop tomcat
- In the genprof window press "S" to scan for events
- Answer the questions about the initial profile for tomcat
@@ -124,7 +124,7 @@ tomcat execution.
- Stop the tomcat server
- Deploy your WAR file or equivalent files under the container.
- execute "genprof PATH_TO_CATALINA.SH"
- In a seperate window start tomcat and then exercise your web application
- In a separate window start tomcat and then exercise your web application
- In the genprof window press "S" to scan for events
During the prompting you will be asked questions similar to:
@@ -180,7 +180,7 @@ all subsequent resource requests will be mediated in this hew hat (or security
context).
If you choose to use the default hat: genprof will mediate all resource
requests in the default hat for the duration of processing this request.
When the request processng is complete the valve will change_hat back to the
When the request processing is complete the valve will change_hat back to the
parent context.

View File

@@ -6,7 +6,7 @@
# the source tree
# =====================
# It doesn't make sence for AppArmor to mediate PF_UNIX, filter it out. Search
# It doesn't make sense for AppArmor to mediate PF_UNIX, filter it out. Search
# for "PF_" constants since that is what is required in bits/socket.h, but
# rewrite as "AF_".

View File

@@ -58,7 +58,7 @@ if test "$with_perl" = "yes"; then
AC_PATH_PROG(PERL, perl)
test -z "$PERL" && AC_MSG_ERROR([perl is required when enabling perl bindings])
perl_includedir="`$PERL -e 'use Config; print $Config{archlib}'`/CORE"
AC_CHECK_FILE($perl_includedir/perl.h, enable_perl=yes, enable_perl=no)
AS_IF([test -e "$perl_includedir/perl.h"], enable_perl=yes, enable_perl=no)
fi

View File

@@ -125,7 +125,7 @@ layer. Binary policy cache files will be located in the directory
returned by this function.
The aa_policy_cache_dir_levels() function provides access to the number
of directories that are being overlayed to create the policy cache.
of directories that are being overlaid to create the policy cache.
=head1 RETURN VALUE

View File

@@ -21,6 +21,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#ifdef __cplusplus

View File

@@ -13,7 +13,7 @@ AC_DEFUN([AC_PYTHON_DEVEL],[
PYTHON_VERSION=""
fi
AC_PATH_PROG([PYTHON_CONFIG],[`basename [$PYTHON]-config`])
AC_PATH_TOOL([PYTHON_CONFIG],[`basename [$PYTHON]-config`])
if test -z "$PYTHON_CONFIG"; then
AC_MSG_ERROR([Cannot find python$PYTHON_VERSION-config in your system path])
fi

View File

@@ -26,9 +26,9 @@ INCLUDES = $(all_includes)
# For more information, see:
# http://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
#
AA_LIB_CURRENT = 8
AA_LIB_CURRENT = 9
AA_LIB_REVISION = 0
AA_LIB_AGE = 7
AA_LIB_AGE = 8
SUFFIXES = .pc.in .pc

View File

@@ -373,7 +373,7 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
| TOK_KEY_CAPABILITY TOK_EQUALS TOK_DIGITS
{ /* need to reverse map number to string, need to figure out
* how to get auto generation of reverse mapping table into
* autotools Makefile. For now just drop assumming capname is
* autotools Makefile. For now just drop assuming capname is
* present which it should be with current kernels */
}
| TOK_KEY_CAPNAME TOK_EQUALS TOK_QUOTED_STRING
@@ -381,7 +381,7 @@ key: TOK_KEY_OPERATION TOK_EQUALS TOK_QUOTED_STRING
ret_record->name = $3;
}
| TOK_KEY_OFFSET TOK_EQUALS TOK_DIGITS
{ /* offset is used for reporting where an error occured unpacking
{ /* offset is used for reporting where an error occurred unpacking
* loaded policy. We can just drop this currently
*/
}

View File

@@ -227,9 +227,10 @@ static inline pid_t aa_gettid(void)
* present.
*/
static pthread_once_t proc_attr_base_ctl = PTHREAD_ONCE_INIT;
static char *proc_attr_base = "/proc/%d/attr/%s";
static char *proc_attr_base_stacking = "/proc/%d/attr/apparmor/%s";
static char *proc_attr_base_unavailable = "/proc/%d/attr/apparmor/unavailable/%s";
static const char *proc_attr_base_old = "/proc/%d/attr/%s";
static const char *proc_attr_base_stacking = "/proc/%d/attr/apparmor/%s";
static const char *proc_attr_base_unavailable = "/proc/%d/attr/apparmor/unavailable/%s";
static const char *proc_attr_base;
static void proc_attr_base_init_once(void)
{
@@ -238,17 +239,21 @@ static void proc_attr_base_init_once(void)
/* if we fail we just fall back to the default value */
if (asprintf(&tmp, "/proc/%d/attr/apparmor/current", aa_gettid())) {
autoclose int fd = open(tmp, O_RDONLY);
if (fd != -1)
if (fd != -1) {
proc_attr_base = proc_attr_base_stacking;
} else if (!is_enabled() && is_private_enabled()) {
/* new stacking interfaces aren't available and apparmor
* is disabled, but available. do not use the
* /proc/<pid>/attr/ * interfaces as they could be
* in use by another LSM
*/
proc_attr_base = proc_attr_base_unavailable;
return;
}
}
/* else default to pre-assigned value */
if (!is_enabled() && is_private_enabled()) {
/* new stacking interfaces aren't available and apparmor
* is disabled, but available. do not use the
* /proc/<pid>/attr/ * interfaces as they could be
* in use by another LSM
*/
proc_attr_base = proc_attr_base_unavailable;
return;
}
proc_attr_base = proc_attr_base_old;
}
static char *procattr_path(pid_t pid, const char *attr)
@@ -262,6 +267,38 @@ static char *procattr_path(pid_t pid, const char *attr)
return NULL;
}
static int procattr_open(pid_t tid, const char *attr, int flags)
{
char *tmp;
int fd;
tmp = procattr_path(tid, attr);
if (!tmp) {
return -1;
}
fd = open(tmp, flags);
free(tmp);
/* Test is we can fallback to a different interface this is ugly.
* If only the old interface is available:
* proc_attr_base == proc_attr_base_old - no fallback
* else if is_enabled()
* apparmor is available on the old interface
* we do NOT use is_private_enabled() as
* 1. the new private interface would have been tried first above
* 2. that can be true even when another LSM is using the
* old interface where is_enabled() is only successful if
* the old interface is available to apparmor.
*/
if (fd == -1 && errno == EACCES && proc_attr_base != proc_attr_base_old && is_enabled()) {
if (asprintf(&tmp, proc_attr_base_old, tid, attr) < 0)
return -1;
fd = open(tmp, flags);
free(tmp);
}
return fd;
}
/**
* parse_unconfined - check for the unconfined label
* @con: the confinement context
@@ -371,12 +408,7 @@ int aa_getprocattr_raw(pid_t tid, const char *attr, char *buf, int len,
goto out;
}
tmp = procattr_path(tid, attr);
if (!tmp)
goto out;
fd = open(tmp, O_RDONLY);
free(tmp);
fd = procattr_open(tid, attr, O_RDONLY);
if (fd == -1) {
goto out;
}
@@ -487,18 +519,13 @@ static int setprocattr(pid_t tid, const char *attr, const char *buf, int len)
{
int rc = -1;
int fd, ret;
char *ctl = NULL;
if (!buf) {
errno = EINVAL;
goto out;
}
ctl = procattr_path(tid, attr);
if (!ctl)
goto out;
fd = open(ctl, O_WRONLY);
fd = procattr_open(tid, attr, O_WRONLY);
if (fd == -1) {
goto out;
}
@@ -519,9 +546,6 @@ static int setprocattr(pid_t tid, const char *attr, const char *buf, int len)
(void)close(fd);
out:
if (ctl) {
free(ctl);
}
return rc;
}
@@ -1101,9 +1125,9 @@ int aa_query_link_path_len(const char *label, size_t label_len,
query[pos] = 0;
query[++pos] = AA_CLASS_FILE;
memcpy(query + pos + 1, link, link_len);
/* The kernel does the query in two parts we could similate this
/* The kernel does the query in two parts; we could simulate this
* doing the following, however as long as policy is compiled
* correctly this isn't requied, and it requires and extra round
* correctly this isn't required, and it requires an extra round
* trip to the kernel and adds a race on policy replacement between
* the two queries.
*

View File

@@ -90,7 +90,7 @@ static int write_buffer(int fd, const char *buffer, int size)
/**
* write_policy_buffer - load compiled policy into the kernel
* @fd: kernel iterface to write to
* @fd: kernel interface to write to
* @atomic: whether to load all policy in buffer atomically (true)
* @buffer: buffer of policy to load
* @size: the size of the data in the buffer
@@ -205,7 +205,7 @@ static int write_policy_file_to_iface(aa_kernel_interface *kernel_interface,
* @apparmorfs: path to the apparmor directory of the mounted securityfs (can
* be NULL and the path will be auto discovered)
*
* Returns: 0 on success, -1 on error with errnot set and *@kernel_interface
* Returns: 0 on success, -1 on error with errno set and *@kernel_interface
* pointing to NULL
*/
int aa_kernel_interface_new(aa_kernel_interface **kernel_interface,

View File

@@ -117,6 +117,7 @@ APPARMOR_2.13.1 {
APPARMOR_3.0 {
global:
aa_features_new_from_file;
aa_features_write_to_fd;
aa_features_value;
local:
@@ -126,6 +127,7 @@ APPARMOR_3.0 {
PRIVATE {
global:
_aa_is_blacklisted;
_aa_asprintf;
_aa_autofree;
_aa_autoclose;
_aa_autofclose;

View File

@@ -63,7 +63,7 @@ struct ignored_suffix_t {
};
static struct ignored_suffix_t ignored_suffixes[] = {
/* Debian packging files, which are in flux during install
/* Debian packaging files, which are in flux during install
should be silently ignored. */
{ ".dpkg-new", 9, 1 },
{ ".dpkg-old", 9, 1 },
@@ -147,7 +147,7 @@ int _aa_is_blacklisted(const char *name)
return 0;
}
/* automaticly free allocated variables tagged with autofree on fn exit */
/* automatically free allocated variables tagged with autofree on fn exit */
void _aa_autofree(void *p)
{
void **_p = (void**)p;
@@ -474,7 +474,7 @@ int _aa_dirat_for_each(int dirfd, const char *name, void *data,
return -1;
}
num_dirs = readdirfd(cb_dirfd, &namelist, NULL);
num_dirs = readdirfd(cb_dirfd, &namelist, alphasort);
if (num_dirs == -1) {
PDEBUG("scandirat of directory '%s' failed: %m\n", name);
return -1;

View File

@@ -14,7 +14,7 @@ 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
CC="$(CC)" CFLAGS="$(PYTHON_CPPFLAGS) $(EXTRA_WARNINGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(PYTHON_LDFLAGS)" $(PYTHON) setup.py build
CC="$(CC)" CFLAGS="$(PYTHON_CPPFLAGS) $(EXTRA_WARNINGS)" LDSHARED="$(CC) -shared" LDFLAGS="$(PYTHON_LDFLAGS) $(LDFLAGS)" $(PYTHON) setup.py build
install-exec-local:
$(PYTHON) setup.py install --root="/$(DESTDIR)" --prefix="$(prefix)"

View File

@@ -1,5 +1,5 @@
# Runs all tests with the extention "multi" for several times.
# Each testprogram <programname>.multi has an own subdirectory
# Runs all tests with the extension "multi" for several times.
# Each test program <programname>.multi has its own subdirectory
# <programmname> in which several testcases are defined for this program
# Each testcase has 3 files:
#

View File

@@ -54,7 +54,7 @@ endif
CPPFLAGS += -D_GNU_SOURCE
STDLIB_INCLUDE:="\#include <stdlib.h>"
HAVE_REALLOCARRAY:=$(shell echo $(STDLIB_INCLUDE) | cpp ${CPPFLAGS} | grep -q reallocarray && echo true)
HAVE_REALLOCARRAY:=$(shell echo $(STDLIB_INCLUDE) | ${CPP} ${CPPFLAGS} - - | grep -q reallocarray && echo true)
WARNINGS = -Wall
CXX_WARNINGS = ${WARNINGS} ${EXTRA_WARNINGS}

View File

@@ -37,7 +37,7 @@ static struct supported_cond supported_conds[] = {
{ "type", true, false, false, local_cond },
{ "protocol", false, false, false, local_cond },
{ "label", true, false, false, peer_cond },
{ NULL, false, false, false, local_cond }, /* eol sentinal */
{ NULL, false, false, false, local_cond }, /* eol sentinel */
};
bool af_rule::cond_check(struct supported_cond *conds, struct cond_entry *ent,

View File

@@ -29,7 +29,7 @@
#include "profile.h"
#include "af_unix.h"
/* See unix(7) for autobind address definiation */
/* See unix(7) for autobind address definition */
#define autobind_address_pattern "\\x00[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]";
int parse_unix_mode(const char *str_mode, int *mode, int fail)
@@ -40,7 +40,7 @@ int parse_unix_mode(const char *str_mode, int *mode, int fail)
static struct supported_cond supported_conds[] = {
{ "addr", true, false, false, either_cond },
{ NULL, false, false, false, local_cond }, /* sentinal */
{ NULL, false, false, false, local_cond }, /* sentinel */
};
void unix_rule::move_conditionals(struct cond_entry *conds)
@@ -194,14 +194,18 @@ void unix_rule::downgrade_rule(Profile &prof) {
yyerror(_("Memory allocation error."));
if (sock_type_n != -1)
mask = 1 << sock_type_n;
if (deny) {
prof.net.deny[AF_UNIX] |= mask;
if (!audit)
prof.net.quiet[AF_UNIX] |= mask;
} else {
if (!deny) {
prof.net.allow[AF_UNIX] |= mask;
if (audit)
prof.net.audit[AF_UNIX] |= mask;
} else {
/* deny rules have to be dropped because the downgrade makes
* the rule less specific meaning it will make the profile more
* restrictive and may end up denying accesses that might be
* allowed by the profile.
*/
if (warnflags & WARN_RULE_NOT_ENFORCED)
rule_t::warn_once(prof.name, "deny unix socket rule not enforced, can't be downgraded to generic network rule\n");
}
}
@@ -322,8 +326,9 @@ int unix_rule::gen_policy_re(Profile &prof)
rule_t::warn_once(prof.name, "downgrading extended network unix socket rule to generic network rule\n");
/* TODO: add ability to abort instead of downgrade */
return RULE_OK;
} else {
warn_once(prof.name);
}
warn_once(prof.name);
return RULE_NOT_SUPPORTED;
}
@@ -351,7 +356,7 @@ int unix_rule::gen_policy_re(Profile &prof)
/* local label option */
if (!write_label(tmp, label))
goto fail;
/* seperator */
/* separator */
tmp << "\\x00";
buf = tmp.str();
@@ -372,7 +377,7 @@ int unix_rule::gen_policy_re(Profile &prof)
/* local label option */
if (!write_label(buffer, label))
goto fail;
/* seperator */
/* separator */
buffer << "\\x00";
/* create already masked off */

View File

@@ -241,9 +241,6 @@ B<DBUS ACCESS LIST> = Comma separated list of I<DBUS ACCESS>
B<DBUS ACCESS> = ( 'send' | 'receive' | 'bind' | 'eavesdrop' | 'r' | 'read' | 'w' | 'write' | 'rw' )
Some accesses are incompatible with some rules; see below.
B<AARE> = B<?*[]{}^>
See below for meanings.
B<UNIX RULE> = [ I<QUALIFIERS> ] 'unix' [ I<UNIX ACCESS EXPR> ] [ I<UNIX RULE CONDS> ] [ I<UNIX LOCAL EXPR> ] [ I<UNIX PEER EXPR> ]
B<UNIX ACCESS EXPR> = ( I<UNIX ACCESS> | I<UNIX ACCESS LIST> )
@@ -300,6 +297,9 @@ B<QUOTED FILEGLOB> = '"' I<UNQUOTED FILEGLOB> '"'
B<UNQUOTED FILEGLOB> = (must start with '/' (after variable expansion), B<AARE> have special meanings; see below. May include I<VARIABLE>. Rules with embedded spaces or tabs must be quoted. Rules must end with '/' to apply to directories.)
B<AARE> = B<?*[]{}^>
See section "Globbing (AARE)" below for meanings.
B<ACCESS> = ( 'r' | 'w' | 'a' | 'l' | 'k' | 'm' | I<EXEC TRANSITION> )+ (not all combinations are allowed; see below.)
B<EXEC TRANSITION> = ( 'ix' | 'ux' | 'Ux' | 'px' | 'Px' | 'cx' | 'Cx' | 'pix' | 'Pix' | 'cix' | 'Cix' | 'pux' | 'PUx' | 'cux' | 'CUx' | 'x' )
@@ -1273,7 +1273,7 @@ I<auto> keyword. Eg.
To indicate that the rule only applies to auto binding of unix domain
sockets. It is important to note this only applies to the I<bind>
permission as once the socket is bound to an address it is
indistiguishable from a socket that have an addr bound with a
indistinguishable from a socket that have an addr bound with a
specified name. When the I<auto> keyword is used with other permissions
or as part of a peer addr it will be replaced with a pattern that
can match an autobound socket. Eg. For some kernels
@@ -1513,9 +1513,10 @@ F</etc/apparmor.d/tunables/alias>, which is included by
F</etc/apparmor.d/tunables/global>. F</etc/apparmor.d/tunables/global> is
typically included at the beginning of an AppArmor profile.
=head2 Globbing
=head2 Globbing (AARE)
File resources may be specified with a globbing syntax similar to that
File resources and other parameters accepting an AARE
may be specified with a globbing syntax similar to that
used by popular shells, such as csh(1), bash(1), zsh(1).
=over 4
@@ -1548,6 +1549,12 @@ will substitute for any single character not matching a, b or c
will expand to one rule to match ab, one rule to match cd
Can also include variables.
=item B<@{variable}>
will expand to all values assigned to the given variable.
=back
When AppArmor looks up a directory the pathname being looked up will
@@ -1752,7 +1759,7 @@ If the policy abi is specified as B<kernel> then the running kernel's
abi will be used. This should never be used in shipped policy as it
can cause system breakage when a new kernel is installed.
=head3 ABI compatability with AppArmor 2.x
=head3 ABI compatibility with AppArmor 2.x
AppArmor 3 remains compatible with AppArmor 2.x by detecting when a
profile does not have a feature ABI specified. In this case the policy

View File

@@ -98,6 +98,62 @@ cannot call the following system calls:
iopl(2) ptrace(2) reboot(2) setdomainname(2)
sethostname(2) swapoff(2) swapon(2) sysctl(2)
=head2 Complain mode
Instead of denying access to resources the profile does not have a rule for
AppArmor can "allow" the access and log a message for the operation
that triggers it. This is called I<complain mode>. It is important to
note that rules that are present in the profile are still applied, so
allow rules will still quiet or force audit messages, and deny rules
will still result in denials and quieting of denial messages (see
I<Turn off deny audit quieting> if this is a problem).
Complain mode can be used to develop profiles incrementally as an
application is exercised. The logged accesses can be added to the
profile and then can the application further excercised to discover further
additions that are needed. Because AppArmor allows the accesses the
application will behave as it would if AppArmor was not confining it.
B<Warning> complain mode does not provide any security, only
auditing, while it is enabled. It should not be used in a hostile
environment or bad behaviors may be logged and added to the profile
as if they are resource accesses that should be used by the
application.
B<Note> complain mode can be very noisy with new or empty profiles,
but with developed profiles might not log anything if the profile
covers the application behavior well. See I<Audit Rate Limiting> if
complain mode is generating too many log messages.
To set a profile and any children or hat profiles the profile may contain
into complain mode use
aa-complain /etc/apparmor.d/<the-application>
To manually set a specific profile in complain mode, add the
C<complain> flag, and then manually reload the profile:
profile foo flags=(complain) { ... }
Note that the C<complain> flag must also be added manually to any
hats or children profiles of the profile or they will continue to
use the previous mode.
To enable complain mode globally, run:
echo -n complain > /sys/module/apparmor/parameters/mode
or to set it on boot add:
apparmor.mode=complain
as a kernel boot paramenter.
B<Warning> Setting complain mode gloabally disables all apparmor
security protections. It can be useful during debugging or profile
development, but setting it selectively on a per profile basis is
safer.
=head1 ERRORS
When a confined process tries to access a file it does not have permission
@@ -158,6 +214,12 @@ To enable debug mode, run:
echo 1 > /sys/module/apparmor/parameters/debug
or to set it on boot add:
apparmor.debug=1
as a kernel boot paramenter.
=head2 Turn off deny audit quieting
By default, operations that trigger C<deny> rules are not logged.
@@ -167,6 +229,12 @@ To turn off deny audit quieting, run:
echo -n noquiet >/sys/module/apparmor/parameters/audit
or to set it on boot add:
apparmor.audit=noquiet
as a kernel boot paramenter.
=head2 Force audit mode
AppArmor can log a message for every operation that triggers a rule
@@ -183,6 +251,14 @@ To enable force audit mode globally, run:
echo -n all > /sys/module/apparmor/parameters/audit
or to set it on boot add:
apparmor.audit=all
as a kernel boot paramenter.
B<Audit Rate Limiting>
If auditd is not running, to avoid losing too many of the extra log
messages, you will likely have to turn off rate limiting by doing:

View File

@@ -352,12 +352,15 @@ Eg.
-jx4 OR --jobs=x4 sets the jobs to # of cpus * 4
-jx1 is equivalent to -jauto
The default value is the number of cpus in the system.
The default value is the number of cpus in the system. Note that if jobs
is a positive integer number the --jobs-max parameter is automatically
set to the same value.
=item --max-jobs n
Set a hard cap on the value that can be specified by the --jobs flag.
It takes the same set of options available to the --jobs option, and
When --jobs is set to a scaling value (ie. auto or xN) the specify a
hard cap on the value that can be specified by the --jobs flag. It
takes the same set of options available to the --jobs option, and
defaults to 8*cpus
=item -O n, --optimize=n
@@ -393,6 +396,23 @@ This option tells the parser to not attempt to rebuild the cache on
failure, instead the parser continues on with processing the remaining
profiles.
=item --estimated-compile-size
Adjust the internal parameter used to estimate how agressive the parser
can be when compiling policy. This may include changes to how or when
caches are dropped or how many compile units (jobs) are launched. The
value should slightly larger than the largest Resident Set Size (RSS)
encountered for the type of policy being compiled.
A value that is too small may result in the parser exhausting system
resources when compiling large policy. A value too large may slow
policy compiles down.
The value specified may include a suffix of I<KB>, I<MB>, I<GB>, to
make it easier to adjust the size.
Note: config-file and command line options will override values chosen
by tuning affected by the option.
=item --config-file
Specify the config file to use instead of

View File

@@ -27,7 +27,7 @@
=head1 NAME
AppArmor profile xattr(7) matching
apparmor_xattrs - AppArmor profile xattr(7) matching
=head1 DESCRIPTION

View File

@@ -8,6 +8,8 @@
{"bpf", CAP_BPF, CAP_SYS_ADMIN, CAPFLAG_BASE_FEATURE},
{"checkpoint_restore", CAP_CHECKPOINT_RESTORE, CAP_SYS_ADMIN, CAPFLAG_BASE_FEATURE},
{"chown", CAP_CHOWN, NO_BACKMAP_CAP, CAPFLAG_BASE_FEATURE},
{"dac_override", CAP_DAC_OVERRIDE, NO_BACKMAP_CAP, CAPFLAG_BASE_FEATURE},

View File

@@ -29,6 +29,10 @@
#define CAP_BPF 39
#endif
#ifndef CAP_CHECKPOINT_RESTORE
#define CAP_CHECKPOINT_RESTORE 40
#endif
typedef enum capability_flags {
CAPFLAGS_CLEAR = 0,
CAPFLAG_BASE_FEATURE = 1,

View File

@@ -8,7 +8,7 @@ chfa.{h,cc} - code to build a highly compressed runtime readonly version
of an hfa.
aare_rules.{h,cc} - code to that binds parse -> expr-tree -> hfa generation
-> chfa generation into a basic interface for converting
rules to a runtime ready statemachine.
rules to a runtime ready state machine.
Regular Expression Scanner Generator
====================================
@@ -19,12 +19,12 @@ Notes in the scanner File Format
The file format used is based on the GNU flex table file format
(--tables-file option; see Table File Format in the flex info pages and
the flex sources for documentation). The magic number used in the header
is set to 0x1B5E783D insted of 0xF13C57B1 though, which is meant to
is set to 0x1B5E783D instead of 0xF13C57B1 though, which is meant to
indicate that the file format logically is not the same: the YY_ID_CHK
(check) and YY_ID_DEF (default) tables are used differently.
Flex uses state compression to store only the differences between states
for states that are similar. The amount of compresion influences the parse
for states that are similar. The amount of compression influences the parse
speed.
The following two states could be stored as in the tables outlined

View File

@@ -61,12 +61,12 @@ void aare_rules::add_to_rules(Node *tree, Node *perms)
expr_map[perms] = tree;
}
static Node *cat_with_null_seperator(Node *l, Node *r)
static Node *cat_with_null_separator(Node *l, Node *r)
{
return new CatNode(new CatNode(l, new CharNode(0)), r);
}
static Node *cat_with_oob_seperator(Node *l, Node *r)
static Node *cat_with_oob_separator(Node *l, Node *r)
{
return new CatNode(new CatNode(l, new CharNode(transchar(-1, true))), r);
}
@@ -85,9 +85,9 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
if (regex_parse(&subtree, rulev[i]))
goto err;
if (oob)
tree = cat_with_oob_seperator(tree, subtree);
tree = cat_with_oob_separator(tree, subtree);
else
tree = cat_with_null_seperator(tree, subtree);
tree = cat_with_null_separator(tree, subtree);
}
/*
@@ -97,11 +97,11 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
*/
exact_match = 1;
for (depth_first_traversal i(tree); i && exact_match; i++) {
if (dynamic_cast<StarNode *>(*i) ||
dynamic_cast<PlusNode *>(*i) ||
dynamic_cast<AnyCharNode *>(*i) ||
dynamic_cast<CharSetNode *>(*i) ||
dynamic_cast<NotCharSetNode *>(*i))
if ((*i)->is_type(NODE_TYPE_STAR) ||
(*i)->is_type(NODE_TYPE_PLUS) ||
(*i)->is_type(NODE_TYPE_ANYCHAR) ||
(*i)->is_type(NODE_TYPE_CHARSET) ||
(*i)->is_type(NODE_TYPE_NOTCHARSET))
exact_match = 0;
}
@@ -111,15 +111,15 @@ bool aare_rules::add_rule_vec(int deny, uint32_t perms, uint32_t audit,
accept = unique_perms.insert(deny, perms, audit, exact_match);
if (flags & DFA_DUMP_RULE_EXPR) {
const char *seperator;
const char *separator;
if (oob)
seperator = "\\-x01";
separator = "\\-x01";
else
seperator = "\\x00";
separator = "\\x00";
cerr << "rule: ";
cerr << rulev[0];
for (int i = 1; i < count; i++) {
cerr << seperator;
cerr << separator;
cerr << rulev[i];
}
cerr << " -> ";

View File

@@ -23,7 +23,7 @@
* it can be factored so that the set of important nodes is smaller.
* Having a reduced set of important nodes generally results in a dfa that
* is closer to minimum (fewer redundant states are created). It also
* results in fewer important nodes in a the state set during subset
* results in fewer important nodes in the state set during subset
* construction resulting in less memory used to create a dfa.
*
* Generally it is worth doing expression tree simplification before dfa
@@ -150,7 +150,7 @@ void Node::dump_syntax_tree(ostream &os)
}
/*
* Normalize the regex parse tree for factoring and cancelations. Normalization
* Normalize the regex parse tree for factoring and cancellations. Normalization
* reorganizes internal (alt and cat) nodes into a fixed "normalized" form that
* simplifies factoring code, in that it produces a canonicalized form for
* the direction being normalized so that the factoring code does not have
@@ -172,10 +172,10 @@ void Node::dump_syntax_tree(ostream &os)
* dir to !dir. Until no dir direction node meets the criterial.
* Then recurse to the children (which will have a different node type)
* to make sure they are normalized.
* Normalization of a child node is guarenteed to not affect the
* Normalization of a child node is guaranteed to not affect the
* normalization of the parent.
*
* For cat nodes the depth first traverse order is guarenteed to be
* For cat nodes the depth first traverse order is guaranteed to be
* maintained. This is not necessary for altnodes.
*
* Eg. For left normalization
@@ -210,7 +210,7 @@ int TwoChildNode::normalize_eps(int dir)
// Test for E | (E | E) and E . (E . E) which will
// result in an infinite loop
Node *c = child[!dir];
if (dynamic_cast<TwoChildNode *>(c) &&
if (c->is_type(NODE_TYPE_TWOCHILD) &&
&epsnode == c->child[dir] &&
&epsnode == c->child[!dir]) {
c->release();
@@ -229,7 +229,7 @@ void CatNode::normalize(int dir)
for (;;) {
if (normalize_eps(dir)) {
continue;
} else if (dynamic_cast<CatNode *>(child[dir])) {
} else if (child[dir]->is_type(NODE_TYPE_CAT)) {
// (ab)c -> a(bc)
rotate_node(this, dir);
} else {
@@ -248,11 +248,11 @@ void AltNode::normalize(int dir)
for (;;) {
if (normalize_eps(dir)) {
continue;
} else if (dynamic_cast<AltNode *>(child[dir])) {
} else if (child[dir]->is_type(NODE_TYPE_ALT)) {
// (a | b) | c -> a | (b | c)
rotate_node(this, dir);
} else if (dynamic_cast<CharSetNode *>(child[dir]) &&
dynamic_cast<CharNode *>(child[!dir])) {
} else if (child[dir]->is_type(NODE_TYPE_CHARSET) &&
child[!dir]->is_type(NODE_TYPE_CHAR)) {
// [a] | b -> b | [a]
Node *c = child[dir];
child[dir] = child[!dir];
@@ -344,7 +344,7 @@ static Node *alt_to_charsets(Node *t, int dir)
static Node *basic_alt_factor(Node *t, int dir)
{
if (!dynamic_cast<AltNode *>(t))
if (!t->is_type(NODE_TYPE_ALT))
return t;
if (t->child[dir]->eq(t->child[!dir])) {
@@ -355,8 +355,8 @@ static Node *basic_alt_factor(Node *t, int dir)
return tmp;
}
// (ab) | (ac) -> a(b|c)
if (dynamic_cast<CatNode *>(t->child[dir]) &&
dynamic_cast<CatNode *>(t->child[!dir]) &&
if (t->child[dir]->is_type(NODE_TYPE_CAT) &&
t->child[!dir]->is_type(NODE_TYPE_CAT) &&
t->child[dir]->child[dir]->eq(t->child[!dir]->child[dir])) {
// (ab) | (ac) -> a(b|c)
Node *left = t->child[dir];
@@ -369,7 +369,7 @@ static Node *basic_alt_factor(Node *t, int dir)
return left;
}
// a | (ab) -> a (E | b) -> a (b | E)
if (dynamic_cast<CatNode *>(t->child[!dir]) &&
if (t->child[!dir]->is_type(NODE_TYPE_CAT) &&
t->child[dir]->eq(t->child[!dir]->child[dir])) {
Node *c = t->child[!dir];
t->child[dir]->release();
@@ -379,7 +379,7 @@ static Node *basic_alt_factor(Node *t, int dir)
return c;
}
// ab | (a) -> a (b | E)
if (dynamic_cast<CatNode *>(t->child[dir]) &&
if (t->child[dir]->is_type(NODE_TYPE_CAT) &&
t->child[dir]->child[dir]->eq(t->child[!dir])) {
Node *c = t->child[dir];
t->child[!dir]->release();
@@ -394,7 +394,7 @@ static Node *basic_alt_factor(Node *t, int dir)
static Node *basic_simplify(Node *t, int dir)
{
if (dynamic_cast<CatNode *>(t) && &epsnode == t->child[!dir]) {
if (t->is_type(NODE_TYPE_CAT) && &epsnode == t->child[!dir]) {
// aE -> a
Node *tmp = t->child[dir];
t->child[dir] = NULL;
@@ -419,7 +419,7 @@ static Node *basic_simplify(Node *t, int dir)
*/
Node *simplify_tree_base(Node *t, int dir, bool &mod)
{
if (dynamic_cast<ImportantNode *>(t))
if (t->is_type(NODE_TYPE_IMPORTANT))
return t;
for (int i = 0; i < 2; i++) {
@@ -442,15 +442,15 @@ Node *simplify_tree_base(Node *t, int dir, bool &mod)
}
/* all tests after this must meet 2 alt node condition */
if (!dynamic_cast<AltNode *>(t) ||
!dynamic_cast<AltNode *>(t->child[!dir]))
if (!t->is_type(NODE_TYPE_ALT) ||
!t->child[!dir]->is_type(NODE_TYPE_ALT))
break;
// a | (a | b) -> (a | b)
// a | (b | (c | a)) -> (b | (c | a))
Node *p = t;
Node *i = t->child[!dir];
for (; dynamic_cast<AltNode *>(i); p = i, i = i->child[!dir]) {
for (; i->is_type(NODE_TYPE_ALT); p = i, i = i->child[!dir]) {
if (t->child[dir]->eq(i->child[dir])) {
Node *tmp = t->child[!dir];
t->child[!dir] = NULL;
@@ -475,19 +475,19 @@ Node *simplify_tree_base(Node *t, int dir, bool &mod)
int count = 0;
Node *subject = t->child[dir];
Node *a = subject;
if (dynamic_cast<CatNode *>(subject))
if (subject->is_type(NODE_TYPE_CAT))
a = subject->child[dir];
for (pp = p = t, i = t->child[!dir];
dynamic_cast<AltNode *>(i);) {
if ((dynamic_cast<CatNode *>(i->child[dir]) &&
i->is_type(NODE_TYPE_ALT);) {
if ((i->child[dir]->is_type(NODE_TYPE_CAT) &&
a->eq(i->child[dir]->child[dir])) ||
(a->eq(i->child[dir]))) {
// extract matching alt node
p->child[!dir] = i->child[!dir];
i->child[!dir] = subject;
subject = basic_simplify(i, dir);
if (dynamic_cast<CatNode *>(subject))
if (subject->is_type(NODE_TYPE_CAT))
a = subject->child[dir];
else
a = subject;
@@ -502,7 +502,7 @@ Node *simplify_tree_base(Node *t, int dir, bool &mod)
}
// last altnode in chain check other dir as well
if ((dynamic_cast<CatNode *>(i) &&
if ((i->is_type(NODE_TYPE_CAT) &&
a->eq(i->child[dir])) || (a->eq(i))) {
count++;
if (t == p) {
@@ -528,7 +528,7 @@ int debug_tree(Node *t)
{
int nodes = 1;
if (!dynamic_cast<ImportantNode *>(t)) {
if (!t->is_type(NODE_TYPE_IMPORTANT)) {
if (t->child[0])
nodes += debug_tree(t->child[0]);
if (t->child[1])
@@ -539,30 +539,30 @@ int debug_tree(Node *t)
static void count_tree_nodes(Node *t, struct node_counts *counts)
{
if (dynamic_cast<AltNode *>(t)) {
if (t->is_type(NODE_TYPE_ALT)) {
counts->alt++;
count_tree_nodes(t->child[0], counts);
count_tree_nodes(t->child[1], counts);
} else if (dynamic_cast<CatNode *>(t)) {
} else if (t->is_type(NODE_TYPE_CAT)) {
counts->cat++;
count_tree_nodes(t->child[0], counts);
count_tree_nodes(t->child[1], counts);
} else if (dynamic_cast<PlusNode *>(t)) {
} else if (t->is_type(NODE_TYPE_PLUS)) {
counts->plus++;
count_tree_nodes(t->child[0], counts);
} else if (dynamic_cast<StarNode *>(t)) {
} else if (t->is_type(NODE_TYPE_STAR)) {
counts->star++;
count_tree_nodes(t->child[0], counts);
} else if (dynamic_cast<OptionalNode *>(t)) {
} else if (t->is_type(NODE_TYPE_OPTIONAL)) {
counts->optional++;
count_tree_nodes(t->child[0], counts);
} else if (dynamic_cast<CharNode *>(t)) {
} else if (t->is_type(NODE_TYPE_CHAR)) {
counts->charnode++;
} else if (dynamic_cast<AnyCharNode *>(t)) {
} else if (t->is_type(NODE_TYPE_ANYCHAR)) {
counts->any++;
} else if (dynamic_cast<CharSetNode *>(t)) {
} else if (t->is_type(NODE_TYPE_CHARSET)) {
counts->charset++;
} else if (dynamic_cast<NotCharSetNode *>(t)) {
} else if (t->is_type(NODE_TYPE_NOTCHARSET)) {
counts->notcharset++;
}
}
@@ -635,7 +635,8 @@ Node *simplify_tree(Node *t, dfaflags_t flags)
void flip_tree(Node *node)
{
for (depth_first_traversal i(node); i; i++) {
if (CatNode *cat = dynamic_cast<CatNode *>(*i)) {
if ((*i)->is_type(NODE_TYPE_CAT)) {
CatNode *cat = static_cast<CatNode *>(*i);
swap(cat->child[0], cat->child[1]);
}
}

View File

@@ -222,16 +222,43 @@ typedef struct Cases {
ostream &operator<<(ostream &os, Node &node);
#define NODE_TYPE_NODE 0
#define NODE_TYPE_INNER (1 << 0)
#define NODE_TYPE_ONECHILD (1 << 1)
#define NODE_TYPE_TWOCHILD (1 << 2)
#define NODE_TYPE_LEAF (1 << 3)
#define NODE_TYPE_EPS (1 << 4)
#define NODE_TYPE_IMPORTANT (1 << 5)
#define NODE_TYPE_C (1 << 6)
#define NODE_TYPE_CHAR (1 << 7)
#define NODE_TYPE_CHARSET (1 << 8)
#define NODE_TYPE_NOTCHARSET (1 << 9)
#define NODE_TYPE_ANYCHAR (1 << 10)
#define NODE_TYPE_STAR (1 << 11)
#define NODE_TYPE_OPTIONAL (1 << 12)
#define NODE_TYPE_PLUS (1 << 13)
#define NODE_TYPE_CAT (1 << 14)
#define NODE_TYPE_ALT (1 << 15)
#define NODE_TYPE_SHARED (1 << 16)
#define NODE_TYPE_ACCEPT (1 << 17)
#define NODE_TYPE_MATCHFLAG (1 << 18)
#define NODE_TYPE_EXACTMATCHFLAG (1 << 19)
#define NODE_TYPE_DENYMATCHFLAG (1 << 20)
/* An abstract node in the syntax tree. */
class Node {
public:
Node(): nullable(false), label(0) { child[0] = child[1] = 0; }
Node(Node *left): nullable(false), label(0)
Node(): nullable(false), type_flags(NODE_TYPE_NODE), label(0)
{
child[0] = child[1] = 0;
}
Node(Node *left): nullable(false), type_flags(NODE_TYPE_NODE), label(0)
{
child[0] = left;
child[1] = 0;
}
Node(Node *left, Node *right): nullable(false), label(0)
Node(Node *left, Node *right): nullable(false),
type_flags(NODE_TYPE_NODE), label(0)
{
child[0] = left;
child[1] = right;
@@ -302,6 +329,13 @@ public:
NodeSet firstpos, lastpos, followpos;
/* child 0 is left, child 1 is right */
Node *child[2];
/*
* Bitmap that stores supported pointer casts for the Node, composed
* by the NODE_TYPE_* flags. This is used by is_type() as a substitute
* of costly dynamic_cast calls.
*/
unsigned type_flags;
bool is_type(unsigned type) { return type_flags & type; }
unsigned int label; /* unique number for debug etc */
/**
@@ -315,25 +349,34 @@ public:
class InnerNode: public Node {
public:
InnerNode(): Node() { };
InnerNode(Node *left): Node(left) { };
InnerNode(Node *left, Node *right): Node(left, right) { };
InnerNode(): Node() { type_flags |= NODE_TYPE_INNER; };
InnerNode(Node *left): Node(left) { type_flags |= NODE_TYPE_INNER; };
InnerNode(Node *left, Node *right): Node(left, right)
{
type_flags |= NODE_TYPE_INNER;
};
};
class OneChildNode: public InnerNode {
public:
OneChildNode(Node *left): InnerNode(left) { };
OneChildNode(Node *left): InnerNode(left)
{
type_flags |= NODE_TYPE_ONECHILD;
};
};
class TwoChildNode: public InnerNode {
public:
TwoChildNode(Node *left, Node *right): InnerNode(left, right) { };
TwoChildNode(Node *left, Node *right): InnerNode(left, right)
{
type_flags |= NODE_TYPE_TWOCHILD;
};
virtual int normalize_eps(int dir);
};
class LeafNode: public Node {
public:
LeafNode(): Node() { };
LeafNode(): Node() { type_flags |= NODE_TYPE_LEAF; };
virtual void normalize(int dir __attribute__((unused))) { return; }
};
@@ -342,6 +385,7 @@ class EpsNode: public LeafNode {
public:
EpsNode(): LeafNode()
{
type_flags |= NODE_TYPE_EPS;
nullable = true;
label = 0;
}
@@ -356,7 +400,7 @@ public:
void compute_lastpos() { }
int eq(Node *other)
{
if (dynamic_cast<EpsNode *>(other))
if (other->is_type(NODE_TYPE_EPS))
return 1;
return 0;
}
@@ -373,7 +417,7 @@ public:
*/
class ImportantNode: public LeafNode {
public:
ImportantNode(): LeafNode() { }
ImportantNode(): LeafNode() { type_flags |= NODE_TYPE_IMPORTANT; }
void compute_firstpos() { firstpos.insert(this); }
void compute_lastpos() { lastpos.insert(this); }
virtual void follow(Cases &cases) = 0;
@@ -386,7 +430,7 @@ public:
*/
class CNode: public ImportantNode {
public:
CNode(): ImportantNode() { }
CNode(): ImportantNode() { type_flags |= NODE_TYPE_C; }
int is_accept(void) { return false; }
int is_postprocess(void) { return false; }
};
@@ -394,7 +438,7 @@ public:
/* Match one specific character (/c/). */
class CharNode: public CNode {
public:
CharNode(transchar c): c(c) { }
CharNode(transchar c): c(c) { type_flags |= NODE_TYPE_CHAR; }
void follow(Cases &cases)
{
NodeSet **x = &cases.cases[c];
@@ -408,8 +452,8 @@ public:
}
int eq(Node *other)
{
CharNode *o = dynamic_cast<CharNode *>(other);
if (o) {
if (other->is_type(NODE_TYPE_CHAR)) {
CharNode *o = static_cast<CharNode *>(other);
return c == o->c;
}
return 0;
@@ -439,7 +483,10 @@ public:
/* Match a set of characters (/[abc]/). */
class CharSetNode: public CNode {
public:
CharSetNode(Chars &chars): chars(chars) { }
CharSetNode(Chars &chars): chars(chars)
{
type_flags |= NODE_TYPE_CHARSET;
}
void follow(Cases &cases)
{
for (Chars::iterator i = chars.begin(); i != chars.end(); i++) {
@@ -455,8 +502,11 @@ public:
}
int eq(Node *other)
{
CharSetNode *o = dynamic_cast<CharSetNode *>(other);
if (!o || chars.size() != o->chars.size())
if (!other->is_type(NODE_TYPE_CHARSET))
return 0;
CharSetNode *o = static_cast<CharSetNode *>(other);
if (chars.size() != o->chars.size())
return 0;
for (Chars::iterator i = chars.begin(), j = o->chars.begin();
@@ -498,7 +548,10 @@ public:
/* Match all except one character (/[^abc]/). */
class NotCharSetNode: public CNode {
public:
NotCharSetNode(Chars &chars): chars(chars) { }
NotCharSetNode(Chars &chars): chars(chars)
{
type_flags |= NODE_TYPE_NOTCHARSET;
}
void follow(Cases &cases)
{
if (!cases.otherwise)
@@ -522,8 +575,11 @@ public:
}
int eq(Node *other)
{
NotCharSetNode *o = dynamic_cast<NotCharSetNode *>(other);
if (!o || chars.size() != o->chars.size())
if (!other->is_type(NODE_TYPE_NOTCHARSET))
return 0;
NotCharSetNode *o = static_cast<NotCharSetNode *>(other);
if (chars.size() != o->chars.size())
return 0;
for (Chars::iterator i = chars.begin(), j = o->chars.begin();
@@ -565,7 +621,7 @@ public:
/* Match any character (/./). */
class AnyCharNode: public CNode {
public:
AnyCharNode() { }
AnyCharNode() { type_flags |= NODE_TYPE_ANYCHAR; }
void follow(Cases &cases)
{
if (!cases.otherwise)
@@ -579,7 +635,7 @@ public:
}
int eq(Node *other)
{
if (dynamic_cast<AnyCharNode *>(other))
if (other->is_type(NODE_TYPE_ANYCHAR))
return 1;
return 0;
}
@@ -589,7 +645,11 @@ public:
/* Match a node zero or more times. (This is a unary operator.) */
class StarNode: public OneChildNode {
public:
StarNode(Node *left): OneChildNode(left) { nullable = true; }
StarNode(Node *left): OneChildNode(left)
{
type_flags |= NODE_TYPE_STAR;
nullable = true;
}
void compute_firstpos() { firstpos = child[0]->firstpos; }
void compute_lastpos() { lastpos = child[0]->lastpos; }
void compute_followpos()
@@ -601,7 +661,7 @@ public:
}
int eq(Node *other)
{
if (dynamic_cast<StarNode *>(other))
if (other->is_type(NODE_TYPE_STAR))
return child[0]->eq(other->child[0]);
return 0;
}
@@ -618,12 +678,16 @@ public:
/* Match a node zero or one times. */
class OptionalNode: public OneChildNode {
public:
OptionalNode(Node *left): OneChildNode(left) { nullable = true; }
OptionalNode(Node *left): OneChildNode(left)
{
type_flags |= NODE_TYPE_OPTIONAL;
nullable = true;
}
void compute_firstpos() { firstpos = child[0]->firstpos; }
void compute_lastpos() { lastpos = child[0]->lastpos; }
int eq(Node *other)
{
if (dynamic_cast<OptionalNode *>(other))
if (other->is_type(NODE_TYPE_OPTIONAL))
return child[0]->eq(other->child[0]);
return 0;
}
@@ -638,7 +702,9 @@ public:
/* Match a node one or more times. (This is a unary operator.) */
class PlusNode: public OneChildNode {
public:
PlusNode(Node *left): OneChildNode(left) {
PlusNode(Node *left): OneChildNode(left)
{
type_flags |= NODE_TYPE_PLUS;
}
void compute_nullable() { nullable = child[0]->nullable; }
void compute_firstpos() { firstpos = child[0]->firstpos; }
@@ -651,7 +717,7 @@ public:
}
}
int eq(Node *other) {
if (dynamic_cast<PlusNode *>(other))
if (other->is_type(NODE_TYPE_PLUS))
return child[0]->eq(other->child[0]);
return 0;
}
@@ -667,7 +733,10 @@ public:
/* Match a pair of consecutive nodes. */
class CatNode: public TwoChildNode {
public:
CatNode(Node *left, Node *right): TwoChildNode(left, right) { }
CatNode(Node *left, Node *right): TwoChildNode(left, right)
{
type_flags |= NODE_TYPE_CAT;
}
void compute_nullable()
{
nullable = child[0]->nullable && child[1]->nullable;
@@ -695,7 +764,7 @@ public:
}
int eq(Node *other)
{
if (dynamic_cast<CatNode *>(other)) {
if (other->is_type(NODE_TYPE_CAT)) {
if (!child[0]->eq(other->child[0]))
return 0;
return child[1]->eq(other->child[1]);
@@ -730,7 +799,10 @@ public:
/* Match one of two alternative nodes. */
class AltNode: public TwoChildNode {
public:
AltNode(Node *left, Node *right): TwoChildNode(left, right) { }
AltNode(Node *left, Node *right): TwoChildNode(left, right)
{
type_flags |= NODE_TYPE_ALT;
}
void compute_nullable()
{
nullable = child[0]->nullable || child[1]->nullable;
@@ -745,7 +817,7 @@ public:
}
int eq(Node *other)
{
if (dynamic_cast<AltNode *>(other)) {
if (other->is_type(NODE_TYPE_ALT)) {
if (!child[0]->eq(other->child[0]))
return 0;
return child[1]->eq(other->child[1]);
@@ -780,7 +852,10 @@ public:
class SharedNode: public ImportantNode {
public:
SharedNode() { }
SharedNode()
{
type_flags |= NODE_TYPE_SHARED;
}
void release(void)
{
/* don't delete SharedNodes via release as they are shared, and
@@ -803,14 +878,17 @@ public:
*/
class AcceptNode: public SharedNode {
public:
AcceptNode() { }
AcceptNode() { type_flags |= NODE_TYPE_ACCEPT; }
int is_accept(void) { return true; }
int is_postprocess(void) { return false; }
};
class MatchFlag: public AcceptNode {
public:
MatchFlag(uint32_t flag, uint32_t audit): flag(flag), audit(audit) { }
MatchFlag(uint32_t flag, uint32_t audit): flag(flag), audit(audit)
{
type_flags |= NODE_TYPE_MATCHFLAG;
}
ostream &dump(ostream &os) { return os << "< 0x" << hex << flag << '>'; }
uint32_t flag;
@@ -819,12 +897,18 @@ public:
class ExactMatchFlag: public MatchFlag {
public:
ExactMatchFlag(uint32_t flag, uint32_t audit): MatchFlag(flag, audit) {}
ExactMatchFlag(uint32_t flag, uint32_t audit): MatchFlag(flag, audit)
{
type_flags |= NODE_TYPE_EXACTMATCHFLAG;
}
};
class DenyMatchFlag: public MatchFlag {
public:
DenyMatchFlag(uint32_t flag, uint32_t quiet): MatchFlag(flag, quiet) {}
DenyMatchFlag(uint32_t flag, uint32_t quiet): MatchFlag(flag, quiet)
{
type_flags |= NODE_TYPE_DENYMATCHFLAG;
}
};
/* Traverse the syntax tree depth-first in an iterator-like manner. */
@@ -833,7 +917,7 @@ class depth_first_traversal {
void push_left(Node *node) {
pos.push(node);
while (dynamic_cast<InnerNode *>(node)) {
while (node->is_type(NODE_TYPE_INNER)) {
pos.push(node->child[0]);
node = node->child[0];
}

View File

@@ -651,13 +651,13 @@ void DFA::minimize(dfaflags_t flags)
list<Partition *> partitions;
/* Set up the initial partitions
* minimium of - 1 non accepting, and 1 accepting
* minimum of - 1 non accepting, and 1 accepting
* if trans hashing is used the accepting and non-accepting partitions
* can be further split based on the number and type of transitions
* a state makes.
* If permission hashing is enabled the accepting partitions can
* be further divided by permissions. This can result in not
* obtaining a truely minimized dfa but comes close, and can speedup
* obtaining a truly minimized dfa but comes close, and can speedup
* minimization.
*/
int accept_count = 0;
@@ -753,7 +753,7 @@ void DFA::minimize(dfaflags_t flags)
/* Remap the dfa so it uses the representative states
* Use the first state of a partition as the representative state
* At this point all states with in a partion have transitions
* At this point all states with in a partition have transitions
* to states within the same partitions, however this can slow
* down compressed dfa compression as there are more states,
*/
@@ -813,7 +813,7 @@ void DFA::minimize(dfaflags_t flags)
}
/* Now that the states have been remapped, remove all states
* that are not the representive states for their partition, they
* that are not the representative states for their partition, they
* will have a label == -1
*/
for (Partition::iterator i = states.begin(); i != states.end();) {
@@ -875,7 +875,7 @@ static int diff_partition(State *state, Partition &part, int max_range, int uppe
/**
* diff_encode - compress dfa by differentially encoding state transitions
* @dfa_flags: flags controling dfa creation
* @dfa_flags: flags controlling dfa creation
*
* This function reduces the number of transitions that need to be stored
* by encoding transitions as the difference between the state and a
@@ -889,7 +889,7 @@ static int diff_partition(State *state, Partition &part, int max_range, int uppe
* - The number of state transitions needed to match an input of length
* m will be 2m
*
* To guarentee this the ordering and distance calculation is done in the
* To guarantee this the ordering and distance calculation is done in the
* following manner.
* - A DAG of the DFA is created starting with the start state(s).
* - A state can only be relative (have a differential encoding) to
@@ -1352,17 +1352,18 @@ int accept_perms(NodeSet *state, perms_t &perms, bool filedfa)
return error;
for (NodeSet::iterator i = state->begin(); i != state->end(); i++) {
MatchFlag *match;
if (!(match = dynamic_cast<MatchFlag *>(*i)))
if (!(*i)->is_type(NODE_TYPE_MATCHFLAG))
continue;
if (dynamic_cast<ExactMatchFlag *>(match)) {
MatchFlag *match = static_cast<MatchFlag *>(*i);
if (match->is_type(NODE_TYPE_EXACTMATCHFLAG)) {
/* exact match only ever happens with x */
if (filedfa && !is_merged_x_consistent(exact_match_allow,
match->flag))
error = 1;;
exact_match_allow |= match->flag;
exact_audit |= match->audit;
} else if (dynamic_cast<DenyMatchFlag *>(match)) {
} else if (match->is_type(NODE_TYPE_DENYMATCHFLAG)) {
perms.deny |= match->flag;
perms.quiet |= match->audit;
} else {

View File

@@ -189,7 +189,7 @@ struct DiffDag {
* accept: the accept permissions for the state
* trans: set of transitions from this state
* otherwise: the default state for transitions not in @trans
* parition: Is a temporary work variable used during dfa minimization.
* partition: Is a temporary work variable used during dfa minimization.
* it can be replaced with a map, but that is slower and uses more
* memory.
* proto: Is a temporary work variable used during dfa creation. It can

View File

@@ -76,7 +76,7 @@ static inline Chars* insert_char_range(Chars* cset, transchar a, transchar b)
%%
/* FIXME: Does not parse "[--]", "[---]", "[^^-x]". I don't actually know
which precise grammer Perl regexs use, and rediscovering that
which precise grammar Perl regexs use, and rediscovering that
is proving to be painful. */
regex : /* empty */ { *root = $$ = &epsnode; }

View File

@@ -206,7 +206,7 @@
* AppArmor mount rule encoding
*
* TODO:
* add semantic checking of options against specified filesytem types
* add semantic checking of options against specified filesystem types
* to catch mount options that can't be covered.
*
*
@@ -457,7 +457,7 @@ ostream &mnt_rule::dump(ostream &os)
else if (allow & AA_MAY_PIVOTROOT)
os << "pivotroot";
else
os << "error: unknonwn mount perm";
os << "error: unknown mount perm";
os << " (0x" << hex << flags << " - 0x" << inv_flags << ") ";
if (dev_type) {

View File

@@ -1,7 +1,7 @@
# parser.conf is a global AppArmor config file for the apparmor_parser
#
# It can be used to specify the default options for the parser, which
# can then be overriden by options passed on the command line.
# can then be overridden by options passed on the command line.
#
# Leading whitespace is ignored and lines that begin with # are treated
# as comments.
@@ -43,7 +43,7 @@
#skip-read-cache
#### Set Optimizaions. Multiple Optimizations can be set, one per line ####
#### Set Optimizations. Multiple Optimizations can be set, one per line ####
# For supported optimizations see
# apparmor_parser --help=O
@@ -65,10 +65,15 @@
### policy to be used in AppArmor 3.x without the warning
### Warning from stdin (stdin line 1): apparmor_parser: File 'example'
### missing feature abi, falling back to default policy feature abi.
### For more info please see
### https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorpolicyfeaturesabi
### Turn off abi rule warnings without pinning the abi
#warn=no-abi
### Only a single feature ABI rule should be used at a time.
## Pin older policy to the 5.4 kernel abi
#policy-features=/etc/apparmor.d/abi/kernel-5.4-outoftree-network
#policy-features=/etc/apparmor.d/abi/kernel-5.4-vanilla
## Pin older policy to the 5.4 kernel abi + out of tree network and af_unix
#policy-features=/etc/apparmor.d/abi/kernel-5.4-vanilla
#policy-features=/etc/apparmor.d/abi/kernel-5.4-outoftree-network

View File

@@ -373,7 +373,6 @@ extern int skip_mode_force;
extern int abort_on_error;
extern int skip_bad_cache_rebuild;
extern int mru_skip_cache;
extern int debug_cache;
/* provided by parser_lex.l (cannot be used in tst builds) */
extern FILE *yyin;

View File

@@ -23,7 +23,7 @@
We support 2 types of includes
#include <name> which searches for the first occurance of name in the
#include <name> which searches for the first occurrence of name in the
apparmor directory path.
#include "name" which will search for a relative or absolute pathed
@@ -60,7 +60,7 @@
static char *path[MAX_PATH] = { NULL };
static int npath = 0;
/* default base directory is /etc/apparmor.d, it can be overriden
/* default base directory is /etc/apparmor.d, it can be overridden
with the -b option. */
const char *basedir;

View File

@@ -359,7 +359,7 @@ void sd_serialize_xtable(std::ostringstream &buf, char **table)
int len = strlen(table[i]) + 1;
/* if its a namespace make sure the second : is overwritten
* with 0, so that the namespace and name are \0 seperated
* with 0, so that the namespace and name are \0 separated
*/
if (*table[i] == ':') {
char *tmp = table[i] + 1;

View File

@@ -87,7 +87,10 @@ int mru_skip_cache = 1;
* n : use that number of processes/threads to compile policy
*/
#define JOBS_AUTO LONG_MIN
long jobs_max = -8; /* 8 * cpus */
#define DEFAULT_JOBS_MAX -8
#define DEFAULT_ESTIMATED_JOB_SIZE (50 * 1024 * 1024)
long estimated_job_size = DEFAULT_ESTIMATED_JOB_SIZE;
long jobs_max = -DEFAULT_JOBS_MAX; /* 8 * cpus */
long jobs = JOBS_AUTO; /* default: number of processor cores */
long njobs = 0;
long jobs_scale = 0; /* number of chance to resample online
@@ -129,6 +132,7 @@ static const char *config_file = "/etc/apparmor/parser.conf";
#define ARG_OVERRIDE_POLICY_ABI 141
#define EARLY_ARG_CONFIG_FILE 142
#define ARG_WERROR 143
#define ARG_ESTIMATED_COMPILE_SIZE 144
/* Make sure to update BOTH the short and long_options */
static const char *short_options = "ad::f:h::rRVvI:b:BCD:NSm:M:qQn:XKTWkL:O:po:j:";
@@ -183,6 +187,7 @@ struct option long_options[] = {
{"print-config-file", 0, 0, ARG_PRINT_CONFIG_FILE}, /* no short option */
{"override-policy-abi", 1, 0, ARG_OVERRIDE_POLICY_ABI}, /* no short option */
{"config-file", 1, 0, EARLY_ARG_CONFIG_FILE}, /* early option, no short option */
{"estimated-compile-size", 1, 0, ARG_ESTIMATED_COMPILE_SIZE}, /* no short option, not in help */
{NULL, 0, 0, 0},
};
@@ -259,7 +264,7 @@ optflag_table_t warnflag_table[] = {
{ 1, "jobs", "enable job control warnings", WARN_JOBS },
{ 1, "dangerous", "warn on dangerous policy", WARN_DANGEROUS },
{ 1, "unexpected", "warn when an unexpected condition is found", WARN_UNEXPECTED },
{ 1, "format", "warn on unnecessary or confusing formating", WARN_FORMAT },
{ 1, "format", "warn on unnecessary or confusing formatting", WARN_FORMAT },
{ 1, "missing", "warn when missing qualifier and a default is used", WARN_MISSING },
{ 1, "override", "warn when overriding", WARN_OVERRIDE },
{ 1, "dev", "turn on warnings that are useful for profile development", WARN_DEV },
@@ -413,6 +418,19 @@ static long process_jobs_arg(const char *arg, const char *val) {
return n;
}
static long str_to_size(const char *s)
{
if (*s == '\0')
return 1;
else if (strcmp(s, "KB") == 0)
return 1024;
else if (strcmp(s, "MB") == 0)
return 1024*1024;
else if (strcmp(s, "GB") == 0)
return 1024*1024*1024;
return -1;
}
#define EARLY_ARG 1
#define LATE_ARG 2
#define TWOPASS_ARG (EARLY_ARG | LATE_ARG)
@@ -433,7 +451,7 @@ int arg_pass(int c) {
return LATE_ARG;
}
/* process a single argment from getopt_long
/* process a single argument from getopt_long
* Returns: 1 if an action arg, else 0
*/
#define DUMP_HEADER " variables \tDump variables\n" \
@@ -730,6 +748,8 @@ static int process_arg(int c, char *optarg)
jobs = process_jobs_arg("-j", optarg);
if (jobs == 0)
jobs_max = 0;
else if (jobs != JOBS_AUTO && jobs < LONG_MAX)
jobs_max = jobs;
break;
case ARG_MAX_JOBS:
jobs_max = process_jobs_arg("max-jobs", optarg);
@@ -748,6 +768,21 @@ static int process_arg(int c, char *optarg)
case ARG_PRINT_CONFIG_FILE:
printf("%s\n", config_file);
break;
case ARG_ESTIMATED_COMPILE_SIZE:
/* used to auto tune parser on low resource systems */
{
char *end;
long mult;
long long tmp = strtoll(optarg, &end, 0);
if (end == optarg ||
(errno == ERANGE && (tmp == LLONG_MIN || tmp == LLONG_MAX)) ||
(mult = str_to_size(end)) == -1) {
PERROR("%s: --estimated-compile-size invalid size '%s'", progname, optarg);
exit(1);
}
estimated_job_size = tmp * mult;
}
break;
default:
/* 'unrecognized option' error message gets printed by getopt_long() */
exit(1);
@@ -1159,9 +1194,11 @@ int process_profile(int option, aa_kernel_interface *kernel_interface,
/* cache file generated by load_policy */
retval = load_policy(option, kernel_interface, cachetmp);
if (retval == 0 && write_cache) {
if (cachetmp == -1) {
if (force_complain) {
pwarn(WARN_CACHE, "Caching disabled for: '%s' due to force complain\n", basename);
} else if (cachetmp == -1) {
unlink(cachetmpname);
pwarn(WARN_CACHE, "Warning failed to create cache: %s\n",
pwarn(WARN_CACHE, "Failed to create cache: %s\n",
basename);
} else {
install_cache(cachetmpname, writecachename);
@@ -1256,7 +1293,7 @@ do { \
* from work_spawn and work_sync. We could throw a C++ exception, is it
* worth doing it to avoid the exit here.
*
* atm not all resources maybe cleanedup at exit
* atm not all resources may be cleaned up at exit
*/
int last_error = 0;
void handle_work_result(int retval)
@@ -1284,33 +1321,120 @@ static long compute_jobs(long n, long j)
return j;
}
static void setup_parallel_compile(void)
static void setup_parallel_compile(long ncpus, long maxcpus)
{
/* jobs and paralell_max set by default, config or args */
long n = sysconf(_SC_NPROCESSORS_ONLN);
long maxn = sysconf(_SC_NPROCESSORS_CONF);
if (n == -1)
/* unable to determine number of processors, default to 1 */
n = 1;
if (maxn == -1)
/* unable to determine number of processors, default to 1 */
maxn = 1;
jobs = compute_jobs(n, jobs);
jobs_max = compute_jobs(maxn, jobs_max);
/* jobs and parallel_max set by default, config or args */
if (jobs < 0 || jobs == JOBS_AUTO)
jobs_scale = 1;
jobs = compute_jobs(ncpus, jobs);
jobs_max = compute_jobs(maxcpus, jobs_max);
if (jobs > jobs_max) {
pwarn(WARN_JOBS, "%s: Warning capping number of jobs to %ld * # of cpus == '%ld'",
pwarn(WARN_JOBS, "%s: Capping number of jobs to %ld * # of cpus == '%ld'",
progname, jobs_max, jobs);
jobs = jobs_max;
} else if (jobs < jobs_max)
} else if (jobs_scale && jobs < jobs_max)
/* the bigger the difference the more sample chances given */
jobs_scale = jobs_max + 1 - n;
jobs_scale = jobs_max + 1 - ncpus;
njobs = 0;
if (debug_jobs)
fprintf(stderr, "jobs: %ld\n", jobs);
}
/*
* Tune parameters to adjust the parser to adapt to low memory, low power
* systems.
* with a profile compile taking up to 10s of MB, launching a lot of
* parallel compiles is a bad idea on lauch 16 parallel compiles with
* only 50 MB free.
*
*/
#define PREFIX_TOTAL "MemTotal:"
#define PREFIX_FREE "MemFree:"
#define PREFIX_CACHE "Cached:"
static bool get_memstat(long long &mem_total, long long &mem_free,
long long &mem_cache)
{
char *line, buf[256];
autofclose FILE *f = NULL;
mem_total = mem_free = mem_cache = -1;
/* parse /proc/meminfo to get a rough idea of available mem,
look into libstatgrab as alternative */
f = fopen("/proc/meminfo", "r");
if (f == NULL) {
PDEBUG("Failed to open /proc/meminfo");
return false;
}
while ((line = fgets(buf, sizeof(buf), f)) != NULL) {
long long value;
if (sscanf(buf, "%*s %lld kB", &value) != 1)
continue;
if (strncmp(buf, PREFIX_FREE, strlen(PREFIX_FREE)) == 0)
mem_free = value * 1024;
else if (strncmp(buf, PREFIX_TOTAL, strlen(PREFIX_TOTAL)) == 0)
mem_total = value * 1024;
else if (strncmp(buf, PREFIX_CACHE, strlen(PREFIX_CACHE)) == 0)
mem_cache = value * 1024;
}
if (mem_free == -1 || mem_total == -1 || mem_cache == -1) {
PDEBUG("Failed to parse mem value");
return false;
}
mem_free += mem_cache;
return true;
}
static void auto_tune_parameters(void)
{
long long mem_total, mem_free, mem_cache;
long ncpus = sysconf(_SC_NPROCESSORS_ONLN);
long maxcpus = sysconf(_SC_NPROCESSORS_CONF);
if (ncpus == -1) {
PDEBUG("Unable to determine number of processors, default to 1");
ncpus = 1;
}
if (maxcpus == -1) {
PDEBUG("Unable to determine number of processors, default to 1");
maxcpus = 1;
}
/* only override if config or param hasn't overridden */
if (get_memstat(mem_total, mem_free, mem_cache) == true &&
jobs == JOBS_AUTO) {
long estimated_jobs = (long) (mem_free / estimated_job_size);
if (mem_free < 2) {
/* -j0 - no workers */
jobs = jobs_max = 0;
PDEBUG("Auto tune: --jobs=0");
} else if (estimated_jobs < ncpus) {
/* --jobs=estimate_jobs */
jobs = estimated_jobs;
PDEBUG("Auto tune: --jobs=%d", estimate_jobs);
} else {
long long n = estimated_jobs / ncpus;
if (n < -DEFAULT_JOBS_MAX) {
/* --jobs=cpus*n */
jobs = -n;
PDEBUG("Auto tune: --jobs=%d", jobs);
}
}
} else {
PDEBUG("Unable to get meminfo, using defaults");
}
setup_parallel_compile(ncpus, maxcpus);
}
struct dir_cb_data {
aa_kernel_interface *kernel_interface;
const char *dirname; /* name of the parent dir */
@@ -1414,7 +1538,7 @@ int main(int argc, char *argv[])
process_config_file(config_file);
optind = process_args(argc, argv);
setup_parallel_compile();
auto_tune_parameters();
setlocale(LC_MESSAGES, "");
bindtextdomain(PACKAGE, LOCALEDIR);

View File

@@ -326,7 +326,8 @@ bool add_cap_feature_mask(struct aa_features *features, capability_flags flags)
value = aa_features_value(features, "caps/mask", &valuelen);
if (!value)
return false;
/* nothing to add, just use existing set */
return true;
n = 0;
for (capstr = strn_token(value, len);

View File

@@ -534,7 +534,7 @@ static int process_profile_name_xmatch(Profile *prof)
int len;
tbuf.clear();
/* prepend \x00 to every value. This is
* done to separate the existance of the
* done to separate the existence of the
* xattr from a null value match.
*
* if an xattr exists, a single \x00 will
@@ -642,6 +642,7 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
int pos;
vec[0] = tbuf.c_str();
if (entry->link_name) {
filter_slashes(entry->link_name);
ptype = convert_aaregex_to_pcre(entry->link_name, 0, glob_default, lbuf, &pos);
if (ptype == ePatternInvalid)
return FALSE;

View File

@@ -847,13 +847,13 @@ int main(void)
MY_TEST(retval == 0, "get boolean variable 2");
retval = get_boolean_var("non_existant");
MY_TEST(retval < 0, "get nonexistant boolean variable");
MY_TEST(retval < 0, "get nonexistent boolean variable");
retval = get_boolean_var("stereopuff");
MY_TEST(retval < 0, "get boolean variable that's declared a set var");
retptr = get_set_var("daves_not_here_man");
MY_TEST(retptr == NULL, "get non-existent set variable");
MY_TEST(retptr == NULL, "get nonexistent set variable");
retptr = get_set_var("abuse");
MY_TEST(retptr == NULL, "get set variable that's declared a boolean");

View File

@@ -1,5 +1,5 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR NOVELL, Inc.
# Copyright (C) YEAR Canonical Ltd
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: apparmor@lists.ubuntu.com\n"
"POT-Creation-Date: 2014-09-13 00:11-0700\n"
"POT-Creation-Date: 2020-10-14 03:51-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,95 +17,106 @@ msgstr ""
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: ../parser_include.c:113 ../parser_include.c:111
#: ../parser_include.c:113 ../parser_include.c:111 ../parser_include.c:96
msgid "Error: Out of memory.\n"
msgstr ""
#: ../parser_include.c:123 ../parser_include.c:121
#: ../parser_include.c:123 ../parser_include.c:121 ../parser_include.c:106
#, c-format
msgid "Error: basedir %s is not a directory, skipping.\n"
msgstr ""
#: ../parser_include.c:137
#: ../parser_include.c:137 ../parser_include.c:122
#, c-format
msgid "Error: Could not add directory %s to search path.\n"
msgstr ""
#: ../parser_include.c:147 ../parser_include.c:151
#: ../parser_include.c:147 ../parser_include.c:151 ../parser_include.c:136
msgid "Error: Could not allocate memory.\n"
msgstr ""
#: ../parser_interface.c:69 ../parser_interface.c:72 ../parser_interface.c:49
#: ../parser_interface.c:52
msgid "Bad write position\n"
msgstr ""
#: ../parser_interface.c:72 ../parser_interface.c:75 ../parser_interface.c:52
#: ../parser_interface.c:55
msgid "Permission denied\n"
msgstr ""
#: ../parser_interface.c:75 ../parser_interface.c:78 ../parser_interface.c:55
#: ../parser_interface.c:58
msgid "Out of memory\n"
msgstr ""
#: ../parser_interface.c:78 ../parser_interface.c:81 ../parser_interface.c:58
#: ../parser_interface.c:61
msgid "Couldn't copy profile: Bad memory address\n"
msgstr ""
#: ../parser_interface.c:81 ../parser_interface.c:84 ../parser_interface.c:61
#: ../parser_interface.c:64
msgid "Profile doesn't conform to protocol\n"
msgstr ""
#: ../parser_interface.c:84 ../parser_interface.c:87 ../parser_interface.c:64
#: ../parser_interface.c:67
msgid "Profile does not match signature\n"
msgstr ""
#: ../parser_interface.c:87 ../parser_interface.c:90 ../parser_interface.c:67
#: ../parser_interface.c:70
msgid "Profile version not supported by Apparmor module\n"
msgstr ""
#: ../parser_interface.c:90 ../parser_interface.c:93 ../parser_interface.c:70
#: ../parser_interface.c:73
msgid "Profile already exists\n"
msgstr ""
#: ../parser_interface.c:93 ../parser_interface.c:96 ../parser_interface.c:73
#: ../parser_interface.c:76
msgid "Profile doesn't exist\n"
msgstr ""
#: ../parser_interface.c:96 ../parser_interface.c:99 ../parser_interface.c:76
#: ../parser_interface.c:79
msgid "Permission denied; attempted to load a profile while confined?\n"
msgstr ""
#: ../parser_interface.c:99 ../parser_interface.c:102 ../parser_interface.c:79
#: ../parser_interface.c:82
#, c-format
msgid "Unknown error (%d): %s\n"
msgstr ""
#: ../parser_interface.c:116 ../parser_interface.c:119
#: ../parser_interface.c:96
#: ../parser_interface.c:116 ../parser_interface.c:119 ../parser_interface.c:96
#: ../parser_interface.c:100
#, c-format
msgid "%s: Unable to add \"%s\". "
msgstr ""
#: ../parser_interface.c:121 ../parser_interface.c:124
#: ../parser_interface.c:101
#: ../parser_interface.c:101 ../parser_interface.c:105
#, c-format
msgid "%s: Unable to replace \"%s\". "
msgstr ""
#: ../parser_interface.c:126 ../parser_interface.c:129
#: ../parser_interface.c:106
#: ../parser_interface.c:106 ../parser_interface.c:110
#, c-format
msgid "%s: Unable to remove \"%s\". "
msgstr ""
#: ../parser_interface.c:131 ../parser_interface.c:134
#: ../parser_interface.c:111
#: ../parser_interface.c:111 ../parser_interface.c:115
#, c-format
msgid "%s: Unable to write to stdout\n"
msgstr ""
#: ../parser_interface.c:135 ../parser_interface.c:138
#: ../parser_interface.c:115
#: ../parser_interface.c:115 ../parser_interface.c:119
#, c-format
msgid "%s: Unable to write to output file\n"
msgstr ""
@@ -113,24 +124,25 @@ msgstr ""
#: ../parser_interface.c:138 ../parser_interface.c:162
#: ../parser_interface.c:141 ../parser_interface.c:165
#: ../parser_interface.c:118 ../parser_interface.c:142
#: ../parser_interface.c:123 ../parser_interface.c:147
#, c-format
msgid "%s: ASSERT: Invalid option: %d\n"
msgstr ""
#: ../parser_interface.c:147 ../parser_interface.c:150
#: ../parser_interface.c:127
#: ../parser_interface.c:127 ../parser_interface.c:132
#, c-format
msgid "Addition succeeded for \"%s\".\n"
msgstr ""
#: ../parser_interface.c:151 ../parser_interface.c:154
#: ../parser_interface.c:131
#: ../parser_interface.c:131 ../parser_interface.c:136
#, c-format
msgid "Replacement succeeded for \"%s\".\n"
msgstr ""
#: ../parser_interface.c:155 ../parser_interface.c:158
#: ../parser_interface.c:135
#: ../parser_interface.c:135 ../parser_interface.c:140
#, c-format
msgid "Removal succeeded for \"%s\".\n"
msgstr ""
@@ -141,7 +153,7 @@ msgid "PANIC bad increment buffer %p pos %p ext %p size %d res %p\n"
msgstr ""
#: ../parser_interface.c:656 ../parser_interface.c:658
#: ../parser_interface.c:446
#: ../parser_interface.c:446 ../parser_interface.c:476
#, c-format
msgid "profile %s network rules not enforced\n"
msgstr ""
@@ -186,7 +198,7 @@ msgid "%s: Unable to write entire profile entry\n"
msgstr ""
#: ../parser_interface.c:839 ../parser_interface.c:831
#: ../parser_interface.c:593
#: ../parser_interface.c:593 ../parser_interface.c:579
#, c-format
msgid "%s: Unable to write entire profile entry to cache\n"
msgstr ""
@@ -196,7 +208,7 @@ msgstr ""
msgid "Could not open '%s'"
msgstr ""
#: parser_lex.l:104 parser_lex.l:167 parser_lex.l:173
#: parser_lex.l:104 parser_lex.l:167 parser_lex.l:173 parser_lex.l:174
#, c-format
msgid "fstat failed for '%s'"
msgstr ""
@@ -222,7 +234,7 @@ msgstr ""
msgid "Found unexpected character: '%s'"
msgstr ""
#: parser_lex.l:386 parser_lex.l:418 parser_lex.l:428
#: parser_lex.l:386 parser_lex.l:418 parser_lex.l:428 parser_lex.l:474
msgid "Variable declarations do not accept trailing commas"
msgstr ""
@@ -242,6 +254,7 @@ msgid "%s: Could not allocate memory for subdomainbase mount point\n"
msgstr ""
#: ../parser_main.c:577 ../parser_main.c:616 ../parser_main.c:479
#: ../parser_main.c:1444
#, c-format
msgid ""
"Warning: unable to find a suitable fs in %s, is it mounted?\n"
@@ -249,6 +262,7 @@ msgid ""
msgstr ""
#: ../parser_main.c:597 ../parser_main.c:635 ../parser_main.c:498
#: ../parser_main.c:822
#, c-format
msgid ""
"%s: Sorry. You need root privileges to run this program.\n"
@@ -256,6 +270,7 @@ msgid ""
msgstr ""
#: ../parser_main.c:604 ../parser_main.c:642 ../parser_main.c:505
#: ../parser_main.c:828
#, c-format
msgid ""
"%s: Warning! You've set this program setuid root.\n"
@@ -264,7 +279,7 @@ msgid ""
msgstr ""
#: ../parser_main.c:704 ../parser_main.c:813 ../parser_main.c:836
#: ../parser_main.c:946 ../parser_main.c:860
#: ../parser_main.c:946 ../parser_main.c:860 ../parser_main.c:1038
#, c-format
msgid "Error: Could not read profile %s: %s.\n"
msgstr ""
@@ -286,26 +301,36 @@ msgstr ""
#: parser_yacc.y:1166 parser_yacc.y:1170 parser_yacc.y:1180 parser_yacc.y:1190
#: parser_yacc.y:1298 parser_yacc.y:1376 parser_yacc.y:1479 parser_yacc.y:1490
#: parser_yacc.y:1565 parser_yacc.y:1583 parser_yacc.y:1590 parser_yacc.y:1639
#: ../network.c:314 ../af_unix.cc:203
#: ../network.c:314 ../af_unix.cc:203 ../parser_misc.c:215 ../parser_misc.c:939
#: parser_yacc.y:343 parser_yacc.y:367 parser_yacc.y:533 parser_yacc.y:543
#: parser_yacc.y:660 parser_yacc.y:741 parser_yacc.y:750 parser_yacc.y:1171
#: parser_yacc.y:1219 parser_yacc.y:1255 parser_yacc.y:1264 parser_yacc.y:1268
#: parser_yacc.y:1278 parser_yacc.y:1288 parser_yacc.y:1382 parser_yacc.y:1460
#: parser_yacc.y:1592 parser_yacc.y:1597 parser_yacc.y:1674 parser_yacc.y:1692
#: parser_yacc.y:1699 parser_yacc.y:1748 ../network.c:315 ../af_unix.cc:194
msgid "Memory allocation error."
msgstr ""
#: ../parser_main.c:740 ../parser_main.c:872 ../parser_main.c:757
#: ../parser_main.c:975
#, c-format
msgid "Cached load succeeded for \"%s\".\n"
msgstr ""
#: ../parser_main.c:744 ../parser_main.c:876 ../parser_main.c:761
#: ../parser_main.c:979
#, c-format
msgid "Cached reload succeeded for \"%s\".\n"
msgstr ""
#: ../parser_main.c:910 ../parser_main.c:1058 ../parser_main.c:967
#: ../parser_main.c:1132
#, c-format
msgid "%s: Errors found in file. Aborting.\n"
msgstr ""
#: ../parser_misc.c:426 ../parser_misc.c:597 ../parser_misc.c:339
#: ../parser_misc.c:532
msgid ""
"Uppercase qualifiers \"RWLIMX\" are deprecated, please convert to lowercase\n"
"See the apparmor.d(5) manpage for details.\n"
@@ -313,14 +338,17 @@ msgstr ""
#: ../parser_misc.c:467 ../parser_misc.c:474 ../parser_misc.c:638
#: ../parser_misc.c:645 ../parser_misc.c:380 ../parser_misc.c:387
#: ../parser_misc.c:573 ../parser_misc.c:580
msgid "Conflict 'a' and 'w' perms are mutually exclusive."
msgstr ""
#: ../parser_misc.c:491 ../parser_misc.c:662 ../parser_misc.c:404
#: ../parser_misc.c:597
msgid "Exec qualifier 'i' invalid, conflicting qualifier already specified"
msgstr ""
#: ../parser_misc.c:502 ../parser_misc.c:673 ../parser_misc.c:415
#: ../parser_misc.c:608
#, c-format
msgid ""
"Unconfined exec qualifier (%c%c) allows some dangerous environment variables "
@@ -329,22 +357,26 @@ msgstr ""
#: ../parser_misc.c:510 ../parser_misc.c:551 ../parser_misc.c:681
#: ../parser_misc.c:722 ../parser_misc.c:423 ../parser_misc.c:464
#: ../parser_misc.c:616 ../parser_misc.c:657
#, c-format
msgid "Exec qualifier '%c' invalid, conflicting qualifier already specified"
msgstr ""
#: ../parser_misc.c:537 ../parser_misc.c:545 ../parser_misc.c:708
#: ../parser_misc.c:716 ../parser_misc.c:450 ../parser_misc.c:458
#: ../parser_misc.c:643 ../parser_misc.c:651
#, c-format
msgid "Exec qualifier '%c%c' invalid, conflicting qualifier already specified"
msgstr ""
#: ../parser_misc.c:593 ../parser_misc.c:764 ../parser_misc.c:506
#: ../parser_misc.c:699
#, c-format
msgid "Internal: unexpected mode character '%c' in input"
msgstr ""
#: ../parser_misc.c:615 ../parser_misc.c:786 ../parser_misc.c:528
#: ../parser_misc.c:721
#, c-format
msgid "Internal error generated invalid perm 0x%llx\n"
msgstr ""
@@ -356,10 +388,12 @@ msgid "AppArmor parser error: %s\n"
msgstr ""
#: ../parser_merge.c:92 ../parser_merge.c:91 ../parser_merge.c:83
#: ../parser_merge.c:71
msgid "Couldn't merge entries. Out of Memory\n"
msgstr ""
#: ../parser_merge.c:111 ../parser_merge.c:113 ../parser_merge.c:105
#: ../parser_merge.c:93
#, c-format
msgid "profile %s: has merged rule %s with conflicting x modifiers\n"
msgstr ""
@@ -368,114 +402,117 @@ msgstr ""
msgid "Profile attachment must begin with a '/'."
msgstr ""
#: parser_yacc.y:260 parser_yacc.y:302 parser_yacc.y:348
#: parser_yacc.y:260 parser_yacc.y:302 parser_yacc.y:348 parser_yacc.y:407
msgid ""
"Profile names must begin with a '/', namespace or keyword 'profile' or 'hat'."
msgstr ""
#: parser_yacc.y:296 parser_yacc.y:338 parser_yacc.y:384
#: parser_yacc.y:296 parser_yacc.y:338 parser_yacc.y:384 parser_yacc.y:449
#, c-format
msgid "Failed to create alias %s -> %s\n"
msgstr ""
#: parser_yacc.y:417 parser_yacc.y:460 parser_yacc.y:506
#: parser_yacc.y:417 parser_yacc.y:460 parser_yacc.y:506 parser_yacc.y:581
msgid "Profile flag chroot_relative conflicts with namespace_relative"
msgstr ""
#: parser_yacc.y:421 parser_yacc.y:464 parser_yacc.y:510
#: parser_yacc.y:421 parser_yacc.y:464 parser_yacc.y:510 parser_yacc.y:585
msgid "Profile flag mediate_deleted conflicts with delegate_deleted"
msgstr ""
#: parser_yacc.y:424 parser_yacc.y:467 parser_yacc.y:513
#: parser_yacc.y:424 parser_yacc.y:467 parser_yacc.y:513 parser_yacc.y:588
msgid "Profile flag attach_disconnected conflicts with no_attach_disconnected"
msgstr ""
#: parser_yacc.y:427 parser_yacc.y:470 parser_yacc.y:516
#: parser_yacc.y:427 parser_yacc.y:470 parser_yacc.y:516 parser_yacc.y:591
msgid "Profile flag chroot_attach conflicts with chroot_no_attach"
msgstr ""
#: parser_yacc.y:441 parser_yacc.y:484 parser_yacc.y:530
#: parser_yacc.y:441 parser_yacc.y:484 parser_yacc.y:530 parser_yacc.y:607
msgid "Profile flag 'debug' is no longer valid."
msgstr ""
#: parser_yacc.y:463 parser_yacc.y:506 parser_yacc.y:552
#: parser_yacc.y:463 parser_yacc.y:506 parser_yacc.y:552 parser_yacc.y:629
#, c-format
msgid "Invalid profile flag: %s."
msgstr ""
#: parser_yacc.y:498 parser_yacc.y:520 parser_yacc.y:548 parser_yacc.y:594
#: parser_yacc.y:673
msgid "Assert: `rule' returned NULL."
msgstr ""
#: parser_yacc.y:501 parser_yacc.y:546 parser_yacc.y:552 parser_yacc.y:584
#: parser_yacc.y:598 parser_yacc.y:630
#: parser_yacc.y:598 parser_yacc.y:630 parser_yacc.y:677 parser_yacc.y:709
msgid ""
"Invalid mode, in deny rules 'x' must not be preceded by exec qualifier 'i', "
"'p', or 'u'"
msgstr ""
#: parser_yacc.y:524 parser_yacc.y:556 parser_yacc.y:602
#: parser_yacc.y:524 parser_yacc.y:556 parser_yacc.y:602 parser_yacc.y:681
msgid ""
"Invalid mode, 'x' must be preceded by exec qualifier 'i', 'p', 'c', or 'u'"
msgstr ""
#: parser_yacc.y:549 parser_yacc.y:587 parser_yacc.y:633
#: parser_yacc.y:549 parser_yacc.y:587 parser_yacc.y:633 parser_yacc.y:712
msgid "Invalid mode, 'x' must be preceded by exec qualifier 'i', 'p', or 'u'"
msgstr ""
#: parser_yacc.y:574 parser_yacc.y:612 parser_yacc.y:614 parser_yacc.y:660
#: parser_yacc.y:739
msgid "Assert: `network_rule' return invalid protocol."
msgstr ""
#: parser_yacc.y:649 parser_yacc.y:696 parser_yacc.y:786
#: parser_yacc.y:649 parser_yacc.y:696 parser_yacc.y:786 parser_yacc.y:867
msgid "Assert: `change_profile' returned NULL."
msgstr ""
#: parser_yacc.y:680 parser_yacc.y:720 parser_yacc.y:810
#: parser_yacc.y:680 parser_yacc.y:720 parser_yacc.y:810 parser_yacc.y:905
msgid "Assert: 'hat rule' returned NULL."
msgstr ""
#: parser_yacc.y:689 parser_yacc.y:729 parser_yacc.y:819
#: parser_yacc.y:689 parser_yacc.y:729 parser_yacc.y:819 parser_yacc.y:914
msgid "Assert: 'local_profile rule' returned NULL."
msgstr ""
#: parser_yacc.y:824 parser_yacc.y:885 parser_yacc.y:992
#: parser_yacc.y:824 parser_yacc.y:885 parser_yacc.y:992 parser_yacc.y:1077
#, c-format
msgid "Unset boolean variable %s used in if-expression"
msgstr ""
#: parser_yacc.y:882 parser_yacc.y:986 parser_yacc.y:1092
#: parser_yacc.y:882 parser_yacc.y:986 parser_yacc.y:1092 parser_yacc.y:1181
msgid "unsafe rule missing exec permissions"
msgstr ""
#: parser_yacc.y:901 parser_yacc.y:954 parser_yacc.y:1060
#: parser_yacc.y:901 parser_yacc.y:954 parser_yacc.y:1060 parser_yacc.y:1148
msgid "subset can only be used with link rules."
msgstr ""
#: parser_yacc.y:903 parser_yacc.y:956 parser_yacc.y:1062
#: parser_yacc.y:903 parser_yacc.y:956 parser_yacc.y:1062 parser_yacc.y:1150
msgid "link and exec perms conflict on a file rule using ->"
msgstr ""
#: parser_yacc.y:905 parser_yacc.y:958 parser_yacc.y:1064
#: parser_yacc.y:905 parser_yacc.y:958 parser_yacc.y:1064 parser_yacc.y:1152
msgid "link perms are not allowed on a named profile transition.\n"
msgstr ""
#: parser_yacc.y:921 parser_yacc.y:1003 parser_yacc.y:1109
#: parser_yacc.y:921 parser_yacc.y:1003 parser_yacc.y:1109 parser_yacc.y:1198
#, c-format
msgid "missing an end of line character? (entry: %s)"
msgstr ""
#: parser_yacc.y:975 parser_yacc.y:985 parser_yacc.y:1057 parser_yacc.y:1067
#: parser_yacc.y:1145 parser_yacc.y:1155
#: parser_yacc.y:1145 parser_yacc.y:1155 parser_yacc.y:1234 parser_yacc.y:1244
msgid "Invalid network entry."
msgstr ""
#: parser_yacc.y:1039 parser_yacc.y:1048 parser_yacc.y:1254 parser_yacc.y:1510
#: parser_yacc.y:1617
#, c-format
msgid "Invalid capability %s."
msgstr ""
#: parser_yacc.y:1066 parser_yacc.y:1269 parser_yacc.y:1525
#: parser_yacc.y:1066 parser_yacc.y:1269 parser_yacc.y:1525 parser_yacc.y:1637
#, c-format
msgid "AppArmor parser error for %s%s%s at line %d: %s\n"
msgstr ""
@@ -491,17 +528,20 @@ msgid "%s: Illegal open {, nesting groupings not allowed\n"
msgstr ""
#: ../parser_regex.c:265 ../parser_regex.c:274 ../parser_regex.c:278
#: ../parser_regex.c:306
#, c-format
msgid "%s: Regex grouping error: Invalid number of items between {}\n"
msgstr ""
#: ../parser_regex.c:271 ../parser_regex.c:280 ../parser_regex.c:284
#: ../parser_regex.c:312
#, c-format
msgid ""
"%s: Regex grouping error: Invalid close }, no matching open { detected\n"
msgstr ""
#: ../parser_regex.c:337 ../parser_regex.c:343 ../parser_regex.c:361
#: ../parser_regex.c:403
#, c-format
msgid ""
"%s: Regex grouping error: Unclosed grouping or character class, expecting "
@@ -514,16 +554,19 @@ msgid "%s: Internal buffer overflow detected, %d characters exceeded\n"
msgstr ""
#: ../parser_regex.c:355 ../parser_regex.c:361 ../parser_regex.c:377
#: ../parser_regex.c:419
#, c-format
msgid "%s: Unable to parse input line '%s'\n"
msgstr ""
#: ../parser_regex.c:397 ../parser_regex.c:405 ../parser_regex.c:421
#: ../parser_regex.c:487
#, c-format
msgid "%s: Invalid profile name '%s' - bad regular expression\n"
msgstr ""
#: ../parser_policy.c:202 ../parser_policy.c:402 ../parser_policy.c:375
#: ../parser_policy.c:383
#, c-format
msgid "ERROR merging rules for profile %s, failed to load\n"
msgstr ""
@@ -537,16 +580,19 @@ msgid ""
msgstr ""
#: ../parser_policy.c:279 ../parser_policy.c:359 ../parser_policy.c:332
#: ../parser_policy.c:340
#, c-format
msgid "ERROR processing regexs for profile %s, failed to load\n"
msgstr ""
#: ../parser_policy.c:306 ../parser_policy.c:389 ../parser_policy.c:362
#: ../parser_policy.c:370
#, c-format
msgid "ERROR expanding variables for profile %s, failed to load\n"
msgstr ""
#: ../parser_policy.c:390 ../parser_policy.c:382 ../parser_policy.c:355
#: ../parser_policy.c:363
#, c-format
msgid "ERROR adding hat access rule for profile %s\n"
msgstr ""
@@ -576,7 +622,7 @@ msgstr ""
msgid "%s: Errors found in combining rules postprocessing. Aborting.\n"
msgstr ""
#: parser_lex.l:180 parser_lex.l:186
#: parser_lex.l:180 parser_lex.l:186 parser_lex.l:187
#, c-format
msgid "Could not process include directory '%s' in '%s'"
msgstr ""
@@ -586,7 +632,8 @@ msgid "Feature buffer full."
msgstr ""
#: ../parser_main.c:1115 ../parser_main.c:1132 ../parser_main.c:1024
#: ../parser_main.c:1041
#: ../parser_main.c:1041 ../parser_main.c:1332 ../parser_main.c:1354
#: ../parser_misc.c:280 ../parser_misc.c:299 ../parser_misc.c:308
msgid "Out of memory"
msgstr ""
@@ -615,11 +662,11 @@ msgstr ""
msgid "Internal error generated invalid DBus perm 0x%x\n"
msgstr ""
#: parser_yacc.y:575 parser_yacc.y:621
#: parser_yacc.y:575 parser_yacc.y:621 parser_yacc.y:700
msgid "deny prefix not allowed"
msgstr ""
#: parser_yacc.y:612 parser_yacc.y:658
#: parser_yacc.y:612 parser_yacc.y:658 parser_yacc.y:737
msgid "owner prefix not allowed"
msgstr ""
@@ -635,41 +682,41 @@ msgstr ""
msgid "owner prefix not allow on capability rules"
msgstr ""
#: parser_yacc.y:1357 parser_yacc.y:1613
#: parser_yacc.y:1357 parser_yacc.y:1613 parser_yacc.y:1722
#, c-format
msgid "invalid mount conditional %s%s"
msgstr ""
#: parser_yacc.y:1374 parser_yacc.y:1628
#: parser_yacc.y:1374 parser_yacc.y:1628 parser_yacc.y:1737
msgid "bad mount rule"
msgstr ""
#: parser_yacc.y:1381 parser_yacc.y:1635
#: parser_yacc.y:1381 parser_yacc.y:1635 parser_yacc.y:1744
msgid "mount point conditions not currently supported"
msgstr ""
#: parser_yacc.y:1398 parser_yacc.y:1650
#: parser_yacc.y:1398 parser_yacc.y:1650 parser_yacc.y:1759
#, c-format
msgid "invalid pivotroot conditional '%s'"
msgstr ""
#: ../parser_regex.c:241 ../parser_regex.c:236
#: ../parser_regex.c:241 ../parser_regex.c:236 ../parser_regex.c:264
#, c-format
msgid ""
"%s: Regex grouping error: Invalid close ], no matching open [ detected\n"
msgstr ""
#: ../parser_regex.c:257 ../parser_regex.c:256
#: ../parser_regex.c:257 ../parser_regex.c:256 ../parser_regex.c:284
#, c-format
msgid "%s: Regex grouping error: Exceeded maximum nesting of {}\n"
msgstr ""
#: ../parser_policy.c:366 ../parser_policy.c:339
#: ../parser_policy.c:366 ../parser_policy.c:339 ../parser_policy.c:347
#, c-format
msgid "ERROR processing policydb rules for profile %s, failed to load\n"
msgstr ""
#: ../parser_policy.c:396 ../parser_policy.c:369
#: ../parser_policy.c:396 ../parser_policy.c:369 ../parser_policy.c:377
#, c-format
msgid "ERROR replacing aliases for profile %s, failed to load\n"
msgstr ""
@@ -689,51 +736,244 @@ msgstr ""
msgid "Error: Could not read cache file '%s', skipping...\n"
msgstr ""
#: ../parser_misc.c:575
#: ../parser_misc.c:575 ../parser_misc.c:768
#, c-format
msgid "Internal: unexpected %s mode character '%c' in input"
msgstr ""
#: ../parser_misc.c:599
#: ../parser_misc.c:599 ../parser_misc.c:792
#, c-format
msgid "Internal error generated invalid %s perm 0x%x\n"
msgstr ""
#: parser_yacc.y:703
#: parser_yacc.y:703 parser_yacc.y:784
msgid "owner prefix not allowed on mount rules"
msgstr ""
#: parser_yacc.y:720
#: parser_yacc.y:720 parser_yacc.y:801
msgid "owner prefix not allowed on dbus rules"
msgstr ""
#: parser_yacc.y:736
#: parser_yacc.y:736 parser_yacc.y:817
msgid "owner prefix not allowed on signal rules"
msgstr ""
#: parser_yacc.y:752
#: parser_yacc.y:752 parser_yacc.y:833
msgid "owner prefix not allowed on ptrace rules"
msgstr ""
#: parser_yacc.y:768
#: parser_yacc.y:768 parser_yacc.y:849 parser_yacc.y:869
msgid "owner prefix not allowed on unix rules"
msgstr ""
#: parser_yacc.y:794
#: parser_yacc.y:794 parser_yacc.y:885
msgid "owner prefix not allowed on capability rules"
msgstr ""
#: parser_yacc.y:1293
#: parser_yacc.y:1293 parser_yacc.y:1377
#, c-format
msgid "dbus rule: invalid conditional group %s=()"
msgstr ""
#: parser_yacc.y:1371
#: parser_yacc.y:1371 parser_yacc.y:1455
#, c-format
msgid "unix rule: invalid conditional group %s=()"
msgstr ""
#: ../parser_regex.c:368
#: ../parser_regex.c:368 ../parser_regex.c:410
#, c-format
msgid "%s: Regex error: trailing '\\' escape character\n"
msgstr ""
#: ../parser_common.c:112
#, c-format
msgid "%s from %s (%s%sline %d): %s"
msgstr ""
#: ../parser_common.c:113
msgid "Warning converted to Error"
msgstr ""
#: ../parser_common.c:113
msgid "Warning"
msgstr ""
#: ../parser_interface.c:524
#, c-format
msgid "Unable to open stdout - %s\n"
msgstr ""
#: ../parser_interface.c:533
#, c-format
msgid "Unable to open output file - %s\n"
msgstr ""
#: parser_lex.l:326
msgid "Failed to process filename\n"
msgstr ""
#: parser_lex.l:720
#, c-format
msgid "Lexer found unexpected character: '%s' (0x%x) in state: %s"
msgstr ""
#: ../parser_main.c:915
#, c-format
msgid "Unable to print the cache directory: %m\n"
msgstr ""
#: ../parser_main.c:951
#, c-format
msgid "Error: Could not load profile %s: %s\n"
msgstr ""
#: ../parser_main.c:961
#, c-format
msgid "Error: Could not replace profile %s: %s\n"
msgstr ""
#: ../parser_main.c:966
#, c-format
msgid "Error: Invalid load option specified: %d\n"
msgstr ""
#: ../parser_main.c:1077
#, c-format
msgid "Could not get cachename for '%s'\n"
msgstr ""
#: ../parser_main.c:1434
msgid "Kernel features abi not found"
msgstr ""
#: ../parser_main.c:1438
msgid "Failed to add kernel capabilities to known capabilities set"
msgstr ""
#: ../parser_main.c:1465
#, c-format
msgid "Failed to clear cache files (%s): %s\n"
msgstr ""
#: ../parser_main.c:1474
msgid ""
"The --create-cache-dir option is deprecated. Please use --write-cache.\n"
msgstr ""
#: ../parser_main.c:1479
#, c-format
msgid "Failed setting up policy cache (%s): %s\n"
msgstr ""
#: ../parser_misc.c:904
#, c-format
msgid "Namespace not terminated: %s\n"
msgstr ""
#: ../parser_misc.c:906
#, c-format
msgid "Empty namespace: %s\n"
msgstr ""
#: ../parser_misc.c:908
#, c-format
msgid "Empty named transition profile name: %s\n"
msgstr ""
#: ../parser_misc.c:910
#, c-format
msgid "Unknown error while parsing label: %s\n"
msgstr ""
#: parser_yacc.y:306
msgid "Failed to setup default policy feature abi"
msgstr ""
#: parser_yacc.y:308
#, c-format
msgid ""
"%s: File '%s' missing feature abi, falling back to default policy feature "
"abi\n"
msgstr ""
#: parser_yacc.y:313
msgid "Failed to add policy capabilities to known capabilities set"
msgstr ""
#: parser_yacc.y:350
msgid "Profile names must begin with a '/' or a namespace"
msgstr ""
#: parser_yacc.y:372
msgid "Profile attachment must begin with a '/' or variable."
msgstr ""
#: parser_yacc.y:375
#, c-format
msgid "profile id: invalid conditional group %s=()"
msgstr ""
#: parser_yacc.y:404
msgid ""
"The use of file paths as profile names is deprecated. See man apparmor.d for "
"more information\n"
msgstr ""
#: parser_yacc.y:573
#, c-format
msgid "Profile flag '%s' conflicts with '%s'"
msgstr ""
#: parser_yacc.y:954
msgid "RLIMIT 'cpu' no units specified using default units of seconds\n"
msgstr ""
#: parser_yacc.y:966
msgid ""
"RLIMIT 'rttime' no units specified using default units of microseconds\n"
msgstr ""
#: parser_yacc.y:1582
msgid "Exec condition is required when unsafe or safe keywords are present"
msgstr ""
#: parser_yacc.y:1584
msgid "Exec condition must begin with '/'."
msgstr ""
#: parser_yacc.y:1643
#, c-format
msgid "AppArmor parser error at line %d: %s\n"
msgstr ""
#: parser_yacc.y:1790
#, c-format
msgid "Could not open '%s': %m"
msgstr ""
#: parser_yacc.y:1795
#, c-format
msgid "fstat failed for '%s': %m"
msgstr ""
#: parser_yacc.y:1809
#, c-format
msgid "failed to find features abi '%s': %m"
msgstr ""
#: parser_yacc.y:1813
#, c-format
msgid ""
"%s: %s features abi '%s' differs from policy declared feature abi, using the "
"features abi declared in policy\n"
msgstr ""
#: ../parser_regex.c:98 ../parser_regex.c:238
#, c-format
msgid "%s: Invalid glob type %d\n"
msgstr ""
#: ../parser_regex.c:693
#, c-format
msgid "The current kernel does not support stacking of named transitions: %s\n"
msgstr ""

View File

@@ -179,7 +179,7 @@ void install_cache(const char *cachetmpname, const char *cachename)
}
if (rename(cachetmpname, cachename) < 0) {
pwarn(WARN_CACHE, "Warning failed to write cache: %s\n", cachename);
pwarn(WARN_CACHE, "Failed to write cache: %s\n", cachename);
unlink(cachetmpname);
}
else if (show_cache) {

View File

@@ -36,7 +36,6 @@ extern int cond_clear_cache; /* only applies if write is set */
extern int force_clear_cache; /* force clearing regargless of state */
extern int create_cache_dir; /* create the cache dir if missing? */
extern int mru_skip_cache;
extern int debug_cache;
void set_cache_tstamp(struct timespec t);
void update_mru_tstamp(FILE *file, const char *path);

View File

@@ -112,7 +112,7 @@ static const char *const sig_names[MAXMAPPED_SIG + 1] = {
"lost",
"unused",
"exists", /* always last existance test mapped to MAXMAPPED_SIG */
"exists", /* always last existence test mapped to MAXMAPPED_SIG */
};

View File

@@ -240,7 +240,7 @@ and may grant confined processes specific mount operations.
The security model of the various versions of NFS is that files are
looked up by name as usual, but after that lookup, each file is only
identified by a file handle in successive acesses. The file handle at a
identified by a file handle in successive accesses. The file handle at a
minimum includes some sort of filesystem identifier and the file's inode
number. In Linux, the file handles used by most filesystems also
include the inode number of the parent directory; this may change in the
@@ -816,7 +816,7 @@ one (this option may be used even if no profile by that name exists):
\subsection{Anatomy of a Profile}
AppArmor profiles use a simple declaritive language, fully described in
AppArmor profiles use a simple declarative language, fully described in
the apparmor.d(5) manual page. By convention, profiles are stored in
/etc/{\H}apparmor.d/. The AppArmor parser supports a simple cpp-style
include mechanism to allow sharing pieces of policy. A simple profile

View File

@@ -23,7 +23,7 @@ tests: error_output caching minimize equality parser_sanity
GEN_TRANS_DIRS=simple_tests/generated_x/ simple_tests/generated_perms_leading/ simple_tests/generated_perms_safe/ simple_tests/generated_dbus
gen_xtrans: $(GEN_TRANS_DIRS)
./gen-xtrans.pl
./gen-xtrans.py
$(GEN_TRANS_DIRS):
mkdir $@

View File

@@ -10,7 +10,7 @@ against a different parser, or use a different set of profiles for the
simple.pl test, you can change those settings in 'uservars.conf'.
You can also override which parser is used through make by specifying
the PARSER veriable. For example, to run the tests on the system parser,
the PARSER variable. For example, to run the tests on the system parser,
run 'make PARSER=/sbin/apparmor_parser'.
Adding to the testsuite
@@ -61,7 +61,7 @@ The simple script looks for a few special comments in the profile,
expected parse result of PASS.
- #=TODO -- marks the test as being for a future item to implement and
thus are expected testsuite failures and hsould be ignored.
thus are expected testsuite failures and should be ignored.
- #=DISABLED -- skips the test, and marks it as a failed TODO task.
Useful if the particular testcase causes the parser to infinite

View File

@@ -568,7 +568,7 @@ verify_binary_equality "set rlimit memlock <= 2GB" \
# Unfortunately we can not just compare an empty profile and hat to a
# ie. "/t { ^test { /f r, }}"
# to the second profile with the equivalent rule inserted manually
# because policy write permission "w" actually expands to mutiple permissions
# because policy write permission "w" actually expands to multiple permissions
# under the hood, and the parser is not adding those permissions
# to the rules it auto generates
# So we insert the rule with "append" permissions, and rely on the parser
@@ -618,6 +618,20 @@ verify_binary_equality "mount rules slash filtering" \
"@{FOO}=/foo
/t { mount /dev//@{FOO} -> /mnt/bar, }"
# verify slash filtering for link rules
verify_binary_equality "link rules slash filtering" \
"/t { link /dev/foo -> /mnt/bar, }" \
"/t { link ///dev/foo -> /mnt/bar, }" \
"/t { link /dev/foo -> /mnt//bar, }" \
"/t { link /dev///foo -> ////mnt/bar, }" \
"@{BAR}=/mnt/
/t { link /dev///foo -> @{BAR}/bar, }" \
"@{FOO}=/dev/
/t { link @{FOO}//foo -> /mnt/bar, }" \
"@{FOO}=/dev/
@{BAR}=/mnt/
/t { link @{FOO}/foo -> @{BAR}/bar, }" \
if [ $fails -ne 0 ] || [ $errors -ne 0 ]
then
printf "ERRORS: %d\nFAILS: %d\n" $errors $fails 2>&1

View File

@@ -26,7 +26,7 @@ class AAErrorTests(testlib.AATestTemplate):
self.maxDiff = None
self.cmd_prefix = [config.parser, '--config-file=./parser.conf', '-S', '-I', 'errors']
def _run_test(self, profile, message=None, is_error=True):
def _run_test(self, profile, message='', is_error=True):
cmd = self.cmd_prefix + [profile]
(rc, out, outerr) = self._run_cmd(cmd, stdout=subprocess.DEVNULL)
@@ -36,8 +36,14 @@ class AAErrorTests(testlib.AATestTemplate):
else:
self.assertEqual(rc, 0, report)
if message:
self.assertIn(message, outerr, report)
ignore_messages = [
'Cache read/write disabled: interface file missing. (Kernel needs AppArmor 2.4 compatibility patch.)\n',
]
for ign in ignore_messages:
if ign in outerr:
outerr = outerr.replace(ign, '')
self.assertEqual(message, outerr, report)
def test_okay(self):
self._run_test('errors/okay.sd', is_error=False)
@@ -45,32 +51,32 @@ class AAErrorTests(testlib.AATestTemplate):
def test_single(self):
self._run_test(
'errors/single.sd',
"AppArmor parser error for errors/single.sd in profile errors/single.sd at line 3: Could not open 'failure'",
"AppArmor parser error for errors/single.sd in profile errors/single.sd at line 3: Could not open 'failure'\n",
)
def test_double(self):
self._run_test(
'errors/double.sd',
"AppArmor parser error for errors/double.sd in profile errors/includes/busted at line 66: Could not open 'does-not-exist'",
"AppArmor parser error for errors/double.sd in profile errors/includes/busted at line 66: Could not open 'does-not-exist'\n",
)
def test_modefail(self):
self._run_test(
'errors/modefail.sd',
"AppArmor parser error for errors/modefail.sd in profile errors/modefail.sd at line 6: syntax error, unexpected TOK_ID, expecting TOK_MODE",
"AppArmor parser error for errors/modefail.sd in profile errors/modefail.sd at line 6: syntax error, unexpected TOK_ID, expecting TOK_MODE\n",
)
def test_multi_include(self):
self._run_test(
'errors/multi_include.sd',
"AppArmor parser error for errors/multi_include.sd in profile errors/multi_include.sd at line 12: Could not open 'failure'",
"AppArmor parser error for errors/multi_include.sd in profile errors/multi_include.sd at line 12: Could not open 'failure'\n",
)
def test_deprecation1(self):
self.cmd_prefix.extend(['--warn=deprecated'])
self._run_test(
'errors/deprecation1.sd',
"Warning from errors/deprecation1.sd (errors/deprecation1.sd line 6): The use of file paths as profile names is deprecated. See man apparmor.d for more information",
"Warning from errors/deprecation1.sd (errors/deprecation1.sd line 6): The use of file paths as profile names is deprecated. See man apparmor.d for more information\n",
is_error=False
)
@@ -78,7 +84,7 @@ class AAErrorTests(testlib.AATestTemplate):
self.cmd_prefix.extend(['--warn=deprecated'])
self._run_test(
'errors/deprecation2.sd',
"Warning from errors/deprecation2.sd (errors/deprecation2.sd line 6): The use of file paths as profile names is deprecated. See man apparmor.d for more information",
"Warning from errors/deprecation2.sd (errors/deprecation2.sd line 6): The use of file paths as profile names is deprecated. See man apparmor.d for more information\n",
is_error=False
)

View File

@@ -1,235 +0,0 @@
#!/usr/bin/perl
use strict;
use Locale::gettext;
use POSIX;
setlocale(LC_MESSAGES, "");
my $prefix="simple_tests/generated_x";
my $prefix_leading="simple_tests/generated_perms_leading";
my $prefix_safe="simple_tests/generated_perms_safe";
my @trans_types = ("p", "P", "c", "C", "u", "i");
my @modifiers = ("i", "u");
my %trans_modifiers = (
"p" => \@modifiers,
"P" => \@modifiers,
"c" => \@modifiers,
"C" => \@modifiers,
);
my @targets = ("", "target", "target2");
my @null_target = ("");
my %named_trans = (
"p" => \@targets,
"P" => \@targets,
"c" => \@targets,
"C" => \@targets,
"u" => \@null_target,
"i" => \@null_target,
);
my %safe_map = (
"p" => "unsafe",
"P" => "safe",
"c" => "unsafe",
"C" => "safe",
"u" => "",
"i" => "",
);
my %invert_safe = (
"safe" => "unsafe",
"unsafe" => "safe",
);
# audit qualifier disabled for now it really shouldn't affect the conflict
# test but it may be worth checking every once in awhile
#my @qualifiers = ("", "owner", "audit", "audit owner");
my @qualifiers = ("", "owner");
my $count = 0;
gen_conflicting_x();
gen_overlap_re_exact();
gen_dominate_re_re();
gen_ambiguous_re_re();
gen_leading_perms("exact", "/bin/cat", "/bin/cat");
gen_leading_perms("exact-re", "/bin/*", "/bin/*");
gen_leading_perms("overlap", "/*", "/bin/cat");
gen_leading_perms("dominate", "/**", "/*");
gen_leading_perms("ambiguous", "/a*", "/*b");
gen_safe_perms("exact", "PASS", "", "/bin/cat", "/bin/cat");
gen_safe_perms("exact-re", "PASS", "", "/bin/*", "/bin/*");
gen_safe_perms("overlap", "PASS", "", "/*", "/bin/cat");
gen_safe_perms("dominate", "PASS", "", "/**", "/*");
gen_safe_perms("ambiguous", "PASS", "", "/a*", "/*b");
gen_safe_perms("exact", "FAIL", "inv", "/bin/cat", "/bin/cat");
gen_safe_perms("exact-re", "FAIL", "inv", "/bin/*", "/bin/*");
gen_safe_perms("overlap", "PASS", "inv", "/*", "/bin/cat");
gen_safe_perms("dominate", "FAIL", "inv", "/**", "/*");
gen_safe_perms("ambiguous", "FAIL", "inv", "/a*", "/*b");
print "Generated $count xtransition interaction tests\n";
sub gen_list {
my @output;
foreach my $trans (@trans_types) {
if ($trans_modifiers{$trans}) {
foreach my $mod (@{$trans_modifiers{$trans}}) {
push @output, "${trans}${mod}x";
}
}
push @output, "${trans}x";
}
return @output;
}
sub print_rule($$$$$$) {
my ($file, $leading, $qual, $name, $perm, $target) = @_;
if ($leading) {
print $file "\t${qual} ${perm} ${name}";
} else {
print $file "\t${qual} ${name} ${perm}";
}
if ($target ne "") {
print $file " -> $target";
}
print $file ",\n";
}
sub gen_file($$$$$$$$$$$$) {
my ($name, $xres, $leading1, $qual1, $rule1, $perm1, $target1, $leading2, $qual2, $rule2, $perm2, $target2) = @_;
# print "$xres $rule1 $perm1 $target1 $rule2 $perm2 $target2\n";
my $file;
unless (open $file, ">$name") {
print("couldn't open $name\n");
exit 1;
}
print $file "#\n";
print $file "#=DESCRIPTION ${name}\n";
print $file "#=EXRESULT ${xres}\n";
print $file "#\n";
print $file "/usr/bin/foo {\n";
print_rule($file, $leading1, $qual1, $rule1, $perm1, $target1);
print_rule($file, $leading2, $qual2, $rule2, $perm2, $target2);
print $file "}\n";
close($file);
$count++;
}
#NOTE: currently we don't do px to cx, or cx to px conversion
# so
# /foo {
# /* px -> /foo//bar,
# /* cx -> bar,
#
# will conflict
#
#NOTE: conflict tests don't tests leading permissions or using unsafe keywords
# It is assumed that there are extra tests to verify 1 to 1 coorispondance
sub gen_files($$$$) {
my ($name, $rule1, $rule2, $default) = @_;
my @perms = gen_list();
# print "@perms\n";
foreach my $i (@perms) {
foreach my $t (@{$named_trans{substr($i, 0, 1)}}) {
foreach my $q (@qualifiers) {
foreach my $j (@perms) {
foreach my $u (@{$named_trans{substr($j, 0, 1)}}) {
foreach my $r (@qualifiers) {
my $file="${prefix}/${name}-$q$i$t-$r$j$u.sd";
# print "$file\n";
#override failures when transitions are the same
my $xres = ${default};
if ($i eq $j && $t eq $u) {
$xres = "PASS";
}
# print "foo $xres $rule1 $i $t $rule2 $j $u\n";
gen_file($file, $xres, 0, $q, $rule1, $i, $t, 0, $r, $rule2, $j, $u);
}
}
}
}
}
}
}
sub gen_conflicting_x {
gen_files("conflict", "/bin/cat", "/bin/cat", "FAIL");
}
sub gen_overlap_re_exact {
gen_files("exact", "/bin/cat", "/bin/*", "PASS");
}
# we currently don't support this, once supported change to "PASS"
sub gen_dominate_re_re {
gen_files("dominate", "/bin/*", "/bin/**", "FAIL");
}
sub gen_ambiguous_re_re {
gen_files("ambiguous", "/bin/a*", "/bin/*b", "FAIL");
}
# test that rules that lead with permissions don't conflict with
# the same rule using trailing permissions.
sub gen_leading_perms($$$) {
my ($name, $rule1, $rule2) = @_;
my @perms = gen_list();
foreach my $i (@perms) {
foreach my $t (@{$named_trans{substr($i, 0, 1)}}) {
foreach my $q (@qualifiers) {
my $file="${prefix_leading}/${name}-$q$i$t.sd";
# print "$file\n";
gen_file($file, "PASS", 0, $q, $rule1, $i, $t, 1, $q, $rule2, $i, $t);
}
}
}
}
# test for rules with leading safe or unsafe keywords.
# check they are equivalent to their counter part,
# or if $invert that they properly conflict with their counterpart
sub gen_safe_perms($$$$$) {
my ($name, $xres, $invert, $rule1, $rule2) = @_;
my @perms = gen_list();
foreach my $i (@perms) {
foreach my $t (@{$named_trans{substr($i, 0, 1)}}) {
foreach my $q (@qualifiers) {
my $qual = $safe_map{substr($i, 0, 1)};
if ($invert) {
$qual = $invert_safe{$qual};
}
if (! $invert || $qual) {
my $file="${prefix_safe}/${name}-$invert-$q${qual}-rule-$i$t.sd";
# print "$file\n";
gen_file($file, $xres, 0, "$q $qual", $rule1, $i, $t, 1, $q, $rule2, $i, $t);
$file="${prefix_safe}/${name}-$invert-$q$qual${i}-rule-$t.sd";
gen_file($file, $xres, 0, $q, $rule1, $i, $t, 1, "$q $qual", $rule2, $i, $t);
}
}
}
}
}

219
parser/tst/gen-xtrans.py Executable file
View File

@@ -0,0 +1,219 @@
#!/usr/bin/python3
# ------------------------------------------------------------------
#
# Copyright (C) 2010-2011 Canonical Ltd.
# Copyright (C) 2020 Christian Boltz
#
# 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.
#
# ------------------------------------------------------------------
from testlib import write_file
prefix = "simple_tests/generated_x"
prefix_leading = "simple_tests/generated_perms_leading"
prefix_safe = "simple_tests/generated_perms_safe"
trans_types = ("p", "P", "c", "C", "u", "i")
modifiers = ("i", "u")
trans_modifiers = {
"p": modifiers,
"P": modifiers,
"c": modifiers,
"C": modifiers,
}
targets = ("", "target", "target2")
# null_target uses "_" instead of "" because "" gets skipped in some for loops. Replace with "" when actually using the value.
null_target = ("_")
named_trans = {
"p": targets,
"P": targets,
"c": targets,
"C": targets,
"u": null_target,
"i": null_target,
}
safe_map = {
"p": "unsafe",
"P": "safe",
"c": "unsafe",
"C": "safe",
"u": "",
"i": "",
}
invert_safe = {
"safe": "unsafe",
"unsafe": "safe",
'': '',
}
# audit qualifier disabled for now it really shouldn't affect the conflict
# test but it may be worth checking every once in awhile
# qualifiers = ("", "owner", "audit", "audit owner")
qualifiers = ("", "owner")
count = 0
def gen_list():
output = []
for trans in trans_types:
if trans in trans_modifiers:
for mod in trans_modifiers[trans]:
output.append("%s%sx" % (trans, mod))
output.append("%sx" % trans)
return output
def test_gen_list():
''' test if gen_list returns the expected output '''
expected = "pix pux px Pix Pux Px cix cux cx Cix Cux Cx ux ix".split()
actual = gen_list()
if actual != expected:
raise Exception("gen_list produced unexpected result, expected %s, got %s" % (expected, actual))
def build_rule(leading, qual, name, perm, target):
rule = ''
if leading:
rule += "\t%s %s %s" % (qual, perm, name)
else:
rule += "\t%s %s %s" % (qual, name, perm)
if target != "":
rule += " -> %s" % target
rule += ",\n"
return rule
def gen_file (name, xres, leading1, qual1, rule1, perm1, target1, leading2, qual2, rule2, perm2, target2):
global count
count += 1
content = ''
content += "#\n"
content += "#=DESCRIPTION %s\n" % name
content += "#=EXRESULT %s\n" % xres
content += "#\n"
content += "/usr/bin/foo {\n"
content += build_rule(leading1, qual1, rule1, perm1, target1)
content += build_rule(leading2, qual2, rule2, perm2, target2)
content += "}\n"
write_file('', name, content)
# NOTE: currently we don't do px to cx, or cx to px conversion
# so
# /foo {
# /* px -> /foo//bar,
# /* cx -> bar,
#
# will conflict
#
# NOTE: conflict tests don't tests leading permissions or using unsafe keywords
# It is assumed that there are extra tests to verify 1 to 1 coorispondance
def gen_files(name, rule1, rule2, default):
perms = gen_list()
for i in perms:
for t in named_trans[i[0]]:
if t == '_':
t = ''
for q in qualifiers:
for j in perms:
for u in named_trans[j[0]]:
if u == '_':
u = ''
for r in qualifiers:
file = prefix + '/' + name + '-' + q + i + t + '-' + r + j + u + '.sd'
# override failures when transitions are the same
xres = default
if (i == j and t == u):
xres = "PASS"
gen_file(file, xres, 0, q, rule1, i, t, 0, r, rule2, j, u)
def gen_conflicting_x():
gen_files("conflict", "/bin/cat", "/bin/cat", "FAIL")
def gen_overlap_re_exact():
gen_files("exact", "/bin/cat", "/bin/*", "PASS")
# we currently don't support this, once supported change to "PASS"
def gen_dominate_re_re():
gen_files("dominate", "/bin/*", "/bin/**", "FAIL")
def gen_ambiguous_re_re():
gen_files("ambiguous", "/bin/a*", "/bin/*b", "FAIL")
# test that rules that lead with permissions don't conflict with
# the same rule using trailing permissions.
def gen_leading_perms (name, rule1, rule2):
perms = gen_list()
for i in perms:
for t in named_trans[i[0]]:
if t == '_':
t = ''
for q in qualifiers:
file = prefix_leading + '/' + name + '-' + q + i + t + ".sd"
gen_file(file, "PASS", 0, q, rule1, i, t, 1, q, rule2, i, t)
# test for rules with leading safe or unsafe keywords.
# check they are equivalent to their counter part,
# or if $invert that they properly conflict with their counterpart
def gen_safe_perms(name, xres, invert, rule1, rule2):
perms = gen_list()
for i in perms:
for t in named_trans[i[0]]:
if t == '_':
t = ''
for q in qualifiers:
qual = safe_map[i[0]]
if invert:
qual = invert_safe[qual]
if (not invert or qual):
file = prefix_safe + '/' + name + '-' + invert + '-' + q + qual + '-' + 'rule-' + i + t + '.sd'
gen_file(file, xres, 0, '%s %s' % (q, qual), rule1, i, t, 1, q, rule2, i, t)
file = prefix_safe + '/' + name + '-' + invert + '-' + q + qual + i + '-' + 'rule-' + t + '.sd'
gen_file(file, xres, 0, q, rule1, i, t, 1, '%s %s' % (q, qual), rule2, i, t)
test_gen_list()
gen_conflicting_x()
gen_overlap_re_exact()
gen_dominate_re_re()
gen_ambiguous_re_re()
gen_leading_perms("exact", "/bin/cat", "/bin/cat")
gen_leading_perms("exact-re", "/bin/*", "/bin/*")
gen_leading_perms("overlap", "/*", "/bin/cat")
gen_leading_perms("dominate", "/**", "/*")
gen_leading_perms("ambiguous", "/a*", "/*b")
gen_safe_perms("exact", "PASS", "", "/bin/cat", "/bin/cat")
gen_safe_perms("exact-re", "PASS", "", "/bin/*", "/bin/*")
gen_safe_perms("overlap", "PASS", "", "/*", "/bin/cat")
gen_safe_perms("dominate", "PASS", "", "/**", "/*")
gen_safe_perms("ambiguous", "PASS", "", "/a*", "/*b")
gen_safe_perms("exact", "FAIL", "inv", "/bin/cat", "/bin/cat")
gen_safe_perms("exact-re", "FAIL", "inv", "/bin/*", "/bin/*")
gen_safe_perms("overlap", "PASS", "inv", "/*", "/bin/cat")
gen_safe_perms("dominate", "FAIL", "inv", "/**", "/*")
gen_safe_perms("ambiguous", "FAIL", "inv", "/a*", "/*b")
print ("Generated %s xtransition interaction tests" % count)

View File

@@ -5,7 +5,7 @@ APPARMOR_PARSER="${APPARMOR_PARSER:-../apparmor_parser}"
# Format of -D dfa-states
# dfa-states output is split into 2 parts:
# the accept state infomation
# the accept state information
# {state} (allow deny audit XXX) ignore XXX for now
# followed by the transition table information
# {Y} -> {Z}: 0xXX Char #0xXX is the hex dump of Char
@@ -43,7 +43,7 @@ APPARMOR_PARSER="${APPARMOR_PARSER:-../apparmor_parser}"
# These tests currently only look at the accept state permissions
#
# To view any of these DFAs as graphs replace --D dfa-states with -D dfa-graph
# strip of the test stuff around the parser command and use the the dot
# strip of the test stuff around the parser command and use the dot
# command to convert
# Eg.
# echo "/t { /a r, /b w, /c a, /d l, /e k, /f m, deny /** w, }" | ./apparmor_parser -QT -O minimize -D dfa-graph --quiet 2>min.graph
@@ -100,7 +100,7 @@ fi
echo "ok"
# same test as above except with deny 'w' perm added to /**, this does not
# elimnates the states with 'w' and 'a' because the quiet information is
# eliminates the states with 'w' and 'a' because the quiet information is
# being carried
#
# {1} <== (allow/deny/audit/quiet)
@@ -119,7 +119,7 @@ fi
echo "ok"
# same test as above except with audit deny 'w' perm added to /**, with the
# parameter this elimnates the states with 'w' and 'a' because
# parameter this eliminates the states with 'w' and 'a' because
# the quiet information is NOT being carried
#
# {1} <== (allow/deny/audit/quiet)
@@ -139,7 +139,7 @@ echo "ok"
# The x transition test profile is setup so that there are 3 conflicting x
# permissions, two are on paths that won't collide during dfa creation. The
# 3rd is a generic permission that should be overriden during dfa creation.
# 3rd is a generic permission that should be overridden during dfa creation.
#
# This should result in a dfa that specifies transitions on 'a' and 'b' to
# unique states that store the alternate accept information. However
@@ -190,7 +190,7 @@ fi
echo "ok"
# now try audit + denying x and make sure perms are cleared
# notice that the deny info is being carried, by an artifical trap state
# notice that the deny info is being carried, by an artificial trap state
# {1} <== (allow/deny/audit/quiet)
# {3} (0x 0/fe17f85/0/0)

View File

@@ -1,5 +1,5 @@
#
#=DESCRIPTION validate some uses of capabilties.
#=DESCRIPTION validate some uses of capabilities.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005

View File

@@ -1,5 +1,5 @@
#
#=DESCRIPTION validate some uses of capabilties.
#=DESCRIPTION validate some uses of capabilities.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005

View File

@@ -1,5 +1,5 @@
#
#=DESCRIPTION validate some uses of capabilties.
#=DESCRIPTION validate some uses of capabilities.
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005

View File

@@ -1,5 +1,5 @@
#
#=DESCRIPTION validate some uses of capabilties.
#=DESCRIPTION validate some uses of capabilities.
#=EXRESULT FAIL
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005

View File

@@ -1,4 +1,4 @@
#=DESCRIPTION conditional else in invlaid locations
#=DESCRIPTION conditional else in invalid locations
#=EXRESULT FAIL
$BAR = false

View File

@@ -1,5 +1,5 @@
#
#=DESCRIPTION m and [upi]x do not conflict, seperate rules
#=DESCRIPTION m and [upi]x do not conflict, separate rules
#=EXRESULT PASS
# vim:syntax=apparmor
#

View File

@@ -1,5 +1,5 @@
#
#=DESCRIPTION m and [upi]x do not conflict, seperate rules
#=DESCRIPTION m and [upi]x do not conflict, separate rules
#=EXRESULT PASS
#
/usr/bin/foo {

View File

@@ -1,5 +1,5 @@
#
#=DESCRIPTION m and [upi]x do not conflict, seperate rules
#=DESCRIPTION m and [upi]x do not conflict, separate rules
#=EXRESULT PASS
#
/usr/bin/foo {

View File

@@ -1,5 +1,5 @@
#
#=DESCRIPTION netdomain tcp connect w/multiple from statments
#=DESCRIPTION netdomain tcp connect w/multiple from statements
#=EXRESULT FAIL
/tmp/tcp/tcp_client {
tcp_connect from 10.0.0.17/16:50-100 from 127.0.0.1 via eth1,

View File

@@ -1,6 +1,6 @@
#
# $Id$
#=DESCRIPTION Basic namespace test wit named profile, duplicate mode bits
#=DESCRIPTION Basic namespace test with named profile, duplicate mode bits
#=EXRESULT PASS
# vim:syntax=subdomain
# Last Modified: Sun Apr 17 19:44:44 2005

View File

@@ -1,5 +1,5 @@
#
#=DESCRIPTION simple max virtual memory szie rlimit test
#=DESCRIPTION simple max virtual memory size rlimit test
#=EXRESULT PASS
profile rlimit {

View File

@@ -47,10 +47,10 @@ else
PYTHONPATH=../utils/:$(PYTHON_DIST_BUILD_PATH)
PARSER?=../parser/apparmor_parser
# use ../utils logprof
LOGPROF?=LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) PYTHONPATH=$(PYTHONPATH) $(PYTHON) ../utils/aa-logprof
LOGPROF?=LD_LIBRARY_PATH=$(LD_LIBRARY_PATH) PYTHONPATH=$(PYTHONPATH) $(PYTHON) ../utils/aa-logprof --configdir ../utils/test/
endif
# $(PWD) is wrong when using "make -C profiles" - explicitely set it here to get the right value
# $(PWD) is wrong when using "make -C profiles" - explicitly set it here to get the right value
PWD=$(shell pwd)
.PHONY: test-dependencies

View File

@@ -17,6 +17,7 @@
# .ICEauthority files required for X authentication, per user
owner @{HOME}/.ICEauthority r,
owner @{run}/user/*/ICEauthority r,
# .Xauthority files required for X connections, per user
owner @{HOME}/.Xauthority r,
@@ -29,7 +30,7 @@
owner @{run}/user/*/xauth_* r,
# the unix socket to use to connect to the display
/tmp/.X11-unix/* r,
/tmp/.X11-unix/* rw,
unix (connect, receive, send)
type=stream
peer=(addr="@/tmp/.X11-unix/X[0-9]*"),
@@ -51,6 +52,8 @@
# Xcompose
owner @{HOME}/.XCompose r,
/var/cache/libx11/compose/* r,
deny /var/cache/libx11/compose/* wlk,
# mouse themes
/etc/X11/cursors/ r,

View File

@@ -29,8 +29,8 @@
# include <abstractions/ubuntu-browsers>
# include <abstractions/ubuntu-email>
#
# # Add if accesibility access is considered as required
# # (for message boxe in case exo-open fails)
# # Add if accessibility access is considered as required
# # (for message box in case exo-open fails)
# include <abstractions/dbus-accessibility>
#
# # < add additional allowed applications here >

View File

@@ -52,6 +52,8 @@
owner @{HOME}/.fonts.conf.d/** r,
owner @{HOME}/.config/fontconfig/ r,
owner @{HOME}/.config/fontconfig/** r,
owner @{HOME}/.Fontmatrix/Activated/ r,
owner @{HOME}/.Fontmatrix/Activated/** r,
/usr/local/share/fonts/ r,
/usr/local/share/fonts/** r,

View File

@@ -29,8 +29,8 @@
# include <abstractions/ubuntu-browsers>
# include <abstractions/ubuntu-email>
#
# # Add if accesibility access is considered as required
# # (for message boxe in case exo-open fails)
# # Add if accessibility access is considered as required
# # (for message box in case exo-open fails)
# include <abstractions/dbus-accessibility>
#
# # Add if audio support for message box is

View File

@@ -12,11 +12,18 @@
# User files
owner @{HOME}/.cache/ w, # if user clears all caches
owner @{HOME}/.cache/mesa_shader_cache/ w,
owner @{HOME}/.cache/mesa_shader_cache/ rw,
owner @{HOME}/.cache/mesa_shader_cache/index rw,
owner @{HOME}/.cache/mesa_shader_cache/??/ w,
owner @{HOME}/.cache/mesa_shader_cache/??/* rwk,
owner @{HOME}/.cache/mesa_shader_cache/[a-f0-9][a-f0-9]/ rw,
owner @{HOME}/.cache/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]* rw,
owner @{HOME}/.cache/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]*.tmp rwk,
# Fallback location when @{HOME}/.cache is not available
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/ rw,
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/index rw,
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/[a-f0-9][a-f0-9]/ rw,
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]* rw,
owner /tmp/Temp-[a-f0-9]*/mesa_shader_cache/[a-f0-9][a-f0-9]/[0-9a-f]*.tmp rwk,
# Include additions to the abstraction
include if exists <abstractions/mesa.d>

View File

@@ -2,7 +2,7 @@
#
# Copyright (C) 2002-2005 Novell/SUSE
# Copyright (C) 2015-2018 Canonical, Ltd.
# Copyright (C) 2020 Christian Boltz
# Copyright (C) 2020-2021 Christian Boltz
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -26,6 +26,7 @@
/etc/mailname r,
/etc/postfix/*.cf r,
/etc/postfix/*.db rk,
/etc/postfix/*.lmdb rk,
@{PROC}/net/if_inet6 r,
/usr/lib/postfix/*.so mr,
/usr/lib{,32,64}/sasl2/* mr,

View File

@@ -24,7 +24,7 @@
audit deny @{HOME}/.kde{,4}/{,share/,share/apps/} w,
audit deny @{HOME}/.kde{,4}/share/apps/kmail{,2}/{,**} mrwkl,
audit deny @{HOME}/.kde{,4}/share/apps/kwallet/{,**} mrwkl,
audit deny @{HOME}/.local/share/kwalletd/{,**} mrwkl,
# Include additions to the abstraction
include if exists <abstractions/private-files-strict.d>

View File

@@ -11,20 +11,16 @@
abi <abi/3.0>,
/etc/ssl/ r,
/etc/ssl/certs/ r,
/etc/ssl/certs/* r,
/etc/pki/trust/ r,
/etc/pki/trust/* r,
/etc/pki/trust/anchors/ r,
/etc/pki/trust/anchors/** r,
/usr/share/ca-certificates/ r,
/usr/share/ca-certificates/** r,
/etc/ca-certificates/{,**} r,
/etc/{,libre}ssl/ r,
/etc/{,libre}ssl/cert.pem r,
/etc/{,libre}ssl/certs/{,**} r,
/etc/pki/trust/{,*} r,
/etc/pki/trust/anchors/{,**} r,
/usr/share/ca-certificates/{,**} r,
/usr/share/ssl/certs/ca-bundle.crt r,
/usr/local/share/ca-certificates/ r,
/usr/local/share/ca-certificates/** r,
/var/lib/ca-certificates/ r,
/var/lib/ca-certificates/** r,
/usr/local/share/ca-certificates/{,**} r,
/var/lib/ca-certificates/{,**} r,
# acmetool
/var/lib/acme/certs/*/chain r,

View File

@@ -14,7 +14,7 @@
# it is intended to be included in profiles for svnserve/apache2 and maybe
# some repository viewers like trac/viewvc
# no hooks exec by default; please define whatever you need explicitely.
# no hooks exec by default; please define whatever you need explicitly.
/srv/svn/**/conf/* r,
/srv/svn/**/format r,

View File

@@ -38,3 +38,4 @@
/usr/lib/icecat-*/icecat Cx -> sanitized_helper,
/usr/bin/opera Cx -> sanitized_helper,
/opt/google/chrome{,-beta,-unstable}/google-chrome{,-beta,-unstable} Cx -> sanitized_helper,
/opt/brave.com/brave{,-beta,-dev,-nightly}/brave-browser{,-beta,-dev,-nightly} Cx -> sanitized_helper,

View File

@@ -28,10 +28,7 @@
/usr/lib/mozilla/kmozillahelper Cxr -> sanitized_helper,
# Exo-aware applications
/usr/bin/exo-open ixr,
/usr/lib/@{multiarch}/xfce4/exo-1/exo-helper-1 ixr,
/etc/xdg/xdg-xubuntu/xfce4/helpers.rc r,
/etc/xdg/xfce4/helpers.rc r,
include <abstractions/exo-open>
# unity webapps integration. Could go in its own abstraction
owner /run/user/*/dconf/user rw,

View File

@@ -14,6 +14,7 @@
audit deny @{HOME}/.gnome2_private/{,**} mrwkl,
audit deny @{HOME}/.kde{,4}/{,share/,share/apps/} w,
audit deny @{HOME}/.kde{,4}/share/apps/kwallet/{,**} mrwkl,
audit deny @{HOME}/.local/share/kwalletd/{,**} mrwkl,
# Comment this out if using gpg plugin/addons
audit deny @{HOME}/.gnupg/{,**} mrwkl,

View File

@@ -74,6 +74,12 @@ profile sanitized_helper {
/opt/google/chrome{,-beta,-unstable}/chrome Pixr,
/opt/google/chrome{,-beta,-unstable}/{,**/}lib*.so{,.*} m,
# The same is needed for Brave
/opt/brave.com/brave{,-beta,-dev,-nightly}/chrome-sandbox PUxr,
/opt/brave.com/brave{,-beta,-dev,-nightly}/brave-browser{,-beta,-dev,-nightly} Pixr,
/opt/brave.com/brave{,-beta,-dev,-nightly}/brave Pixr,
/opt/brave.com/brave{,-beta,-dev,-nightly}/{,**/}lib*.so{,.*} m,
# Full access
/ r,
/** rwkl,

View File

@@ -14,5 +14,8 @@
owner @{run}/user/*/wayland-[0-9]* rw,
owner @{run}/user/*/{mesa,mutter,sdl,wayland-cursor,weston,xwayland}-shared-* rw,
#For compositors based on wlroots
owner /dev/shm/wlroots-* rw,
# Include additions to the abstraction
include if exists <abstractions/wayland.d>

View File

@@ -14,7 +14,8 @@
# some services update wtmp, utmp, and lastlog with per-user
# connection information
/var/log/lastlog rwk,
/var/log/wtmp wk,
/var/log/wtmp rwk,
/var/log/btmp rwk,
@{run}/utmp rwk,
# Include additions to the abstraction

View File

@@ -41,7 +41,7 @@
include <abstractions/base>
# for openin with `exo-open`
# for opening with `exo-open`
include <abstractions/exo-open>
# for opening with `gio open <uri>`

View File

@@ -0,0 +1,27 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2020 SUSE LLC
#
# 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: ft=apparmor
include <tunables/global>
profile dovecot-director /usr/lib/dovecot/director flags=(attach_disconnected) {
include <abstractions/base>
include <abstractions/dovecot-common>
include <abstractions/nameservice>
capability setuid,
capability sys_chroot,
/run/dovecot/login/proxy-notify rw,
/usr/lib/dovecot/director mr,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.director>
}

View File

@@ -0,0 +1,22 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2020 SUSE LLC
#
# 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: ft=apparmor
include <tunables/global>
profile dovecot-doveadm-server /usr/lib/dovecot/doveadm-server flags=(attach_disconnected) {
include <abstractions/base>
include <abstractions/dovecot-common>
/usr/lib/dovecot/doveadm-server mr,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.doveadm-server>
}

View File

@@ -21,7 +21,6 @@ profile dovecot-imap /usr/lib/dovecot/imap {
include <abstractions/dovecot-common>
capability setuid,
deny capability block_suspend,
network unix stream,

View File

@@ -0,0 +1,36 @@
# ------------------------------------------------------------------
#
# Copyright (C) 2020 SUSE LLC
# Copyright (C) 2009-2010 Canonical Ltd.
# Copyright (C) 2011-2013 Christian Boltz
#
# 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: ft=apparmor
# for https://wiki.dovecot.org/Replication
include <tunables/dovecot>
include <tunables/global>
profile dovecot-replicator /usr/lib/dovecot/replicator {
include <abstractions/base>
include <abstractions/dovecot-common>
include <abstractions/nameservice>
network unix stream,
/etc/dovecot/conf.d/ r,
/etc/dovecot/conf.d/** r,
/etc/dovecot/dovecot.conf r,
/usr/lib/dovecot/replicator mr,
/usr/share/dovecot/** r,
/{,var/}run/dovecot/auth-master rw,
@{DOVECOT_MAILSTORE}/ rw,
@{DOVECOT_MAILSTORE}/** rwlk,
/var/lib/dovecot/replicator.db rw,
# Site-specific additions and overrides. See local/README for details.
include if exists <local/usr.lib.dovecot.replicator>
}

View File

@@ -70,8 +70,6 @@ profile dnsmasq /usr/{bin,sbin}/dnsmasq flags=(attach_disconnected) {
# access to iface mtu needed for Router Advertisement messages in IPv6
# Neighbor Discovery protocol (RFC 2461)
@{PROC}/sys/net/ipv6/conf/*/mtu r,
# closing superfluous file descriptors scans /proc/self/fd/ to find open ones
@{PROC}/@{pid}/fd/ r,
# for the read-only TFTP server
@{TFTP_DIR}/ r,

View File

@@ -33,8 +33,8 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
capability sys_chroot,
capability sys_resource,
signal send set=(int,quit,term) peer=/usr/lib/dovecot/*,
signal send set=(int,quit,term) peer=dovecot-*,
signal send set=(int,quit,term,kill) peer=/usr/lib/dovecot/*,
signal send set=(int,quit,term,kill) peer=dovecot-*,
unix (receive, send) type=stream peer=(label=/usr/lib/dovecot/anvil),
unix (receive, send) type=stream peer=(label=dovecot-anvil),
@@ -50,6 +50,8 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
/usr/lib/dovecot/auth mrPx,
/usr/lib/dovecot/config mrPx,
/usr/lib/dovecot/dict mrPx,
/usr/lib/dovecot/director mrPx,
/usr/lib/dovecot/doveadm-server mrPx,
/usr/lib/dovecot/dovecot-auth Pxmr,
/usr/lib/dovecot/imap Pxmr,
/usr/lib/dovecot/imap-login Pxmr,
@@ -59,11 +61,13 @@ profile dovecot /usr/{bin,sbin}/dovecot flags=(attach_disconnected) {
/usr/lib/dovecot/managesieve-login Pxmr,
/usr/lib/dovecot/pop3 mrPx,
/usr/lib/dovecot/pop3-login Pxmr,
/usr/lib/dovecot/replicator mrPx,
/usr/lib/dovecot/script-login Px,
/usr/lib/dovecot/ssl-build-param rix,
/usr/lib/dovecot/ssl-params mrPx,
/usr/lib/dovecot/stats Px,
/usr/{bin,sbin}/dovecot mrix,
/usr/share/dovecot/dh.pem r,
/usr/share/dovecot/protocols.d/ r,
/usr/share/dovecot/protocols.d/** r,
/var/lib/dovecot/ w,

View File

@@ -23,6 +23,7 @@ profile nscd /usr/{bin,sbin}/nscd {
capability setgid,
capability setuid,
/etc/machine-id r,
/etc/netgroup r,
/etc/nscd.conf r,
/usr/{bin,sbin}/nscd rmix,
@@ -30,7 +31,7 @@ profile nscd /usr/{bin,sbin}/nscd {
@{run}/nscd/ rw,
@{run}/nscd/db* rwl,
@{run}/nscd/socket wl,
/{var/cache,var/lib,var/run,run}/nscd/{passwd,group,services,hosts,netgroup} rw,
/{var/cache,var/db,var/lib,var/run,run}/nscd/{passwd,group,services,hosts,netgroup} rw,
@{run}/{nscd/,}nscd.pid rwl,
/var/lib/libvirt/dnsmasq/ r,
/var/lib/libvirt/dnsmasq/*.status r,

View File

@@ -17,6 +17,7 @@ profile ntpd /usr/{bin,sbin}/{,open}ntpd flags=(attach_disconnected) {
include <abstractions/base>
include <abstractions/nameservice>
include <abstractions/openssl>
include <abstractions/ssl_certs>
include <abstractions/xad>
capability dac_override,

View File

@@ -2,6 +2,7 @@
#
# Copyright (C) 2002-2006 Novell/SUSE
# Copyright (C) 2018 Canonical, Ltd.
# Copyright (C) 2021 Christian Boltz
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -25,6 +26,7 @@ profile postfix-flush /usr/lib/postfix/{bin/,sbin/,}flush {
/{var/spool/postfix/,}deferred/[0-9A-F]/[0-9A-F]* rwl,
/{var/spool/postfix/,}deferred/[0-9A-F]/ rwl,
/{var/spool/postfix/,}flush/ rwl,
/{var/spool/postfix/,}flush/* w, # filename is based on hostname
/{var/spool/postfix/,}flush/[0-9A-F]/[0-9A-F]/* rwl,
/{var/spool/postfix/,}flush/[0-9A-F]/[0-9A-F]/ rwl,
/{var/spool/postfix/,}flush/[0-9A-F]/ rwl,
@@ -33,7 +35,7 @@ profile postfix-flush /usr/lib/postfix/{bin/,sbin/,}flush {
/{var/spool/postfix/,}incoming/[0-9A-F]/[0-9A-F]/ rwl,
/{var/spool/postfix/,}incoming/[0-9A-F]/ rwl,
/{var/spool/postfix/,}public/qmgr w,
/{var/spool/postfix/,}pid/unix.flush rw,
/{var/spool/postfix/,}pid/unix.flush rwk,
/etc/mtab r,
@{HOME}/.forward r,

View File

@@ -2,6 +2,7 @@
#
# Copyright (C) 2002-2006 Novell/SUSE
# Copyright (C) 2018 Canonical, Ltd.
# Copyright (C) 2021 Christian Boltz
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
@@ -31,9 +32,9 @@ profile postfix-local /usr/lib/postfix/{bin/,sbin/,}local {
/{usr/,}bin/date mixr,
/dev/tty rw,
/etc/{postfix/,}aliases.db rk,
# mailman on SuSE is configed to have its own alias file
/var/lib/mailman/data/aliases.db rk,
/etc/aliases.{lm,}db rk,
# mailman on SuSE is configured to have its own alias file
/var/lib/mailman/data/aliases.{lm,}db rk,
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/* rw,
/{var/spool/postfix/,}active/[0-9A-F]/[0-9A-F]/ rw,
/{var/spool/postfix/,}active/[0-9A-F]/ rw,
@@ -41,9 +42,6 @@ profile postfix-local /usr/lib/postfix/{bin/,sbin/,}local {
/{var/spool/postfix/,}pid/unix.local rwk,
/{var/spool/postfix/,}private/{bounce,defer,flush,lmtp,local,rewrite} rw,
/{var/spool/postfix/,}public/{cleanup,flush} rw,
/etc/postfix/virtual.db r,
/etc/postfix/lists.db r,
# deliver mail
/var/mail/* wk,
}

Some files were not shown because too many files have changed in this diff Show More