]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blobdiff - security/apparmor/file.c
apparmor: push path lookup into mediation loop
[mirror_ubuntu-zesty-kernel.git] / security / apparmor / file.c
index fb8f2c563874796046df9161ca88b9ddbecce20f..546f7688416b104f2376551d28f25a6afac64137 100644 (file)
@@ -286,6 +286,7 @@ int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name,
                   struct aa_perms *perms)
 {
        int e = 0;
+
        if (profile_unconfined(profile) ||
            ((flags & PATH_SOCK_COND) && !PROFILE_MEDIATES_AF(profile, AF_UNIX)))
                return 0;
@@ -296,6 +297,27 @@ int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name,
                             cond->uid, NULL, e);
 }
 
+
+static int profile_path_perm(const char *op, struct aa_profile *profile,
+                            const struct path *path, char *buffer, u32 request,
+                            struct path_cond *cond, int flags,
+                            struct aa_perms *perms)
+{
+       const char *name;
+       int error;
+
+       if (profile_unconfined(profile))
+               return 0;
+
+       error = path_name(op, &profile->label, path,
+                         flags | profile->path_flags, buffer, &name, cond,
+                         request);
+       if (error)
+               return error;
+       return __aa_path_perm(op, profile, name, request, cond, flags,
+                             perms);
+}
+
 /**
  * aa_path_perm - do permissions check & audit for @path
  * @op: operation being checked
@@ -312,22 +334,15 @@ int aa_path_perm(const char *op, struct aa_label *label,
                 struct path_cond *cond)
 {
        struct aa_perms perms = {};
-       char *buffer = NULL;
-       const char *name;
        struct aa_profile *profile;
+       char *buffer = NULL;
        int error;
 
-       /* TODO: fix path lookup flags */
-       flags |= labels_profile(label)->path_flags |
-               (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
+       flags |= PATH_DELEGATE_DELETED | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
        get_buffers(buffer);
-
-       error = path_name(op, label, path, flags | PATH_DELEGATE_DELETED,
-                         buffer, &name, cond, request);
-       if (!error)
-               error = fn_for_each_confined(label, profile,
-                               __aa_path_perm(op, profile, name, request, cond,
-                                              flags, &perms));
+       error = fn_for_each_confined(label, profile,
+                       profile_path_perm(op, profile, path, buffer, request,
+                                         cond, flags, &perms));
 
        put_buffers(buffer);
        return error;
@@ -353,15 +368,30 @@ static inline bool xindex_is_subset(u32 link, u32 target)
        return 1;
 }
 
-static int profile_path_link(struct aa_profile *profile, const char *lname,
-                            const char *tname, struct path_cond *cond)
+static int profile_path_link(struct aa_profile *profile,
+                            const struct path *link, char *buffer,
+                            const struct path *target, char *buffer2,
+                            struct path_cond *cond)
 {
+       const char *lname, *tname = NULL;
        struct aa_perms lperms, perms;
        const char *info = NULL;
        u32 request = AA_MAY_LINK;
        unsigned int state;
-       int e = -EACCES;
+       int error;
 
+       error = path_name(OP_LINK, &profile->label, link, profile->path_flags,
+                         buffer, &lname, cond, AA_MAY_LINK);
+       if (error)
+               goto audit;
+
+       /* buffer2 freed below, tname is pointer in buffer2 */
+       error = path_name(OP_LINK, &profile->label, target, profile->path_flags,
+                         buffer2, &tname, cond, AA_MAY_LINK);
+       if (error)
+               goto audit;
+
+       error = -EACCES;
        /* aa_str_perms - handles the case of the dfa being NULL */
        state = aa_str_perms(profile->file.dfa, profile->file.start, lname,
                             cond, &lperms);
@@ -412,11 +442,11 @@ static int profile_path_link(struct aa_profile *profile, const char *lname,
        }
 
 done_tests:
-       e = 0;
+       error = 0;
 
 audit:
        return aa_audit_file(profile, &lperms, OP_LINK, request, lname, tname,
-                            NULL, cond->uid, info, e);
+                            NULL, cond->uid, info, error);
 }
 
 /**
@@ -447,31 +477,14 @@ int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
                d_backing_inode(old_dentry)->i_mode
        };
        char *buffer = NULL, *buffer2 = NULL;
-       const char *lname, *tname = NULL;
        struct aa_profile *profile;
        int error;
 
-       /* TODO: fix path lookup flags, auditing of failed path for profile */
-       profile = labels_profile(label);
        /* buffer freed below, lname is pointer in buffer */
        get_buffers(buffer, buffer2);
-       error = path_name(OP_LINK, label, &link,
-                         labels_profile(label)->path_flags, buffer,
-                         &lname, &cond, AA_MAY_LINK);
-       if (error)
-               goto out;
-
-       /* buffer2 freed below, tname is pointer in buffer2 */
-       error = path_name(OP_LINK, label, &target,
-                         labels_profile(label)->path_flags, buffer2, &tname,
-                         &cond, AA_MAY_LINK);
-       if (error)
-               goto out;
-
        error = fn_for_each_confined(label, profile,
-                       profile_path_link(profile, lname, tname, &cond));
-
-out:
+                       profile_path_link(profile, &link, buffer, &target,
+                                         buffer2, &cond));
        put_buffers(buffer, buffer2);
 
        return error;
@@ -508,7 +521,6 @@ static int __file_path_perm(const char *op, struct aa_label *label,
                .uid = file_inode(file)->i_uid,
                .mode = file_inode(file)->i_mode
        };
-       const char *name;
        char *buffer;
        int flags, error;
 
@@ -517,19 +529,13 @@ static int __file_path_perm(const char *op, struct aa_label *label,
                /* TODO: check for revocation on stale profiles */
                return 0;
 
-       /* TODO: fix path lookup flags */
-       flags = PATH_DELEGATE_DELETED | labels_profile(label)->path_flags |
-               (S_ISDIR(cond.mode) ? PATH_IS_DIR : 0);
+       flags = PATH_DELEGATE_DELETED | (S_ISDIR(cond.mode) ? PATH_IS_DIR : 0);
        get_buffers(buffer);
 
-       error = path_name(op, label, &file->f_path,
-                         flags | PATH_DELEGATE_DELETED, buffer, &name, &cond,
-                         request);
-
        /* check every profile in task label not in current cache */
        error = fn_for_each_not_in_set(flabel, label, profile,
-                       __aa_path_perm(op, profile, name, request, &cond, 0,
-                                      &perms));
+                       profile_path_perm(op, profile, &file->f_path, buffer,
+                                         request, &cond, flags, &perms));
        if (denied) {
                /* check every profile in file label that was not tested
                 * in the initial check above.
@@ -539,8 +545,9 @@ static int __file_path_perm(const char *op, struct aa_label *label,
                /* TODO: don't audit here */
                last_error(error,
                        fn_for_each_not_in_set(label, flabel, profile,
-                               __aa_path_perm(op, profile, name, request,
-                                              &cond, 0, &perms)));
+                               profile_path_perm(op, profile, &file->f_path,
+                                                 buffer, request, &cond, flags,
+                                                 &perms)));
        }
        if (!error)
                update_file_ctx(file_ctx(file), label, request);