Trying to execute a binary located at a disconnected path (e.g. through
execveat() with AT_EMPTY_PATH) would result in a permission denial due to
a path lookup failure, even when in complain mode. Instead, create a new
learning profile, as would be done for any other complain mode execution
of a binary not covered by a profile's execution rules. Because of the
path aliasing that can occur in situations with disconnected paths, do not
behave as if attach_disconnected was specified as a profile flag (unless,
of course, the loaded profile itself has that flag set).

Signed-off-by: Ryan Lee <ryan....@canonical.com>
---

v1 -> v2: fix grammar nit identified by Christian Boltz

 security/apparmor/domain.c | 34 ++++++++++++++++++++++++++--------
 1 file changed, 26 insertions(+), 8 deletions(-)

diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 9703ec2bfa78..e383f37a1536 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -661,6 +661,13 @@ static struct aa_label *profile_transition(const struct 
cred *subj_cred,
                        AA_DEBUG(DEBUG_DOMAIN, "name lookup ix on error");
                        error = 0;
                        new = aa_get_newest_label(&profile->label);
+               } else if (COMPLAIN_MODE(profile)) {
+                       AA_DEBUG(DEBUG_DOMAIN, "name lookup ix on error");
+                       error = 0;
+
+                       name = bprm->filename;
+                       // TODO: helper function to detangle control flow (?)
+                       goto create_learning_profile;
                }
                name = bprm->filename;
                goto audit;
@@ -837,7 +844,7 @@ static struct aa_label *handle_onexec(const struct cred 
*subj_cred,
                error = fn_for_each_in_ns(label, profile,
                                profile_onexec(subj_cred, profile, onexec, 
stack,
                                               bprm, buffer, cond, unsafe));
-               if (error)
+               if (error && !COMPLAIN_MODE(profile))
                        return ERR_PTR(error);
                new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
                                aa_get_newest_label(onexec),
@@ -850,7 +857,7 @@ static struct aa_label *handle_onexec(const struct cred 
*subj_cred,
                error = fn_for_each_in_ns(label, profile,
                                profile_onexec(subj_cred, profile, onexec, 
stack, bprm,
                                               buffer, cond, unsafe));
-               if (error)
+               if (error && !COMPLAIN_MODE(profile))
                        return ERR_PTR(error);
                new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
                                aa_label_merge(&profile->label, onexec,
@@ -860,17 +867,28 @@ static struct aa_label *handle_onexec(const struct cred 
*subj_cred,
                                                   cond, unsafe));
        }
 
-       if (new)
-               return new;
-
-       /* TODO: get rid of GLOBAL_ROOT_UID */
-       error = fn_for_each_in_ns(label, profile,
+       /*
+        * error should only be set at this point if we're in complain mode
+        * Any remaining error after this block would be an error in the
+        * auditing process itself, which we'd want to bubble up
+        */
+       if (error) {
+               /* TODO: get rid of GLOBAL_ROOT_UID */
+               error = fn_for_each_in_ns(label, profile,
                        aa_audit_file(subj_cred, profile, &nullperms,
                                      OP_CHANGE_ONEXEC,
                                      AA_MAY_ONEXEC, bprm->filename, NULL,
                                      onexec, GLOBAL_ROOT_UID,
                                      "failed to build target label", -ENOMEM, 
false));
-       return ERR_PTR(error);
+       }
+       if (error) {
+               // Decrement refcount on any learning profile created earlier
+               aa_put_label(new);
+               return ERR_PTR(error);
+       }
+
+       AA_BUG(!new);
+       return new;
 }
 
 /**
-- 
2.43.0


Reply via email to