]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
apparmor: convert delegating deleted files to mediate deleted files
authorJohn Johansen <john.johansen@canonical.com>
Tue, 2 Aug 2016 10:49:35 +0000 (03:49 -0700)
committerTim Gardner <tim.gardner@canonical.com>
Mon, 20 Feb 2017 03:57:58 +0000 (20:57 -0700)
This is a semantic change that may need to be reverted but we can not
properly do delegation atm and doing blind delegation is a security
hole.

Files that have the necessary labeling can still be delegated however
mediation will be required for deleted files that need to be revalidated.

Note: we code is setup to specify DELEGATE_DELETED but aliases it on
the backend to MEDIATE_DELETED. This will have to be partially reverted/
changed for profile replacement causing a revalidation.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Signed-off-by: Leann Ogasawara <leann.ogasawara@canonical.com>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
security/apparmor/file.c
security/apparmor/path.c

index d2473b63046dd72814aa69b5a02e1d0993ad9858..fb8f2c563874796046df9161ca88b9ddbecce20f 100644 (file)
@@ -167,17 +167,13 @@ static inline bool is_deleted(struct dentry *dentry)
 
 static int path_name(const char *op, struct aa_label *label,
                     const struct path *path, int flags, char *buffer,
-                    const char**name, struct path_cond *cond, u32 request,
-                    bool delegate_deleted)
+                    const char**name, struct path_cond *cond, u32 request)
 {
        struct aa_profile *profile;
        const char *info = NULL;
        int error = aa_path_name(path, flags, buffer, name, &info,
                                 labels_profile(label)->disconnected);
        if (error) {
-               if (error == -ENOENT && is_deleted(path->dentry) &&
-                   delegate_deleted)
-                       return 0;
                fn_for_each_confined(label, profile,
                        aa_audit_file(profile, &nullperms, op, request, *name,
                                      NULL, NULL, cond->uid, info, error));
@@ -326,8 +322,8 @@ int aa_path_perm(const char *op, struct aa_label *label,
                (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0);
        get_buffers(buffer);
 
-       error = path_name(op, label, path, flags, buffer, &name, cond,
-                         request, true);
+       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,
@@ -461,14 +457,14 @@ int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
        get_buffers(buffer, buffer2);
        error = path_name(OP_LINK, label, &link,
                          labels_profile(label)->path_flags, buffer,
-                         &lname, &cond, AA_MAY_LINK, false);
+                         &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, false);
+                         &cond, AA_MAY_LINK);
        if (error)
                goto out;
 
@@ -526,17 +522,9 @@ static int __file_path_perm(const char *op, struct aa_label *label,
                (S_ISDIR(cond.mode) ? PATH_IS_DIR : 0);
        get_buffers(buffer);
 
-       error = path_name(op, label, &file->f_path, flags, buffer, &name, &cond,
-                         request, true);
-       if (error) {
-               if (error == 1)
-                       /* Access to open files that are deleted are
-                        * given a pass (implicit delegation)
-                        */
-                       /* TODO not needed when full perms cached */
-                       error = 0;
-               goto out;
-       }
+       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,
@@ -557,7 +545,6 @@ static int __file_path_perm(const char *op, struct aa_label *label,
        if (!error)
                update_file_ctx(file_ctx(file), label, request);
 
-out:
        put_buffers(buffer);
 
        return error;
index 3511a0f63a7d76d6f2634ce0587eabb30f5812b1..3061334e4370793c27b78834405e8880fc34ff1c 100644 (file)
@@ -162,7 +162,7 @@ static int d_namespace_path(const struct path *path, char *buf, char **name,
         *    allocated.
         */
        if (d_unlinked(path->dentry) && d_is_positive(path->dentry) &&
-           !(flags & PATH_MEDIATE_DELETED)) {
+           !(flags & (PATH_MEDIATE_DELETED | PATH_DELEGATE_DELETED))) {
                        error = -ENOENT;
                        goto out;
        }