aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2014-12-30 09:26:21 -0500
committerPaul Moore <pmoore@redhat.com>2014-12-30 09:26:21 -0500
commitfcf22d8267ad2601fe9b6c549d1be96401c23e0b (patch)
treeb03e9bd8e5986b0a670a7f41bedf366b6f6df121 /kernel
parent041d7b98ffe59c59fdd639931dea7d74f9aa9a59 (diff)
audit: create private file name copies when auditing inodes
Unfortunately, while commit 4a928436 ("audit: correctly record file names with different path name types") fixed a problem where we were not recording filenames, it created a new problem by attempting to use these file names after they had been freed. This patch resolves the issue by creating a copy of the filename which the audit subsystem frees after it is done with the string. At some point it would be nice to resolve this issue with refcounts, or something similar, instead of having to allocate/copy strings, but that is almost surely beyond the scope of a -rcX patch so we'll defer that for later. On the plus side, only audit users should be impacted by the string copying. Reported-by: Toralf Foerster <toralf.foerster@gmx.de> Signed-off-by: Paul Moore <pmoore@redhat.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/auditsc.c49
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 }
1892out: 1923out:
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;