summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2018-01-10 17:22:38 -0500
committerKees Cook <keescook@chromium.org>2018-01-15 15:07:44 -0500
commitb394d468e7d75637e682a9be4a1181b27186c593 (patch)
tree1c0894b3aafc06a4ee6bfc6facc81d192781de66
parent4f5e838605c264fcf16c3ff9495bd83da99acc6a (diff)
usercopy: Enhance and rename report_usercopy()
In preparation for refactoring the usercopy checks to pass offset to the hardened usercopy report, this renames report_usercopy() to the more accurate usercopy_abort(), marks it as noreturn because it is, adds a hopefully helpful comment for anyone investigating such reports, makes the function available to the slab allocators, and adds new "detail" and "offset" arguments. Signed-off-by: Kees Cook <keescook@chromium.org>
-rw-r--r--include/linux/uaccess.h6
-rw-r--r--mm/usercopy.c24
-rw-r--r--tools/objtool/check.c1
3 files changed, 26 insertions, 5 deletions
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 251e655d407f..38b6442dc569 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -273,4 +273,10 @@ extern long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count);
273#define unsafe_put_user(x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0) 273#define unsafe_put_user(x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0)
274#endif 274#endif
275 275
276#ifdef CONFIG_HARDENED_USERCOPY
277void __noreturn usercopy_abort(const char *name, const char *detail,
278 bool to_user, unsigned long offset,
279 unsigned long len);
280#endif
281
276#endif /* __LINUX_UACCESS_H__ */ 282#endif /* __LINUX_UACCESS_H__ */
diff --git a/mm/usercopy.c b/mm/usercopy.c
index 5df1e68d4585..8006baa4caac 100644
--- a/mm/usercopy.c
+++ b/mm/usercopy.c
@@ -58,11 +58,25 @@ static noinline int check_stack_object(const void *obj, unsigned long len)
58 return GOOD_STACK; 58 return GOOD_STACK;
59} 59}
60 60
61static void report_usercopy(unsigned long len, bool to_user, const char *type) 61/*
62 * If this function is reached, then CONFIG_HARDENED_USERCOPY has found an
63 * unexpected state during a copy_from_user() or copy_to_user() call.
64 * There are several checks being performed on the buffer by the
65 * __check_object_size() function. Normal stack buffer usage should never
66 * trip the checks, and kernel text addressing will always trip the check.
67 * For cache objects, copies must be within the object size.
68 */
69void __noreturn usercopy_abort(const char *name, const char *detail,
70 bool to_user, unsigned long offset,
71 unsigned long len)
62{ 72{
63 pr_emerg("kernel memory %s attempt detected %s '%s' (%lu bytes)\n", 73 pr_emerg("Kernel memory %s attempt detected %s %s%s%s%s (offset %lu, size %lu)!\n",
64 to_user ? "exposure" : "overwrite", 74 to_user ? "exposure" : "overwrite",
65 to_user ? "from" : "to", type ? : "unknown", len); 75 to_user ? "from" : "to",
76 name ? : "unknown?!",
77 detail ? " '" : "", detail ? : "", detail ? "'" : "",
78 offset, len);
79
66 /* 80 /*
67 * For greater effect, it would be nice to do do_group_exit(), 81 * For greater effect, it would be nice to do do_group_exit(),
68 * but BUG() actually hooks all the lock-breaking and per-arch 82 * but BUG() actually hooks all the lock-breaking and per-arch
@@ -260,6 +274,6 @@ void __check_object_size(const void *ptr, unsigned long n, bool to_user)
260 return; 274 return;
261 275
262report: 276report:
263 report_usercopy(n, to_user, err); 277 usercopy_abort(err, NULL, to_user, 0, n);
264} 278}
265EXPORT_SYMBOL(__check_object_size); 279EXPORT_SYMBOL(__check_object_size);
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 9b341584eb1b..ae39444896d4 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -138,6 +138,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
138 "__reiserfs_panic", 138 "__reiserfs_panic",
139 "lbug_with_loc", 139 "lbug_with_loc",
140 "fortify_panic", 140 "fortify_panic",
141 "usercopy_abort",
141 }; 142 };
142 143
143 if (func->bind == STB_WEAK) 144 if (func->bind == STB_WEAK)