Skip to content

Commit

Permalink
audit: fix filename matching in __audit_inode() and __audit_inode_chi…
Browse files Browse the repository at this point in the history
…ld()

In all likelihood there were some subtle, and perhaps not so subtle,
bugs with filename matching in audit_inode() and audit_inode_child()
for some time, however, recent changes to the audit filename code have
definitely broken the filename matching code.  The breakage could
result in duplicate filenames in the audit log and other odd audit
record entries.  This patch fixes the filename matching code and
restores some sanity to the filename audit records.

CC: [email protected]
CC: [email protected]
Signed-off-by: Paul Moore <[email protected]>
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
pcmoore authored and Al Viro committed Jan 23, 2015
1 parent fd3522f commit 57c59f5
Showing 1 changed file with 25 additions and 9 deletions.
34 changes: 25 additions & 9 deletions kernel/auditsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 */
Expand Down Expand Up @@ -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;
}
Expand All @@ -1949,18 +1965,17 @@ 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) ||
!audit_compare_dname_path(dname, n->name->name,
found_parent ?
found_parent->name_len :
AUDIT_NAME_FULL)) {
if (n->type == AUDIT_TYPE_UNKNOWN)
n->type = type;
found_child = n;
break;
}
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 57c59f5

Please sign in to comment.