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>hifive-unleashed-5.1
parent
4f5e838605
commit
b394d468e7
|
@ -273,4 +273,10 @@ extern long strncpy_from_unsafe(char *dst, const void *unsafe_addr, long count);
|
||||||
#define unsafe_put_user(x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0)
|
#define unsafe_put_user(x, ptr, err) do { if (unlikely(__put_user(x, ptr))) goto err; } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_HARDENED_USERCOPY
|
||||||
|
void __noreturn usercopy_abort(const char *name, const char *detail,
|
||||||
|
bool to_user, unsigned long offset,
|
||||||
|
unsigned long len);
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* __LINUX_UACCESS_H__ */
|
#endif /* __LINUX_UACCESS_H__ */
|
||||||
|
|
|
@ -58,11 +58,25 @@ static noinline int check_stack_object(const void *obj, unsigned long len)
|
||||||
return GOOD_STACK;
|
return GOOD_STACK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void report_usercopy(unsigned long len, bool to_user, const char *type)
|
/*
|
||||||
|
* If this function is reached, then CONFIG_HARDENED_USERCOPY has found an
|
||||||
|
* unexpected state during a copy_from_user() or copy_to_user() call.
|
||||||
|
* There are several checks being performed on the buffer by the
|
||||||
|
* __check_object_size() function. Normal stack buffer usage should never
|
||||||
|
* trip the checks, and kernel text addressing will always trip the check.
|
||||||
|
* For cache objects, copies must be within the object size.
|
||||||
|
*/
|
||||||
|
void __noreturn usercopy_abort(const char *name, const char *detail,
|
||||||
|
bool to_user, unsigned long offset,
|
||||||
|
unsigned long len)
|
||||||
{
|
{
|
||||||
pr_emerg("kernel memory %s attempt detected %s '%s' (%lu bytes)\n",
|
pr_emerg("Kernel memory %s attempt detected %s %s%s%s%s (offset %lu, size %lu)!\n",
|
||||||
to_user ? "exposure" : "overwrite",
|
to_user ? "exposure" : "overwrite",
|
||||||
to_user ? "from" : "to", type ? : "unknown", len);
|
to_user ? "from" : "to",
|
||||||
|
name ? : "unknown?!",
|
||||||
|
detail ? " '" : "", detail ? : "", detail ? "'" : "",
|
||||||
|
offset, len);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For greater effect, it would be nice to do do_group_exit(),
|
* For greater effect, it would be nice to do do_group_exit(),
|
||||||
* but BUG() actually hooks all the lock-breaking and per-arch
|
* 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)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
report:
|
report:
|
||||||
report_usercopy(n, to_user, err);
|
usercopy_abort(err, NULL, to_user, 0, n);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(__check_object_size);
|
EXPORT_SYMBOL(__check_object_size);
|
||||||
|
|
|
@ -138,6 +138,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
|
||||||
"__reiserfs_panic",
|
"__reiserfs_panic",
|
||||||
"lbug_with_loc",
|
"lbug_with_loc",
|
||||||
"fortify_panic",
|
"fortify_panic",
|
||||||
|
"usercopy_abort",
|
||||||
};
|
};
|
||||||
|
|
||||||
if (func->bind == STB_WEAK)
|
if (func->bind == STB_WEAK)
|
||||||
|
|
Loading…
Reference in New Issue