aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2015-01-22 00:00:16 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-01-23 00:23:58 -0500
commit57c59f5837bdfd0b4fee3b02a44857e263a09bfa (patch)
tree3977c4bdd3271e3bc5210803d39eb4f11199ecf1 /kernel
parentfd3522fdc84023b050bb40318d9fc71a9adc22bc (diff)
audit: fix filename matching in __audit_inode() and __audit_inode_child()
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: viro@zeniv.linux.org.uk CC: linux-fsdevel@vger.kernel.org Signed-off-by: Paul Moore <pmoore@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/auditsc.c34
1 files changed, 25 insertions, 9 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 132dbcdef6ec..4f521964ccaa 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1846,6 +1846,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
1846 /* The struct filename _must_ have a populated ->name */ 1846 /* The struct filename _must_ have a populated ->name */
1847 BUG_ON(!name->name); 1847 BUG_ON(!name->name);
1848#endif 1848#endif
1849
1849 /* 1850 /*
1850 * If we have a pointer to an audit_names entry already, then we can 1851 * If we have a pointer to an audit_names entry already, then we can
1851 * just use it directly if the type is correct. 1852 * just use it directly if the type is correct.
@@ -1863,7 +1864,17 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
1863 } 1864 }
1864 1865
1865 list_for_each_entry_reverse(n, &context->names_list, list) { 1866 list_for_each_entry_reverse(n, &context->names_list, list) {
1866 if (!n->name || strcmp(n->name->name, name->name)) 1867 if (n->ino) {
1868 /* valid inode number, use that for the comparison */
1869 if (n->ino != inode->i_ino ||
1870 n->dev != inode->i_sb->s_dev)
1871 continue;
1872 } else if (n->name) {
1873 /* inode number has not been set, check the name */
1874 if (strcmp(n->name->name, name->name))
1875 continue;
1876 } else
1877 /* no inode and no name (?!) ... this is odd ... */
1867 continue; 1878 continue;
1868 1879
1869 /* match the correct record type */ 1880 /* match the correct record type */
@@ -1936,11 +1947,16 @@ void __audit_inode_child(const struct inode *parent,
1936 1947
1937 /* look for a parent entry first */ 1948 /* look for a parent entry first */
1938 list_for_each_entry(n, &context->names_list, list) { 1949 list_for_each_entry(n, &context->names_list, list) {
1939 if (!n->name || n->type != AUDIT_TYPE_PARENT) 1950 if (!n->name ||
1951 (n->type != AUDIT_TYPE_PARENT &&
1952 n->type != AUDIT_TYPE_UNKNOWN))
1940 continue; 1953 continue;
1941 1954
1942 if (n->ino == parent->i_ino && 1955 if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev &&
1943 !audit_compare_dname_path(dname, n->name->name, n->name_len)) { 1956 !audit_compare_dname_path(dname,
1957 n->name->name, n->name_len)) {
1958 if (n->type == AUDIT_TYPE_UNKNOWN)
1959 n->type = AUDIT_TYPE_PARENT;
1944 found_parent = n; 1960 found_parent = n;
1945 break; 1961 break;
1946 } 1962 }
@@ -1949,11 +1965,8 @@ void __audit_inode_child(const struct inode *parent,
1949 /* is there a matching child entry? */ 1965 /* is there a matching child entry? */
1950 list_for_each_entry(n, &context->names_list, list) { 1966 list_for_each_entry(n, &context->names_list, list) {
1951 /* can only match entries that have a name */ 1967 /* can only match entries that have a name */
1952 if (!n->name || n->type != type) 1968 if (!n->name ||
1953 continue; 1969 (n->type != type && n->type != AUDIT_TYPE_UNKNOWN))
1954
1955 /* if we found a parent, make sure this one is a child of it */
1956 if (found_parent && (n->name != found_parent->name))
1957 continue; 1970 continue;
1958 1971
1959 if (!strcmp(dname, n->name->name) || 1972 if (!strcmp(dname, n->name->name) ||
@@ -1961,6 +1974,8 @@ void __audit_inode_child(const struct inode *parent,
1961 found_parent ? 1974 found_parent ?
1962 found_parent->name_len : 1975 found_parent->name_len :
1963 AUDIT_NAME_FULL)) { 1976 AUDIT_NAME_FULL)) {
1977 if (n->type == AUDIT_TYPE_UNKNOWN)
1978 n->type = type;
1964 found_child = n; 1979 found_child = n;
1965 break; 1980 break;
1966 } 1981 }
@@ -1989,6 +2004,7 @@ void __audit_inode_child(const struct inode *parent,
1989 found_child->name_put = false; 2004 found_child->name_put = false;
1990 } 2005 }
1991 } 2006 }
2007
1992 if (inode) 2008 if (inode)
1993 audit_copy_inode(found_child, dentry, inode); 2009 audit_copy_inode(found_child, dentry, inode);
1994 else 2010 else