]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - kernel/auditsc.c
Merge branch 'upstream' of git://git.infradead.org/users/pcmoore/audit
[karo-tx-linux.git] / kernel / auditsc.c
index 37c69ab561dad881c9fd76eaac1ed5b48e5bab52..072566dd0caf7739fc42b7d59c6791c29dc89343 100644 (file)
@@ -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;