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>
(cherry picked from commit 855dbd4ac8)
Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
John Johansen 2021-01-14 10:46:50 -08:00
parent 57d56dc2c0
commit ff392e6f49

View file

@ -204,14 +204,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");
}
}