diff options
Diffstat (limited to 'kernel/auditsc.c')
| -rw-r--r-- | kernel/auditsc.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index c75522a83678..072566dd0caf 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 */ |
| @@ -1877,12 +1878,48 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
| 1877 | } | 1878 | } |
| 1878 | 1879 | ||
| 1879 | out_alloc: | 1880 | out_alloc: |
| 1880 | /* unable to find the name from a previous getname(). Allocate a new | 1881 | /* unable to find an entry with both a matching name and type */ |
| 1881 | * anonymous entry. | 1882 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
| 1882 | */ | ||
| 1883 | n = audit_alloc_name(context, AUDIT_TYPE_NORMAL); | ||
| 1884 | if (!n) | 1883 | if (!n) |
| 1885 | return; | 1884 | return; |
| 1885 | /* unfortunately, while we may have a path name to record with the | ||
| 1886 | * inode, we can't always rely on the string lasting until the end of | ||
| 1887 | * the syscall so we need to create our own copy, it may fail due to | ||
| 1888 | * memory allocation issues, but we do our best */ | ||
| 1889 | if (name) { | ||
| 1890 | /* we can't use getname_kernel() due to size limits */ | ||
| 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; | ||
| 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 | } | ||
| 1886 | out: | 1923 | out: |
| 1887 | if (parent) { | 1924 | if (parent) { |
| 1888 | 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; |
