X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=kernel%2Fauditsc.c;h=09c7b6b4f8e69e1c98dca80200898c2ca7a26214;hb=563a0d1236c2c58d584ef122a5cdc9930e5860b3;hp=f4a7756f999cddcf344e685ea561f358812c41fd;hpb=940e3a8dd6683a3787faf769b3df7a06f1c2fa31;p=~andy%2Flinux diff --git a/kernel/auditsc.c b/kernel/auditsc.c index f4a7756f999..09c7b6b4f8e 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -120,6 +120,7 @@ struct audit_names { struct audit_cap_data fcap; unsigned int fcap_ver; int name_len; /* number of name's characters to log */ + unsigned char type; /* record type */ bool name_put; /* call __putname() for this name */ /* * This was an allocated audit_names and not from the array of @@ -1995,7 +1996,8 @@ retry: #endif } -static struct audit_names *audit_alloc_name(struct audit_context *context) +static struct audit_names *audit_alloc_name(struct audit_context *context, + unsigned char type) { struct audit_names *aname; @@ -2010,6 +2012,7 @@ static struct audit_names *audit_alloc_name(struct audit_context *context) } aname->ino = (unsigned long)-1; + aname->type = type; list_add_tail(&aname->list, &context->names_list); context->name_count++; @@ -2040,7 +2043,7 @@ void __audit_getname(const char *name) return; } - n = audit_alloc_name(context); + n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); if (!n) return; @@ -2132,13 +2135,13 @@ static void audit_copy_inode(struct audit_names *name, const struct dentry *dent } /** - * audit_inode - store the inode and device from a lookup + * __audit_inode - store the inode and device from a lookup * @name: name being audited * @dentry: dentry being audited - * - * Called from fs/namei.c:path_lookup(). + * @parent: does this dentry represent the parent? */ -void __audit_inode(const char *name, const struct dentry *dentry) +void __audit_inode(const char *name, const struct dentry *dentry, + unsigned int parent) { struct audit_context *context = current->audit_context; const struct inode *inode = dentry->d_inode; @@ -2147,24 +2150,48 @@ void __audit_inode(const char *name, const struct dentry *dentry) if (!context->in_syscall) return; + if (!name) + goto out_alloc; + list_for_each_entry_reverse(n, &context->names_list, list) { - if (n->name && (n->name == name)) - goto out; + /* does the name pointer match? */ + if (n->name != name) + continue; + + /* match the correct record type */ + if (parent) { + if (n->type == AUDIT_TYPE_PARENT || + n->type == AUDIT_TYPE_UNKNOWN) + goto out; + } else { + if (n->type != AUDIT_TYPE_PARENT) + goto out; + } } - /* unable to find the name from a previous getname() */ - n = audit_alloc_name(context); +out_alloc: + /* unable to find the name from a previous getname(). Allocate a new + * anonymous entry. + */ + n = audit_alloc_name(context, AUDIT_TYPE_NORMAL); if (!n) return; out: + if (parent) { + n->name_len = n->name ? parent_len(n->name) : AUDIT_NAME_FULL; + n->type = AUDIT_TYPE_PARENT; + } else { + n->name_len = AUDIT_NAME_FULL; + n->type = AUDIT_TYPE_NORMAL; + } handle_path(dentry); audit_copy_inode(n, dentry, inode); } /** - * audit_inode_child - collect inode info for created/removed objects - * @dentry: dentry being audited + * __audit_inode_child - collect inode info for created/removed objects * @parent: inode of dentry parent + * @dentry: dentry being audited * * For syscalls that create or remove filesystem objects, audit_inode * can only collect information for the filesystem object's parent. @@ -2174,15 +2201,14 @@ out: * must be hooked prior, in order to capture the target inode during * unsuccessful attempts. */ -void __audit_inode_child(const struct dentry *dentry, - const struct inode *parent) +void __audit_inode_child(const struct inode *parent, + const struct dentry *dentry) { struct audit_context *context = current->audit_context; const char *found_parent = NULL, *found_child = NULL; const struct inode *inode = dentry->d_inode; const char *dname = dentry->d_name.name; struct audit_names *n; - int dirlen = 0; if (!context->in_syscall) return; @@ -2196,8 +2222,7 @@ void __audit_inode_child(const struct dentry *dentry, continue; if (n->ino == parent->i_ino && - !audit_compare_dname_path(dname, n->name, &dirlen)) { - n->name_len = dirlen; /* update parent data in place */ + !audit_compare_dname_path(dname, n->name)) { found_parent = n->name; goto add_names; } @@ -2210,11 +2235,12 @@ void __audit_inode_child(const struct dentry *dentry, /* strcmp() is the more likely scenario */ if (!strcmp(dname, n->name) || - !audit_compare_dname_path(dname, n->name, &dirlen)) { + !audit_compare_dname_path(dname, n->name)) { if (inode) - audit_copy_inode(n, NULL, inode); + audit_copy_inode(n, dentry, inode); else n->ino = (unsigned long)-1; + n->type = AUDIT_TYPE_NORMAL; found_child = n->name; goto add_names; } @@ -2222,14 +2248,14 @@ void __audit_inode_child(const struct dentry *dentry, add_names: if (!found_parent) { - n = audit_alloc_name(context); + n = audit_alloc_name(context, AUDIT_TYPE_NORMAL); if (!n) return; audit_copy_inode(n, NULL, parent); } if (!found_child) { - n = audit_alloc_name(context); + n = audit_alloc_name(context, AUDIT_TYPE_NORMAL); if (!n) return; @@ -2244,7 +2270,7 @@ add_names: } if (inode) - audit_copy_inode(n, NULL, inode); + audit_copy_inode(n, dentry, inode); } } EXPORT_SYMBOL_GPL(__audit_inode_child);