diff options
author | Kees Cook <keescook@chromium.org> | 2018-01-10 17:22:38 -0500 |
---|---|---|
committer | Kees Cook <keescook@chromium.org> | 2018-01-15 15:07:44 -0500 |
commit | b394d468e7d75637e682a9be4a1181b27186c593 (patch) | |
tree | 1c0894b3aafc06a4ee6bfc6facc81d192781de66 | |
parent | 4f5e838605c264fcf16c3ff9495bd83da99acc6a (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.h | 6 | ||||
-rw-r--r-- | mm/usercopy.c | 24 | ||||
-rw-r--r-- | tools/objtool/check.c | 1 |
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 | ||
277 | void __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 | ||
61 | static 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 | */ | ||
69 | void __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 | ||
262 | report: | 276 | report: |
263 | report_usercopy(n, to_user, err); | 277 | usercopy_abort(err, NULL, to_user, 0, n); |
264 | } | 278 | } |
265 | EXPORT_SYMBOL(__check_object_size); | 279 | EXPORT_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) |