audit: fix filename matching in __audit_inode() and __audit_inode_child()
[firefly-linux-kernel-4.4.55.git] / kernel / auditsc.c
index 132dbcdef6ec7517f26a85c99c7b16fa2209b09b..4f521964ccaa9ac30696506fd81f4d72151da771 100644 (file)
@@ -1846,6 +1846,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
        /* The struct filename _must_ have a populated ->name */
        BUG_ON(!name->name);
 #endif
+
        /*
         * If we have a pointer to an audit_names entry already, then we can
         * just use it directly if the type is correct.
@@ -1863,7 +1864,17 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
        }
 
        list_for_each_entry_reverse(n, &context->names_list, list) {
-               if (!n->name || strcmp(n->name->name, name->name))
+               if (n->ino) {
+                       /* valid inode number, use that for the comparison */
+                       if (n->ino != inode->i_ino ||
+                           n->dev != inode->i_sb->s_dev)
+                               continue;
+               } else if (n->name) {
+                       /* inode number has not been set, check the name */
+                       if (strcmp(n->name->name, name->name))
+                               continue;
+               } else
+                       /* no inode and no name (?!) ... this is odd ... */
                        continue;
 
                /* match the correct record type */
@@ -1936,11 +1947,16 @@ void __audit_inode_child(const struct inode *parent,
 
        /* look for a parent entry first */
        list_for_each_entry(n, &context->names_list, list) {
-               if (!n->name || n->type != AUDIT_TYPE_PARENT)
+               if (!n->name ||
+                   (n->type != AUDIT_TYPE_PARENT &&
+                    n->type != AUDIT_TYPE_UNKNOWN))
                        continue;
 
-               if (n->ino == parent->i_ino &&
-                   !audit_compare_dname_path(dname, n->name->name, n->name_len)) {
+               if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev &&
+                   !audit_compare_dname_path(dname,
+                                             n->name->name, n->name_len)) {
+                       if (n->type == AUDIT_TYPE_UNKNOWN)
+                               n->type = AUDIT_TYPE_PARENT;
                        found_parent = n;
                        break;
                }
@@ -1949,11 +1965,8 @@ void __audit_inode_child(const struct inode *parent,
        /* is there a matching child entry? */
        list_for_each_entry(n, &context->names_list, list) {
                /* can only match entries that have a name */
-               if (!n->name || n->type != type)
-                       continue;
-
-               /* if we found a parent, make sure this one is a child of it */
-               if (found_parent && (n->name != found_parent->name))
+               if (!n->name ||
+                   (n->type != type && n->type != AUDIT_TYPE_UNKNOWN))
                        continue;
 
                if (!strcmp(dname, n->name->name) ||
@@ -1961,6 +1974,8 @@ void __audit_inode_child(const struct inode *parent,
                                                found_parent ?
                                                found_parent->name_len :
                                                AUDIT_NAME_FULL)) {
+                       if (n->type == AUDIT_TYPE_UNKNOWN)
+                               n->type = type;
                        found_child = n;
                        break;
                }
@@ -1989,6 +2004,7 @@ void __audit_inode_child(const struct inode *parent,
                        found_child->name_put = false;
                }
        }
+
        if (inode)
                audit_copy_inode(found_child, dentry, inode);
        else