From: glider@google.com
To: Alexander Viro <viro@zeniv.linux.org.uk>,
Vegard Nossum <vegard.nossum@oracle.com>,
Dmitry Vyukov <dvyukov@google.com>,
linux-mm@kvack.org
Cc: akpm@linux-foundation.org, aryabinin@virtuozzo.com,
luto@kernel.org, ard.biesheuvel@linaro.org, arnd@arndb.de,
hch@lst.de, dmitry.torokhov@gmail.com, edumazet@google.com,
ericvh@gmail.com, gregkh@linuxfoundation.org,
harry.wentland@amd.com, herbert@gondor.apana.org.au,
mingo@elte.hu, axboe@kernel.dk, martin.petersen@oracle.com,
schwidefsky@de.ibm.com, mst@redhat.com, monstr@monstr.eu,
pmladek@suse.com, sergey.senozhatsky@gmail.com,
rostedt@goodmis.org, tiwai@suse.com, tytso@mit.edu,
tglx@linutronix.de, wsa@the-dreams.de, gor@linux.ibm.com,
iii@linux.ibm.com, mark.rutland@arm.com, willy@infradead.org,
rdunlap@infradead.org, andreyknvl@google.com, elver@google.com,
Alexander Potapenko <glider@google.com>
Subject: [PATCH RFC v2 23/25] kmsan: hooks for copy_to_user() and friends
Date: Wed, 30 Oct 2019 15:22:35 +0100 [thread overview]
Message-ID: <20191030142237.249532-24-glider@google.com> (raw)
In-Reply-To: <20191030142237.249532-1-glider@google.com>
Memory that is copied from userspace must be unpoisoned.
Before copying memory to userspace, check it and report an error if it
contains uninitialized bits.
Signed-off-by: Alexander Potapenko <glider@google.com>
To: Alexander Potapenko <glider@google.com>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Cc: Vegard Nossum <vegard.nossum@oracle.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: linux-mm@kvack.org
---
Change-Id: I38428b9c7d1909b8441dcec1749b080494a7af99
---
arch/x86/include/asm/uaccess.h | 12 ++++++++++++
include/asm-generic/cacheflush.h | 7 ++++++-
include/asm-generic/uaccess.h | 12 ++++++++++--
include/linux/uaccess.h | 32 +++++++++++++++++++++++++++-----
lib/iov_iter.c | 6 ++++++
lib/usercopy.c | 6 +++++-
6 files changed, 66 insertions(+), 9 deletions(-)
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 61d93f062a36..ac4b26583f7c 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -6,6 +6,7 @@
*/
#include <linux/compiler.h>
#include <linux/kasan-checks.h>
+#include <linux/kmsan-checks.h>
#include <linux/string.h>
#include <asm/asm.h>
#include <asm/page.h>
@@ -174,6 +175,7 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
ASM_CALL_CONSTRAINT \
: "0" (ptr), "i" (sizeof(*(ptr)))); \
(x) = (__force __typeof__(*(ptr))) __val_gu; \
+ kmsan_unpoison_shadow(&(x), sizeof(*(ptr))); \
__builtin_expect(__ret_gu, 0); \
})
@@ -248,6 +250,7 @@ extern void __put_user_8(void);
__chk_user_ptr(ptr); \
might_fault(); \
__pu_val = x; \
+ kmsan_check_memory(&(__pu_val), sizeof(*(ptr))); \
switch (sizeof(*(ptr))) { \
case 1: \
__put_user_x(1, __pu_val, ptr, __ret_pu); \
@@ -270,7 +273,9 @@ extern void __put_user_8(void);
#define __put_user_size(x, ptr, size, label) \
do { \
+ __typeof__(*(ptr)) __pus_val = x; \
__chk_user_ptr(ptr); \
+ kmsan_check_memory(&(__pus_val), size); \
switch (size) { \
case 1: \
__put_user_goto(x, ptr, "b", "b", "iq", label); \
@@ -295,7 +300,10 @@ do { \
*/
#define __put_user_size_ex(x, ptr, size) \
do { \
+ __typeof__(*(ptr)) __puse_val; \
__chk_user_ptr(ptr); \
+ __puse_val = x; \
+ kmsan_check_memory(&(__puse_val), size); \
switch (size) { \
case 1: \
__put_user_asm_ex(x, ptr, "b", "b", "iq"); \
@@ -363,6 +371,7 @@ do { \
default: \
(x) = __get_user_bad(); \
} \
+ kmsan_unpoison_shadow(&(x), size); \
} while (0)
#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \
@@ -413,6 +422,7 @@ do { \
default: \
(x) = __get_user_bad(); \
} \
+ kmsan_unpoison_shadow(&(x), size); \
} while (0)
#define __get_user_asm_ex(x, addr, itype, rtype, ltype) \
@@ -428,11 +438,13 @@ do { \
#define __put_user_nocheck(x, ptr, size) \
({ \
__label__ __pu_label; \
+ __typeof__(*(ptr)) __pun_val = x; \
int __pu_err = -EFAULT; \
__typeof__(*(ptr)) __pu_val = (x); \
__typeof__(ptr) __pu_ptr = (ptr); \
__typeof__(size) __pu_size = (size); \
__uaccess_begin(); \
+ kmsan_check_memory(&(__pun_val), size); \
__put_user_size(__pu_val, __pu_ptr, __pu_size, __pu_label); \
__pu_err = 0; \
__pu_label: \
diff --git a/include/asm-generic/cacheflush.h b/include/asm-generic/cacheflush.h
index a950a22c4890..707531dccf5e 100644
--- a/include/asm-generic/cacheflush.h
+++ b/include/asm-generic/cacheflush.h
@@ -4,6 +4,7 @@
/* Keep includes the same across arches. */
#include <linux/mm.h>
+#include <linux/kmsan-checks.h>
#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 0
@@ -72,10 +73,14 @@ static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
+ kmsan_check_memory(src, len); \
memcpy(dst, src, len); \
flush_icache_user_range(vma, page, vaddr, len); \
} while (0)
#define copy_from_user_page(vma, page, vaddr, dst, src, len) \
- memcpy(dst, src, len)
+ do { \
+ memcpy(dst, src, len); \
+ kmsan_unpoison_shadow(dst, len); \
+ } while (0)
#endif /* __ASM_CACHEFLUSH_H */
diff --git a/include/asm-generic/uaccess.h b/include/asm-generic/uaccess.h
index e935318804f8..18a50333ffc0 100644
--- a/include/asm-generic/uaccess.h
+++ b/include/asm-generic/uaccess.h
@@ -142,7 +142,11 @@ static inline int __access_ok(unsigned long addr, unsigned long size)
static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
{
- return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0;
+ int n;
+
+ n = raw_copy_to_user(ptr, x, size);
+ kmsan_copy_to_user(ptr, x, size, n);
+ return unlikely(n) ? -EFAULT : 0;
}
#define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k)
@@ -203,7 +207,11 @@ extern int __put_user_bad(void) __attribute__((noreturn));
#ifndef __get_user_fn
static inline int __get_user_fn(size_t size, const void __user *ptr, void *x)
{
- return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0;
+ int copied, to_copy = size;
+
+ copied = raw_copy_from_user(x, ptr, size);
+ kmsan_unpoison_shadow(to, to_copy - res);
+ return unlikely(copied) ? -EFAULT : 0;
}
#define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k)
diff --git a/include/linux/uaccess.h b/include/linux/uaccess.h
index d4ee6e942562..4257b5f80689 100644
--- a/include/linux/uaccess.h
+++ b/include/linux/uaccess.h
@@ -5,6 +5,7 @@
#include <linux/sched.h>
#include <linux/thread_info.h>
#include <linux/kasan-checks.h>
+#include <linux/kmsan-checks.h>
#define uaccess_kernel() segment_eq(get_fs(), KERNEL_DS)
@@ -58,18 +59,26 @@
static __always_inline __must_check unsigned long
__copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
{
+ unsigned long to_copy = n;
+
kasan_check_write(to, n);
check_object_size(to, n, false);
- return raw_copy_from_user(to, from, n);
+ n = raw_copy_from_user(to, from, n);
+ kmsan_unpoison_shadow(to, to_copy - n);
+ return n;
}
static __always_inline __must_check unsigned long
__copy_from_user(void *to, const void __user *from, unsigned long n)
{
+ unsigned long to_copy = n;
+
might_fault();
kasan_check_write(to, n);
check_object_size(to, n, false);
- return raw_copy_from_user(to, from, n);
+ n = raw_copy_from_user(to, from, n);
+ kmsan_unpoison_shadow(to, to_copy - n);
+ return n;
}
/**
@@ -88,29 +97,39 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
static __always_inline __must_check unsigned long
__copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
{
+ unsigned long to_copy = n;
+
kasan_check_read(from, n);
check_object_size(from, n, true);
- return raw_copy_to_user(to, from, n);
+ n = raw_copy_to_user(to, from, n);
+ kmsan_copy_to_user(to, from, to_copy, n);
+ return n;
}
static __always_inline __must_check unsigned long
__copy_to_user(void __user *to, const void *from, unsigned long n)
{
+ unsigned long to_copy = n;
+
might_fault();
kasan_check_read(from, n);
check_object_size(from, n, true);
- return raw_copy_to_user(to, from, n);
+ n = raw_copy_to_user(to, from, n);
+ kmsan_copy_to_user(to, from, to_copy, n);
+ return n;
}
#ifdef INLINE_COPY_FROM_USER
static inline __must_check unsigned long
_copy_from_user(void *to, const void __user *from, unsigned long n)
{
- unsigned long res = n;
+ unsigned long res = n, to_copy = n;
+
might_fault();
if (likely(access_ok(from, n))) {
kasan_check_write(to, n);
res = raw_copy_from_user(to, from, n);
+ kmsan_unpoison_shadow(to, to_copy - res);
}
if (unlikely(res))
memset(to + (n - res), 0, res);
@@ -125,10 +144,13 @@ _copy_from_user(void *, const void __user *, unsigned long);
static inline __must_check unsigned long
_copy_to_user(void __user *to, const void *from, unsigned long n)
{
+ unsigned long to_copy = n;
+
might_fault();
if (access_ok(to, n)) {
kasan_check_read(from, n);
n = raw_copy_to_user(to, from, n);
+ kmsan_copy_to_user(to, from, to_copy, n);
}
return n;
}
diff --git a/lib/iov_iter.c b/lib/iov_iter.c
index 639d5e7014c1..f038676068b2 100644
--- a/lib/iov_iter.c
+++ b/lib/iov_iter.c
@@ -137,18 +137,24 @@
static int copyout(void __user *to, const void *from, size_t n)
{
+ size_t to_copy = n;
+
if (access_ok(to, n)) {
kasan_check_read(from, n);
n = raw_copy_to_user(to, from, n);
+ kmsan_copy_to_user(to, from, to_copy, n);
}
return n;
}
static int copyin(void *to, const void __user *from, size_t n)
{
+ size_t to_copy = n;
+
if (access_ok(from, n)) {
kasan_check_write(to, n);
n = raw_copy_from_user(to, from, n);
+ kmsan_unpoison_shadow(to, to_copy - n);
}
return n;
}
diff --git a/lib/usercopy.c b/lib/usercopy.c
index cbb4d9ec00f2..abfd93edecba 100644
--- a/lib/usercopy.c
+++ b/lib/usercopy.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include <linux/kmsan-checks.h>
#include <linux/uaccess.h>
#include <linux/bitops.h>
@@ -7,11 +8,12 @@
#ifndef INLINE_COPY_FROM_USER
unsigned long _copy_from_user(void *to, const void __user *from, unsigned long n)
{
- unsigned long res = n;
+ unsigned long res = n, to_copy = n;
might_fault();
if (likely(access_ok(from, n))) {
kasan_check_write(to, n);
res = raw_copy_from_user(to, from, n);
+ kmsan_unpoison_shadow(to, to_copy - res);
}
if (unlikely(res))
memset(to + (n - res), 0, res);
@@ -23,10 +25,12 @@ EXPORT_SYMBOL(_copy_from_user);
#ifndef INLINE_COPY_TO_USER
unsigned long _copy_to_user(void __user *to, const void *from, unsigned long n)
{
+ unsigned long to_copy = n;
might_fault();
if (likely(access_ok(to, n))) {
kasan_check_read(from, n);
n = raw_copy_to_user(to, from, n);
+ kmsan_copy_to_user(to, from, to_copy, n);
}
return n;
}
--
2.24.0.rc0.303.g954a862665-goog
next prev parent reply other threads:[~2019-10-30 14:24 UTC|newest]
Thread overview: 61+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-10-30 14:22 [PATCH RFC v2 00/25] Add KernelMemorySanitizer infrastructure glider
2019-10-30 14:22 ` [PATCH RFC v2 01/25] stackdepot: check depot_index before accessing the stack slab glider
2019-10-30 14:22 ` [PATCH RFC v2 02/25] stackdepot: prevent Clang from optimizing away stackdepot_memcmp() glider
2019-11-01 5:50 ` Sergey Senozhatsky
2019-11-06 11:43 ` Alexander Potapenko
2019-11-07 6:08 ` Sergey Senozhatsky
2019-11-07 9:04 ` Arnd Bergmann
2019-11-07 9:22 ` Alexander Potapenko
2019-11-07 9:28 ` Arnd Bergmann
2019-11-07 9:43 ` Alexander Potapenko
[not found] ` <47fdac13-fa2c-2acd-2480-5e6d4db208f8@virtuozzo.com>
2019-11-07 10:00 ` Arnd Bergmann
[not found] ` <6875c6e6-2f1f-f8e6-e5d7-d451c48397ff@virtuozzo.com>
2019-11-07 10:30 ` Alexander Potapenko
2019-10-30 14:22 ` [PATCH RFC v2 03/25] kasan: stackdepot: move filter_irq_stacks() to stackdepot.c glider
2019-10-30 14:22 ` [PATCH RFC v2 04/25] stackdepot: reserve 5 extra bits in depot_stack_handle_t glider
2019-10-30 14:22 ` [PATCH RFC v2 05/25] kmsan: add ReST documentation glider
2019-10-30 14:22 ` [PATCH RFC v2 06/25] kmsan: gfp: introduce __GFP_NO_KMSAN_SHADOW glider
2019-10-30 14:22 ` [PATCH RFC v2 07/25] kmsan: introduce __no_sanitize_memory and __SANITIZE_MEMORY__ glider
2019-10-30 15:50 ` Andrey Konovalov
2019-11-01 12:52 ` Alexander Potapenko
2019-10-30 14:22 ` [PATCH RFC v2 08/25] kmsan: reduce vmalloc space glider
2019-10-30 14:22 ` [PATCH RFC v2 09/25] kmsan: add KMSAN runtime glider
2019-11-08 12:08 ` Dmitry Vyukov
2019-11-08 12:17 ` Dmitry Vyukov
2019-11-21 12:06 ` Alexander Potapenko
2019-11-13 8:13 ` Wolfram Sang
2019-11-21 12:01 ` Alexander Potapenko
2019-10-30 14:22 ` [PATCH RFC v2 10/25] kmsan: define READ_ONCE_NOCHECK() glider
2019-11-05 14:21 ` Mark Rutland
2019-11-21 12:08 ` Alexander Potapenko
2019-10-30 14:22 ` [PATCH RFC v2 11/25] kmsan: x86: sync metadata pages on page fault glider
2019-10-30 14:22 ` [PATCH RFC v2 12/25] kmsan: add tests for KMSAN glider
2019-10-30 14:22 ` [PATCH RFC v2 13/25] kmsan: make READ_ONCE_TASK_STACK() return initialized values glider
2019-10-30 14:22 ` [PATCH RFC v2 14/25] kmsan: Kconfig changes to disable options incompatible with KMSAN glider
2019-10-30 14:34 ` Qian Cai
2019-10-30 14:34 ` Christoph Hellwig
2019-10-30 14:22 ` [PATCH RFC v2 15/25] kmsan: Changing existing files to enable KMSAN builds glider
2019-10-30 14:36 ` Christoph Hellwig
2019-10-30 14:22 ` [PATCH RFC v2 16/25] kmsan: disable KMSAN instrumentation for certain kernel parts glider
2019-10-30 14:22 ` [PATCH RFC v2 17/25] kmsan: mm: call KMSAN hooks from SLUB code glider
2019-10-30 16:07 ` Andrey Konovalov
2019-10-30 14:22 ` [PATCH RFC v2 18/25] kmsan: call KMSAN hooks where needed glider
2019-10-31 11:49 ` Petr Mladek
2019-11-01 8:26 ` Sergey Senozhatsky
2019-11-05 14:12 ` Alexander Potapenko
2019-11-06 9:04 ` Petr Mladek
2019-11-06 9:07 ` Sergey Senozhatsky
2019-10-30 14:22 ` [PATCH RFC v2 19/25] kmsan: disable instrumentation of certain functions glider
2019-10-30 14:22 ` [PATCH RFC v2 20/25] kmsan: unpoison |tlb| in arch_tlb_gather_mmu() glider
2019-10-30 14:22 ` [PATCH RFC v2 21/25] kmsan: use __msan_memcpy() where possible glider
2019-10-30 14:22 ` [PATCH RFC v2 22/25] kmsan: unpoisoning buffers from devices etc glider
2019-10-30 14:38 ` Christoph Hellwig
2019-11-05 15:02 ` Alexander Potapenko
2019-11-07 13:00 ` Alexander Potapenko
2019-11-13 11:07 ` Alexander Potapenko
2019-11-01 22:25 ` kbuild test robot
2019-11-03 18:16 ` kbuild test robot
2019-10-30 14:22 ` glider [this message]
2019-11-01 23:08 ` [PATCH RFC v2 23/25] kmsan: hooks for copy_to_user() and friends kbuild test robot
2019-11-03 22:10 ` kbuild test robot
2019-10-30 14:22 ` [PATCH RFC v2 24/25] kmsan: disable strscpy() optimization under KMSAN glider
2019-10-30 14:22 ` [PATCH RFC v2 25/25] net: kasan: kmsan: support CONFIG_GENERIC_CSUM on x86, enable it for KASAN/KMSAN glider
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20191030142237.249532-24-glider@google.com \
--to=glider@google.com \
--cc=akpm@linux-foundation.org \
--cc=andreyknvl@google.com \
--cc=ard.biesheuvel@linaro.org \
--cc=arnd@arndb.de \
--cc=aryabinin@virtuozzo.com \
--cc=axboe@kernel.dk \
--cc=dmitry.torokhov@gmail.com \
--cc=dvyukov@google.com \
--cc=edumazet@google.com \
--cc=elver@google.com \
--cc=ericvh@gmail.com \
--cc=gor@linux.ibm.com \
--cc=gregkh@linuxfoundation.org \
--cc=harry.wentland@amd.com \
--cc=hch@lst.de \
--cc=herbert@gondor.apana.org.au \
--cc=iii@linux.ibm.com \
--cc=linux-mm@kvack.org \
--cc=luto@kernel.org \
--cc=mark.rutland@arm.com \
--cc=martin.petersen@oracle.com \
--cc=mingo@elte.hu \
--cc=monstr@monstr.eu \
--cc=mst@redhat.com \
--cc=pmladek@suse.com \
--cc=rdunlap@infradead.org \
--cc=rostedt@goodmis.org \
--cc=schwidefsky@de.ibm.com \
--cc=sergey.senozhatsky@gmail.com \
--cc=tglx@linutronix.de \
--cc=tiwai@suse.com \
--cc=tytso@mit.edu \
--cc=vegard.nossum@oracle.com \
--cc=viro@zeniv.linux.org.uk \
--cc=willy@infradead.org \
--cc=wsa@the-dreams.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.