diff options
Diffstat (limited to 'kernel/auditsc.c')
-rw-r--r-- | kernel/auditsc.c | 49 |
1 files changed, 40 insertions, 9 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 287b3d381174..793e9e98f7f8 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -72,6 +72,8 @@ | |||
72 | #include <linux/fs_struct.h> | 72 | #include <linux/fs_struct.h> |
73 | #include <linux/compat.h> | 73 | #include <linux/compat.h> |
74 | #include <linux/ctype.h> | 74 | #include <linux/ctype.h> |
75 | #include <linux/string.h> | ||
76 | #include <uapi/linux/limits.h> | ||
75 | 77 | ||
76 | #include "audit.h" | 78 | #include "audit.h" |
77 | 79 | ||
@@ -1861,8 +1863,7 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
1861 | } | 1863 | } |
1862 | 1864 | ||
1863 | list_for_each_entry_reverse(n, &context->names_list, list) { | 1865 | list_for_each_entry_reverse(n, &context->names_list, list) { |
1864 | /* does the name pointer match? */ | 1866 | if (!n->name || strcmp(n->name->name, name->name)) |
1865 | if (!n->name || n->name->name != name->name) | ||
1866 | continue; | 1867 | continue; |
1867 | 1868 | ||
1868 | /* match the correct record type */ | 1869 | /* match the correct record type */ |
@@ -1881,14 +1882,44 @@ out_alloc: | |||
1881 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); | 1882 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
1882 | if (!n) | 1883 | if (!n) |
1883 | return; | 1884 | return; |
1884 | if (name) | 1885 | /* unfortunately, while we may have a path name to record with the |
1885 | /* since name is not NULL we know there is already a matching | 1886 | * inode, we can't always rely on the string lasting until the end of |
1886 | * name record, see audit_getname(), so there must be a type | 1887 | * the syscall so we need to create our own copy, it may fail due to |
1887 | * mismatch; reuse the string path since the original name | 1888 | * memory allocation issues, but we do our best */ |
1888 | * record will keep the string valid until we free it in | 1889 | if (name) { |
1889 | * audit_free_names() */ | 1890 | /* we can't use getname_kernel() due to size limits */ |
1890 | n->name = name; | 1891 | size_t len = strlen(name->name) + 1; |
1892 | struct filename *new = __getname(); | ||
1893 | |||
1894 | if (unlikely(!new)) | ||
1895 | goto out; | ||
1896 | |||
1897 | if (len <= (PATH_MAX - sizeof(*new))) { | ||
1898 | new->name = (char *)(new) + sizeof(*new); | ||
1899 | new->separate = false; | ||
1900 | } else if (len <= PATH_MAX) { | ||
1901 | /* this looks odd, but is due to final_putname() */ | ||
1902 | struct filename *new2; | ||
1891 | 1903 | ||
1904 | new2 = kmalloc(sizeof(*new2), GFP_KERNEL); | ||
1905 | if (unlikely(!new2)) { | ||
1906 | __putname(new); | ||
1907 | goto out; | ||
1908 | } | ||
1909 | new2->name = (char *)new; | ||
1910 | new2->separate = true; | ||
1911 | new = new2; | ||
1912 | } else { | ||
1913 | /* we should never get here, but let's be safe */ | ||
1914 | __putname(new); | ||
1915 | goto out; | ||
1916 | } | ||
1917 | strlcpy((char *)new->name, name->name, len); | ||
1918 | new->uptr = NULL; | ||
1919 | new->aname = n; | ||
1920 | n->name = new; | ||
1921 | n->name_put = true; | ||
1922 | } | ||
1892 | out: | 1923 | out: |
1893 | if (parent) { | 1924 | if (parent) { |
1894 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; | 1925 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; |