* [PATCH] uaccess: Zero destination buffer on overflow attempt
@ 2017-07-05 20:01 Kees Cook
0 siblings, 0 replies; only message in thread
From: Kees Cook @ 2017-07-05 20:01 UTC (permalink / raw)
To: Andrew Morton
Cc: Al Viro, Andi Kleen, Arnd Bergmann, Hoeun Ryu,
Hans-Christian Noren Egtvedt, linux-kernel
When the destination buffer size is known at build time but the runtime
size to copy into it is not known, the copy_from_user() will WARN when
it is too large and the copy_from_user() will fail. However, it was not
zeroing the destination buffer (for which it knows the correct size). This
fixes that corner case and adds a test for it in test_user_copy.c.
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Kees Cook <keescook@chromium.org>
---
include/linux/uaccess.h | 5 +++--
lib/test_user_copy.c | 12 ++++++++++++
2 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index 201418d5e15c..e350d81eb763 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -152,9 +152,10 @@ copy_from_user(void *to, const void __user *from, unsigned long n)
if (likely(sz < 0 || sz >= n)) {
check_object_size(to, n, false);
n = _copy_from_user(to, from, n);
- } else if (!__builtin_constant_p(n))
+ } else if (!__builtin_constant_p(n)) {
copy_user_overflow(sz, n);
- else
+ memset(to, 0, sz);
+ } else
__bad_copy_user();
return n;
diff --git a/lib/test_user_copy.c b/lib/test_user_copy.c
index 4621db801b23..c7a1da157c53 100644
--- a/lib/test_user_copy.c
+++ b/lib/test_user_copy.c
@@ -57,6 +57,8 @@ static int __init test_user_copy_init(void)
char __user *usermem;
char *bad_usermem;
unsigned long user_addr;
+ volatile int unconst = 0;
+ char charbuf[8];
u8 val_u8;
u16 val_u16;
u32 val_u32;
@@ -124,6 +126,7 @@ static int __init test_user_copy_init(void)
/* Prepare kernel memory with check values. */
memset(kmem, 0x5a, PAGE_SIZE);
memset(kmem + PAGE_SIZE, 0, PAGE_SIZE);
+ memset(charbuf, 0x6a, sizeof(charbuf));
/* Reject kernel-to-kernel copies through copy_from_user(). */
ret |= test(!copy_from_user(kmem, (char __user *)(kmem + PAGE_SIZE),
@@ -134,6 +137,15 @@ static int __init test_user_copy_init(void)
ret |= test(memcmp(kmem + PAGE_SIZE, kmem, PAGE_SIZE),
"zeroing failure for illegal all-kernel copy_from_user");
+ /* Reject copies into too-small buffers. */
+ ret |= test(!copy_from_user(charbuf, usermem,
+ sizeof(charbuf) + 1 + unconst),
+ "illegal too-large copy_from_user passed");
+
+ /* Destination buffer should have been entirely zeroed. */
+ ret |= test(memcmp(kmem + PAGE_SIZE, charbuf, sizeof(charbuf)),
+ "zeroing failure for illegal too-large copy_from_user");
+
#if 0
/*
* When running with SMAP/PAN/etc, this will Oops the kernel
--
2.7.4
--
Kees Cook
Pixel Security
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2017-07-05 20:01 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-05 20:01 [PATCH] uaccess: Zero destination buffer on overflow attempt Kees Cook
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.