|
@@ -72,6 +72,8 @@
|
|
|
#include <linux/fs_struct.h>
|
|
|
#include <linux/compat.h>
|
|
|
#include <linux/ctype.h>
|
|
|
+#include <linux/string.h>
|
|
|
+#include <uapi/linux/limits.h>
|
|
|
|
|
|
#include "audit.h"
|
|
|
|
|
@@ -1861,8 +1863,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry,
|
|
|
}
|
|
|
|
|
|
list_for_each_entry_reverse(n, &context->names_list, list) {
|
|
|
- /* does the name pointer match? */
|
|
|
- if (!n->name || n->name->name != name->name)
|
|
|
+ if (!n->name || strcmp(n->name->name, name->name))
|
|
|
continue;
|
|
|
|
|
|
/* match the correct record type */
|
|
@@ -1881,14 +1882,44 @@ out_alloc:
|
|
|
n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
|
|
|
if (!n)
|
|
|
return;
|
|
|
- if (name)
|
|
|
- /* since name is not NULL we know there is already a matching
|
|
|
- * name record, see audit_getname(), so there must be a type
|
|
|
- * mismatch; reuse the string path since the original name
|
|
|
- * record will keep the string valid until we free it in
|
|
|
- * audit_free_names() */
|
|
|
- n->name = name;
|
|
|
+ /* unfortunately, while we may have a path name to record with the
|
|
|
+ * inode, we can't always rely on the string lasting until the end of
|
|
|
+ * the syscall so we need to create our own copy, it may fail due to
|
|
|
+ * memory allocation issues, but we do our best */
|
|
|
+ if (name) {
|
|
|
+ /* we can't use getname_kernel() due to size limits */
|
|
|
+ size_t len = strlen(name->name) + 1;
|
|
|
+ struct filename *new = __getname();
|
|
|
+
|
|
|
+ if (unlikely(!new))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ if (len <= (PATH_MAX - sizeof(*new))) {
|
|
|
+ new->name = (char *)(new) + sizeof(*new);
|
|
|
+ new->separate = false;
|
|
|
+ } else if (len <= PATH_MAX) {
|
|
|
+ /* this looks odd, but is due to final_putname() */
|
|
|
+ struct filename *new2;
|
|
|
|
|
|
+ new2 = kmalloc(sizeof(*new2), GFP_KERNEL);
|
|
|
+ if (unlikely(!new2)) {
|
|
|
+ __putname(new);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ new2->name = (char *)new;
|
|
|
+ new2->separate = true;
|
|
|
+ new = new2;
|
|
|
+ } else {
|
|
|
+ /* we should never get here, but let's be safe */
|
|
|
+ __putname(new);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ strlcpy((char *)new->name, name->name, len);
|
|
|
+ new->uptr = NULL;
|
|
|
+ new->aname = n;
|
|
|
+ n->name = new;
|
|
|
+ n->name_put = true;
|
|
|
+ }
|
|
|
out:
|
|
|
if (parent) {
|
|
|
n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL;
|