[PATCH v7 07/12] mm: slub: introduce metadata_access_enable()/metadata_access_disable()

2014-11-24 Thread Andrey Ryabinin
Wrap access to object's metadata in external functions with
metadata_access_enable()/metadata_access_disable() function calls.

This hooks separates payload accesses from metadata accesses
which might be useful for different checkers (e.g. KASan).

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 mm/slub.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/mm/slub.c b/mm/slub.c
index 0c01584..88ad8b8 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -467,13 +467,23 @@ static int slub_debug;
 static char *slub_debug_slabs;
 static int disable_higher_order_debug;
 
+static inline void metadata_access_enable(void)
+{
+}
+
+static inline void metadata_access_disable(void)
+{
+}
+
 /*
  * Object debugging
  */
 static void print_section(char *text, u8 *addr, unsigned int length)
 {
+   metadata_access_enable();
print_hex_dump(KERN_ERR, text, DUMP_PREFIX_ADDRESS, 16, 1, addr,
length, 1);
+   metadata_access_disable();
 }
 
 static struct track *get_track(struct kmem_cache *s, void *object,
@@ -503,7 +513,9 @@ static void set_track(struct kmem_cache *s, void *object,
trace.max_entries = TRACK_ADDRS_COUNT;
trace.entries = p-addrs;
trace.skip = 3;
+   metadata_access_enable();
save_stack_trace(trace);
+   metadata_access_disable();
 
/* See rant in lockdep.c */
if (trace.nr_entries != 0 
@@ -677,7 +689,9 @@ static int check_bytes_and_report(struct kmem_cache *s, 
struct page *page,
u8 *fault;
u8 *end;
 
+   metadata_access_enable();
fault = memchr_inv(start, value, bytes);
+   metadata_access_disable();
if (!fault)
return 1;
 
@@ -770,7 +784,9 @@ static int slab_pad_check(struct kmem_cache *s, struct page 
*page)
if (!remainder)
return 1;
 
+   metadata_access_enable();
fault = memchr_inv(end - remainder, POISON_INUSE, remainder);
+   metadata_access_disable();
if (!fault)
return 1;
while (end  fault  end[-1] == POISON_INUSE)
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v7 12/12] x86_64: kasan: add interceptors for memset/memmove/memcpy functions

2014-11-24 Thread Andrey Ryabinin
Recently instrumentation of builtin functions calls was removed from GCC 5.0.
To check the memory accessed by such functions, userspace asan always uses
interceptors for them.

So now we should do this as well. This patch declares memset/memmove/memcpy
as weak symbols. In mm/kasan/kasan.c we have our own implementation
of those functions which checks memory before accessing it.

Default memset/memmove/memcpy now now always have aliases with '__' prefix.
For files that built without kasan instrumentation (e.g. mm/slub.c)
original mem* replaced (via #define) with prefixed variants,
cause we don't want to check memory accesses there.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 arch/x86/boot/compressed/eboot.c |  2 ++
 arch/x86/boot/compressed/misc.h  |  1 +
 arch/x86/include/asm/string_64.h | 18 +-
 arch/x86/kernel/x8664_ksyms_64.c | 10 --
 arch/x86/lib/memcpy_64.S |  2 ++
 arch/x86/lib/memmove_64.S|  4 
 arch/x86/lib/memset_64.S | 10 ++
 mm/kasan/kasan.c | 28 +++-
 8 files changed, 67 insertions(+), 8 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 1acf605..8f46fa7 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -14,6 +14,8 @@
 #include asm/desc.h
 
 #undef memcpy  /* Use memcpy from misc.c */
+#undef memset
+#undef memmove
 
 #include eboot.h
 
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 24e3e56..04477d6 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -7,6 +7,7 @@
  * we just keep it from happening
  */
 #undef CONFIG_PARAVIRT
+#undef CONFIG_KASAN
 #ifdef CONFIG_X86_32
 #define _ASM_X86_DESC_H 1
 #endif
diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h
index 19e2c46..e466119 100644
--- a/arch/x86/include/asm/string_64.h
+++ b/arch/x86/include/asm/string_64.h
@@ -27,11 +27,12 @@ static __always_inline void *__inline_memcpy(void *to, 
const void *from, size_t
function. */
 
 #define __HAVE_ARCH_MEMCPY 1
+extern void *__memcpy(void *to, const void *from, size_t len);
+
 #ifndef CONFIG_KMEMCHECK
 #if (__GNUC__ == 4  __GNUC_MINOR__ = 3) || __GNUC__  4
 extern void *memcpy(void *to, const void *from, size_t len);
 #else
-extern void *__memcpy(void *to, const void *from, size_t len);
 #define memcpy(dst, src, len)  \
 ({ \
size_t __len = (len);   \
@@ -53,9 +54,11 @@ extern void *__memcpy(void *to, const void *from, size_t 
len);
 
 #define __HAVE_ARCH_MEMSET
 void *memset(void *s, int c, size_t n);
+void *__memset(void *s, int c, size_t n);
 
 #define __HAVE_ARCH_MEMMOVE
 void *memmove(void *dest, const void *src, size_t count);
+void *__memmove(void *dest, const void *src, size_t count);
 
 int memcmp(const void *cs, const void *ct, size_t count);
 size_t strlen(const char *s);
@@ -63,6 +66,19 @@ char *strcpy(char *dest, const char *src);
 char *strcat(char *dest, const char *src);
 int strcmp(const char *cs, const char *ct);
 
+#if defined(CONFIG_KASAN)  !defined(__SANITIZE_ADDRESS__)
+
+/*
+ * For files that not instrumented (e.g. mm/slub.c) we
+ * should use not instrumented version of mem* functions.
+ */
+
+#undef memcpy
+#define memcpy(dst, src, len) __memcpy(dst, src, len)
+#define memmove(dst, src, len) __memmove(dst, src, len)
+#define memset(s, c, n) __memset(s, c, n)
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_X86_STRING_64_H */
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 0406819..37d8fa4 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -50,13 +50,19 @@ EXPORT_SYMBOL(csum_partial);
 #undef memset
 #undef memmove
 
+extern void *__memset(void *, int, __kernel_size_t);
+extern void *__memcpy(void *, const void *, __kernel_size_t);
+extern void *__memmove(void *, const void *, __kernel_size_t);
 extern void *memset(void *, int, __kernel_size_t);
 extern void *memcpy(void *, const void *, __kernel_size_t);
-extern void *__memcpy(void *, const void *, __kernel_size_t);
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+EXPORT_SYMBOL(__memset);
+EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(__memmove);
 
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(__memcpy);
 EXPORT_SYMBOL(memmove);
 
 #ifndef CONFIG_DEBUG_VIRTUAL
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
index 56313a3..d79db86 100644
--- a/arch/x86/lib/memcpy_64.S
+++ b/arch/x86/lib/memcpy_64.S
@@ -53,6 +53,8 @@
 .Lmemcpy_e_e:
.previous
 
+.weak memcpy
+
 ENTRY(__memcpy)
 ENTRY(memcpy)
CFI_STARTPROC
diff --git a/arch/x86/lib/memmove_64.S b/arch/x86/lib/memmove_64.S
index 65268a6..9c4b530 100644
--- a/arch/x86/lib/memmove_64.S
+++ b/arch

[PATCH v7 08/12] mm: slub: add kernel address sanitizer support for slub allocator

2014-11-24 Thread Andrey Ryabinin
With this patch kasan will be able to catch bugs in memory allocated
by slub.
Initially all objects in newly allocated slab page, marked as free.
Later, when allocation of slub object happens, requested by caller
number of bytes marked as accessible, and the rest of the object
(including slub's metadata) marked as redzone (inaccessible).

We also mark object as accessible if ksize was called for this object.
There is some places in kernel where ksize function is called to inquire
size of really allocated area. Such callers could validly access whole
allocated memory, so it should be marked as accessible.

Code in slub.c and slab_common.c files could validly access to object's
metadata, so instrumentation for this files are disabled.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/kasan.h | 21 
 include/linux/slab.h  | 11 --
 lib/Kconfig.kasan |  1 +
 mm/Makefile   |  3 ++
 mm/kasan/kasan.c  | 92 +++
 mm/kasan/kasan.h  |  4 +++
 mm/kasan/report.c | 25 ++
 mm/slab_common.c  |  5 ++-
 mm/slub.c | 35 ++--
 9 files changed, 191 insertions(+), 6 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 9714fba..0463b90 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -32,6 +32,16 @@ void kasan_unpoison_shadow(const void *address, size_t size);
 
 void kasan_alloc_pages(struct page *page, unsigned int order);
 void kasan_free_pages(struct page *page, unsigned int order);
+void kasan_mark_slab_padding(struct kmem_cache *s, void *object,
+   struct page *page);
+
+void kasan_kmalloc_large(const void *ptr, size_t size);
+void kasan_kfree_large(const void *ptr);
+void kasan_kmalloc(struct kmem_cache *s, const void *object, size_t size);
+void kasan_krealloc(const void *object, size_t new_size);
+
+void kasan_slab_alloc(struct kmem_cache *s, void *object);
+void kasan_slab_free(struct kmem_cache *s, void *object);
 
 #else /* CONFIG_KASAN */
 
@@ -42,6 +52,17 @@ static inline void kasan_disable_local(void) {}
 
 static inline void kasan_alloc_pages(struct page *page, unsigned int order) {}
 static inline void kasan_free_pages(struct page *page, unsigned int order) {}
+static inline void kasan_mark_slab_padding(struct kmem_cache *s, void *object,
+   struct page *page) {}
+
+static inline void kasan_kmalloc_large(void *ptr, size_t size) {}
+static inline void kasan_kfree_large(const void *ptr) {}
+static inline void kasan_kmalloc(struct kmem_cache *s, const void *object,
+   size_t size) {}
+static inline void kasan_krealloc(const void *object, size_t new_size) {}
+
+static inline void kasan_slab_alloc(struct kmem_cache *s, void *object) {}
+static inline void kasan_slab_free(struct kmem_cache *s, void *object) {}
 
 #endif /* CONFIG_KASAN */
 
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 8a2457d..5dc0d69 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -104,6 +104,7 @@
(unsigned long)ZERO_SIZE_PTR)
 
 #include linux/kmemleak.h
+#include linux/kasan.h
 
 struct mem_cgroup;
 /*
@@ -326,7 +327,10 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
 static __always_inline void *kmem_cache_alloc_trace(struct kmem_cache *s,
gfp_t flags, size_t size)
 {
-   return kmem_cache_alloc(s, flags);
+   void *ret = kmem_cache_alloc(s, flags);
+
+   kasan_kmalloc(s, ret, size);
+   return ret;
 }
 
 static __always_inline void *
@@ -334,7 +338,10 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
  gfp_t gfpflags,
  int node, size_t size)
 {
-   return kmem_cache_alloc_node(s, gfpflags, node);
+   void *ret = kmem_cache_alloc_node(s, gfpflags, node);
+
+   kasan_kmalloc(s, ret, size);
+   return ret;
 }
 #endif /* CONFIG_TRACING */
 
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index 386cc8b..1fa4fe8 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -6,6 +6,7 @@ if HAVE_ARCH_KASAN
 config KASAN
bool AddressSanitizer: runtime memory debugger
depends on !MEMORY_HOTPLUG
+   depends on SLUB_DEBUG
help
  Enables address sanitizer - runtime memory debugger,
  designed to find out-of-bounds accesses and use-after-free bugs.
diff --git a/mm/Makefile b/mm/Makefile
index 33d9971..5f0138f 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -2,6 +2,9 @@
 # Makefile for the linux memory manager.
 #
 
+KASAN_SANITIZE_slab_common.o := n
+KASAN_SANITIZE_slub.o := n
+
 mmu-y  := nommu.o
 mmu-$(CONFIG_MMU)  := gup.o highmem.o memory.o mincore.o \
   mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index b336073..9f5326e 100644
--- a/mm/kasan/kasan.c
+++ b/mm

[PATCH v7 06/12] mm: slub: share slab_err and object_err functions

2014-11-24 Thread Andrey Ryabinin
Remove static and add function declarations to mm/slab.h so they
could be used by kernel address sanitizer.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/slub_def.h | 5 +
 mm/slub.c| 4 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index c75bc1d..144b5cb 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -115,4 +115,9 @@ static inline void *virt_to_obj(struct kmem_cache *s, void 
*slab_page, void *x)
return x - ((x - slab_page) % s-size);
 }
 
+__printf(3, 4)
+void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...);
+void object_err(struct kmem_cache *s, struct page *page,
+   u8 *object, char *reason);
+
 #endif /* _LINUX_SLUB_DEF_H */
diff --git a/mm/slub.c b/mm/slub.c
index 95d2142..0c01584 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -629,14 +629,14 @@ static void print_trailer(struct kmem_cache *s, struct 
page *page, u8 *p)
dump_stack();
 }
 
-static void object_err(struct kmem_cache *s, struct page *page,
+void object_err(struct kmem_cache *s, struct page *page,
u8 *object, char *reason)
 {
slab_bug(s, %s, reason);
print_trailer(s, page, object);
 }
 
-static void slab_err(struct kmem_cache *s, struct page *page,
+void slab_err(struct kmem_cache *s, struct page *page,
const char *fmt, ...)
 {
va_list args;
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v7 10/12] kmemleak: disable kasan instrumentation for kmemleak

2014-11-24 Thread Andrey Ryabinin
kmalloc internally round up allocation size, and kmemleak
uses rounded up size as object's size. This makes kasan
to complain while kmemleak scans memory or calculates of object's
checksum. The simplest solution here is to disable kasan.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 mm/kmemleak.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 3cda50c..9bda1b3 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -98,6 +98,7 @@
 #include asm/processor.h
 #include linux/atomic.h
 
+#include linux/kasan.h
 #include linux/kmemcheck.h
 #include linux/kmemleak.h
 #include linux/memory_hotplug.h
@@ -1113,7 +1114,10 @@ static bool update_checksum(struct kmemleak_object 
*object)
if (!kmemcheck_is_obj_initialized(object-pointer, object-size))
return false;
 
+   kasan_disable_local();
object-checksum = crc32(0, (void *)object-pointer, object-size);
+   kasan_enable_local();
+
return object-checksum != old_csum;
 }
 
@@ -1164,7 +1168,9 @@ static void scan_block(void *_start, void *_end,
  BYTES_PER_POINTER))
continue;
 
+   kasan_disable_local();
pointer = *ptr;
+   kasan_enable_local();
 
object = find_and_get_object(pointer, 1);
if (!object)
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v7 01/12] Add kernel address sanitizer infrastructure.

2014-11-24 Thread Andrey Ryabinin
Socket Socket  Message  Elapsed
Size   SizeSize Time Throughput
bytes  bytes   bytessecs.10^6bits/sec

no debug:   87380  16384  1638430.0041624.72

kasan inline:   87380  16384  1638430.0012870.54

kasan outline:  87380  16384  1638430.0010586.39

kmemcheck:  87380  16384  1638430.03  20.23

- Also kmemcheck couldn't work on several CPUs. It always sets number 
of CPUs to 1.
  KASan doesn't have such limitation.

DEBUG_PAGEALLOC:
- KASan is slower than DEBUG_PAGEALLOC, but KASan works on sub-page
  granularity level, so it able to find more bugs.

SLUB_DEBUG (poisoning, redzones):
- SLUB_DEBUG has lower overhead than KASan.

- SLUB_DEBUG in most cases are not able to detect bad reads,
  KASan able to detect both reads and writes.

- In some cases (e.g. redzone overwritten) SLUB_DEBUG detect
  bugs only on allocation/freeing of object. KASan catch
  bugs right before it will happen, so we always know exact
  place of first bad read/write.

[1] https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel
[2] https://code.google.com/p/address-sanitizer/wiki/FoundBugs
[3] https://code.google.com/p/thread-sanitizer/wiki/FoundBugs
[4] https://code.google.com/p/memory-sanitizer/wiki/FoundBugs
[5] 
https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel#Trophies

Based on work by Andrey Konovalov adech...@gmail.com

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 Documentation/kasan.txt   | 169 +++
 Makefile  |  23 ++-
 drivers/firmware/efi/libstub/Makefile |   1 +
 include/linux/kasan.h |  42 
 include/linux/sched.h |   3 +
 lib/Kconfig.debug |   2 +
 lib/Kconfig.kasan |  43 
 mm/Makefile   |   1 +
 mm/kasan/Makefile |   7 +
 mm/kasan/kasan.c  | 374 ++
 mm/kasan/kasan.h  |  49 +
 mm/kasan/report.c | 205 +++
 scripts/Makefile.lib  |  10 +
 13 files changed, 927 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/kasan.txt
 create mode 100644 include/linux/kasan.h
 create mode 100644 lib/Kconfig.kasan
 create mode 100644 mm/kasan/Makefile
 create mode 100644 mm/kasan/kasan.c
 create mode 100644 mm/kasan/kasan.h
 create mode 100644 mm/kasan/report.c

diff --git a/Documentation/kasan.txt b/Documentation/kasan.txt
new file mode 100644
index 000..a3a9009
--- /dev/null
+++ b/Documentation/kasan.txt
@@ -0,0 +1,169 @@
+Kernel address sanitizer
+
+
+0. Overview
+===
+
+Kernel Address sanitizer (KASan) is a dynamic memory error detector. It 
provides
+a fast and comprehensive solution for finding use-after-free and out-of-bounds
+bugs.
+
+KASan uses compile-time instrumentation for checking every memory access,
+therefore you will need a certain version of GCC = 4.9.2
+
+Currently KASan is supported only for x86_64 architecture and requires that the
+kernel be built with the SLUB allocator.
+
+1. Usage
+=
+
+To enable KASAN configure kernel with:
+
+ CONFIG_KASAN = y
+
+and choose between CONFIG_KASAN_OUTLINE and CONFIG_KASAN_INLINE. Outline/inline
+is compiler instrumentation types. The former produces smaller binary the
+latter is 1.1 - 2 times faster. Inline instrumentation requires GCC 5.0 or
+latter.
+
+Currently KASAN works only with the SLUB memory allocator.
+For better bug detection and nicer report, enable CONFIG_STACKTRACE and put
+at least 'slub_debug=U' in the boot cmdline.
+
+To disable instrumentation for specific files or directories, add a line
+similar to the following to the respective kernel Makefile:
+
+For a single file (e.g. main.o):
+KASAN_SANITIZE_main.o := n
+
+For all files in one directory:
+KASAN_SANITIZE := n
+
+1.1 Error reports
+==
+
+A typical out of bounds access report looks like this:
+
+==
+BUG: AddressSanitizer: out of bounds access in kmalloc_oob_right+0x65/0x75 
[test_kasan] at addr 8800693bc5d3
+Write of size 1 by task modprobe/1689
+=
+BUG kmalloc-128 (Not tainted): kasan error
+-
+
+Disabling lock debugging due to kernel taint
+INFO: Allocated in kmalloc_oob_right+0x3d/0x75 [test_kasan] age=0 cpu=0 
pid=1689
+ __slab_alloc+0x4b4/0x4f0
+ kmem_cache_alloc_trace+0x10b/0x190
+ kmalloc_oob_right+0x3d/0x75 [test_kasan]
+ init_module+0x9/0x47 [test_kasan]
+ do_one_initcall+0x99/0x200
+ load_module+0x2cb3/0x3b20
+ SyS_finit_module+0x76/0x80

[PATCH v7 04/12] mm: page_alloc: add kasan hooks on alloc and free paths

2014-11-24 Thread Andrey Ryabinin
Add kernel address sanitizer hooks to mark allocated page's addresses
as accessible in corresponding shadow region.
Mark freed pages as inaccessible.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/kasan.h |  6 ++
 mm/compaction.c   |  2 ++
 mm/kasan/kasan.c  | 14 ++
 mm/kasan/kasan.h  |  1 +
 mm/kasan/report.c |  7 +++
 mm/page_alloc.c   |  3 +++
 6 files changed, 33 insertions(+)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 01c99fe..9714fba 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -30,6 +30,9 @@ static inline void kasan_disable_local(void)
 
 void kasan_unpoison_shadow(const void *address, size_t size);
 
+void kasan_alloc_pages(struct page *page, unsigned int order);
+void kasan_free_pages(struct page *page, unsigned int order);
+
 #else /* CONFIG_KASAN */
 
 static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
@@ -37,6 +40,9 @@ static inline void kasan_unpoison_shadow(const void *address, 
size_t size) {}
 static inline void kasan_enable_local(void) {}
 static inline void kasan_disable_local(void) {}
 
+static inline void kasan_alloc_pages(struct page *page, unsigned int order) {}
+static inline void kasan_free_pages(struct page *page, unsigned int order) {}
+
 #endif /* CONFIG_KASAN */
 
 #endif /* LINUX_KASAN_H */
diff --git a/mm/compaction.c b/mm/compaction.c
index a857225..a5c8e84 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -16,6 +16,7 @@
 #include linux/sysfs.h
 #include linux/balloon_compaction.h
 #include linux/page-isolation.h
+#include linux/kasan.h
 #include internal.h
 
 #ifdef CONFIG_COMPACTION
@@ -61,6 +62,7 @@ static void map_pages(struct list_head *list)
list_for_each_entry(page, list, lru) {
arch_alloc_page(page, 0);
kernel_map_pages(page, 1, 1);
+   kasan_alloc_pages(page, 0);
}
 }
 
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index f77be01..b336073 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -247,6 +247,20 @@ static __always_inline void check_memory_region(unsigned 
long addr,
kasan_report(addr, size, write);
 }
 
+void kasan_alloc_pages(struct page *page, unsigned int order)
+{
+   if (likely(!PageHighMem(page)))
+   kasan_unpoison_shadow(page_address(page), PAGE_SIZE  order);
+}
+
+void kasan_free_pages(struct page *page, unsigned int order)
+{
+   if (likely(!PageHighMem(page)))
+   kasan_poison_shadow(page_address(page),
+   PAGE_SIZE  order,
+   KASAN_FREE_PAGE);
+}
+
 void __asan_load1(unsigned long addr)
 {
check_memory_region(addr, 1, false);
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 6da1d78..2a6a961 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -6,6 +6,7 @@
 #define KASAN_SHADOW_SCALE_SIZE (1UL  KASAN_SHADOW_SCALE_SHIFT)
 #define KASAN_SHADOW_MASK   (KASAN_SHADOW_SCALE_SIZE - 1)
 
+#define KASAN_FREE_PAGE 0xFF  /* page was freed */
 #define KASAN_SHADOW_GAP0xF9  /* address belongs to shadow memory */
 
 struct access_info {
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 56a2089..8ac3b6b 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -57,6 +57,9 @@ static void print_error_description(struct access_info *info)
case 0 ... KASAN_SHADOW_SCALE_SIZE - 1:
bug_type = out of bounds access;
break;
+   case KASAN_FREE_PAGE:
+   bug_type = use after free;
+   break;
case KASAN_SHADOW_GAP:
bug_type = wild memory access;
break;
@@ -78,6 +81,10 @@ static void print_address_description(struct access_info 
*info)
page = virt_to_head_page((void *)info-access_addr);
 
switch (shadow_val) {
+   case KASAN_FREE_PAGE:
+   dump_page(page, kasan error);
+   dump_stack();
+   break;
case KASAN_SHADOW_GAP:
pr_err(No metainfo is available for this access.\n);
dump_stack();
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b0e6eab..3829589 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -58,6 +58,7 @@
 #include linux/page-debug-flags.h
 #include linux/hugetlb.h
 #include linux/sched/rt.h
+#include linux/kasan.h
 
 #include asm/sections.h
 #include asm/tlbflush.h
@@ -758,6 +759,7 @@ static bool free_pages_prepare(struct page *page, unsigned 
int order)
 
trace_mm_page_free(page, order);
kmemcheck_free_shadow(page, order);
+   kasan_free_pages(page, order);
 
if (PageAnon(page))
page-mapping = NULL;
@@ -940,6 +942,7 @@ static int prep_new_page(struct page *page, unsigned int 
order, gfp_t gfp_flags)
 
arch_alloc_page(page, order);
kernel_map_pages(page, 1  order, 1);
+   kasan_alloc_pages(page, order);
 
if (gfp_flags  __GFP_ZERO

[PATCH v7 11/12] lib: add kasan test module

2014-11-24 Thread Andrey Ryabinin
This is a test module doing various nasty things like
out of bounds accesses, use after free. It is useful for testing
kernel debugging features like kernel address sanitizer.

It mostly concentrates on testing of slab allocator, but we
might want to add more different stuff here in future (like
stack/global variables out of bounds accesses and so on).

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 lib/Kconfig.kasan |   8 ++
 lib/Makefile  |   1 +
 lib/test_kasan.c  | 254 ++
 3 files changed, 263 insertions(+)
 create mode 100644 lib/test_kasan.c

diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index 1fa4fe8..8548646 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -43,4 +43,12 @@ config KASAN_INLINE
 
 endchoice
 
+config TEST_KASAN
+   tristate Module for testing kasan for bug detection
+   depends on m  KASAN
+   help
+ This is a test module doing various nasty things like
+ out of bounds accesses, use after free. It is useful for testing
+ kernel debugging features like kernel address sanitizer.
+
 endif
diff --git a/lib/Makefile b/lib/Makefile
index 750617c..1d8211a 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_TEST_LKM) += test_module.o
 obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
 obj-$(CONFIG_TEST_BPF) += test_bpf.o
 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
+obj-$(CONFIG_TEST_KASAN) += test_kasan.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/test_kasan.c b/lib/test_kasan.c
new file mode 100644
index 000..896dee5
--- /dev/null
+++ b/lib/test_kasan.c
@@ -0,0 +1,254 @@
+/*
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Andrey Ryabinin a.ryabi...@samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) kasan test: %s  fmt, __func__
+
+#include linux/kernel.h
+#include linux/printk.h
+#include linux/slab.h
+#include linux/string.h
+#include linux/module.h
+
+static noinline void __init kmalloc_oob_right(void)
+{
+   char *ptr;
+   size_t size = 123;
+
+   pr_info(out-of-bounds to right\n);
+   ptr = kmalloc(size, GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 'x';
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_oob_left(void)
+{
+   char *ptr;
+   size_t size = 15;
+
+   pr_info(out-of-bounds to left\n);
+   ptr = kmalloc(size, GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   *ptr = *(ptr - 1);
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_node_oob_right(void)
+{
+   char *ptr;
+   size_t size = 4096;
+
+   pr_info(kmalloc_node(): out-of-bounds to right\n);
+   ptr = kmalloc_node(size, GFP_KERNEL, 0);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 0;
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_large_oob_rigth(void)
+{
+   char *ptr;
+   size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
+
+   pr_info(kmalloc large allocation: out-of-bounds to right\n);
+   ptr = kmalloc(size, GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 0;
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_oob_krealloc_more(void)
+{
+   char *ptr1, *ptr2;
+   size_t size1 = 17;
+   size_t size2 = 19;
+
+   pr_info(out-of-bounds after krealloc more\n);
+   ptr1 = kmalloc(size1, GFP_KERNEL);
+   ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1);
+   return;
+   }
+
+   ptr2[size2] = 'x';
+   kfree(ptr2);
+}
+
+static noinline void __init kmalloc_oob_krealloc_less(void)
+{
+   char *ptr1, *ptr2;
+   size_t size1 = 17;
+   size_t size2 = 15;
+
+   pr_info(out-of-bounds after krealloc less\n);
+   ptr1 = kmalloc(size1, GFP_KERNEL);
+   ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1);
+   return;
+   }
+   ptr2[size1] = 'x';
+   kfree(ptr2);
+}
+
+static noinline void __init kmalloc_oob_16(void)
+{
+   struct {
+   u64 words[2];
+   } *ptr1, *ptr2;
+
+   pr_info(kmalloc out-of-bounds for 16-bytes access\n);
+   ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
+   ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1

[PATCH v7 03/12] x86_64: add KASan support

2014-11-24 Thread Andrey Ryabinin
This patch adds arch specific code for kernel address sanitizer.

16TB of virtual addressed used for shadow memory.
It's located in range [0xd900 - 0xe900]
which belongs to vmalloc area.

At early stage we map whole shadow region with zero page.
Latter, after pages mapped to direct mapping address range
we unmap zero pages from corresponding shadow (see kasan_map_shadow())
and allocate and map a real shadow memory reusing vmemmap_populate()
function.

Also replace __pa with __pa_nodebug before shadow initialized.
__pa with CONFIG_DEBUG_VIRTUAL=y make external function call (__phys_addr)
__phys_addr is instrumented, so __asan_load could be called before
shadow area initialized.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 arch/x86/Kconfig  |   1 +
 arch/x86/boot/Makefile|   2 +
 arch/x86/boot/compressed/Makefile |   2 +
 arch/x86/include/asm/kasan.h  |  27 ++
 arch/x86/kernel/Makefile  |   2 +
 arch/x86/kernel/dumpstack.c   |   5 +-
 arch/x86/kernel/head64.c  |   9 +++-
 arch/x86/kernel/head_64.S |  28 ++
 arch/x86/kernel/setup.c   |   3 ++
 arch/x86/mm/Makefile  |   3 ++
 arch/x86/mm/kasan_init_64.c   | 107 ++
 arch/x86/realmode/Makefile|   2 +-
 arch/x86/realmode/rm/Makefile |   1 +
 arch/x86/vdso/Makefile|   1 +
 lib/Kconfig.kasan |   2 +
 15 files changed, 191 insertions(+), 4 deletions(-)
 create mode 100644 arch/x86/include/asm/kasan.h
 create mode 100644 arch/x86/mm/kasan_init_64.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ec21dfd..0ccd17a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -84,6 +84,7 @@ config X86
select HAVE_CMPXCHG_LOCAL
select HAVE_CMPXCHG_DOUBLE
select HAVE_ARCH_KMEMCHECK
+   select HAVE_ARCH_KASAN if X86_64
select HAVE_USER_RETURN_NOTIFIER
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
select HAVE_ARCH_JUMP_LABEL
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 5b016e2..1ef2724 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -14,6 +14,8 @@
 # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
 # The number is the same as you would ordinarily press at bootup.
 
+KASAN_SANITIZE := n
+
 SVGA_MODE  := -DSVGA_MODE=NORMAL_VGA
 
 targets:= vmlinux.bin setup.bin setup.elf bzImage
diff --git a/arch/x86/boot/compressed/Makefile 
b/arch/x86/boot/compressed/Makefile
index 44a866b..0cb8703 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -16,6 +16,8 @@
 #  (see scripts/Makefile.lib size_append)
 #  compressed vmlinux.bin.all + u32 size of vmlinux.bin.all
 
+KASAN_SANITIZE := n
+
 targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma 
\
vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
 
diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
new file mode 100644
index 000..47e0d42
--- /dev/null
+++ b/arch/x86/include/asm/kasan.h
@@ -0,0 +1,27 @@
+#ifndef _ASM_X86_KASAN_H
+#define _ASM_X86_KASAN_H
+
+#define KASAN_SHADOW_START 0xd900UL
+#define KASAN_SHADOW_END   0xe900UL
+
+#ifndef __ASSEMBLY__
+
+extern pte_t zero_pte[];
+extern pte_t zero_pmd[];
+extern pte_t zero_pud[];
+
+extern pte_t poisoned_pte[];
+extern pte_t poisoned_pmd[];
+extern pte_t poisoned_pud[];
+
+#ifdef CONFIG_KASAN
+void __init kasan_map_zero_shadow(pgd_t *pgd);
+void __init kasan_init(void);
+#else
+static inline void kasan_map_zero_shadow(pgd_t *pgd) { }
+static inline void kasan_init(void) { }
+#endif
+
+#endif
+
+#endif
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 5d4502c..74d3f3e 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -16,6 +16,8 @@ CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
 
+KASAN_SANITIZE_head$(BITS).o := n
+
 CFLAGS_irq.o := -I$(src)/../include/asm/trace
 
 obj-y  := process_$(BITS).o signal.o entry_$(BITS).o
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index b74ebc7..cf3df1d 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -265,7 +265,10 @@ int __die(const char *str, struct pt_regs *regs, long err)
printk(SMP );
 #endif
 #ifdef CONFIG_DEBUG_PAGEALLOC
-   printk(DEBUG_PAGEALLOC);
+   printk(DEBUG_PAGEALLOC );
+#endif
+#ifdef CONFIG_KASAN
+   printk(KASAN);
 #endif
printk(\n);
if (notify_die(DIE_OOPS, str, regs, err,
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index eda1a86..b9e4e50 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -27,6 +27,7 @@
 #include asm/bios_ebda.h
 #include asm/bootparam_utils.h
 #include asm/microcode.h
+#include asm/kasan.h
 
 /*
  * Manage page tables very early on.
@@ -46,7

[PATCH v7 05/12] mm: slub: introduce virt_to_obj function.

2014-11-24 Thread Andrey Ryabinin
virt_to_obj takes kmem_cache address, address of slab page,
address x pointing somewhere inside slab object,
and returns address of the begging of object.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/slub_def.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index d82abd4..c75bc1d 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -110,4 +110,9 @@ static inline void sysfs_slab_remove(struct kmem_cache *s)
 }
 #endif
 
+static inline void *virt_to_obj(struct kmem_cache *s, void *slab_page, void *x)
+{
+   return x - ((x - slab_page) % s-size);
+}
+
 #endif /* _LINUX_SLUB_DEF_H */
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v7 02/12] x86_64: load_percpu_segment: read irq_stack_union.gs_base before load_segment

2014-11-24 Thread Andrey Ryabinin
Reading irq_stack_union.gs_base after load_segment creates troubles for kasan.
Compiler inserts __asan_load in between load_segment and wrmsrl. If kernel
built with stackprotector this will result in boot failure because __asan_load
has stackprotector.

To avoid this irq_stack_union.gs_base stored to temporary variable before
load_segment, so __asan_load will be called before load_segment().

There are two alternative ways to fix this:
 a) Add __attribute__((no_sanitize_address)) to load_percpu_segment(),
which tells compiler to not instrument this function. However this
will result in build failure with CONFIG_KASAN=y and 
CONFIG_OPTIMIZE_INLINING=y.

 b) Add -fno-stack-protector for mm/kasan/kasan.c

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 arch/x86/kernel/cpu/common.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 8779d63..97f56f6 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -389,8 +389,10 @@ void load_percpu_segment(int cpu)
 #ifdef CONFIG_X86_32
loadsegment(fs, __KERNEL_PERCPU);
 #else
+   void *gs_base = per_cpu(irq_stack_union.gs_base, cpu);
+
loadsegment(gs, 0);
-   wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, 
cpu));
+   wrmsrl(MSR_GS_BASE, (unsigned long)gs_base);
 #endif
load_stack_canary_segment();
 }
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v7 03/12] x86_64: add KASan support

2014-11-24 Thread Andrey Ryabinin
2014-11-24 21:45 GMT+03:00 Sasha Levin sasha.le...@oracle.com:
 On 11/24/2014 01:02 PM, Andrey Ryabinin wrote:
 +static int kasan_die_handler(struct notifier_block *self,
 +  unsigned long val,
 +  void *data)
 +{
 + if (val == DIE_GPF) {
 + pr_emerg(CONFIG_KASAN_INLINE enabled\n);
 + pr_emerg(GPF could be caused by NULL-ptr deref or user memory 
 access\n);
 + }
 + return NOTIFY_OK;
 +}
 +
 +static struct notifier_block kasan_die_notifier = {
 + .notifier_call = kasan_die_handler,
 +};

 This part fails to compile:

   CC  arch/x86/mm/kasan_init_64.o
 arch/x86/mm/kasan_init_64.c: In function ‘kasan_die_handler’:
 arch/x86/mm/kasan_init_64.c:72:13: error: ‘DIE_GPF’ undeclared (first use in 
 this function)
   if (val == DIE_GPF) {
  ^
 arch/x86/mm/kasan_init_64.c:72:13: note: each undeclared identifier is 
 reported only once for each function it appears in
 arch/x86/mm/kasan_init_64.c: In function ‘kasan_init’:
 arch/x86/mm/kasan_init_64.c:89:2: error: implicit declaration of function 
 ‘register_die_notifier’ [-Werror=implicit-function-declaration]
   register_die_notifier(kasan_die_notifier);
   ^
 cc1: some warnings being treated as errors
 make[1]: *** [arch/x86/mm/kasan_init_64.o] Error 1


 Simple fix:


Thanks, I thought I've fixed this, but apparently I forgot to commit it.


 diff --git a/arch/x86/mm/kasan_init_64.c b/arch/x86/mm/kasan_init_64.c
 index 70041fd..c8f7f3e 100644
 --- a/arch/x86/mm/kasan_init_64.c
 +++ b/arch/x86/mm/kasan_init_64.c
 @@ -5,6 +5,7 @@
  #include linux/vmalloc.h

  #include asm/tlbflush.h
 +#include linux/kdebug.h

  extern pgd_t early_level4_pgt[PTRS_PER_PGD];
  extern struct range pfn_mapped[E820_X_MAX];


 Thanks,
 Sasha


-- 
Best regards,
Andrey Ryabinin
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] x86: update memory map about hypervisor-reserved area

2014-09-18 Thread Andrey Ryabinin
2014-09-18 19:46 GMT+04:00 Dave Hansen d...@sr71.net:

 From: Dave Hansen dave.han...@linux.intel.com

 Peter Anvin says:
 0x8800 is the lowest usable address because we have
 agreed to leave 0x8000-0x8800 for the
 hypervisor or other non-OS uses.

 Let's call this out in the documentation.

 This came up during the kernel address sanitizer discussions
 where it was proposed to use this area for other kernel things.

 Signed-off-by: Dave Hansen dave.han...@linux.intel.com
 Cc: Andrey Ryabinin ryabinin@gmail.com
 Cc: Dmitry Vyukov dvyu...@google.com
 Cc: Andi Kleen a...@firstfloor.org
 Cc: x...@kernel.org
 Cc: linux...@kvack.org
 Cc: Thomas Gleixner t...@linutronix.de
 Cc: Ingo Molnar mi...@redhat.com
 ---

  b/Documentation/x86/x86_64/mm.txt |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff -puN Documentation/x86/x86_64/mm.txt~update-x86-mm-doc 
 Documentation/x86/x86_64/mm.txt
 --- a/Documentation/x86/x86_64/mm.txt~update-x86-mm-doc 2014-09-17 
 21:44:10.499781092 -0700
 +++ b/Documentation/x86/x86_64/mm.txt   2014-09-17 21:44:31.852740822 -0700
 @@ -5,7 +5,7 @@ Virtual memory map with 4 level page tab

   - 7fff (=47 bits) user space, different per mm
  hole caused by [48:63] sign extension
 -8000 - 80ff (=40 bits) guard hole
 +8000 - 80ff (=40 bits) guard hole, reserved for 
 hypervisor

8000 - 87ff (=43 bits) guard hole, reserved
for hypervisor

  8800 - c7ff (=64 TB) direct mapping of all phys. 
 memory
  c800 - c8ff (=40 bits) hole
  c900 - e8ff (=45 bits) vmalloc/ioremap space
 _



-- 
Best regards,
Andrey Ryabinin
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 09/13] mm: slub: add kernel address sanitizer support for slub allocator

2014-09-26 Thread Andrey Ryabinin
On 09/26/2014 08:48 AM, Dmitry Vyukov wrote:
 On Wed, Sep 24, 2014 at 5:44 AM, Andrey Ryabinin a.ryabi...@samsung.com 
 wrote:
 --- a/lib/Kconfig.kasan
 +++ b/lib/Kconfig.kasan
 @@ -6,6 +6,7 @@ if HAVE_ARCH_KASAN
  config KASAN
 bool AddressSanitizer: runtime memory debugger
 depends on !MEMORY_HOTPLUG
 +   depends on SLUB_DEBUG
 
 
 What does SLUB_DEBUG do? I think that generally we don't want any
 other *heavy* debug checks to be required for kasan.
 

SLUB_DEBUG enables support for different debugging features.
It doesn't enables this debugging features by default, it only allows
you to switch them on/off in runtime.
Generally SLUB_DEBUG option is enabled in most kernels. SLUB_DEBUG disabled
only with intention to get minimal kernel.

Without SLUB_DEBUG there will be no redzones, no user tracking info 
(allocation/free stacktraces).
KASAN won't be so usefull without SLUB_DEBUG.


[...]

 --- a/mm/kasan/kasan.c
 +++ b/mm/kasan/kasan.c
 @@ -30,6 +30,7 @@
  #include linux/kasan.h

  #include kasan.h
 +#include ../slab.h

  /*
   * Poisons the shadow memory for 'size' bytes starting from 'addr'.
 @@ -265,6 +266,102 @@ void kasan_free_pages(struct page *page, unsigned int 
 order)
 KASAN_FREE_PAGE);
  }

 +void kasan_free_slab_pages(struct page *page, int order)
 
 Doesn't this callback followed by actually freeing the pages, and so
 kasan_free_pages callback that will poison the range? If so, I would
 prefer to not double poison.
 

Yes, this could be removed.

 
 +{
 +   kasan_poison_shadow(page_address(page),
 +   PAGE_SIZE  order, KASAN_SLAB_FREE);
 +}
 +
 +void kasan_mark_slab_padding(struct kmem_cache *s, void *object)
 +{
 +   unsigned long object_end = (unsigned long)object + s-size;
 +   unsigned long padding_end = round_up(object_end, PAGE_SIZE);
 +   unsigned long padding_start = round_up(object_end,
 +   KASAN_SHADOW_SCALE_SIZE);
 +   size_t size = padding_end - padding_start;
 +
 +   if (size)
 +   kasan_poison_shadow((void *)padding_start,
 +   size, KASAN_SLAB_PADDING);
 +}
 +
 +void kasan_slab_alloc(struct kmem_cache *cache, void *object)
 +{
 +   kasan_kmalloc(cache, object, cache-object_size);
 +}
 +
 +void kasan_slab_free(struct kmem_cache *cache, void *object)
 +{
 +   unsigned long size = cache-size;
 +   unsigned long rounded_up_size = round_up(size, 
 KASAN_SHADOW_SCALE_SIZE);
 +
 
 Add a comment saying that SLAB_DESTROY_BY_RCU objects can be legally
 used after free.
 

Ok.

 +   if (unlikely(cache-flags  SLAB_DESTROY_BY_RCU))
 +   return;
 +
 +   kasan_poison_shadow(object, rounded_up_size, KASAN_KMALLOC_FREE);
 +}
 +
 +void kasan_kmalloc(struct kmem_cache *cache, const void *object, size_t 
 size)
 +{
 +   unsigned long redzone_start;
 +   unsigned long redzone_end;
 +
 +   if (unlikely(object == NULL))
 +   return;
 +
 +   redzone_start = round_up((unsigned long)(object + size),
 +   KASAN_SHADOW_SCALE_SIZE);
 +   redzone_end = (unsigned long)object + cache-size;
 +
 +   kasan_unpoison_shadow(object, size);
 +   kasan_poison_shadow((void *)redzone_start, redzone_end - 
 redzone_start,
 +   KASAN_KMALLOC_REDZONE);
 +
 +}
 +EXPORT_SYMBOL(kasan_kmalloc);
 +
 +void kasan_kmalloc_large(const void *ptr, size_t size)
 +{
 +   struct page *page;
 +   unsigned long redzone_start;
 +   unsigned long redzone_end;
 +
 +   if (unlikely(ptr == NULL))
 +   return;
 +
 +   page = virt_to_page(ptr);
 +   redzone_start = round_up((unsigned long)(ptr + size),
 +   KASAN_SHADOW_SCALE_SIZE);
 +   redzone_end = (unsigned long)ptr + (PAGE_SIZE  
 compound_order(page));
 
 If size == N*PAGE_SIZE - KASAN_SHADOW_SCALE_SIZE - 1, the object does
 not receive any redzone at all. 

If size == N*PAGE_SIZE - KASAN_SHADOW_SCALE_SIZE - 1, there will be redzone
KASAN_SHADOW_SCALE_SIZE + 1 bytes. There will be no readzone if and only if
(size == PAGE_SIZE  compound_order(page))

 Can we pass full memory block size
 from above to fix it? Will compound_order(page) do?
 

What is full memory block size?
PAGE_SIZE  compound_order(page) is how much was really allocated.


[..]


  static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node)
 @@ -1416,8 +1426,10 @@ static struct page *new_slab(struct kmem_cache *s, 
 gfp_t flags, int node)
 setup_object(s, page, p);
 if (likely(idx  page-objects))
 set_freepointer(s, p, p + s-size);
 
 Sorry, I don't fully follow this code, so I will just ask some questions.
 Can we have some slab padding after last object in this case as well?
 
This case is for not the last object. Padding is the place after the last 
object.
The last object initialized bellow in else case

Re: [PATCH v3 00/13] Kernel address sanitizer - runtime memory debugger.

2014-09-26 Thread Andrey Ryabinin
2014-09-26 21:01 GMT+04:00 Sasha Levin sasha.le...@oracle.com:
 On 09/24/2014 08:43 AM, Andrey Ryabinin wrote:
 Hi.

 This is a third iteration of kerenel address sanitizer (KASan).

 KASan is a runtime memory debugger designed to find use-after-free
 and out-of-bounds bugs.

 Currently KASAN supported only for x86_64 architecture and requires kernel
 to be build with SLUB allocator.
 KASAN uses compile-time instrumentation for checking every memory access, 
 therefore you
 will need a fresh GCC = v5.0.0.

 Hi Andrey,

 I tried this patchset, with the latest gcc, and I'm seeing the following:

 arch/x86/kernel/head.o: In function 
 `_GLOBAL__sub_I_00099_0_reserve_ebda_region':
 /home/sasha/linux-next/arch/x86/kernel/head.c:71: undefined reference to 
 `__asan_init_v4'
 init/built-in.o: In function `_GLOBAL__sub_I_00099_0___ksymtab_system_state':
 /home/sasha/linux-next/init/main.c:1034: undefined reference to 
 `__asan_init_v4'
 init/built-in.o: In function `_GLOBAL__sub_I_00099_0_init_uts_ns':
 /home/sasha/linux-next/init/version.c:50: undefined reference to 
 `__asan_init_v4'
 init/built-in.o: In function `_GLOBAL__sub_I_00099_0_root_mountflags':
 /home/sasha/linux-next/init/do_mounts.c:638: undefined reference to 
 `__asan_init_v4'
 init/built-in.o: In function `_GLOBAL__sub_I_00099_0_rd_prompt':
 /home/sasha/linux-next/init/do_mounts_rd.c:361: undefined reference to 
 `__asan_init_v4'
 init/built-in.o:/home/sasha/linux-next/init/do_mounts_md.c:312: more 
 undefined references to `__asan_init_v4' follow


 What am I missing?


__asan_init_v* is a version of compiler's api. Recently it was changed
in gcc - https://gcc.gnu.org/ml/gcc-patches/2014-09/msg01872.html

To fix this, just add:

void __asan_init_v4(void) {}
EXPORT_SYMBOL(__asan_init_v4);

 to the mm/kasan/kasan.c

I'll fix this in next spin.


 Thanks,
 Sasha

 --



-- 
Best regards,
Andrey Ryabinin
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 00/13] Kernel address sanitizer - runtime memory debugger.

2014-09-26 Thread Andrey Ryabinin
2014-09-26 21:07 GMT+04:00 Dmitry Vyukov dvyu...@google.com:
 On Fri, Sep 26, 2014 at 10:01 AM, Sasha Levin sasha.le...@oracle.com wrote:
 On 09/24/2014 08:43 AM, Andrey Ryabinin wrote:
 Hi.

 This is a third iteration of kerenel address sanitizer (KASan).

 KASan is a runtime memory debugger designed to find use-after-free
 and out-of-bounds bugs.

 Currently KASAN supported only for x86_64 architecture and requires kernel
 to be build with SLUB allocator.
 KASAN uses compile-time instrumentation for checking every memory access, 
 therefore you
 will need a fresh GCC = v5.0.0.

 Hi Andrey,

 I tried this patchset, with the latest gcc, and I'm seeing the following:

 arch/x86/kernel/head.o: In function 
 `_GLOBAL__sub_I_00099_0_reserve_ebda_region':
 /home/sasha/linux-next/arch/x86/kernel/head.c:71: undefined reference to 
 `__asan_init_v4'
 init/built-in.o: In function `_GLOBAL__sub_I_00099_0___ksymtab_system_state':
 /home/sasha/linux-next/init/main.c:1034: undefined reference to 
 `__asan_init_v4'
 init/built-in.o: In function `_GLOBAL__sub_I_00099_0_init_uts_ns':
 /home/sasha/linux-next/init/version.c:50: undefined reference to 
 `__asan_init_v4'
 init/built-in.o: In function `_GLOBAL__sub_I_00099_0_root_mountflags':
 /home/sasha/linux-next/init/do_mounts.c:638: undefined reference to 
 `__asan_init_v4'
 init/built-in.o: In function `_GLOBAL__sub_I_00099_0_rd_prompt':
 /home/sasha/linux-next/init/do_mounts_rd.c:361: undefined reference to 
 `__asan_init_v4'
 init/built-in.o:/home/sasha/linux-next/init/do_mounts_md.c:312: more 
 undefined references to `__asan_init_v4' follow


 What am I missing?


 Emission of __asan_init_vx needs to be disabled when
 -fsanitize=kernel-address. Our kernel does not boot with them at all.
 It probably hits some limit for something that can be increased. But I
 don't want to investigate what that limit is, as __asan_init is not
 needed for kasan at all.


__asan_init_vx maybe not needed for kernel, but we still need somehow
to identify
compiler's asan version (e.g. for globals).
We could add some define to GCC or just something like this in kernel:
#if __GNUC__ == 5
#define ASAN_V4


-- 
Best regards,
Andrey Ryabinin
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH v3 13/13] kasan: introduce inline instrumentation

2014-09-26 Thread Andrey Ryabinin
2014-09-26 21:18 GMT+04:00 Dmitry Vyukov dvyu...@google.com:

 Yikes!
 So this works during bootstrap, for user memory accesses, valloc
 memory, etc, right?


Yes, this works. Userspace memory access in instrumented code will
produce general protection fault,
so it won't be unnoticed.


-- 
Best regards,
Andrey Ryabinin
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v3 11/13] kmemleak: disable kasan instrumentation for kmemleak

2014-09-26 Thread Andrey Ryabinin
2014-09-26 21:10 GMT+04:00 Dmitry Vyukov dvyu...@google.com:
 Looks good to me.

 We can disable kasan instrumentation of this file as well.


Yes, but why? I don't think we need that.

 On Wed, Sep 24, 2014 at 5:44 AM, Andrey Ryabinin a.ryabi...@samsung.com 
 wrote:
 kmalloc internally round up allocation size, and kmemleak
 uses rounded up size as object's size. This makes kasan
 to complain while kmemleak scans memory or calculates of object's
 checksum. The simplest solution here is to disable kasan.

 Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
 ---
  mm/kmemleak.c | 6 ++
  1 file changed, 6 insertions(+)

 diff --git a/mm/kmemleak.c b/mm/kmemleak.c
 index 3cda50c..9bda1b3 100644
 --- a/mm/kmemleak.c
 +++ b/mm/kmemleak.c
 @@ -98,6 +98,7 @@
  #include asm/processor.h
  #include linux/atomic.h

 +#include linux/kasan.h
  #include linux/kmemcheck.h
  #include linux/kmemleak.h
  #include linux/memory_hotplug.h
 @@ -1113,7 +1114,10 @@ static bool update_checksum(struct kmemleak_object 
 *object)
 if (!kmemcheck_is_obj_initialized(object-pointer, object-size))
 return false;

 +   kasan_disable_local();
 object-checksum = crc32(0, (void *)object-pointer, object-size);
 +   kasan_enable_local();
 +
 return object-checksum != old_csum;
  }

 @@ -1164,7 +1168,9 @@ static void scan_block(void *_start, void *_end,
   BYTES_PER_POINTER))
 continue;

 +   kasan_disable_local();
 pointer = *ptr;
 +   kasan_enable_local();

 object = find_and_get_object(pointer, 1);
 if (!object)
 --
 2.1.1




-- 
Best regards,
Andrey Ryabinin
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC PATCH v3 13/13] kasan: introduce inline instrumentation

2014-09-29 Thread Andrey Ryabinin
On 09/29/2014 06:28 PM, Dmitry Vyukov wrote:
 On Fri, Sep 26, 2014 at 9:33 PM, Andrey Ryabinin ryabinin@gmail.com 
 wrote:
 2014-09-26 21:18 GMT+04:00 Dmitry Vyukov dvyu...@google.com:

 Yikes!
 So this works during bootstrap, for user memory accesses, valloc
 memory, etc, right?


 Yes, this works. Userspace memory access in instrumented code will
 produce general protection fault,
 so it won't be unnoticed.
 
 
 Great!
 What happens during early bootstrap when shadow is not mapped yet?
 

Shadow mapped very early. Any instrumented code executes only after shadow 
mapped.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] kernel: irq: use a kmem_cache for allocating struct irq_desc

2014-11-10 Thread Andrey Ryabinin
After enabling alignment checks in UBSan I've noticed a lot of
reports like this:

UBSan: Undefined behaviour in ../kernel/irq/chip.c:195:14
member access within misaligned address 88003e80d6f8
for type 'struct irq_desc' which requires 16 byte alignment

struct irq_desc declared with cacheline_internodealigned_in_smp
attribute. However in some cases it allocated dynamically via kmalloc().
In general case kmalloc() guaranties only sizeof(void *) alignment.
We should use a separate slab cache to make struct irq_desc
properly aligned on SMP configuration.

This also could slightly reduce memory usage on some configurations.
E.g. in my setup sizeof(struct irq_desc) == 320. Which means that
kmalloc-512 will be used for allocating irg_desc via kmalloc().
In that case using separate slab cache will save us 192 bytes per
each irq_desc.

Note: UBSan reports says that 'struct irq_desc' requires 16 byte alignment.
It's wrong, in my setup it should be 64 bytes. This looks like a gcc bug,
but it doesn't change the fact that irq_desc is misaligned.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 kernel/irq/irqdesc.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index a1782f8..f22cb87 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -23,6 +23,8 @@
  */
 static struct lock_class_key irq_desc_lock_class;
 
+static struct kmem_cache *irq_desc_cachep;
+
 #if defined(CONFIG_SMP)
 static void __init init_irq_default_affinity(void)
 {
@@ -137,9 +139,10 @@ static struct irq_desc *alloc_desc(int irq, int node, 
struct module *owner)
struct irq_desc *desc;
gfp_t gfp = GFP_KERNEL;
 
-   desc = kzalloc_node(sizeof(*desc), gfp, node);
+   desc = kmem_cache_zalloc_node(irq_desc_cachep, gfp, node);
if (!desc)
return NULL;
+
/* allocate based on nr_cpu_ids */
desc-kstat_irqs = alloc_percpu(unsigned int);
if (!desc-kstat_irqs)
@@ -158,7 +161,7 @@ static struct irq_desc *alloc_desc(int irq, int node, 
struct module *owner)
 err_kstat:
free_percpu(desc-kstat_irqs);
 err_desc:
-   kfree(desc);
+   kmem_cache_free(irq_desc_cachep, desc);
return NULL;
 }
 
@@ -174,7 +177,7 @@ static void free_desc(unsigned int irq)
 
free_masks(desc);
free_percpu(desc-kstat_irqs);
-   kfree(desc);
+   kmem_cache_free(irq_desc_cachep, desc);
 }
 
 static int alloc_descs(unsigned int start, unsigned int cnt, int node,
@@ -218,6 +221,8 @@ int __init early_irq_init(void)
 
init_irq_default_affinity();
 
+   irq_desc_cachep = KMEM_CACHE(irq_desc, SLAB_PANIC);
+
/* Let arch update nr_irqs and return the nr of preallocated irqs */
initcnt = arch_probe_nr_irqs();
printk(KERN_INFO NR_IRQS:%d nr_irqs:%d %d\n, NR_IRQS, nr_irqs, 
initcnt);
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/3] mm: sl[aou]b: introduce kmem_cache_zalloc_node()

2014-11-10 Thread Andrey Ryabinin
kmem_cache_zalloc_node() allocates zeroed memory for a particular
cache from a specified memory node. To be used for struct irq_desc.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/slab.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/slab.h b/include/linux/slab.h
index c265bec..b3248fa 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -574,6 +574,12 @@ static inline void *kmem_cache_zalloc(struct kmem_cache 
*k, gfp_t flags)
return kmem_cache_alloc(k, flags | __GFP_ZERO);
 }
 
+static inline void *kmem_cache_zalloc_node(struct kmem_cache *k, gfp_t flags,
+   int node)
+{
+   return kmem_cache_alloc_node(k, flags | __GFP_ZERO, node);
+}
+
 /**
  * kzalloc - allocate memory. The memory is set to zero.
  * @size: how many bytes of memory are required.
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] kernel: irq: use kmem_cache for allocating struct irqaction

2014-11-10 Thread Andrey Ryabinin
After enabling alignment checks in UBSan I've noticed several
reports like this:

   UBSan: Undefined behaviour in kernel/irq/manage.c:1315:13
   member access within misaligned address 88007c274558
   for type 'struct irqaction' which requires 16 byte alignment

struct irqaction declared with cacheline_internodealigned_in_smp
attribute. However in some cases it allocated dynamically via kmalloc().
In general case kmalloc() guaranties only sizeof(void *) alignment.
We should use a separate slab cache to make struct irqaction
properly aligned on SMP configuration.

Note: UBSan reports says that 'struct irqaction' requires 16 byte alignment.
It's wrong, in my setup it should be 64 bytes. This looks like a gcc bug,
but it doesn't change the fact that irqaction is misaligned.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 kernel/irq/internals.h |  2 ++
 kernel/irq/irqdesc.c   |  1 +
 kernel/irq/manage.c| 14 --
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/kernel/irq/internals.h b/kernel/irq/internals.h
index 4332d76..95b61c5 100644
--- a/kernel/irq/internals.h
+++ b/kernel/irq/internals.h
@@ -7,6 +7,7 @@
  */
 #include linux/irqdesc.h
 #include linux/kernel_stat.h
+#include linux/slab.h
 
 #ifdef CONFIG_SPARSE_IRQ
 # define IRQ_BITMAP_BITS   (NR_IRQS + 8196)
@@ -17,6 +18,7 @@
 #define istate core_internal_state__do_not_mess_with_it
 
 extern bool noirqdebug;
+extern struct kmem_cache *irqaction_cachep;
 
 /*
  * Bits used by threaded handlers:
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index f22cb87..52c3e4f 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -222,6 +222,7 @@ int __init early_irq_init(void)
init_irq_default_affinity();
 
irq_desc_cachep = KMEM_CACHE(irq_desc, SLAB_PANIC);
+   irqaction_cachep = KMEM_CACHE(irqaction, SLAB_PANIC);
 
/* Let arch update nr_irqs and return the nr of preallocated irqs */
initcnt = arch_probe_nr_irqs();
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 0a9104b..7c69597 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -21,6 +21,8 @@
 
 #include internals.h
 
+struct kmem_cache *irqaction_cachep;
+
 #ifdef CONFIG_IRQ_FORCED_THREADING
 __read_mostly bool force_irqthreads;
 
@@ -1409,7 +1411,7 @@ void free_irq(unsigned int irq, void *dev_id)
 #endif
 
chip_bus_lock(desc);
-   kfree(__free_irq(irq, dev_id));
+   kmem_cache_free(irqaction_cachep, __free_irq(irq, dev_id));
chip_bus_sync_unlock(desc);
 }
 EXPORT_SYMBOL(free_irq);
@@ -1487,7 +1489,7 @@ int request_threaded_irq(unsigned int irq, irq_handler_t 
handler,
handler = irq_default_primary_handler;
}
 
-   action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+   action = kmem_cache_zalloc(irqaction_cachep, GFP_KERNEL);
if (!action)
return -ENOMEM;
 
@@ -1502,7 +1504,7 @@ int request_threaded_irq(unsigned int irq, irq_handler_t 
handler,
chip_bus_sync_unlock(desc);
 
if (retval)
-   kfree(action);
+   kmem_cache_free(irqaction_cachep, action);
 
 #ifdef CONFIG_DEBUG_SHIRQ_FIXME
if (!retval  (irqflags  IRQF_SHARED)) {
@@ -1683,7 +1685,7 @@ void free_percpu_irq(unsigned int irq, void __percpu 
*dev_id)
return;
 
chip_bus_lock(desc);
-   kfree(__free_percpu_irq(irq, dev_id));
+   kmem_cache_free(irqaction_cachep, __free_percpu_irq(irq, dev_id));
chip_bus_sync_unlock(desc);
 }
 
@@ -1738,7 +1740,7 @@ int request_percpu_irq(unsigned int irq, irq_handler_t 
handler,
!irq_settings_is_per_cpu_devid(desc))
return -EINVAL;
 
-   action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
+   action = kmem_cache_zalloc(irqaction_cachep, GFP_KERNEL);
if (!action)
return -ENOMEM;
 
@@ -1752,7 +1754,7 @@ int request_percpu_irq(unsigned int irq, irq_handler_t 
handler,
chip_bus_sync_unlock(desc);
 
if (retval)
-   kfree(action);
+   kmem_cache_free(irqaction_cachep, action);
 
return retval;
 }
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v6 00/11] Kernel address sanitizer - runtime memory debugger.

2014-11-10 Thread Andrey Ryabinin
Hi Andrew,

Now we have stable GCC(4.9.2) which supports kasan and from my point of view 
patchset is ready for merging.
I could have sent v7 (it's just rebased v6), but I see no point in doing that 
and bothering people,
unless you are ready to take it.
So how should I proceed?

Thanks,
Andrey.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[BUG] index is out of range for nfnl_group2type[]

2014-11-13 Thread Andrey Ryabinin
FYI I've spotted this:

[  180.202810] 

[  180.203600] UBSan: Undefined behaviour in ../net/netfilter/nfnetlink.c:467:28
[  180.204249] index 9 is out of range for type 'int [9]'
[  180.204697] CPU: 0 PID: 1771 Comm: trinity-main Not tainted 3.18.0-rc4-mm1+ 
#122
[  180.205365] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 
rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
[  180.206498]  0018  0009 
88007bdf7da8
[  180.207220]  82b0ef5f 0092 845ae2e0 
88007bdf7db8
[  180.207887]  8199e489 88007bdf7e18 8199ea22 
0039
[  180.208639] Call Trace:
[  180.208857] dump_stack (lib/dump_stack.c:52)
[  180.209370] ubsan_epilogue (lib/ubsan.c:174)
[  180.209849] __ubsan_handle_out_of_bounds (lib/ubsan.c:400)
[  180.210512] nfnetlink_bind (net/netfilter/nfnetlink.c:467)
[  180.210986] netlink_bind (net/netlink/af_netlink.c:1483)
[  180.211495] SYSC_bind (net/socket.c:1541)
[  180.211940] ? security_socket_setsockopt (security/security.c:1208)
[  180.212541] ? SyS_setsockopt (net/socket.c:1920 net/socket.c:1900)
[  180.213057] ? SyS_write (fs/read_write.c:276 fs/read_write.c:588 
fs/read_write.c:577)
[  180.213506] SyS_bind (net/socket.c:1527)
[  180.213919] system_call_fastpath (arch/x86/kernel/entry_64.S:423)
[  180.214479] 



--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 2/2] UBSan: run-time undefined behavior sanity checker

2014-11-14 Thread Andrey Ryabinin
UBSan uses compile-time instrumentation to catch undefined behavior (UB).
Compiler inserts code that perform certain kinds of checks before
operations that could cause UB. If check fails (i.e. UB detected)
__ubsan_handle_* function called to print error message.

So the most of the work is done by compiler. This patch just
implements ubsan handlers printing errors.

GCC has this capability since 4.9 [1] (see -fsanitize=undefined
option and its suboptions).
However upcoming GCC 5.0 has more checkers implemented [2].
Article [3] has a bit more details about UBSan in the GCC.

Different kinds of checks could be enabled via boot parameter:
ubsan_handle=OEAINVBSLU.
If ubsan_handle not present in cmdline default options are used: ELNVBSLU

O - different kinds of overflows
E - negation overflow, division overflow, division by zero.
A - misaligned memory access.
I - load from/store to an object with insufficient space.
N - null argument declared with nonnull attribute,
  returned null from function which never returns null, null ptr 
dereference.
V - variable size array with non-positive length
B - out-of-bounds accesses.
S - shifting out-of-bounds.
L - load of invalid value (value out of range for the enum type, 
loading other then 0/1 to bool type)
U - __builtin_unreachable() was called

[1] - https://gcc.gnu.org/onlinedocs/gcc-4.9.0/gcc/Debugging-Options.html
[2] - https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html
[3] - 
http://developerblog.redhat.com/2014/10/16/gcc-undefined-behavior-sanitizer-ubsan/

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 Documentation/ubsan.txt   |  69 +
 Makefile  |  10 +-
 arch/x86/Kconfig  |   1 +
 arch/x86/boot/Makefile|   1 +
 arch/x86/boot/compressed/Makefile |   1 +
 arch/x86/realmode/rm/Makefile |   1 +
 arch/x86/vdso/Makefile|   2 +
 drivers/firmware/efi/libstub/Makefile |   1 +
 include/linux/sched.h |   3 +
 lib/Kconfig.debug |  22 ++
 lib/Makefile  |   3 +
 lib/ubsan.c   | 567 ++
 lib/ubsan.h   |  84 +
 scripts/Makefile.lib  |   6 +
 14 files changed, 770 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ubsan.txt
 create mode 100644 lib/ubsan.c
 create mode 100644 lib/ubsan.h

diff --git a/Documentation/ubsan.txt b/Documentation/ubsan.txt
new file mode 100644
index 000..04d6aa6
--- /dev/null
+++ b/Documentation/ubsan.txt
@@ -0,0 +1,69 @@
+Undefined Behavior Sanitizer - UBSan
+
+Overview
+
+
+UBSan is a runtime undefined behaviour checker.
+
+UBSan uses compile-time instrumentation to catch undefined behavior (UB).
+Compiler inserts code that perform certain kinds of checks before operations
+that may cause UB. If check fails (i.e. UB detected) __ubsan_handle_*
+function called to print error message.
+
+GCC has that feature since 4.9 [1] (see -fsanitize=undefined option and its 
suboptions).
+Upcoming GCC 5.0 has more checkers implemented [2].
+
+Usage
+===
+
+To enable UBSAN configure kernel with:
+
+ CONFIG_UBSAN=y
+
+and to check the entire kernel:
+
+CONFIG_UBSAN_SANITIZE_ALL=y
+
+To enable instrumentation for specific files or directories, add a line
+similar to the following to the respective kernel Makefile:
+
+For a single file (e.g. main.o):
+UBSAN_SANITIZE_main.o := y
+
+For all files in one directory:
+UBSAN_SANITIZE := y
+
+To exclude files from being instrumented even if CONFIG_UBSAN_SANITIZE_ALL=y,
+use:
+
+UBSAN_SANITIZE_main.o := n
+and:
+UBSAN_SANITIZE := n
+
+Various types of checkers may be enabled via boot parameter, e.g.:
+ ubsan_handle=OEAINVBSLU
+
+Possible options are:
+O - different kinds of integer overflows
+E - negation overflow, division overflow, division by zero.
+A - misaligned memory access.
+I - load from/store to an object with insufficient space.
+N - passing NULL as argument declared with nonnull attribute,
+ returned null from function which never returns null,
+ null ptr dereference.
+V - variable size array with non-positive length
+B - out-of-bounds memory accesses
+S - shifting out-of-bounds
+L - load of invalid value (value out of range for the enum type,
+  loading other then 0/1 to bool type)
+U - __builtin_unreachable() was called
+
+If ubsan_handle not present in cmdline the default options are used: ELNVBSLU.
+Additionally option 'A' (misaligned access checks) enabled by default if
+architecture doesn't support unaligned accesses.
+
+References
+==
+
+[1] - https://gcc.gnu.org/onlinedocs/gcc-4.9.0

[PATCH v2 0/2] UBSan: run-time undefined behavior sanity checker

2014-11-14 Thread Andrey Ryabinin
Next spin of UBSan and there are two patches from now.
Two there should be; no more, no less. One to embody the UBSan,
the other to not deadlock it.

Patches on top of v3.18-rc4. As usual they are available in git:
git://github.com/aryabinin/linux ubsan/v2

Changes since v1:
   - Refactoring and cleanups in lib/ubsan.c including Sasha's complains.
   - Some spelling fixes from Randy
   - Fixed possible memory corruption on 64 big endian machines, spotted by 
Rasmus.
   - Links to the relevant GCC documentation added into changelog (Peter).
   - Added documentation.
   - Fix deadlock caused by kernel/printk/printk.c instrumentation
(patch kernel: printk: specify alignment for struct printk_log).
   - Dropped useless 'Indirect call of a function through a function pointer of 
the wrong type'
 checker. GCC doesn't support this, and as clang manual says it's for C++ 
only.
   - Added checker for __builtin_unreachable() calls.
   - Removed redundant -fno-sanitize=float-cast-overflow from CFLAGS.
   - Added lock to prevent mixing reports.

Andrey Ryabinin (2):
  kernel: printk: specify alignment for struct printk_log
  UBSan: run-time undefined behavior sanity checker

 Documentation/ubsan.txt   |  69 +
 Makefile  |  10 +-
 arch/x86/Kconfig  |   1 +
 arch/x86/boot/Makefile|   1 +
 arch/x86/boot/compressed/Makefile |   1 +
 arch/x86/realmode/rm/Makefile |   1 +
 arch/x86/vdso/Makefile|   2 +
 drivers/firmware/efi/libstub/Makefile |   1 +
 include/linux/sched.h |   3 +
 kernel/printk/printk.c|  10 +-
 lib/Kconfig.debug |  22 ++
 lib/Makefile  |   3 +
 lib/ubsan.c   | 567 ++
 lib/ubsan.h   |  84 +
 scripts/Makefile.lib  |   6 +
 15 files changed, 775 insertions(+), 6 deletions(-)
 create mode 100644 Documentation/ubsan.txt
 create mode 100644 lib/ubsan.c
 create mode 100644 lib/ubsan.h

-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2 1/2] kernel: printk: specify alignment for struct printk_log

2014-11-14 Thread Andrey Ryabinin
On architectures that have support for efficient unaligned access
struct printk_log has 4-byte alignment.
Specify alignment attribute in type declaration.

The whole point of this patch is to fix deadlock which happening
when UBSan detects unaligned access in printk() thus UBSan recursively
calls printk() with logbuf_lock held by top printk() call.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 kernel/printk/printk.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ced2b84..39be027 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -223,7 +223,11 @@ struct printk_log {
u8 facility;/* syslog facility */
u8 flags:5; /* internal record flags */
u8 level:3; /* syslog level */
-};
+}
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+__packed __aligned(4)
+#endif
+;
 
 /*
  * The logbuf_lock protects kmsg buffer, indices, counters.  This can be taken
@@ -261,11 +265,7 @@ static u32 clear_idx;
 #define LOG_LINE_MAX   (1024 - PREFIX_MAX)
 
 /* record buffer */
-#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
-#define LOG_ALIGN 4
-#else
 #define LOG_ALIGN __alignof__(struct printk_log)
-#endif
 #define __LOG_BUF_LEN (1  CONFIG_LOG_BUF_SHIFT)
 static char __log_buf[__LOG_BUF_LEN] __aligned(LOG_ALIGN);
 static char *log_buf = __log_buf;
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2] kernel: use the gnu89 standard explicitly

2014-11-14 Thread Andrey Ryabinin
2014-10-20 5:40 GMT+03:00 Sasha Levin sasha.le...@oracle.com:
 gcc5 changes the default standard to c11, which makes kernel
 build unhappy.

 Explicitly define the kernel standard to be gnu89 which should
 keep everything working exactly like it was before gcc5.


Ping.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 00/13] Kernel address sanitizer - runtime memory debugger.

2014-09-24 Thread Andrey Ryabinin
 for access; k (1 = k = 7) means that
the first k bytes are valid for access, and other (8 - k) bytes are not;
Any negative value indicates that the entire 8-bytes are inaccessible.
Different negative values used to distinguish between different kinds of
inaccessible memory (redzones, freed memory) (see mm/kasan/kasan.h).

To be able to detect accesses to bad memory we need a special compiler.
Such compiler inserts a specific function calls (__asan_load*(addr), 
__asan_store*(addr))
before each memory access of size 1, 2, 4, 8 or 16.

These functions check whether memory region is valid to access or not by 
checking
corresponding shadow memory. If access is not valid an error printed.


Andrey Ryabinin (13):
  Add kernel address sanitizer infrastructure.
  efi: libstub: disable KASAN for efistub
  x86_64: load_percpu_segment: read irq_stack_union.gs_base before
load_segment
  x86_64: add KASan support
  mm: page_alloc: add kasan hooks on alloc and free paths
  mm: slub: introduce virt_to_obj function.
  mm: slub: share slab_err and object_err functions
  mm: slub: introduce metadata_access_enable()/metadata_access_disable()
  mm: slub: add kernel address sanitizer support for slub allocator
  fs: dcache: manually unpoison dname after allocation to shut up
kasan's reports
  kmemleak: disable kasan instrumentation for kmemleak
  lib: add kasan test module
  kasan: introduce inline instrumentation

 Documentation/kasan.txt   | 179 ++
 Makefile  |  16 +-
 arch/x86/Kconfig  |   1 +
 arch/x86/boot/Makefile|   2 +
 arch/x86/boot/compressed/Makefile |   2 +
 arch/x86/include/asm/kasan.h  |  27 +++
 arch/x86/kernel/Makefile  |   2 +
 arch/x86/kernel/cpu/common.c  |   4 +-
 arch/x86/kernel/dumpstack.c   |   5 +-
 arch/x86/kernel/head64.c  |   9 +-
 arch/x86/kernel/head_64.S |  28 +++
 arch/x86/mm/Makefile  |   3 +
 arch/x86/mm/init.c|   3 +
 arch/x86/mm/kasan_init_64.c   |  87 +++
 arch/x86/realmode/Makefile|   2 +-
 arch/x86/realmode/rm/Makefile |   1 +
 arch/x86/vdso/Makefile|   1 +
 drivers/firmware/efi/libstub/Makefile |   1 +
 fs/dcache.c   |   5 +
 include/linux/kasan.h |  72 ++
 include/linux/sched.h |   3 +
 include/linux/slab.h  |  11 +-
 include/linux/slub_def.h  |   9 +
 lib/Kconfig.debug |   2 +
 lib/Kconfig.kasan |  54 +
 lib/Makefile  |   1 +
 lib/test_kasan.c  | 254 
 mm/Makefile   |   4 +
 mm/compaction.c   |   2 +
 mm/kasan/Makefile |   3 +
 mm/kasan/kasan.c  | 441 ++
 mm/kasan/kasan.h  |  37 +++
 mm/kasan/report.c | 259 
 mm/kmemleak.c |   6 +
 mm/page_alloc.c   |   3 +
 mm/slab_common.c  |   5 +-
 mm/slub.c |  56 -
 scripts/Makefile.lib  |  10 +
 38 files changed, 1595 insertions(+), 15 deletions(-)
 create mode 100644 Documentation/kasan.txt
 create mode 100644 arch/x86/include/asm/kasan.h
 create mode 100644 arch/x86/mm/kasan_init_64.c
 create mode 100644 include/linux/kasan.h
 create mode 100644 lib/Kconfig.kasan
 create mode 100644 lib/test_kasan.c
 create mode 100644 mm/kasan/Makefile
 create mode 100644 mm/kasan/kasan.c
 create mode 100644 mm/kasan/kasan.h
 create mode 100644 mm/kasan/report.c


Cc: Dmitry Vyukov dvyu...@google.com
Cc: Konstantin Serebryany k...@google.com
Cc: Dmitry Chernenkov dmit...@google.com
Cc: Andrey Konovalov adech...@gmail.com
Cc: Yuri Gribov tetra2...@gmail.com
Cc: Konstantin Khlebnikov koc...@gmail.com
Cc: Sasha Levin sasha.le...@oracle.com
Cc: Michal Marek mma...@suse.cz
Cc: Thomas Gleixner t...@linutronix.de
Cc: Ingo Molnar mi...@redhat.com
Cc: Christoph Lameter c...@linux.com
Cc: Pekka Enberg penb...@kernel.org
Cc: David Rientjes rient...@google.com
Cc: Joonsoo Kim iamjoonsoo@lge.com
Cc: Andrew Morton a...@linux-foundation.org
Cc: Dave Hansen dave.han...@intel.com
Cc: Andi Kleen a...@firstfloor.org
Cc: Vegard Nossum vegard.nos...@gmail.com
Cc: H. Peter Anvin h...@zytor.com
Cc: linux-kbu...@vger.kernel.org
Cc: x...@kernel.org
Cc: linux...@kvack.org
Cc: Randy Dunlap rdun...@infradead.org
Cc: Michal Marek mma...@suse.cz
Cc: Ingo Molnar mi...@redhat.com
Cc: Peter Zijlstra pet...@infradead.org
Cc: Alexander Viro v...@zeniv.linux.org.uk
Cc: Dave Jones da...@redhat.com


-- 
2.1.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More

[PATCH v3 01/13] Add kernel address sanitizer infrastructure.

2014-09-24 Thread Andrey Ryabinin
Kernel Address sanitizer (KASan) is a dynamic memory error detector. It provides
fast and comprehensive solution for finding use-after-free and out-of-bounds 
bugs.

KASAN uses compile-time instrumentation for checking every memory access,
therefore fresh GCC = v5.0.0 required.

This patch only adds infrastructure for kernel address sanitizer. It's not
available for use yet. The idea and some code was borrowed from [1].

Basic idea:
The main idea of KASAN is to use shadow memory to record whether each byte of 
memory
is safe to access or not, and use compiler's instrumentation to check the 
shadow memory
on each memory access.

Address sanitizer uses 1/8 of the memory addressable in kernel for shadow memory
and uses direct mapping with a scale and offset to translate a memory
address to its corresponding shadow address.

Here is function to translate address to corresponding shadow address:

 unsigned long kasan_mem_to_shadow(unsigned long addr)
 {
return (addr  KASAN_SHADOW_SCALE_SHIFT) + KASAN_SHADOW_OFFSET;
 }
where KASAN_SHADOW_SCALE_SHIFT = 3.

So for every 8 bytes there is one corresponding byte of shadow memory.
The following encoding used for each shadow byte: 0 means that all 8 bytes of 
the
corresponding memory region are valid for access; k (1 = k = 7) means that
the first k bytes are valid for access, and other (8 - k) bytes are not;
Any negative value indicates that the entire 8-bytes are inaccessible.
Different negative values used to distinguish between different kinds of
inaccessible memory (redzones, freed memory) (see mm/kasan/kasan.h).

To be able to detect accesses to bad memory we need a special compiler.
Such compiler inserts a specific function calls (__asan_load*(addr), 
__asan_store*(addr))
before each memory access of size 1, 2, 4, 8 or 16.

These functions check whether memory region is valid to access or not by 
checking
corresponding shadow memory. If access is not valid an error printed.

[1] https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel

Based on work by Andrey Konovalov adech...@gmail.com

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 Documentation/kasan.txt | 179 ++
 Makefile|  11 +-
 include/linux/kasan.h   |  42 ++
 include/linux/sched.h   |   3 +
 lib/Kconfig.debug   |   2 +
 lib/Kconfig.kasan   |  15 +++
 mm/Makefile |   1 +
 mm/kasan/Makefile   |   3 +
 mm/kasan/kasan.c| 330 
 mm/kasan/kasan.h|  31 +
 mm/kasan/report.c   | 180 ++
 scripts/Makefile.lib|  10 ++
 12 files changed, 805 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/kasan.txt
 create mode 100644 include/linux/kasan.h
 create mode 100644 lib/Kconfig.kasan
 create mode 100644 mm/kasan/Makefile
 create mode 100644 mm/kasan/kasan.c
 create mode 100644 mm/kasan/kasan.h
 create mode 100644 mm/kasan/report.c

diff --git a/Documentation/kasan.txt b/Documentation/kasan.txt
new file mode 100644
index 000..4173783
--- /dev/null
+++ b/Documentation/kasan.txt
@@ -0,0 +1,179 @@
+Kernel address sanitizer
+
+
+0. Overview
+===
+
+Kernel Address sanitizer (KASan) is a dynamic memory error detector. It 
provides
+a fast and comprehensive solution for finding use-after-free and out-of-bounds 
bugs.
+
+KASAN uses compile-time instrumentation for checking every memory access, 
therefore you
+will need a special compiler: GCC = 5.0.0.
+
+Currently KASAN is supported only for x86_64 architecture and requires kernel
+to be built with SLUB allocator.
+
+1. Usage
+=
+
+KASAN requires the kernel to be built with a special compiler (GCC = 5.0.0).
+
+To enable KASAN configure kernel with:
+
+ CONFIG_KASAN = y
+
+Currently KASAN works only with the SLUB memory allocator.
+For better bug detection and nicer report, enable CONFIG_STACKTRACE and put
+'slub_debug=FU' in the boot cmdline.
+
+Do not use slub poisoning with KASan if user is tracking enabled (iow 
slub_debug=PU).
+User tracking info (allocation/free stacktraces) are stored inside slub 
object's metadata.
+Slub poisoning overwrites slub object and its metadata with poison value on 
freeing.
+So if KASan detects a use after free, allocation/free stacktraces are 
overwritten
+and KASan won't be able to print them.
+
+
+For a single file (e.g. main.o):
+KASAN_SANITIZE_main.o := n
+
+For all files in one directory:
+KASAN_SANITIZE := n
+
+Only files which are linked to the main kernel image or are compiled as
+kernel modules are supported by this mechanism.
+
+
+1.1 Error reports
+==
+
+A typical out of bounds access report looks like this:
+
+==
+AddressSanitizer: buffer overflow in kasan_kmalloc_oob_right+0x6a/0x7a at addr 
c6006f1b

[PATCH v3 05/13] mm: page_alloc: add kasan hooks on alloc and free paths

2014-09-24 Thread Andrey Ryabinin
Add kernel address sanitizer hooks to mark allocated page's addresses
as accessible in corresponding shadow region.
Mark freed pages as inaccessible.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/kasan.h |  6 ++
 mm/compaction.c   |  2 ++
 mm/kasan/kasan.c  | 14 ++
 mm/kasan/kasan.h  |  1 +
 mm/kasan/report.c |  7 +++
 mm/page_alloc.c   |  3 +++
 6 files changed, 33 insertions(+)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 01c99fe..9714fba 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -30,6 +30,9 @@ static inline void kasan_disable_local(void)
 
 void kasan_unpoison_shadow(const void *address, size_t size);
 
+void kasan_alloc_pages(struct page *page, unsigned int order);
+void kasan_free_pages(struct page *page, unsigned int order);
+
 #else /* CONFIG_KASAN */
 
 static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
@@ -37,6 +40,9 @@ static inline void kasan_unpoison_shadow(const void *address, 
size_t size) {}
 static inline void kasan_enable_local(void) {}
 static inline void kasan_disable_local(void) {}
 
+static inline void kasan_alloc_pages(struct page *page, unsigned int order) {}
+static inline void kasan_free_pages(struct page *page, unsigned int order) {}
+
 #endif /* CONFIG_KASAN */
 
 #endif /* LINUX_KASAN_H */
diff --git a/mm/compaction.c b/mm/compaction.c
index 92075d5..686b5c2 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -16,6 +16,7 @@
 #include linux/sysfs.h
 #include linux/balloon_compaction.h
 #include linux/page-isolation.h
+#include linux/kasan.h
 #include internal.h
 
 #ifdef CONFIG_COMPACTION
@@ -59,6 +60,7 @@ static void map_pages(struct list_head *list)
list_for_each_entry(page, list, lru) {
arch_alloc_page(page, 0);
kernel_map_pages(page, 1, 1);
+   kasan_alloc_pages(page, 0);
}
 }
 
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index 454df8d..7cfc1fe 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -251,6 +251,20 @@ static __always_inline void check_memory_region(unsigned 
long addr,
kasan_report_error(info);
 }
 
+void kasan_alloc_pages(struct page *page, unsigned int order)
+{
+   if (likely(!PageHighMem(page)))
+   kasan_unpoison_shadow(page_address(page), PAGE_SIZE  order);
+}
+
+void kasan_free_pages(struct page *page, unsigned int order)
+{
+   if (likely(!PageHighMem(page)))
+   kasan_poison_shadow(page_address(page),
+   PAGE_SIZE  order,
+   KASAN_FREE_PAGE);
+}
+
 void __asan_load1(unsigned long addr)
 {
check_memory_region(addr, 1, false);
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 5895e31..5e61799 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -6,6 +6,7 @@
 #define KASAN_SHADOW_SCALE_SIZE (1UL  KASAN_SHADOW_SCALE_SHIFT)
 #define KASAN_SHADOW_MASK   (KASAN_SHADOW_SCALE_SIZE - 1)
 
+#define KASAN_FREE_PAGE 0xFF  /* page was freed */
 #define KASAN_SHADOW_GAP0xF9  /* address belongs to shadow memory */
 
 struct access_info {
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index bf559fa..f9d4e8d 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -57,6 +57,9 @@ static void print_error_description(struct access_info *info)
case 0 ... KASAN_SHADOW_SCALE_SIZE - 1:
bug_type = out of bounds access;
break;
+   case KASAN_FREE_PAGE:
+   bug_type = use after free;
+   break;
case KASAN_SHADOW_GAP:
bug_type = wild memory access;
break;
@@ -75,6 +78,10 @@ static void print_address_description(struct access_info 
*info)
page = virt_to_head_page((void *)info-access_addr);
 
switch (shadow_val) {
+   case KASAN_FREE_PAGE:
+   dump_page(page, kasan error);
+   dump_stack();
+   break;
case KASAN_SHADOW_GAP:
pr_err(No metainfo is available for this access.\n);
dump_stack();
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ee95d0a..ef3604a 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -59,6 +59,7 @@
 #include linux/page-debug-flags.h
 #include linux/hugetlb.h
 #include linux/sched/rt.h
+#include linux/kasan.h
 
 #include asm/sections.h
 #include asm/tlbflush.h
@@ -755,6 +756,7 @@ static bool free_pages_prepare(struct page *page, unsigned 
int order)
 
trace_mm_page_free(page, order);
kmemcheck_free_shadow(page, order);
+   kasan_free_pages(page, order);
 
if (PageAnon(page))
page-mapping = NULL;
@@ -941,6 +943,7 @@ static int prep_new_page(struct page *page, unsigned int 
order, gfp_t gfp_flags)
 
arch_alloc_page(page, order);
kernel_map_pages(page, 1  order, 1);
+   kasan_alloc_pages(page, order);
 
if (gfp_flags  __GFP_ZERO

[RFC PATCH v3 13/13] kasan: introduce inline instrumentation

2014-09-24 Thread Andrey Ryabinin
This patch only demonstration how easy this could be achieved.
GCC doesn't support this feature yet. Two patches required for this:
https://gcc.gnu.org/ml/gcc-patches/2014-09/msg00452.html
https://gcc.gnu.org/ml/gcc-patches/2014-09/msg00605.html

In inline instrumentation mode compiler directly inserts code
checking shadow memory instead of __asan_load/__asan_store
calls.
This is usually faster than outline. In some workloads inline is
2 times faster than outline instrumentation.

The downside of inline instrumentation is bloated kernel's .text size:

size noasan/vmlinux
   text data bss  dec hexfilename
11759720  1566560  946176  14272456  d9c7c8  noasan/vmlinux

size outline/vmlinux
   textdata bss  dec  hexfilename
16553474  1602592  950272  19106338  1238a22 outline/vmlinux

size inline/vmlinux
   textdata bss  dec  hexfilename
32064759  1598688  946176  34609623  21019d7 inline/vmlinux

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 Makefile  |  5 +
 lib/Kconfig.kasan | 24 
 mm/kasan/report.c | 45 +
 3 files changed, 74 insertions(+)

diff --git a/Makefile b/Makefile
index 6cefe5e..fe7c534 100644
--- a/Makefile
+++ b/Makefile
@@ -773,6 +773,11 @@ KBUILD_CFLAGS += $(call cc-option, 
-fno-inline-functions-called-once)
 endif
 
 ifdef CONFIG_KASAN
+ifdef CONFIG_KASAN_INLINE
+CFLAGS_KASAN += $(call cc-option, 
-fasan-shadow-offset=$(CONFIG_KASAN_SHADOW_OFFSET)) \
+$(call cc-option, --param 
asan-instrumentation-with-call-threshold=1)
+endif
+
   ifeq ($(CFLAGS_KASAN),)
 $(warning Cannot use CONFIG_KASAN: \
  -fsanitize=kernel-address not supported by compiler)
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index faddb0e..c4ac040 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -27,4 +27,28 @@ config TEST_KASAN
  out of bounds accesses, use after free. It is usefull for testing
  kernel debugging features like kernel address sanitizer.
 
+choice
+   prompt Instrumentation type
+   depends on KASAN
+   default KASAN_INLINE if X86_64
+
+config KASAN_OUTLINE
+   bool Outline instrumentation
+   help
+ Before every memory access compiler insert function call
+ __asan_load*/__asan_store*. These functions performs check
+ of shadow memory. This is slower than inline instrumentation,
+ however it doesn't bloat size of kernel's .text section so
+ much as inline does.
+
+config KASAN_INLINE
+   bool Inline instrumentation
+   help
+ Compiler directly inserts code checking shadow memory before
+ memory accesses. This is faster than outline (in some workloads
+ it gives about x2 boost over outline instrumentation), but
+ make kernel's .text size much bigger.
+
+endchoice
+
 endif
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index c42f6ba..a9262f8 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -212,3 +212,48 @@ void kasan_report_user_access(struct access_info *info)
=\n);
spin_unlock_irqrestore(report_lock, flags);
 }
+
+#define CALL_KASAN_REPORT(__addr, __size, __is_write) \
+   struct access_info info;  \
+   info.access_addr = __addr;\
+   info.access_size = __size;\
+   info.is_write = __is_write;   \
+   info.ip = _RET_IP_;   \
+   kasan_report_error(info)
+
+#define DEFINE_ASAN_REPORT_LOAD(size) \
+void __asan_report_recover_load##size(unsigned long addr) \
+{ \
+   CALL_KASAN_REPORT(addr, size, false); \
+} \
+EXPORT_SYMBOL(__asan_report_recover_load##size)
+
+#define DEFINE_ASAN_REPORT_STORE(size) \
+void __asan_report_recover_store##size(unsigned long addr) \
+{  \
+   CALL_KASAN_REPORT(addr, size, true);   \
+}  \
+EXPORT_SYMBOL(__asan_report_recover_store##size)
+
+DEFINE_ASAN_REPORT_LOAD(1);
+DEFINE_ASAN_REPORT_LOAD(2);
+DEFINE_ASAN_REPORT_LOAD(4);
+DEFINE_ASAN_REPORT_LOAD(8);
+DEFINE_ASAN_REPORT_LOAD(16);
+DEFINE_ASAN_REPORT_STORE(1);
+DEFINE_ASAN_REPORT_STORE(2);
+DEFINE_ASAN_REPORT_STORE(4);
+DEFINE_ASAN_REPORT_STORE(8);
+DEFINE_ASAN_REPORT_STORE(16);
+
+void __asan_report_recover_load_n(unsigned long addr, size_t size)
+{
+   CALL_KASAN_REPORT(addr, size, false);
+}
+EXPORT_SYMBOL(__asan_report_recover_load_n);
+
+void __asan_report_recover_store_n(unsigned long addr, size_t size)
+{
+   CALL_KASAN_REPORT(addr, size, true);
+}
+EXPORT_SYMBOL(__asan_report_recover_store_n);
-- 
2.1.1

[PATCH v3 10/13] fs: dcache: manually unpoison dname after allocation to shut up kasan's reports

2014-09-24 Thread Andrey Ryabinin
We need to manually unpoison rounded up allocation size for dname
to avoid kasan's reports in dentry_string_cmp().
When CONFIG_DCACHE_WORD_ACCESS=y dentry_string_cmp may access
few bytes beyound requested in kmalloc() size.

dentry_string_cmp() relates on that fact that dentry allocated
using kmalloc and kmalloc internally round up allocation size.
So this is not a bug, but this makes kasan to complain about
such accesses.
To avoid such reports we mark rounded up allocation size in
shadow as accessible.

Reported-by: Dmitry Vyukov dvyu...@google.com
Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 fs/dcache.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/fs/dcache.c b/fs/dcache.c
index 8552986..7811eb2 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -38,6 +38,7 @@
 #include linux/prefetch.h
 #include linux/ratelimit.h
 #include linux/list_lru.h
+#include linux/kasan.h
 #include internal.h
 #include mount.h
 
@@ -1395,6 +1396,10 @@ struct dentry *__d_alloc(struct super_block *sb, const 
struct qstr *name)
kmem_cache_free(dentry_cache, dentry); 
return NULL;
}
+#ifdef CONFIG_DCACHE_WORD_ACCESS
+   kasan_unpoison_shadow(dname,
+   round_up(name-len + 1, sizeof(unsigned long)));
+#endif
} else  {
dname = dentry-d_iname;
}   
-- 
2.1.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 11/13] kmemleak: disable kasan instrumentation for kmemleak

2014-09-24 Thread Andrey Ryabinin
kmalloc internally round up allocation size, and kmemleak
uses rounded up size as object's size. This makes kasan
to complain while kmemleak scans memory or calculates of object's
checksum. The simplest solution here is to disable kasan.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 mm/kmemleak.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 3cda50c..9bda1b3 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -98,6 +98,7 @@
 #include asm/processor.h
 #include linux/atomic.h
 
+#include linux/kasan.h
 #include linux/kmemcheck.h
 #include linux/kmemleak.h
 #include linux/memory_hotplug.h
@@ -1113,7 +1114,10 @@ static bool update_checksum(struct kmemleak_object 
*object)
if (!kmemcheck_is_obj_initialized(object-pointer, object-size))
return false;
 
+   kasan_disable_local();
object-checksum = crc32(0, (void *)object-pointer, object-size);
+   kasan_enable_local();
+
return object-checksum != old_csum;
 }
 
@@ -1164,7 +1168,9 @@ static void scan_block(void *_start, void *_end,
  BYTES_PER_POINTER))
continue;
 
+   kasan_disable_local();
pointer = *ptr;
+   kasan_enable_local();
 
object = find_and_get_object(pointer, 1);
if (!object)
-- 
2.1.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 02/13] efi: libstub: disable KASAN for efistub

2014-09-24 Thread Andrey Ryabinin
KASan as many other options should be disabled for this stub
to prevent build failures.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 drivers/firmware/efi/libstub/Makefile | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index b14bc2b..c5533c7 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -19,6 +19,7 @@ KBUILD_CFLAGS := $(cflags-y) \
   $(call cc-option,-fno-stack-protector)
 
 GCOV_PROFILE   := n
+KASAN_SANITIZE := n
 
 lib-y  := efi-stub-helper.o
 lib-$(CONFIG_EFI_ARMSTUB)  += arm-stub.o fdt.o
-- 
2.1.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 12/13] lib: add kasan test module

2014-09-24 Thread Andrey Ryabinin
This is a test module doing varios nasty things like
out of bounds accesses, use after free. It is usefull for testing
kernel debugging features like kernel address sanitizer.

It mostly concentrates on testing of slab allocator, but we
might want to add more different stuff here in future (like
stack/global variables out of bounds accesses and so on).

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 lib/Kconfig.kasan |   8 ++
 lib/Makefile  |   1 +
 lib/test_kasan.c  | 254 ++
 3 files changed, 263 insertions(+)
 create mode 100644 lib/test_kasan.c

diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index d16b899..faddb0e 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -19,4 +19,12 @@ config KASAN_SHADOW_OFFSET
hex
default 0xdfffe900 if X86_64
 
+config TEST_KASAN
+   tristate Module for testing kasan for bug detection
+   depends on m
+   help
+ This is a test module doing varios nasty things like
+ out of bounds accesses, use after free. It is usefull for testing
+ kernel debugging features like kernel address sanitizer.
+
 endif
diff --git a/lib/Makefile b/lib/Makefile
index 84a56f7..d620d27 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_TEST_MODULE) += test_module.o
 obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
 obj-$(CONFIG_TEST_BPF) += test_bpf.o
 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
+obj-$(CONFIG_TEST_KASAN) += test_kasan.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/test_kasan.c b/lib/test_kasan.c
new file mode 100644
index 000..66a04eb
--- /dev/null
+++ b/lib/test_kasan.c
@@ -0,0 +1,254 @@
+/*
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Andrey Ryabinin a.ryabi...@samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) kasan test: %s  fmt, __func__
+
+#include linux/kernel.h
+#include linux/printk.h
+#include linux/slab.h
+#include linux/string.h
+#include linux/module.h
+
+static noinline void __init kmalloc_oob_right(void)
+{
+   char *ptr;
+   size_t size = 123;
+
+   pr_info(out-of-bounds to right\n);
+   ptr = kmalloc(size , GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 'x';
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_oob_left(void)
+{
+   char *ptr;
+   size_t size = 15;
+
+   pr_info(out-of-bounds to left\n);
+   ptr = kmalloc(size, GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   *ptr = *(ptr - 1);
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_node_oob_right(void)
+{
+   char *ptr;
+   size_t size = 4096;
+
+   pr_info(kmalloc_node(): out-of-bounds to right\n);
+   ptr = kmalloc_node(size , GFP_KERNEL, 0);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 0;
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_large_oob_rigth(void)
+{
+   char *ptr;
+   size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
+
+   pr_info(kmalloc large allocation: out-of-bounds to right\n);
+   ptr = kmalloc(size , GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 0;
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_oob_krealloc_more(void)
+{
+   char *ptr1, *ptr2;
+   size_t size1 = 17;
+   size_t size2 = 19;
+
+   pr_info(out-of-bounds after krealloc more\n);
+   ptr1 = kmalloc(size1, GFP_KERNEL);
+   ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1);
+   return;
+   }
+
+   ptr2[size2] = 'x';
+   kfree(ptr2);
+}
+
+static noinline void __init kmalloc_oob_krealloc_less(void)
+{
+   char *ptr1, *ptr2;
+   size_t size1 = 17;
+   size_t size2 = 15;
+
+   pr_info(out-of-bounds after krealloc less\n);
+   ptr1 = kmalloc(size1, GFP_KERNEL);
+   ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1);
+   return;
+   }
+   ptr2[size1] = 'x';
+   kfree(ptr2);
+}
+
+static noinline void __init kmalloc_oob_16(void)
+{
+   struct {
+   u64 words[2];
+   } *ptr1, *ptr2;
+
+   pr_info(kmalloc out-of-bounds for 16-bytes access\n);
+   ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
+   ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
+   if (!ptr1 || !ptr2

[PATCH v3 06/13] mm: slub: introduce virt_to_obj function.

2014-09-24 Thread Andrey Ryabinin
virt_to_obj takes kmem_cache address, address of slab page,
address x pointing somewhere inside slab object,
and returns address of the begging of object.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/slub_def.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index d82abd4..c75bc1d 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -110,4 +110,9 @@ static inline void sysfs_slab_remove(struct kmem_cache *s)
 }
 #endif
 
+static inline void *virt_to_obj(struct kmem_cache *s, void *slab_page, void *x)
+{
+   return x - ((x - slab_page) % s-size);
+}
+
 #endif /* _LINUX_SLUB_DEF_H */
-- 
2.1.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 09/13] mm: slub: add kernel address sanitizer support for slub allocator

2014-09-24 Thread Andrey Ryabinin
With this patch kasan will be able to catch bugs in memory allocated
by slub.
Initially all objects in newly allocated slab page, marked as free.
Later, when allocation of slub object happens, requested by caller
number of bytes marked as accessible, and the rest of the object
(including slub's metadata) marked as redzone (inaccessible).

We also mark object as accessible if ksize was called for this object.
There is some places in kernel where ksize function is called to inquire
size of really allocated area. Such callers could validly access whole
allocated memory, so it should be marked as accessible.

Code in slub.c and slab_common.c files could validly access to object's
metadata, so instrumentation for this files are disabled.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/kasan.h | 24 +
 include/linux/slab.h  | 11 --
 lib/Kconfig.kasan |  1 +
 mm/Makefile   |  3 ++
 mm/kasan/kasan.c  | 97 +++
 mm/kasan/kasan.h  |  5 +++
 mm/kasan/report.c | 27 ++
 mm/slab_common.c  |  5 ++-
 mm/slub.c | 36 +--
 9 files changed, 203 insertions(+), 6 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 9714fba..4b866fa 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -32,6 +32,17 @@ void kasan_unpoison_shadow(const void *address, size_t size);
 
 void kasan_alloc_pages(struct page *page, unsigned int order);
 void kasan_free_pages(struct page *page, unsigned int order);
+void kasan_mark_slab_padding(struct kmem_cache *s, void *object);
+
+void kasan_kmalloc_large(const void *ptr, size_t size);
+void kasan_kfree_large(const void *ptr);
+void kasan_kmalloc(struct kmem_cache *s, const void *object, size_t size);
+void kasan_krealloc(const void *object, size_t new_size);
+
+void kasan_slab_alloc(struct kmem_cache *s, void *object);
+void kasan_slab_free(struct kmem_cache *s, void *object);
+
+void kasan_free_slab_pages(struct page *page, int order);
 
 #else /* CONFIG_KASAN */
 
@@ -42,6 +53,19 @@ static inline void kasan_disable_local(void) {}
 
 static inline void kasan_alloc_pages(struct page *page, unsigned int order) {}
 static inline void kasan_free_pages(struct page *page, unsigned int order) {}
+static inline void kasan_mark_slab_padding(struct kmem_cache *s,
+   void *object) {}
+
+static inline void kasan_kmalloc_large(void *ptr, size_t size) {}
+static inline void kasan_kfree_large(const void *ptr) {}
+static inline void kasan_kmalloc(struct kmem_cache *s, const void *object,
+   size_t size) {}
+static inline void kasan_krealloc(const void *object, size_t new_size) {}
+
+static inline void kasan_slab_alloc(struct kmem_cache *s, void *object) {}
+static inline void kasan_slab_free(struct kmem_cache *s, void *object) {}
+
+static inline void kasan_free_slab_pages(struct page *page, int order) {}
 
 #endif /* CONFIG_KASAN */
 
diff --git a/include/linux/slab.h b/include/linux/slab.h
index c265bec..5f97037 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -104,6 +104,7 @@
(unsigned long)ZERO_SIZE_PTR)
 
 #include linux/kmemleak.h
+#include linux/kasan.h
 
 struct mem_cgroup;
 /*
@@ -326,7 +327,10 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
 static __always_inline void *kmem_cache_alloc_trace(struct kmem_cache *s,
gfp_t flags, size_t size)
 {
-   return kmem_cache_alloc(s, flags);
+   void *ret = kmem_cache_alloc(s, flags);
+
+   kasan_kmalloc(s, ret, size);
+   return ret;
 }
 
 static __always_inline void *
@@ -334,7 +338,10 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
  gfp_t gfpflags,
  int node, size_t size)
 {
-   return kmem_cache_alloc_node(s, gfpflags, node);
+   void *ret = kmem_cache_alloc_node(s, gfpflags, node);
+
+   kasan_kmalloc(s, ret, size);
+   return ret;
 }
 #endif /* CONFIG_TRACING */
 
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index b458a00..d16b899 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -6,6 +6,7 @@ if HAVE_ARCH_KASAN
 config KASAN
bool AddressSanitizer: runtime memory debugger
depends on !MEMORY_HOTPLUG
+   depends on SLUB_DEBUG
help
  Enables address sanitizer - runtime memory debugger,
  designed to find out-of-bounds accesses and use-after-free bugs.
diff --git a/mm/Makefile b/mm/Makefile
index 7a4b87e..c08a70f 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -2,6 +2,9 @@
 # Makefile for the linux memory manager.
 #
 
+KASAN_SANITIZE_slab_common.o := n
+KASAN_SANITIZE_slub.o := n
+
 mmu-y  := nommu.o
 mmu-$(CONFIG_MMU)  := gup.o highmem.o madvise.o memory.o mincore.o \
   mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
diff --git a/mm/kasan

[PATCH v3 08/13] mm: slub: introduce metadata_access_enable()/metadata_access_disable()

2014-09-24 Thread Andrey Ryabinin
Wrap access to object's metadata in external functions with
metadata_access_enable()/metadata_access_disable() function calls.

This hooks separates payload accesses from metadata accesses
which might be useful for different checkers (e.g. KASan).

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 mm/slub.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/mm/slub.c b/mm/slub.c
index 82282f5..9b1f75c 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -467,13 +467,23 @@ static int slub_debug;
 static char *slub_debug_slabs;
 static int disable_higher_order_debug;
 
+static inline void metadata_access_enable(void)
+{
+}
+
+static inline void metadata_access_disable(void)
+{
+}
+
 /*
  * Object debugging
  */
 static void print_section(char *text, u8 *addr, unsigned int length)
 {
+   metadata_access_enable();
print_hex_dump(KERN_ERR, text, DUMP_PREFIX_ADDRESS, 16, 1, addr,
length, 1);
+   metadata_access_disable();
 }
 
 static struct track *get_track(struct kmem_cache *s, void *object,
@@ -503,7 +513,9 @@ static void set_track(struct kmem_cache *s, void *object,
trace.max_entries = TRACK_ADDRS_COUNT;
trace.entries = p-addrs;
trace.skip = 3;
+   metadata_access_enable();
save_stack_trace(trace);
+   metadata_access_disable();
 
/* See rant in lockdep.c */
if (trace.nr_entries != 0 
@@ -677,7 +689,9 @@ static int check_bytes_and_report(struct kmem_cache *s, 
struct page *page,
u8 *fault;
u8 *end;
 
+   metadata_access_enable();
fault = memchr_inv(start, value, bytes);
+   metadata_access_disable();
if (!fault)
return 1;
 
@@ -770,7 +784,9 @@ static int slab_pad_check(struct kmem_cache *s, struct page 
*page)
if (!remainder)
return 1;
 
+   metadata_access_enable();
fault = memchr_inv(end - remainder, POISON_INUSE, remainder);
+   metadata_access_disable();
if (!fault)
return 1;
while (end  fault  end[-1] == POISON_INUSE)
-- 
2.1.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 03/13] x86_64: load_percpu_segment: read irq_stack_union.gs_base before load_segment

2014-09-24 Thread Andrey Ryabinin
Reading irq_stack_union.gs_base after load_segment creates troubles for kasan.
Compiler inserts __asan_load in between load_segment and wrmsrl. If kernel
built with stackprotector this will result in boot failure because __asan_load
has stackprotector.

To avoid this irq_stack_union.gs_base stored to temporary variable before
load_segment, so __asan_load will be called before load_segment().

There are two alternative ways to fix this:
 a) Add __attribute__((no_sanitize_address)) to load_percpu_segment(),
which tells compiler to not instrument this function. However this
will result in build failure with CONFIG_KASAN=y and 
CONFIG_OPTIMIZE_INLINING=y.

 b) Add -fno-stack-protector for mm/kasan/kasan.c

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 arch/x86/kernel/cpu/common.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index fe52f2d..51d393f 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -389,8 +389,10 @@ void load_percpu_segment(int cpu)
 #ifdef CONFIG_X86_32
loadsegment(fs, __KERNEL_PERCPU);
 #else
+   void *gs_base = per_cpu(irq_stack_union.gs_base, cpu);
+
loadsegment(gs, 0);
-   wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, 
cpu));
+   wrmsrl(MSR_GS_BASE, (unsigned long)gs_base);
 #endif
load_stack_canary_segment();
 }
-- 
2.1.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3 04/13] x86_64: add KASan support

2014-09-24 Thread Andrey Ryabinin
This patch adds arch specific code for kernel address sanitizer.

16TB of virtual addressed used for shadow memory.
It's located in range [0xd900 - 0xe900]
which belongs to vmalloc area.

At early stage we map whole shadow region with zero page.
Latter, after pages mapped to direct mapping address range
we unmap zero pages from corresponding shadow (see kasan_map_shadow())
and allocate and map a real shadow memory reusing vmemmap_populate()
function.

Also replace __pa with __pa_nodebug before shadow initialized.
__pa with CONFIG_DEBUG_VIRTUAL=y make external function call (__phys_addr)
__phys_addr is instrumented, so __asan_load could be called before
shadow area initialized.

Change-Id: I289ea19eab98e572df7f80cacec661813ea61281
Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 arch/x86/Kconfig  |  1 +
 arch/x86/boot/Makefile|  2 +
 arch/x86/boot/compressed/Makefile |  2 +
 arch/x86/include/asm/kasan.h  | 27 
 arch/x86/kernel/Makefile  |  2 +
 arch/x86/kernel/dumpstack.c   |  5 ++-
 arch/x86/kernel/head64.c  |  9 +++-
 arch/x86/kernel/head_64.S | 28 +
 arch/x86/mm/Makefile  |  3 ++
 arch/x86/mm/init.c|  3 ++
 arch/x86/mm/kasan_init_64.c   | 87 +++
 arch/x86/realmode/Makefile|  2 +-
 arch/x86/realmode/rm/Makefile |  1 +
 arch/x86/vdso/Makefile|  1 +
 lib/Kconfig.kasan |  6 +++
 15 files changed, 175 insertions(+), 4 deletions(-)
 create mode 100644 arch/x86/include/asm/kasan.h
 create mode 100644 arch/x86/mm/kasan_init_64.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 2872aaa..cec0c26 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -136,6 +136,7 @@ config X86
select HAVE_ACPI_APEI if ACPI
select HAVE_ACPI_APEI_NMI if ACPI
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
+   select HAVE_ARCH_KASAN if X86_64
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index dbe8dd2..9204cc0 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -14,6 +14,8 @@
 # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
 # The number is the same as you would ordinarily press at bootup.
 
+KASAN_SANITIZE := n
+
 SVGA_MODE  := -DSVGA_MODE=NORMAL_VGA
 
 targets:= vmlinux.bin setup.bin setup.elf bzImage
diff --git a/arch/x86/boot/compressed/Makefile 
b/arch/x86/boot/compressed/Makefile
index 7a801a3..8e5b9b3 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -4,6 +4,8 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
+KASAN_SANITIZE := n
+
 targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma 
\
vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
 
diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
new file mode 100644
index 000..056c943
--- /dev/null
+++ b/arch/x86/include/asm/kasan.h
@@ -0,0 +1,27 @@
+#ifndef _ASM_X86_KASAN_H
+#define _ASM_X86_KASAN_H
+
+#define KASAN_SHADOW_START 0xd900UL
+#define KASAN_SHADOW_END   0xe900UL
+
+#ifndef __ASSEMBLY__
+
+extern pte_t zero_pte[];
+extern pte_t zero_pmd[];
+extern pte_t zero_pud[];
+
+extern pte_t poisoned_pte[];
+extern pte_t poisoned_pmd[];
+extern pte_t poisoned_pud[];
+
+#ifdef CONFIG_KASAN
+void __init kasan_map_zero_shadow(pgd_t *pgd);
+void __init kasan_map_shadow(void);
+#else
+static inline void kasan_map_zero_shadow(pgd_t *pgd) { }
+static inline void kasan_map_shadow(void) { }
+#endif
+
+#endif
+
+#endif
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index ada2e2d..4c59d7f 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -16,6 +16,8 @@ CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
 
+KASAN_SANITIZE_head$(BITS).o := n
+
 CFLAGS_irq.o := -I$(src)/../include/asm/trace
 
 obj-y  := process_$(BITS).o signal.o entry_$(BITS).o
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index b74ebc7..cf3df1d 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -265,7 +265,10 @@ int __die(const char *str, struct pt_regs *regs, long err)
printk(SMP );
 #endif
 #ifdef CONFIG_DEBUG_PAGEALLOC
-   printk(DEBUG_PAGEALLOC);
+   printk(DEBUG_PAGEALLOC );
+#endif
+#ifdef CONFIG_KASAN
+   printk(KASAN);
 #endif
printk(\n);
if (notify_die(DIE_OOPS, str, regs, err,
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index eda1a86..b9e4e50 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -27,6 +27,7 @@
 #include asm/bios_ebda.h
 #include asm/bootparam_utils.h
 #include asm/microcode.h
+#include asm/kasan.h
 
 /*
  * Manage page tables very early on.
@@ -46,7 +47,7 @@ static void __init

[PATCH v3 07/13] mm: slub: share slab_err and object_err functions

2014-09-24 Thread Andrey Ryabinin
Remove static and add function declarations to mm/slab.h so they
could be used by kernel address sanitizer.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/slub_def.h | 4 
 mm/slub.c| 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index c75bc1d..8fed60d 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -115,4 +115,8 @@ static inline void *virt_to_obj(struct kmem_cache *s, void 
*slab_page, void *x)
return x - ((x - slab_page) % s-size);
 }
 
+void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...);
+void object_err(struct kmem_cache *s, struct page *page,
+   u8 *object, char *reason);
+
 #endif /* _LINUX_SLUB_DEF_H */
diff --git a/mm/slub.c b/mm/slub.c
index ae7b9f1..82282f5 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -629,14 +629,14 @@ static void print_trailer(struct kmem_cache *s, struct 
page *page, u8 *p)
dump_stack();
 }
 
-static void object_err(struct kmem_cache *s, struct page *page,
+void object_err(struct kmem_cache *s, struct page *page,
u8 *object, char *reason)
 {
slab_bug(s, %s, reason);
print_trailer(s, page, object);
 }
 
-static void slab_err(struct kmem_cache *s, struct page *page,
+void slab_err(struct kmem_cache *s, struct page *page,
const char *fmt, ...)
 {
va_list args;
-- 
2.1.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: fs: proc: gpf in find_entry

2014-12-23 Thread Andrey Ryabinin
2014-12-22 23:39 GMT+03:00 Eric W. Biederman ebied...@xmission.com:
 Sasha Levin sasha.le...@oracle.com writes:

 On 12/22/2014 12:52 PM, Andrey Ryabinin wrote:
 2014-12-22 18:51 GMT+03:00 Eric W. Biederman ebied...@xmission.com:
 These two instructions:
   11:   4d 85 fftest   %r15,%r15
   14:   0f 84 de 01 00 00   je 0x1f8

 Should prevent a NULL %r15 value from ever reaching the trapping
 instruction.

 If they were executed, then yes. But I think there was jump from somewhere
 to the instructions below those two.

 There is indeed a jump direct to that point, which avoids the %r15
 check.

 Where do you see that direct jump, that certainly has not been posted
 in this thread?

 There are certainly no such code paths I in the source code.  There is
 only one NULL pointer check in find_entry and it is executed every time
 the loop executes.

 So at this point all I know is some set of tools has totally destroyed
 the code and made what Sasha Levin's is testing so far from the source
 code that this is a useless bug report.

 I have no reason to even suspect this bug is actually in the upstream
 kernel.


Generated code looks correct to me (considering that it was built with
sanitizer tools).
So this looks like a real BUG to me.

AFAICT this is 'head' == NULL:

   head = ctl_node-header;
   entry = head-ctl_table[ctl_node - head-node];


 This appears to be a kind of testing that slows development and wastes
 peoples time.  Can someone give me a patch that sets the TAINTED flag
 when KASAN is loaded?


Pay attention to the first line of report:
[ 2015.960381] general protection fault:  [#1] PREEMPT SMP KASAN
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v7 11/12] lib: add kasan test module

2014-11-25 Thread Andrey Ryabinin
On 11/25/2014 02:14 PM, Dmitry Chernenkov wrote:
 I have a bit of concern about tests.
 A) they are not fully automated, there is no checking whether they
 pass or not. This is implemented in our repository using special tags
 in the log 
 (https://github.com/google/kasan/commit/33b267553e7ffe66d5207152a3294112361b75fe;
 don't mmind the TODOs, they weren't broken to begin with), and a
 parser script 
 (https://code.google.com/p/address-sanitizer/source/browse/trunk/tools/kernel_test_parse.py)
 to feed the kernel log to.
 
 B) They are not thorough enough - they don't check false negatives,

False negative means kasan's report on valid access, right? Most of the memory 
accesses
in kernel are valid, so just booting kernel should give you the best check for 
false
negatives you can ever write.

Though I agree that it's not very thorough. Currently this more demonstrational 
module,
and there are a lot of cases not covered by it.

 accesses more than 1 byte away etc.
 
 C) (more of general concern for current Kasan realiability) - when
 running multiple times, some tests are flaky, specificially oob_right
 and uaf2. The latter needs quarantine to work reliably (I know
 Konstantin is working on it). oob_right needs redzones in the
 beginning of the slabs.
 
 I know all of these may seem like long shots, but if we want a
 reliable solution (also a backportable solution), we need to at least
 consider them.
 
 Otherwise, LGTM
 


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v7 07/12] mm: slub: introduce metadata_access_enable()/metadata_access_disable()

2014-11-25 Thread Andrey Ryabinin
On 11/25/2014 03:22 PM, Dmitry Chernenkov wrote:
 LGTM
 
 Does this mean we're going to sanitize the slub code itself?)
 

Nope, to sanitize slub itself we need much more than just this.

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v7 08/12] mm: slub: add kernel address sanitizer support for slub allocator

2014-11-25 Thread Andrey Ryabinin
On 11/25/2014 03:17 PM, Dmitry Chernenkov wrote:
 FYI, when I backported Kasan to 3.14, in kasan_mark_slab_padding()
 sometimes a negative size of padding was generated.

I don't see how this could happen if pointers passed to 
kasan_mark_slab_padding() are correct.

Negative padding would mean that (object + s-size) is crossing slab page 
boundary.
This is either slub allocator bug (very unlikely), or some pointers passed to 
kasan_mark_slab_padding()
not correct.

Or maybe I'm missing something?

 This started
 working when the patch below was applied:
 
 @@ -262,12 +264,11 @@ void kasan_free_pages(struct page *page,
 unsigned int order)
  void kasan_mark_slab_padding(struct kmem_cache *s, void *object,
   struct page *page)
  {
 - unsigned long object_end = (unsigned long)object + s-size;
 - unsigned long padding_start = round_up(object_end,
 - KASAN_SHADOW_SCALE_SIZE);
 - unsigned long padding_end = (unsigned long)page_address(page) +
 - (PAGE_SIZE  compound_order(page));
 - size_t size = padding_end - padding_start;
 + unsigned long page_start = (unsigned long) page_address(page);
 + unsigned long page_end = page_start + (PAGE_SIZE  compound_order(page));
 + unsigned long padding_start = round_up(page_end - s-reserved,
 + KASAN_SHADOW_SCALE_SIZE);
 + size_t size = page_end - padding_start;
 
   kasan_poison_shadow((void *)padding_start, size, KASAN_SLAB_PADDING);
  }
 
 Also, in kasan_slab_free you poison the shadow with FREE not just the
 object space, but also redzones. This is inefficient and will mistake
 right out-of-bounds error for the next object with use-after-free.
 This is fixed here
 https://github.com/google/kasan/commit/4b3238be392ba0bc56bbc934ac545df3ff840782
 , please patch.
 

Makes sense.


 
 LGTM
 



--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v7 01/12] Add kernel address sanitizer infrastructure.

2014-11-25 Thread Andrey Ryabinin
On 11/25/2014 03:40 PM, Dmitry Chernenkov wrote:
 I'm a little concerned with how enabling/disabling works. If an
 enable() is forgotten once, it's disabled forever. If disable() is
 forgotten once, the toggle is reversed for the forseable future. MB
 check for inequality in kasan_enabled()? like current-kasan_depth =
 0 (will need a signed int for the field). Do you think it's going to
 decrease performance?

I think that check in kasan_enabled shouldn't hurt much.
But it also doesn't look very useful for me.

There are only few user of kasan_disable_local/kasan_enable_local, it's easy to 
review them.
And in future we also shouldn't have a lot of new users of those functions.

 
 LGTM
 
 

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC 1/2] compiler: use compiler to detect integer overflows

2014-11-26 Thread Andrey Ryabinin
2014-11-26 17:00 GMT+03:00 Sasha Levin sasha.le...@oracle.com:
 We've used to detect integer overflows by causing an overflow and testing the
 result. For example, to test for addition overflow we would:

 if (a + b  a)
 /* Overflow detected */

 While it works, this is actually an undefined behaviour and we're not

There is a case when such check doesn't work. If a == INT_MIN then  (a + b  a)
always will be false.


 guaranteed to have integers overflowing this way. GCC5 has introduced
 built in macros (which existed in Clang/LLVM for a while) to test for
 addition, subtraction and multiplication overflows.

 Rather than keep relying on the current behaviour of GCC, let's take
 it's olive branch and test for overflows by using the builtin
 functions.

 Changing existing code is simple and can be done using Coccinelle:

 @@ expression X; expression Y; expression Z; constant C; @@
 (
 - X + Y  Y
 + check_add_overflow(X, Y)
 |
 - X - Y  X
 + check_sub_overflow(X, Y)
 |
 - X != 0  Y  C / X
 + check_mul_overflow(X, Y, C)
 )

 Which also makes the code much more clearer, for example:

 -   if (addr + len  addr)
 +   if (check_add_overflow(addr, len))
 return -EFAULT;

 Signed-off-by: Sasha Levin sasha.le...@oracle.com
 ---

 The patch following this one is an example of how changes to existing
 code will look like. It's just one patch out of about 40 which are very
 simiar - so to avoid lots of useless mails I'll avoid sending them until
 this patch looks ok.

  include/linux/compiler-gcc5.h |8 
  include/linux/compiler.h  |   11 +++
  2 files changed, 19 insertions(+)

 diff --git a/include/linux/compiler-gcc5.h b/include/linux/compiler-gcc5.h
 index c8c5659..9d39f66 100644
 --- a/include/linux/compiler-gcc5.h
 +++ b/include/linux/compiler-gcc5.h
 @@ -63,3 +63,11 @@
  #define __HAVE_BUILTIN_BSWAP64__
  #define __HAVE_BUILTIN_BSWAP16__
  #endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP */
 +
 +__maybe_unused static unsigned int gcc_overflow_dummy;

To make you macro bellow work correctly, type of gcc_overflow_dummy
variable has to be typeof(A + B)

E.g. currently you macros will return true for 0xULL + 1ULL.

 +#define check_add_overflow(A, B) \
 +   __builtin_add_overflow((A), (B), gcc_overflow_dummy)
 +#define check_sub_overflow(A, B) \
 +   __builtin_sub_overflow((A), (B), gcc_overflow_dummy)
 +#define check_mul_overflow(A, B, C) \
 +   __builtin_mul_overflow((A), (B), gcc_overflow_dummy)
 diff --git a/include/linux/compiler.h b/include/linux/compiler.h
 index 934a834..7f15a18 100644
 --- a/include/linux/compiler.h
 +++ b/include/linux/compiler.h
 @@ -388,4 +388,15 @@ void ftrace_likely_update(struct ftrace_branch_data *f, 
 int val, int expect);
  # define __kprobes
  # define nokprobe_inline   inline
  #endif
 +
 +#ifndef check_add_overflow
 +#define check_add_overflow(A, B) (((A) + (B))  (A))
 +#endif
 +#ifndef check_sub_overflow
 +#define check_sub_overflow(A, B) (((A) - (B))  (A))
 +#endif
 +#ifndef check_mul_overflow
 +#define check_mul_overflow(A, B, C) ((A) != 0  (B)  (C) / (A))
 +#endif
 +
  #endif /* __LINUX_COMPILER_H */
 --
 1.7.10.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [RFC 2/2] kvm: eventfd: detect integer overflow using check_*_overflow

2014-11-26 Thread Andrey Ryabinin
2014-11-26 17:00 GMT+03:00 Sasha Levin sasha.le...@oracle.com:
 Detect integer overflows using safe operations rather than relying on
 undefined behaviour.


Unsigned overflow is defined.
args-addr and args-len  both unsigned, so there is no UB here.

 Signed-off-by: Sasha Levin sasha.le...@oracle.com
 ---
  virt/kvm/eventfd.c |2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
 index 148b239..2eb044f 100644
 --- a/virt/kvm/eventfd.c
 +++ b/virt/kvm/eventfd.c
 @@ -790,7 +790,7 @@ kvm_assign_ioeventfd(struct kvm *kvm, struct 
 kvm_ioeventfd *args)
 }

 /* check for range overflow */
 -   if (args-addr + args-len  args-addr)
 +   if (check_add_overflow(args-len, args-addr))
 return -EINVAL;

 /* check for extra flags that we don't understand */
 --
 1.7.10.4

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] kernel: sysctl: use 'unsigned long' type for 'zero' variable

2014-12-14 Thread Andrey Ryabinin
On 12/13/2014 11:51 PM, Manfred Spraul wrote:
 Hi,
 
 On 12/04/2014 12:25 AM, Andrew Morton wrote:
 On Wed, 03 Dec 2014 15:41:21 +0300 Andrey Ryabinin a.ryabi...@samsung.com 
 wrote:

 Use the 'unsigned long' type for 'zero' variable to fix this.
 Changing type to 'unsigned long' shouldn't affect any other users
 of this variable.

 Reported-by: Dmitry Vyukov dvyu...@google.com
 Fixes: ed4d4902ebdd (mm, hugetlb: remove hugetlb_zero and 
 hugetlb_infinity)
 Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
 ---
   kernel/sysctl.c | 2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/kernel/sysctl.c b/kernel/sysctl.c
 index 15f2511..45c45c9 100644
 --- a/kernel/sysctl.c
 +++ b/kernel/sysctl.c
 @@ -120,7 +120,7 @@ static int sixty = 60;
 static int __maybe_unused neg_one = -1;
   -static int zero;
 +static unsigned long zero;
 
 After some (useless) playing around (see the attached patch):
 
 Using
.extra1=zero,
 for proc_doulongvec_minmax doesn't make any sense:
 
  __do_proc_doulongvec_minmax() internally contains
   if ((min  val  *min) || (max  val  *max))
 continue;
 
 What about just deleting the offending .extra1=zero line?
 .extra1=NULL has the same effect as .extra1=zero.
 

Agreed, I think this should work.

 -- 
 Manfred
 
 
 

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] sched: core: fix out of bounds read in sched_init_numa()

2014-11-07 Thread Andrey Ryabinin
On latest mm + KASan patchset I've got this:

==
BUG: AddressSanitizer: out of bounds access in sched_init_smp+0x3ba/0x62c 
at addr 88006d4bee6c

=
BUG kmalloc-8 (Not tainted): kasan error

-

Disabling lock debugging due to kernel taint
INFO: Allocated in alloc_vfsmnt+0xb0/0x2c0 age=75 cpu=0 pid=0
 __slab_alloc+0x4b4/0x4f0
 __kmalloc_track_caller+0x15f/0x1e0
 kstrdup+0x44/0x90
 alloc_vfsmnt+0xb0/0x2c0
 vfs_kern_mount+0x35/0x190
 kern_mount_data+0x25/0x50
 pid_ns_prepare_proc+0x19/0x50
 alloc_pid+0x5e2/0x630
 copy_process.part.41+0xdf5/0x2aa0
 do_fork+0xf5/0x460
 kernel_thread+0x21/0x30
 rest_init+0x1e/0x90
 start_kernel+0x522/0x531
 x86_64_start_reservations+0x2a/0x2c
 x86_64_start_kernel+0x15b/0x16a
INFO: Slab 0xea0001b52f80 objects=24 used=22 fp=0x88006d4befc0 
flags=0x1004080
INFO: Object 0x88006d4bed20 @offset=3360 fp=0x88006d4bee70

Bytes b4 88006d4bed10: 00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a  

Object 88006d4bed20: 70 72 6f 63 00 6b 6b a5  
proc.kk.
Redzone 88006d4bed28: cc cc cc cc cc cc cc cc  

Padding 88006d4bee68: 5a 5a 5a 5a 5a 5a 5a 5a  

CPU: 0 PID: 1 Comm: swapper/0 Tainted: GB  3.18.0-rc3-mm1+ #108
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 
rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
 88006d4be000  88006d4bed20 88006c86fd18
 81cd0a59 0058 88006d404240 88006c86fd48
 811fa3a8 88006d404240 ea0001b52f80 88006d4bed20
Call Trace:
dump_stack (lib/dump_stack.c:52)
print_trailer (mm/slub.c:645)
object_err (mm/slub.c:652)
? sched_init_smp (kernel/sched/core.c:6552 kernel/sched/core.c:7063)
kasan_report_error (mm/kasan/report.c:102 mm/kasan/report.c:178)
? kasan_poison_shadow (mm/kasan/kasan.c:48)
? kasan_unpoison_shadow (mm/kasan/kasan.c:54)
? kasan_poison_shadow (mm/kasan/kasan.c:48)
? kasan_kmalloc (mm/kasan/kasan.c:311)
__asan_load4 (mm/kasan/kasan.c:371)
? sched_init_smp (kernel/sched/core.c:6552 kernel/sched/core.c:7063)
sched_init_smp (kernel/sched/core.c:6552 kernel/sched/core.c:7063)
kernel_init_freeable (init/main.c:869 init/main.c:997)
? finish_task_switch (kernel/sched/sched.h:1036 kernel/sched/core.c:2248)
? rest_init (init/main.c:924)
kernel_init (init/main.c:929)
? rest_init (init/main.c:924)
ret_from_fork (arch/x86/kernel/entry_64.S:348)
? rest_init (init/main.c:924)
Read of size 4 by task swapper/0:
Memory state around the buggy address:
 88006d4beb80: fc fc fc fc fc fc fc fc fc fc 00 fc fc fc fc fc
 88006d4bec00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 88006d4bec80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 88006d4bed00: fc fc fc fc 00 fc fc fc fc fc fc fc fc fc fc fc
 88006d4bed80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
88006d4bee00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc 04 fc
  ^
 88006d4bee80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 88006d4bef00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
 88006d4bef80: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
 88006d4bf000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 88006d4bf080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==

Zero 'level' (e.g. on non-NUMA system) causing out of bounds access
in this line:

 sched_max_numa_distance = sched_domains_numa_distance[level - 1];

Fix this by exiting from sched_init_numa() earlier.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
Fixes: 9942f79ba (sched/numa: Export info needed for NUMA balancing on complex 
topologies)
---
   Another option would be to not call sched_init_numa() if nr_node_ids == 1,
   but I'm not sure that there is no such configuration where nr_node_ids  1
   and node_distance(i, j) = node_distance(0, 0) for any i and j.

 kernel/sched/core.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 72d9d92..932c7a9 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6470,6 +6470,10 @@ static void sched_init_numa(void)
if (!sched_debug())
break;
}
+
+   if (!level)
+   return;
+
/*
 * 'level' contains the number of unique distances, excluding

[PATCH] security: smack: fix out-of-bounds access in smk_parse_smack()

2014-11-08 Thread Andrey Ryabinin
From: Andrey Ryabinin a.ryabi...@samsung.com

Setting smack label on file (e.g. 'attr -S -s SMACK64 -V test test')
triggered following spew on the kernel with KASan applied:
==
BUG: AddressSanitizer: out of bounds access in strncpy+0x28/0x60 at addr 
8800059ad064

=
BUG kmalloc-8 (Not tainted): kasan error

-

Disabling lock debugging due to kernel taint
INFO: Slab 0xea166b40 objects=128 used=7 fp=0x8800059ad080 
flags=0x4080
INFO: Object 0x8800059ad060 @offset=96 fp=0x8800059ad080

Bytes b4 8800059ad050: a0 df 9a 05 00 88 ff ff 5a 5a 5a 5a 5a 5a 5a 5a  

Object 8800059ad060: 74 65 73 74 6b 6b 6b a5  
testkkk.
Redzone 8800059ad068: cc cc cc cc cc cc cc cc  

Padding 8800059ad078: 5a 5a 5a 5a 5a 5a 5a 5a  

CPU: 0 PID: 528 Comm: attr Tainted: GB  3.18.0-rc1-mm1+ #5
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  8800059ad064 81534cf2 880005a5bc40
 8112fe1a 00010086 000f059ad060 880006000f90
 0296 ea166b40 8107ca97 880005891060
Call Trace:
? dump_stack (lib/dump_stack.c:52)
? kasan_report_error (mm/kasan/report.c:102 mm/kasan/report.c:178)
? preempt_count_sub (kernel/sched/core.c:2651)
? __asan_load1 (mm/kasan/kasan.h:50 mm/kasan/kasan.c:248 
mm/kasan/kasan.c:358)
? strncpy (lib/string.c:121)
? strncpy (lib/string.c:121)
? smk_parse_smack (security/smack/smack_access.c:457)
? setxattr (fs/xattr.c:343)
? smk_import_entry (security/smack/smack_access.c:514)
? smack_inode_setxattr (security/smack/smack_lsm.c:1093 (discriminator 1))
? security_inode_setxattr (security/security.c:602)
? vfs_setxattr (fs/xattr.c:134)
? setxattr (fs/xattr.c:343)
? setxattr (fs/xattr.c:360)
? get_parent_ip (kernel/sched/core.c:2606)
? preempt_count_sub (kernel/sched/core.c:2651)
? __percpu_counter_add (arch/x86/include/asm/preempt.h:98 
lib/percpu_counter.c:90)
? get_parent_ip (kernel/sched/core.c:2606)
? preempt_count_sub (kernel/sched/core.c:2651)
? __mnt_want_write (arch/x86/include/asm/preempt.h:98 fs/namespace.c:359)
? path_setxattr (fs/xattr.c:380)
? SyS_lsetxattr (fs/xattr.c:397)
? system_call_fastpath (arch/x86/kernel/entry_64.S:423)
Read of size 1 by task attr:
Memory state around the buggy address:
 8800059ace80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 8800059acf00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 8800059acf80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
8800059ad000: 00 fc fc fc 00 fc fc fc 05 fc fc fc 04 fc fc fc
   ^
 8800059ad080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 8800059ad100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
 8800059ad180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==

strncpy() copies one byte more than the source string has.
Fix this by passing the correct length to strncpy().

Now we can remove initialization of the last byte in 'smack' string
because kzalloc() already did this for us.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 security/smack/smack_access.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 5b970ff..ad75ddf 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -452,10 +452,9 @@ char *smk_parse_smack(const char *string, int len)
return NULL;
 
smack = kzalloc(i + 1, GFP_KERNEL);
-   if (smack != NULL) {
-   strncpy(smack, string, i + 1);
-   smack[i] = '\0';
-   }
+   if (smack != NULL)
+   strncpy(smack, string, i);
+
return smack;
 }
 
-- 
1.8.5.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 1/2] kernel: printk: specify alignment for struct printk_log

2014-11-14 Thread Andrey Ryabinin
2014-11-14 20:22 GMT+03:00 Joe Perches j...@perches.com:
 On Fri, 2014-11-14 at 15:50 +0300, Andrey Ryabinin wrote:
 On architectures that have support for efficient unaligned access
 struct printk_log has 4-byte alignment.
 Specify alignment attribute in type declaration.

 The whole point of this patch is to fix deadlock which happening
 when UBSan detects unaligned access in printk() thus UBSan recursively
 calls printk() with logbuf_lock held by top printk() call.
 []
 diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
 []
 @@ -223,7 +223,11 @@ struct printk_log {
   u8 facility;/* syslog facility */
   u8 flags:5; /* internal record flags */
   u8 level:3; /* syslog level */
 -};
 +}
 +#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
 +__packed __aligned(4)
 +#endif

 Why is adding __packed useful or __aligned(4) useful?


On x86_64, from compiler's point of view, 'struct printk_log' should
be 8-byte aligned.
But it stored in log buffer only with 4-byte alignment (LOG_ALIGN define).

This inconsistency makes UBSAN unhappy.  UBSAN uses printk to report errors,
thus any access to 4-byte aligned 'struct printk_log' causing
recursive printk() call from ubsan handler.
And if logbuf_lock was taken we end up with deadlock.
Specifying alignment removes this inconsistency. Now compiler knows
that 'printk_log'
actually aligned on 4, and it makes UBSAN happy and silent.

Attribute 'aligned' without attribute 'packed' can only increase alignment.
So __packed is used here because we need to decrease alignment from 8 to 4.


 The struct is naturally aligned on u64 and should be

Not, always. On 32-bits it will be 4-bytes aligned, on 64-bits - 8-bytes aligned

 the size of 2 u64s.

 struct printk_log {
 u64 ts_nsec;/* timestamp in nanoseconds */
 u16 len;/* length of entire record */
 u16 text_len;   /* length of text buffer */
 u16 dict_len;   /* length of dictionary buffer */
 u8 facility;/* syslog facility */
 u8 flags:5; /* internal record flags */
 u8 level:3; /* syslog level */
 };

 Is there any case when it's not sizeof(u64) * 2?


I think no. As I said __packed used for decreasing alignment only.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [BUG] index is out of range for nfnl_group2type[]

2014-11-17 Thread Andrey Ryabinin
On 11/14/2014 08:44 PM, Pablo Neira Ayuso wrote:
 On Thu, Nov 13, 2014 at 12:00:43PM +0300, Andrey Ryabinin wrote:
 FYI I've spotted this:

 [  180.202810] 
 
 [  180.203600] UBSan: Undefined behaviour in 
 ../net/netfilter/nfnetlink.c:467:28
 [  180.204249] index 9 is out of range for type 'int [9]'
 [  180.204697] CPU: 0 PID: 1771 Comm: trinity-main Not tainted 
 3.18.0-rc4-mm1+ #122
 [  180.205365] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 
 rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
 [  180.206498]  0018  0009 
 88007bdf7da8
 [  180.207220]  82b0ef5f 0092 845ae2e0 
 88007bdf7db8
 [  180.207887]  8199e489 88007bdf7e18 8199ea22 
 0039
 [  180.208639] Call Trace:
 [  180.208857] dump_stack (lib/dump_stack.c:52)
 [  180.209370] ubsan_epilogue (lib/ubsan.c:174)
 [  180.209849] __ubsan_handle_out_of_bounds (lib/ubsan.c:400)
 [  180.210512] nfnetlink_bind (net/netfilter/nfnetlink.c:467)
 [  180.210986] netlink_bind (net/netlink/af_netlink.c:1483)
 [  180.211495] SYSC_bind (net/socket.c:1541)
 [  180.211940] ? security_socket_setsockopt (security/security.c:1208)
 [  180.212541] ? SyS_setsockopt (net/socket.c:1920 net/socket.c:1900)
 [  180.213057] ? SyS_write (fs/read_write.c:276 fs/read_write.c:588 
 fs/read_write.c:577)
 [  180.213506] SyS_bind (net/socket.c:1527)
 [  180.213919] system_call_fastpath (arch/x86/kernel/entry_64.S:423)
 [  180.214479] 
 
 
 Thanks for reporting. I think the attached patch fixes this problem.
 

Yep, It's gone away after applying your patch.

Thanks,
Andrey.

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Out-of-bounds access in nfnetlink_bind

2014-12-02 Thread Andrey Ryabinin
2014-12-02 10:53 GMT+03:00 Dmitry Vyukov dvyu...@google.com:
 Hi,

 I am working on Kernel AddressSanitizer, a fast memory error detector
 for kernel:
 https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel

 Here is an error report that I got while running trinity:

 ==
 BUG: AddressSanitizer: out of bounds access in
 nfnetlink_bind+0xbf/0xe0 at addr 82eef710
 Read of size 4 by task trinity-main/2533
 Out-of-bounds access to the global variable 'nfnl_group2type'
 [82eef6e0-82eef704) defined at
 net/netfilter/nfnetlink.c:43:18
 CPU: 0 PID: 2533 Comm: trinity-main Not tainted 3.18.0-rc1+ #44
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  835173e8 8800b989fd18 82a3d66f 0007
  8800b989fdc0 8800b989fda8 813a3826 0012
   00010018 0296 8800b989fd88
 Call Trace:
  [813a39c1] __asan_report_load4_noabort+0x41/0x50
 mm/kasan/report.c:236
  [824769cf] nfnetlink_bind+0xbf/0xe0 net/netfilter/nfnetlink.c:467
  [82469b71] netlink_bind+0x221/0x7e0 net/netlink/af_netlink.c:1472
  [8238bf77] SYSC_bind+0x117/0x170 net/socket.c:1541
  [8238dc29] SyS_bind+0x9/0x10 net/socket.c:1527
  [82a522a9] system_call_fastpath+0x12/0x17
 arch/x86/kernel/entry_64.S:422
 Memory state around the buggy address:
  82eef480: 00 00 00 00 00 00 00 00 00 00 00 00 00 f8 f8 f8
  82eef500: f8 f8 f8 f8 00 00 00 00 f8 f8 f8 f8 00 00 00 01
  82eef580: f8 f8 f8 f8 00 00 00 00 05 f8 f8 f8 f8 f8 f8 f8
  82eef600: 00 00 04 f8 f8 f8 f8 f8 00 00 f8 f8 f8 f8 f8 f8
  82eef680: 00 00 00 00 07 f8 f8 f8 f8 f8 f8 f8 00 00 00 00
82eef700: 04 f8 f8 f8 f8 f8 f8 f8 00 06 f8 f8 f8 f8 f8 f8
  ^
  82eef780: 00 00 00 05 f8 f8 f8 f8 00 00 00 00 00 f8 f8 f8
  82eef800: f8 f8 f8 f8 00 00 00 00 02 f8 f8 f8 f8 f8 f8 f8
  82eef880: 00 00 00 00 06 f8 f8 f8 f8 f8 f8 f8 00 00 00 04
  82eef900: f8 f8 f8 f8 00 00 00 00 00 04 f8 f8 f8 f8 f8 f8
  82eef980: 00 00 00 07 f8 f8 f8 f8 00 00 00 06 f8 f8 f8 f8
 ==

 My source is on revision f114040e3ea6e07372334ade75d1ee0

 As far as I see netlink_bind just calls nfnetlink_bind with whatever
 groups user has requested; nfnetlink_bind in turn do not do any checks
 before indexing the global nfnl_group2type array with the group.

I've reported this few weeks ago: https://lkml.org/lkml/2014/11/13/65
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Out-of-bounds access in __do_proc_doulongvec_minmax

2014-12-03 Thread Andrey Ryabinin
On 12/03/2014 12:04 PM, Dmitry Vyukov wrote:
 Hi,
 
 I am working on AddressSanitizer, a fast memory error detector for kernel:
 https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel
 
 Here is a bug report that I've got while running trinity:
 
 ==
 BUG: AddressSanitizer: out of bounds access in
 __do_proc_doulongvec_minmax+0x8a0/0x9a0 at addr 83980960
 Read of size 8 by task trinity-c14/6919
 Out-of-bounds access to the global variable 'zero'
 [83980960-83980964) defined at ipc/ipc_sysctl.c:158

This line seems incorrect. Judging from the backtrace below variable 'zero' is
defined in kernel/sysctl.c:123


 
 CPU: 1 PID: 6919 Comm: trinity-c14 Not tainted 3.18.0-rc1+ #50
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  0001 8800b68cf418 82c2d3ae 
  8800b68cf4c0 8800b68cf4a8 813eaa81 000c
  88010b003600 8800b68cf479 0296 
 Call Trace:
  [813ead71] __asan_report_load8_noabort+0x51/0x70
 mm/kasan/report.c:248
  [810cc3e0] __do_proc_doulongvec_minmax+0x8a0/0x9a0
 kernel/sysctl.c:2284
  [ inlined] proc_doulongvec_minmax+0x50/0x80
 do_proc_doulongvec_minmax kernel/sysctl.c:2322
  [810cc530] proc_doulongvec_minmax+0x50/0x80 kernel/sysctl.c:2345
  [813c9e5a] hugetlb_sysctl_handler_common+0x12a/0x3c0
 mm/hugetlb.c:2270
  [813cb45c] hugetlb_mempolicy_sysctl_handler+0x1c/0x20
 mm/hugetlb.c:2293
  [8153e6e9] proc_sys_call_handler+0x179/0x1f0
 fs/proc/proc_sysctl.c:506
  [8153e76f] proc_sys_write+0xf/0x20 fs/proc/proc_sysctl.c:524
  [813f1563] __kernel_write+0x123/0x440 fs/read_write.c:502
  [8147ebaa] write_pipe_buf+0x14a/0x1d0 fs/splice.c:1074
  [ inlined] __splice_from_pipe+0x22e/0x6f0
 splice_from_pipe_feed fs/splice.c:769
  [8147dbde] __splice_from_pipe+0x22e/0x6f0 fs/splice.c:886
  [81483211] splice_from_pipe+0xc1/0x110 fs/splice.c:921
  [81483298] default_file_splice_write+0x18/0x50 fs/splice.c:1086
  [ inlined] direct_splice_actor+0x104/0x1c0 do_splice_from
 fs/splice.c:1128
  [8147cfc4] direct_splice_actor+0x104/0x1c0 fs/splice.c:1284
  [8147e5ba] splice_direct_to_actor+0x24a/0x6f0 fs/splice.c:1237
  [81483424] do_splice_direct+0x154/0x270 fs/splice.c:1327
  [813f3bfb] do_sendfile+0x5fb/0x1260 fs/read_write.c:1266
  [ inlined] SyS_sendfile64+0xfa/0x100 SYSC_sendfile64
 fs/read_write.c:1327
  [813f6bea] SyS_sendfile64+0xfa/0x100 fs/read_write.c:1313
  [82c464f9] ia32_do_call+0x13/0x13 arch/x86/ia32/ia32entry.S:444
 Memory state around the buggy address:
  83980680: 04 f8 f8 f8 f8 f8 f8 f8 02 f8 f8 f8 f8 f8 f8 f8
  83980700: 00 f8 f8 f8 f8 f8 f8 f8 00 f8 f8 f8 f8 f8 f8 f8
  83980780: 00 00 00 00 00 00 00 00 f8 f8 f8 f8 00 00 00 00
  83980800: 00 00 00 00 00 00 00 00 f8 f8 f8 f8 04 f8 f8 f8
  83980880: f8 f8 f8 f8 04 f8 f8 f8 f8 f8 f8 f8 04 f8 f8 f8
 83980900: f8 f8 f8 f8 04 f8 f8 f8 f8 f8 f8 f8 04 f8 f8 f8
^
  83980980: f8 f8 f8 f8 00 00 00 00 f8 f8 f8 f8 00 00 00 00
  83980a00: 02 f8 f8 f8 f8 f8 f8 f8 00 00 00 00 00 00 00 00
  83980a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  83980b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  83980b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ==
 
 The core creates ctl_table as:
 
 static int zero;
 static int one = 1;
 static int int_max = INT_MAX;
 static struct ctl_table ipc_kern_table[] = {
 {
 ...
   {
 .procname = shm_rmid_forced,
 .data = init_ipc_ns.shm_rmid_forced,
 .maxlen = sizeof(init_ipc_ns.shm_rmid_forced),
 .mode = 0644,
 .proc_handler = proc_ipc_dointvec_minmax_orphans,
 .extra1 = zero,
 .extra2 = one,
   },
 
 But later extra1/2 are casted to *unsigned long**:
 
 static int __do_proc_doulongvec_minmax(void *data, struct ctl_table
 *table, int write, ...
 {
   ...
   min = (unsigned long *) table-extra1;
   max = (unsigned long *) table-extra2;
 
 This leads to bogus bounds check for the sysctl value.
 
 The bug is added in commit:
 
 commit 9eefe520c814f6f62c5d36a2ddcd3fb99dfdb30e
 Author: Nadia Derbey nadia.der...@bull.net
 Date:   Fri Jul 25 01:48:08 2008 -0700
 
 Later zero and one were used in a bunch of other ctl_table's.
 

I think you are blaming wrong commit. This bug was introduced by
ed4d4902ebdd7ca8b5a51daaf6bebf4b172895cc (mm, hugetlb: remove hugetlb_zero and 
hugetlb_infinity)

We have two options to fix this. Reintroduce back hugetlb_zero or make 'zero' 
unsigned long instead.
I would prefer the latter, changing type to 'unsigned long' shouldn't harm any 
other users of this 

[PATCH] kernel: sysctl: use 'unsigned long' type for 'zero' variable

2014-12-03 Thread Andrey Ryabinin

Commit ed4d4902ebdd (mm, hugetlb: remove hugetlb_zero and hugetlb_infinity) 
replaced
'unsigned long hugetlb_zero' with 'int zero' leading to out-of-bounds access
in proc_doulongvec_minmax():

==
BUG: AddressSanitizer: out of bounds access in
__do_proc_doulongvec_minmax+0x8a0/0x9a0 at addr 83980960
Read of size 8 by task trinity-c14/6919
Out-of-bounds access to the global variable 'zero'
[83980960-83980964) defined at ipc/ipc_sysctl.c:158

CPU: 1 PID: 6919 Comm: trinity-c14 Not tainted 3.18.0-rc1+ #50
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 
01/01/2011
 0001 8800b68cf418 82c2d3ae 
 8800b68cf4c0 8800b68cf4a8 813eaa81 000c
 88010b003600 8800b68cf479 0296 
Call Trace:
 [813ead71] __asan_report_load8_noabort+0x51/0x70
mm/kasan/report.c:248
 [810cc3e0] __do_proc_doulongvec_minmax+0x8a0/0x9a0
kernel/sysctl.c:2284
 [ inlined] proc_doulongvec_minmax+0x50/0x80
do_proc_doulongvec_minmax kernel/sysctl.c:2322
 [810cc530] proc_doulongvec_minmax+0x50/0x80 
kernel/sysctl.c:2345
 [813c9e5a] hugetlb_sysctl_handler_common+0x12a/0x3c0
mm/hugetlb.c:2270
 [813cb45c] hugetlb_mempolicy_sysctl_handler+0x1c/0x20
mm/hugetlb.c:2293
 [8153e6e9] proc_sys_call_handler+0x179/0x1f0
fs/proc/proc_sysctl.c:506
 [8153e76f] proc_sys_write+0xf/0x20 fs/proc/proc_sysctl.c:524
 [813f1563] __kernel_write+0x123/0x440 fs/read_write.c:502
 [8147ebaa] write_pipe_buf+0x14a/0x1d0 fs/splice.c:1074
 [ inlined] __splice_from_pipe+0x22e/0x6f0
splice_from_pipe_feed fs/splice.c:769
 [8147dbde] __splice_from_pipe+0x22e/0x6f0 fs/splice.c:886
 [81483211] splice_from_pipe+0xc1/0x110 fs/splice.c:921
 [81483298] default_file_splice_write+0x18/0x50 
fs/splice.c:1086
 [ inlined] direct_splice_actor+0x104/0x1c0 do_splice_from
fs/splice.c:1128
 [8147cfc4] direct_splice_actor+0x104/0x1c0 fs/splice.c:1284
 [8147e5ba] splice_direct_to_actor+0x24a/0x6f0 
fs/splice.c:1237
 [81483424] do_splice_direct+0x154/0x270 fs/splice.c:1327
 [813f3bfb] do_sendfile+0x5fb/0x1260 fs/read_write.c:1266
 [ inlined] SyS_sendfile64+0xfa/0x100 SYSC_sendfile64
fs/read_write.c:1327
 [813f6bea] SyS_sendfile64+0xfa/0x100 fs/read_write.c:1313
 [82c464f9] ia32_do_call+0x13/0x13 
arch/x86/ia32/ia32entry.S:444
Memory state around the buggy address:
 83980680: 04 f8 f8 f8 f8 f8 f8 f8 02 f8 f8 f8 f8 f8 f8 f8
 83980700: 00 f8 f8 f8 f8 f8 f8 f8 00 f8 f8 f8 f8 f8 f8 f8
 83980780: 00 00 00 00 00 00 00 00 f8 f8 f8 f8 00 00 00 00
 83980800: 00 00 00 00 00 00 00 00 f8 f8 f8 f8 04 f8 f8 f8
 83980880: f8 f8 f8 f8 04 f8 f8 f8 f8 f8 f8 f8 04 f8 f8 f8
83980900: f8 f8 f8 f8 04 f8 f8 f8 f8 f8 f8 f8 04 f8 f8 f8
   ^
 83980980: f8 f8 f8 f8 00 00 00 00 f8 f8 f8 f8 00 00 00 00
 83980a00: 02 f8 f8 f8 f8 f8 f8 f8 00 00 00 00 00 00 00 00
 83980a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 83980b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 83980b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
==

Use the 'unsigned long' type for 'zero' variable to fix this.
Changing type to 'unsigned long' shouldn't affect any other users
of this variable.

Reported-by: Dmitry Vyukov dvyu...@google.com
Fixes: ed4d4902ebdd (mm, hugetlb: remove hugetlb_zero and hugetlb_infinity)
Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 kernel/sysctl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 15f2511..45c45c9 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -120,7 +120,7 @@ static int sixty = 60;
 
 static int __maybe_unused neg_one = -1;
 
-static int zero;
+static unsigned long zero;
 static int __maybe_unused one = 1;
 static int __maybe_unused two = 2;
 static int __maybe_unused four = 4;
-- 
2.2.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: Out-of-bounds access in __do_proc_doulongvec_minmax

2014-12-03 Thread Andrey Ryabinin
On 12/03/2014 04:27 PM, Dmitry Vyukov wrote:
 On Wed, Dec 3, 2014 at 3:39 PM, Andrey Ryabinin a.ryabi...@samsung.com 
 wrote:
 On 12/03/2014 12:04 PM, Dmitry Vyukov wrote:
 Hi,

 I am working on AddressSanitizer, a fast memory error detector for kernel:
 https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel

 Here is a bug report that I've got while running trinity:

 ==
 BUG: AddressSanitizer: out of bounds access in
 __do_proc_doulongvec_minmax+0x8a0/0x9a0 at addr 83980960
 Read of size 8 by task trinity-c14/6919
 Out-of-bounds access to the global variable 'zero'
 [83980960-83980964) defined at ipc/ipc_sysctl.c:158

 This line seems incorrect. Judging from the backtrace below variable 'zero' 
 is
 defined in kernel/sysctl.c:123



 CPU: 1 PID: 6919 Comm: trinity-c14 Not tainted 3.18.0-rc1+ #50
 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
  0001 8800b68cf418 82c2d3ae 
  8800b68cf4c0 8800b68cf4a8 813eaa81 000c
  88010b003600 8800b68cf479 0296 
 Call Trace:
  [813ead71] __asan_report_load8_noabort+0x51/0x70
 mm/kasan/report.c:248
  [810cc3e0] __do_proc_doulongvec_minmax+0x8a0/0x9a0
 kernel/sysctl.c:2284
  [ inlined] proc_doulongvec_minmax+0x50/0x80
 do_proc_doulongvec_minmax kernel/sysctl.c:2322
  [810cc530] proc_doulongvec_minmax+0x50/0x80 kernel/sysctl.c:2345
  [813c9e5a] hugetlb_sysctl_handler_common+0x12a/0x3c0
 mm/hugetlb.c:2270
  [813cb45c] hugetlb_mempolicy_sysctl_handler+0x1c/0x20
 mm/hugetlb.c:2293
  [8153e6e9] proc_sys_call_handler+0x179/0x1f0
 fs/proc/proc_sysctl.c:506
  [8153e76f] proc_sys_write+0xf/0x20 fs/proc/proc_sysctl.c:524
  [813f1563] __kernel_write+0x123/0x440 fs/read_write.c:502
  [8147ebaa] write_pipe_buf+0x14a/0x1d0 fs/splice.c:1074
  [ inlined] __splice_from_pipe+0x22e/0x6f0
 splice_from_pipe_feed fs/splice.c:769
  [8147dbde] __splice_from_pipe+0x22e/0x6f0 fs/splice.c:886
  [81483211] splice_from_pipe+0xc1/0x110 fs/splice.c:921
  [81483298] default_file_splice_write+0x18/0x50 fs/splice.c:1086
  [ inlined] direct_splice_actor+0x104/0x1c0 do_splice_from
 fs/splice.c:1128
  [8147cfc4] direct_splice_actor+0x104/0x1c0 fs/splice.c:1284
  [8147e5ba] splice_direct_to_actor+0x24a/0x6f0 fs/splice.c:1237
  [81483424] do_splice_direct+0x154/0x270 fs/splice.c:1327
  [813f3bfb] do_sendfile+0x5fb/0x1260 fs/read_write.c:1266
  [ inlined] SyS_sendfile64+0xfa/0x100 SYSC_sendfile64
 fs/read_write.c:1327
  [813f6bea] SyS_sendfile64+0xfa/0x100 fs/read_write.c:1313
  [82c464f9] ia32_do_call+0x13/0x13 arch/x86/ia32/ia32entry.S:444
 Memory state around the buggy address:
  83980680: 04 f8 f8 f8 f8 f8 f8 f8 02 f8 f8 f8 f8 f8 f8 f8
  83980700: 00 f8 f8 f8 f8 f8 f8 f8 00 f8 f8 f8 f8 f8 f8 f8
  83980780: 00 00 00 00 00 00 00 00 f8 f8 f8 f8 00 00 00 00
  83980800: 00 00 00 00 00 00 00 00 f8 f8 f8 f8 04 f8 f8 f8
  83980880: f8 f8 f8 f8 04 f8 f8 f8 f8 f8 f8 f8 04 f8 f8 f8
 83980900: f8 f8 f8 f8 04 f8 f8 f8 f8 f8 f8 f8 04 f8 f8 f8
^
  83980980: f8 f8 f8 f8 00 00 00 00 f8 f8 f8 f8 00 00 00 00
  83980a00: 02 f8 f8 f8 f8 f8 f8 f8 00 00 00 00 00 00 00 00
  83980a80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  83980b00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  83980b80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 ==

 The core creates ctl_table as:

 static int zero;
 static int one = 1;
 static int int_max = INT_MAX;
 static struct ctl_table ipc_kern_table[] = {
 {
 ...
   {
 .procname = shm_rmid_forced,
 .data = init_ipc_ns.shm_rmid_forced,
 .maxlen = sizeof(init_ipc_ns.shm_rmid_forced),
 .mode = 0644,
 .proc_handler = proc_ipc_dointvec_minmax_orphans,
 .extra1 = zero,
 .extra2 = one,
   },

 But later extra1/2 are casted to *unsigned long**:

 static int __do_proc_doulongvec_minmax(void *data, struct ctl_table
 *table, int write, ...
 {
   ...
   min = (unsigned long *) table-extra1;
   max = (unsigned long *) table-extra2;

 This leads to bogus bounds check for the sysctl value.

 The bug is added in commit:

 commit 9eefe520c814f6f62c5d36a2ddcd3fb99dfdb30e
 Author: Nadia Derbey nadia.der...@bull.net
 Date:   Fri Jul 25 01:48:08 2008 -0700

 Later zero and one were used in a bunch of other ctl_table's.


 I think you are blaming wrong commit. This bug was introduced by
 ed4d4902ebdd7ca8b5a51daaf6bebf4b172895cc (mm, hugetlb: remove hugetlb_zero 
 and hugetlb_infinity)

 We have two options to fix this. Reintroduce back hugetlb_zero or make 
 'zero

Re: fs: proc: gpf in find_entry

2014-12-22 Thread Andrey Ryabinin
2014-12-22 17:37 GMT+03:00 Sasha Levin sasha.le...@oracle.com:
 Hi all,

 While fuzzing with trinity inside a KVM tools guest running the latest -next
 kernel, I've stumbled on the following spew:

 [ 2015.960381] general protection fault:  [#1] PREEMPT SMP KASAN

Actually this is NULL-ptr dereference. Since you are using kasan with
inline instrumentation
NULL-ptr deref transforms into GPF.


 [ 2015.970534] RAX:  RBX: 8803a960 RCX: 
 0073
 [ 2015.970534] RDX: 110101c8f3c4 RSI:  RDI: 
 88080e479e20
 [ 2015.970534] RBP: 88080e477a28 R08: 0066 R09: 
 0073
 [ 2015.970534] R10: da0017d55630 R11: dfffe900 R12: 
 88005fc644b8
 [ 2015.970534] R13: dfffe900 R14: 92464884 R15: 
 

[...]

 All code
 
0:   e8 03 42 80 3c  callq  0x3c804208
5:   28 00   sub%al,(%rax)
7:   0f 85 ff 01 00 00   jne0x20c
d:   4c 8b 7b 18 mov0x18(%rbx),%r15
   11:   4d 85 fftest   %r15,%r15
   14:   0f 84 de 01 00 00   je 0x1f8
   1a:   41 f6 c7 07 test   $0x7,%r15b
   1e:   0f 85 d4 01 00 00   jne0x1f8
   24:   4c 89 f8mov%r15,%rax
   27:   48 c1 e8 03 shr$0x3,%rax
   2b:*  42 80 3c 28 00  cmpb   $0x0,(%rax,%r13,1)   -- 
 trapping instruction

Three commands above are result of KASAN's instrumentation.
They check shadow for address in %r15:
 if (*((%r15  3) + kasan_shadow_offset)


   30:   0f 85 b5 01 00 00   jne0x1eb
   36:   4d 8b 37mov(%r15),%r14

And here is memory access, that KASAN checking.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: fs: proc: gpf in find_entry

2014-12-22 Thread Andrey Ryabinin
2014-12-22 18:51 GMT+03:00 Eric W. Biederman ebied...@xmission.com:
 Andrey Ryabinin ryabinin@gmail.com writes:

 2014-12-22 17:37 GMT+03:00 Sasha Levin sasha.le...@oracle.com:
 Hi all,

 While fuzzing with trinity inside a KVM tools guest running the latest -next
 kernel, I've stumbled on the following spew:

 [ 2015.960381] general protection fault:  [#1] PREEMPT SMP KASAN

 Actually this is NULL-ptr dereference. Since you are using kasan with
 inline instrumentation
 NULL-ptr deref transforms into GPF.


 [ 2015.970534] RAX:  RBX: 8803a960 RCX: 
 0073
 [ 2015.970534] RDX: 110101c8f3c4 RSI:  RDI: 
 88080e479e20
 [ 2015.970534] RBP: 88080e477a28 R08: 0066 R09: 
 0073
 [ 2015.970534] R10: da0017d55630 R11: dfffe900 R12: 
 88005fc644b8
 [ 2015.970534] R13: dfffe900 R14: 92464884 R15: 
 

 [...]

 All code
 
0:   e8 03 42 80 3c  callq  0x3c804208
5:   28 00   sub%al,(%rax)
7:   0f 85 ff 01 00 00   jne0x20c
d:   4c 8b 7b 18 mov0x18(%rbx),%r15
   11:   4d 85 fftest   %r15,%r15
   14:   0f 84 de 01 00 00   je 0x1f8
   1a:   41 f6 c7 07 test   $0x7,%r15b
   1e:   0f 85 d4 01 00 00   jne0x1f8
   24:   4c 89 f8mov%r15,%rax
   27:   48 c1 e8 03 shr$0x3,%rax
   2b:*  42 80 3c 28 00  cmpb   $0x0,(%rax,%r13,1)   -- 
 trapping instruction

 Three commands above are result of KASAN's instrumentation.
 They check shadow for address in %r15:
  if (*((%r15  3) + kasan_shadow_offset)


   30:   0f 85 b5 01 00 00   jne0x1eb
   36:   4d 8b 37mov(%r15),%r14

 And here is memory access, that KASAN checking.

 Then frankly I suspect this is a KASAN bug.


Sure it is possible, but I don't see any evidence of kasan bug here.

 These two instructions:
   11:   4d 85 fftest   %r15,%r15
   14:   0f 84 de 01 00 00   je 0x1f8

 Should prevent a NULL %r15 value from ever reaching the trapping
 instruction.

If they were executed, then yes. But I think there was jump from somewhere
to the instructions below those two.


 What other horrible things does KASAN do to the machine code?


kasan insert something like following before any memory access:

s8 *shadow_addr = (add  3) + shadow_offset;

if (unlikely(*shadow_addr))
 if (unlikely(addr  7 = *shadow_addr))
   report_bug(addr);


I suspect that Sasha is using kasan along with ubsan.
In that case generated code much more horrid.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/7] slub: Do not use c-page on free

2014-12-15 Thread Andrey Ryabinin
2014-12-16 5:42 GMT+03:00 Joonsoo Kim iamjoonsoo@lge.com:
 On Mon, Dec 15, 2014 at 08:16:00AM -0600, Christoph Lameter wrote:
 On Mon, 15 Dec 2014, Joonsoo Kim wrote:

   +static bool same_slab_page(struct kmem_cache *s, struct page *page, 
   void *p)
   +{
   + long d = p - page-address;
   +
   + return d  0  d  (1  MAX_ORDER)  d  (compound_order(page)  
   PAGE_SHIFT);
   +}
   +
 
  Somtimes, compound_order() induces one more cacheline access, because
  compound_order() access second struct page in order to get order. Is there
  any way to remove this?

 I already have code there to avoid the access if its within a MAX_ORDER
 page. We could probably go for a smaller setting there. PAGE_COSTLY_ORDER?

 That is the solution to avoid compound_order() call when slab of
 object isn't matched with per cpu slab.

 What I'm asking is whether there is a way to avoid compound_order() call when 
 slab
 of object is matched with per cpu slab or not.


Can we use page-objects for that?

Like this:

return d  0  d  page-objects * s-size;
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/7] slub: Do not use c-page on free

2014-12-16 Thread Andrey Ryabinin
2014-12-16 17:53 GMT+03:00 Christoph Lameter c...@linux.com:
 On Tue, 16 Dec 2014, Joonsoo Kim wrote:

  Like this:
 
  return d  0  d  page-objects * s-size;
 

 Yes! That's what I'm looking for.
 Christoph, how about above change?

 Ok but now there is a multiplication in the fast path.


Another idea - store page's order in the lower bits of page-address.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 3/7] slub: Do not use c-page on free

2014-12-16 Thread Andrey Ryabinin
2014-12-16 18:15 GMT+03:00 Jesper Dangaard Brouer bro...@redhat.com:
 On Tue, 16 Dec 2014 08:53:08 -0600 (CST)
 Christoph Lameter c...@linux.com wrote:

 On Tue, 16 Dec 2014, Joonsoo Kim wrote:

   Like this:
  
   return d  0  d  page-objects * s-size;
  
 
  Yes! That's what I'm looking for.
  Christoph, how about above change?

 Ok but now there is a multiplication in the fast path.

 Could we pre-calculate the value (page-objects * s-size) and e.g store it
 in struct kmem_cache, thus saving the imul ?


No, one kmem_cache could have several pages with different orders,
therefore different page-objects.

 --
 Best regards,
   Jesper Dangaard Brouer
   MSc.CS, Sr. Network Kernel Developer at Red Hat
   Author of http://www.iptv-analyzer.org
   LinkedIn: http://www.linkedin.com/in/brouer
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2] mm: hugetlb: fix type of hugetlb_treat_as_movable variable

2014-12-17 Thread Andrey Ryabinin
hugetlb_treat_as_movable declared as unsigned long, but
proc_dointvec() used for parsing it:

static struct ctl_table vm_table[] = {
...
{
.procname   = hugepages_treat_as_movable,
.data   = hugepages_treat_as_movable,
.maxlen = sizeof(int),
.mode   = 0644,
.proc_handler   = proc_dointvec,
},

This seems harmless, but it's better to use int type here.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/hugetlb.h | 2 +-
 mm/hugetlb.c| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h
index 431b7fc..7d78563 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -86,7 +86,7 @@ void free_huge_page(struct page *page);
 pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud);
 #endif
 
-extern unsigned long hugepages_treat_as_movable;
+extern int hugepages_treat_as_movable;
 extern int sysctl_hugetlb_shm_group;
 extern struct list_head huge_boot_pages;
 
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 85032de..be0e5d0 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -35,7 +35,7 @@
 #include linux/node.h
 #include internal.h
 
-unsigned long hugepages_treat_as_movable;
+int hugepages_treat_as_movable;
 
 int hugetlb_max_hstate __read_mostly;
 unsigned int default_hstate_idx;
-- 
2.2.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/2] hugetlb, sysctl: pass '.extra1 = NULL' rather then '.extra1 = zero'

2014-12-17 Thread Andrey Ryabinin
Commit ed4d4902ebdd (mm, hugetlb: remove hugetlb_zero and hugetlb_infinity) 
replaced
'unsigned long hugetlb_zero' with 'int zero' leading to out-of-bounds access
in proc_doulongvec_minmax().
Use '.extra1 = NULL' instead of '.extra1 = zero'. Passing NULL is equivalent to
passing minimal value, which is 0 for unsigned types.

Reported-by: Dmitry Vyukov dvyu...@google.com
Suggested-by: Manfred Spraul manf...@colorfullife.com
Fixes: ed4d4902ebdd (mm, hugetlb: remove hugetlb_zero and hugetlb_infinity)
Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 kernel/sysctl.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 137c7f6..88ea2d6 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -1248,7 +1248,6 @@ static struct ctl_table vm_table[] = {
.maxlen = sizeof(unsigned long),
.mode   = 0644,
.proc_handler   = hugetlb_sysctl_handler,
-   .extra1 = zero,
},
 #ifdef CONFIG_NUMA
{
@@ -1257,7 +1256,6 @@ static struct ctl_table vm_table[] = {
.maxlen = sizeof(unsigned long),
.mode   = 0644,
.proc_handler   = hugetlb_mempolicy_sysctl_handler,
-   .extra1 = zero,
},
 #endif
 {
@@ -1280,7 +1278,6 @@ static struct ctl_table vm_table[] = {
.maxlen = sizeof(unsigned long),
.mode   = 0644,
.proc_handler   = hugetlb_overcommit_handler,
-   .extra1 = zero,
},
 #endif
{
-- 
2.2.0

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6 09/11] fs: dcache: manually unpoison dname after allocation to shut up kasan's reports

2014-11-05 Thread Andrey Ryabinin
We need to manually unpoison rounded up allocation size for dname
to avoid kasan's reports in dentry_string_cmp().
When CONFIG_DCACHE_WORD_ACCESS=y dentry_string_cmp may access
few bytes beyound requested in kmalloc() size.

dentry_string_cmp() relates on that fact that dentry allocated
using kmalloc and kmalloc internally round up allocation size.
So this is not a bug, but this makes kasan to complain about
such accesses.
To avoid such reports we mark rounded up allocation size in
shadow as accessible.

Reported-by: Dmitry Vyukov dvyu...@google.com
Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 fs/dcache.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/fs/dcache.c b/fs/dcache.c
index d5a23fd..d58ffcc6 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -38,6 +38,8 @@
 #include linux/prefetch.h
 #include linux/ratelimit.h
 #include linux/list_lru.h
+#include linux/kasan.h
+
 #include internal.h
 #include mount.h
 
@@ -1429,6 +1431,10 @@ struct dentry *__d_alloc(struct super_block *sb, const 
struct qstr *name)
}
atomic_set(p-u.count, 1);
dname = p-name;
+#ifdef CONFIG_DCACHE_WORD_ACCESS
+   kasan_unpoison_shadow(dname,
+   round_up(name-len + 1, sizeof(unsigned long)));
+#endif
} else  {
dname = dentry-d_iname;
}   
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6 08/11] mm: slub: add kernel address sanitizer support for slub allocator

2014-11-05 Thread Andrey Ryabinin
With this patch kasan will be able to catch bugs in memory allocated
by slub.
Initially all objects in newly allocated slab page, marked as free.
Later, when allocation of slub object happens, requested by caller
number of bytes marked as accessible, and the rest of the object
(including slub's metadata) marked as redzone (inaccessible).

We also mark object as accessible if ksize was called for this object.
There is some places in kernel where ksize function is called to inquire
size of really allocated area. Such callers could validly access whole
allocated memory, so it should be marked as accessible.

Code in slub.c and slab_common.c files could validly access to object's
metadata, so instrumentation for this files are disabled.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/kasan.h | 21 
 include/linux/slab.h  | 11 --
 lib/Kconfig.kasan |  1 +
 mm/Makefile   |  3 ++
 mm/kasan/kasan.c  | 92 +++
 mm/kasan/kasan.h  |  4 +++
 mm/kasan/report.c | 25 ++
 mm/slab_common.c  |  5 ++-
 mm/slub.c | 35 ++--
 9 files changed, 191 insertions(+), 6 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 9714fba..0463b90 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -32,6 +32,16 @@ void kasan_unpoison_shadow(const void *address, size_t size);
 
 void kasan_alloc_pages(struct page *page, unsigned int order);
 void kasan_free_pages(struct page *page, unsigned int order);
+void kasan_mark_slab_padding(struct kmem_cache *s, void *object,
+   struct page *page);
+
+void kasan_kmalloc_large(const void *ptr, size_t size);
+void kasan_kfree_large(const void *ptr);
+void kasan_kmalloc(struct kmem_cache *s, const void *object, size_t size);
+void kasan_krealloc(const void *object, size_t new_size);
+
+void kasan_slab_alloc(struct kmem_cache *s, void *object);
+void kasan_slab_free(struct kmem_cache *s, void *object);
 
 #else /* CONFIG_KASAN */
 
@@ -42,6 +52,17 @@ static inline void kasan_disable_local(void) {}
 
 static inline void kasan_alloc_pages(struct page *page, unsigned int order) {}
 static inline void kasan_free_pages(struct page *page, unsigned int order) {}
+static inline void kasan_mark_slab_padding(struct kmem_cache *s, void *object,
+   struct page *page) {}
+
+static inline void kasan_kmalloc_large(void *ptr, size_t size) {}
+static inline void kasan_kfree_large(const void *ptr) {}
+static inline void kasan_kmalloc(struct kmem_cache *s, const void *object,
+   size_t size) {}
+static inline void kasan_krealloc(const void *object, size_t new_size) {}
+
+static inline void kasan_slab_alloc(struct kmem_cache *s, void *object) {}
+static inline void kasan_slab_free(struct kmem_cache *s, void *object) {}
 
 #endif /* CONFIG_KASAN */
 
diff --git a/include/linux/slab.h b/include/linux/slab.h
index c265bec..5f97037 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -104,6 +104,7 @@
(unsigned long)ZERO_SIZE_PTR)
 
 #include linux/kmemleak.h
+#include linux/kasan.h
 
 struct mem_cgroup;
 /*
@@ -326,7 +327,10 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
 static __always_inline void *kmem_cache_alloc_trace(struct kmem_cache *s,
gfp_t flags, size_t size)
 {
-   return kmem_cache_alloc(s, flags);
+   void *ret = kmem_cache_alloc(s, flags);
+
+   kasan_kmalloc(s, ret, size);
+   return ret;
 }
 
 static __always_inline void *
@@ -334,7 +338,10 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
  gfp_t gfpflags,
  int node, size_t size)
 {
-   return kmem_cache_alloc_node(s, gfpflags, node);
+   void *ret = kmem_cache_alloc_node(s, gfpflags, node);
+
+   kasan_kmalloc(s, ret, size);
+   return ret;
 }
 #endif /* CONFIG_TRACING */
 
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index 386cc8b..1fa4fe8 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -6,6 +6,7 @@ if HAVE_ARCH_KASAN
 config KASAN
bool AddressSanitizer: runtime memory debugger
depends on !MEMORY_HOTPLUG
+   depends on SLUB_DEBUG
help
  Enables address sanitizer - runtime memory debugger,
  designed to find out-of-bounds accesses and use-after-free bugs.
diff --git a/mm/Makefile b/mm/Makefile
index 63b7871..aa16cec 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -2,6 +2,9 @@
 # Makefile for the linux memory manager.
 #
 
+KASAN_SANITIZE_slab_common.o := n
+KASAN_SANITIZE_slub.o := n
+
 mmu-y  := nommu.o
 mmu-$(CONFIG_MMU)  := gup.o highmem.o memory.o mincore.o \
   mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index 7d4dcc3..37b8b26 100644
--- a/mm/kasan/kasan.c
+++ b/mm

[PATCH] lib: add kasan test module

2014-11-05 Thread Andrey Ryabinin
This is a test module doing various nasty things like
out of bounds accesses, use after free. It is useful for testing
kernel debugging features like kernel address sanitizer.

It mostly concentrates on testing of slab allocator, but we
might want to add more different stuff here in future (like
stack/global variables out of bounds accesses and so on).

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 lib/Kconfig.kasan |   8 ++
 lib/Makefile  |   1 +
 lib/test_kasan.c  | 254 ++
 3 files changed, 263 insertions(+)
 create mode 100644 lib/test_kasan.c

diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index 1fa4fe8..8548646 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -43,4 +43,12 @@ config KASAN_INLINE
 
 endchoice
 
+config TEST_KASAN
+   tristate Module for testing kasan for bug detection
+   depends on m  KASAN
+   help
+ This is a test module doing various nasty things like
+ out of bounds accesses, use after free. It is useful for testing
+ kernel debugging features like kernel address sanitizer.
+
 endif
diff --git a/lib/Makefile b/lib/Makefile
index 84000ec..b387570 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -35,6 +35,7 @@ obj-$(CONFIG_TEST_LKM) += test_module.o
 obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
 obj-$(CONFIG_TEST_BPF) += test_bpf.o
 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
+obj-$(CONFIG_TEST_KASAN) += test_kasan.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/test_kasan.c b/lib/test_kasan.c
new file mode 100644
index 000..896dee5
--- /dev/null
+++ b/lib/test_kasan.c
@@ -0,0 +1,254 @@
+/*
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Andrey Ryabinin a.ryabi...@samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) kasan test: %s  fmt, __func__
+
+#include linux/kernel.h
+#include linux/printk.h
+#include linux/slab.h
+#include linux/string.h
+#include linux/module.h
+
+static noinline void __init kmalloc_oob_right(void)
+{
+   char *ptr;
+   size_t size = 123;
+
+   pr_info(out-of-bounds to right\n);
+   ptr = kmalloc(size, GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 'x';
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_oob_left(void)
+{
+   char *ptr;
+   size_t size = 15;
+
+   pr_info(out-of-bounds to left\n);
+   ptr = kmalloc(size, GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   *ptr = *(ptr - 1);
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_node_oob_right(void)
+{
+   char *ptr;
+   size_t size = 4096;
+
+   pr_info(kmalloc_node(): out-of-bounds to right\n);
+   ptr = kmalloc_node(size, GFP_KERNEL, 0);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 0;
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_large_oob_rigth(void)
+{
+   char *ptr;
+   size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
+
+   pr_info(kmalloc large allocation: out-of-bounds to right\n);
+   ptr = kmalloc(size, GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 0;
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_oob_krealloc_more(void)
+{
+   char *ptr1, *ptr2;
+   size_t size1 = 17;
+   size_t size2 = 19;
+
+   pr_info(out-of-bounds after krealloc more\n);
+   ptr1 = kmalloc(size1, GFP_KERNEL);
+   ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1);
+   return;
+   }
+
+   ptr2[size2] = 'x';
+   kfree(ptr2);
+}
+
+static noinline void __init kmalloc_oob_krealloc_less(void)
+{
+   char *ptr1, *ptr2;
+   size_t size1 = 17;
+   size_t size2 = 15;
+
+   pr_info(out-of-bounds after krealloc less\n);
+   ptr1 = kmalloc(size1, GFP_KERNEL);
+   ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1);
+   return;
+   }
+   ptr2[size1] = 'x';
+   kfree(ptr2);
+}
+
+static noinline void __init kmalloc_oob_16(void)
+{
+   struct {
+   u64 words[2];
+   } *ptr1, *ptr2;
+
+   pr_info(kmalloc out-of-bounds for 16-bytes access\n);
+   ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
+   ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1

[PATCH v6 02/11] x86_64: load_percpu_segment: read irq_stack_union.gs_base before load_segment

2014-11-05 Thread Andrey Ryabinin
Reading irq_stack_union.gs_base after load_segment creates troubles for kasan.
Compiler inserts __asan_load in between load_segment and wrmsrl. If kernel
built with stackprotector this will result in boot failure because __asan_load
has stackprotector.

To avoid this irq_stack_union.gs_base stored to temporary variable before
load_segment, so __asan_load will be called before load_segment().

There are two alternative ways to fix this:
 a) Add __attribute__((no_sanitize_address)) to load_percpu_segment(),
which tells compiler to not instrument this function. However this
will result in build failure with CONFIG_KASAN=y and 
CONFIG_OPTIMIZE_INLINING=y.

 b) Add -fno-stack-protector for mm/kasan/kasan.c

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 arch/x86/kernel/cpu/common.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 4b4f78c..ee5c286 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -389,8 +389,10 @@ void load_percpu_segment(int cpu)
 #ifdef CONFIG_X86_32
loadsegment(fs, __KERNEL_PERCPU);
 #else
+   void *gs_base = per_cpu(irq_stack_union.gs_base, cpu);
+
loadsegment(gs, 0);
-   wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, 
cpu));
+   wrmsrl(MSR_GS_BASE, (unsigned long)gs_base);
 #endif
load_stack_canary_segment();
 }
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6 07/11] mm: slub: introduce metadata_access_enable()/metadata_access_disable()

2014-11-05 Thread Andrey Ryabinin
Wrap access to object's metadata in external functions with
metadata_access_enable()/metadata_access_disable() function calls.

This hooks separates payload accesses from metadata accesses
which might be useful for different checkers (e.g. KASan).

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 mm/slub.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/mm/slub.c b/mm/slub.c
index 1458629..2116ccd 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -467,13 +467,23 @@ static int slub_debug;
 static char *slub_debug_slabs;
 static int disable_higher_order_debug;
 
+static inline void metadata_access_enable(void)
+{
+}
+
+static inline void metadata_access_disable(void)
+{
+}
+
 /*
  * Object debugging
  */
 static void print_section(char *text, u8 *addr, unsigned int length)
 {
+   metadata_access_enable();
print_hex_dump(KERN_ERR, text, DUMP_PREFIX_ADDRESS, 16, 1, addr,
length, 1);
+   metadata_access_disable();
 }
 
 static struct track *get_track(struct kmem_cache *s, void *object,
@@ -503,7 +513,9 @@ static void set_track(struct kmem_cache *s, void *object,
trace.max_entries = TRACK_ADDRS_COUNT;
trace.entries = p-addrs;
trace.skip = 3;
+   metadata_access_enable();
save_stack_trace(trace);
+   metadata_access_disable();
 
/* See rant in lockdep.c */
if (trace.nr_entries != 0 
@@ -677,7 +689,9 @@ static int check_bytes_and_report(struct kmem_cache *s, 
struct page *page,
u8 *fault;
u8 *end;
 
+   metadata_access_enable();
fault = memchr_inv(start, value, bytes);
+   metadata_access_disable();
if (!fault)
return 1;
 
@@ -770,7 +784,9 @@ static int slab_pad_check(struct kmem_cache *s, struct page 
*page)
if (!remainder)
return 1;
 
+   metadata_access_enable();
fault = memchr_inv(end - remainder, POISON_INUSE, remainder);
+   metadata_access_disable();
if (!fault)
return 1;
while (end  fault  end[-1] == POISON_INUSE)
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6 06/11] mm: slub: share slab_err and object_err functions

2014-11-05 Thread Andrey Ryabinin
Remove static and add function declarations to mm/slab.h so they
could be used by kernel address sanitizer.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/slub_def.h | 5 +
 mm/slub.c| 4 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index c75bc1d..144b5cb 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -115,4 +115,9 @@ static inline void *virt_to_obj(struct kmem_cache *s, void 
*slab_page, void *x)
return x - ((x - slab_page) % s-size);
 }
 
+__printf(3, 4)
+void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...);
+void object_err(struct kmem_cache *s, struct page *page,
+   u8 *object, char *reason);
+
 #endif /* _LINUX_SLUB_DEF_H */
diff --git a/mm/slub.c b/mm/slub.c
index 80c170e..1458629 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -629,14 +629,14 @@ static void print_trailer(struct kmem_cache *s, struct 
page *page, u8 *p)
dump_stack();
 }
 
-static void object_err(struct kmem_cache *s, struct page *page,
+void object_err(struct kmem_cache *s, struct page *page,
u8 *object, char *reason)
 {
slab_bug(s, %s, reason);
print_trailer(s, page, object);
 }
 
-static void slab_err(struct kmem_cache *s, struct page *page,
+void slab_err(struct kmem_cache *s, struct page *page,
const char *fmt, ...)
 {
va_list args;
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6 05/11] mm: slub: introduce virt_to_obj function.

2014-11-05 Thread Andrey Ryabinin
virt_to_obj takes kmem_cache address, address of slab page,
address x pointing somewhere inside slab object,
and returns address of the begging of object.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/slub_def.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index d82abd4..c75bc1d 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -110,4 +110,9 @@ static inline void sysfs_slab_remove(struct kmem_cache *s)
 }
 #endif
 
+static inline void *virt_to_obj(struct kmem_cache *s, void *slab_page, void *x)
+{
+   return x - ((x - slab_page) % s-size);
+}
+
 #endif /* _LINUX_SLUB_DEF_H */
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6 00/11] Kernel address sanitizer - runtime memory debugger.

2014-11-05 Thread Andrey Ryabinin
 kmemcheck.
  The only advantage of kmemcheck over KASan is detection of unitialized
  memory reads.

DEBUG_PAGEALLOC:
- KASan is slower than DEBUG_PAGEALLOC, but KASan works on sub-page
  granularity level, so it able to find more bugs.

SLUB_DEBUG (poisoning, redzones):
- SLUB_DEBUG has lower overhead than KASan.

- SLUB_DEBUG in most cases are not able to detect bad reads,
  KASan able to detect both reads and writes.

- In some cases (e.g. redzone overwritten) SLUB_DEBUG detect
  bugs only on allocation/freeing of object. KASan catch
  bugs right before it will happen, so we always know exact
  place of first bad read/write.


Basic idea:
===

The main idea of KASAN is to use shadow memory to record whether each byte 
of memory
is safe to access or not, and use compiler's instrumentation to check the 
shadow memory
on each memory access.

Address sanitizer uses 1/8 of the memory addressable in kernel for shadow 
memory
(on x86_64 16TB of virtual address space reserved for shadow to cover all 
128TB)
and uses direct mapping with a scale and offset to translate a memory
address to its corresponding shadow address.

Here is function to translate address to corresponding shadow address:

 unsigned long kasan_mem_to_shadow(unsigned long addr)
 {
return (addr  KASAN_SHADOW_SCALE_SHIFT) + 
KASAN_SHADOW_OFFSET;
 }
where KASAN_SHADOW_SCALE_SHIFT = 3.

So for every 8 bytes there is one corresponding byte of shadow memory.
The following encoding used for each shadow byte: 0 means that all 8 bytes 
of the
corresponding memory region are valid for access; k (1 = k = 7) means that
the first k bytes are valid for access, and other (8 - k) bytes are not;
Any negative value indicates that the entire 8-bytes are inaccessible.
Different negative values used to distinguish between different kinds of
inaccessible memory (redzones, freed memory) (see mm/kasan/kasan.h).

To be able to detect accesses to bad memory we need a special compiler.
Such compiler inserts a specific function calls (__asan_load*(addr), 
__asan_store*(addr))
before each memory access of size 1, 2, 4, 8 or 16.

These functions check whether memory region is valid to access or not by 
checking
corresponding shadow memory. If access is not valid an error printed.

Andrey Ryabinin (11):
  Add kernel address sanitizer infrastructure.
  x86_64: load_percpu_segment: read irq_stack_union.gs_base before
load_segment
  x86_64: add KASan support
  mm: page_alloc: add kasan hooks on alloc and free paths
  mm: slub: introduce virt_to_obj function.
  mm: slub: share slab_err and object_err functions
  mm: slub: introduce metadata_access_enable()/metadata_access_disable()
  mm: slub: add kernel address sanitizer support for slub allocator
  fs: dcache: manually unpoison dname after allocation to shut up
kasan's reports
  kmemleak: disable kasan instrumentation for kmemleak
  lib: add kasan test module

 Documentation/kasan.txt   | 169 
 Makefile  |  23 +-
 arch/x86/Kconfig  |   1 +
 arch/x86/boot/Makefile|   2 +
 arch/x86/boot/compressed/Makefile |   2 +
 arch/x86/include/asm/kasan.h  |  27 ++
 arch/x86/kernel/Makefile  |   2 +
 arch/x86/kernel/cpu/common.c  |   4 +-
 arch/x86/kernel/dumpstack.c   |   5 +-
 arch/x86/kernel/head64.c  |   9 +-
 arch/x86/kernel/head_64.S |  28 ++
 arch/x86/mm/Makefile  |   3 +
 arch/x86/mm/init.c|   3 +
 arch/x86/mm/kasan_init_64.c   |  87 +++
 arch/x86/realmode/Makefile|   2 +-
 arch/x86/realmode/rm/Makefile |   1 +
 arch/x86/vdso/Makefile|   1 +
 drivers/firmware/efi/libstub/Makefile |   1 +
 fs/dcache.c   |   6 +
 include/linux/kasan.h |  69 +
 include/linux/sched.h |   3 +
 include/linux/slab.h  |  11 +-
 include/linux/slub_def.h  |  10 +
 lib/Kconfig.debug |   2 +
 lib/Kconfig.kasan |  54 
 lib/Makefile  |   1 +
 lib/test_kasan.c  | 254 ++
 mm/Makefile   |   4 +
 mm/compaction.c   |   2 +
 mm/kasan/Makefile |   7 +
 mm/kasan/kasan.c  | 468 ++
 mm/kasan/kasan.h  |  54 
 mm/kasan/report.c | 238 +
 mm/kmemleak.c |   6 +
 mm/page_alloc.c   |   3 +
 mm/slab_common.c  |   5 +-
 mm/slub.c |  55 +++-
 scripts/Makefile.lib

[PATCH v6 04/11] mm: page_alloc: add kasan hooks on alloc and free paths

2014-11-05 Thread Andrey Ryabinin
Add kernel address sanitizer hooks to mark allocated page's addresses
as accessible in corresponding shadow region.
Mark freed pages as inaccessible.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/kasan.h |  6 ++
 mm/compaction.c   |  2 ++
 mm/kasan/kasan.c  | 14 ++
 mm/kasan/kasan.h  |  1 +
 mm/kasan/report.c |  7 +++
 mm/page_alloc.c   |  3 +++
 6 files changed, 33 insertions(+)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 01c99fe..9714fba 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -30,6 +30,9 @@ static inline void kasan_disable_local(void)
 
 void kasan_unpoison_shadow(const void *address, size_t size);
 
+void kasan_alloc_pages(struct page *page, unsigned int order);
+void kasan_free_pages(struct page *page, unsigned int order);
+
 #else /* CONFIG_KASAN */
 
 static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
@@ -37,6 +40,9 @@ static inline void kasan_unpoison_shadow(const void *address, 
size_t size) {}
 static inline void kasan_enable_local(void) {}
 static inline void kasan_disable_local(void) {}
 
+static inline void kasan_alloc_pages(struct page *page, unsigned int order) {}
+static inline void kasan_free_pages(struct page *page, unsigned int order) {}
+
 #endif /* CONFIG_KASAN */
 
 #endif /* LINUX_KASAN_H */
diff --git a/mm/compaction.c b/mm/compaction.c
index e6e7405..aa529ad 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -16,6 +16,7 @@
 #include linux/sysfs.h
 #include linux/balloon_compaction.h
 #include linux/page-isolation.h
+#include linux/kasan.h
 #include internal.h
 
 #ifdef CONFIG_COMPACTION
@@ -59,6 +60,7 @@ static void map_pages(struct list_head *list)
list_for_each_entry(page, list, lru) {
arch_alloc_page(page, 0);
kernel_map_pages(page, 1, 1);
+   kasan_alloc_pages(page, 0);
}
 }
 
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index ea5e464..7d4dcc3 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -247,6 +247,20 @@ static __always_inline void check_memory_region(unsigned 
long addr,
kasan_report(addr, size, write);
 }
 
+void kasan_alloc_pages(struct page *page, unsigned int order)
+{
+   if (likely(!PageHighMem(page)))
+   kasan_unpoison_shadow(page_address(page), PAGE_SIZE  order);
+}
+
+void kasan_free_pages(struct page *page, unsigned int order)
+{
+   if (likely(!PageHighMem(page)))
+   kasan_poison_shadow(page_address(page),
+   PAGE_SIZE  order,
+   KASAN_FREE_PAGE);
+}
+
 void __asan_load1(unsigned long addr)
 {
check_memory_region(addr, 1, false);
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 6da1d78..2a6a961 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -6,6 +6,7 @@
 #define KASAN_SHADOW_SCALE_SIZE (1UL  KASAN_SHADOW_SCALE_SHIFT)
 #define KASAN_SHADOW_MASK   (KASAN_SHADOW_SCALE_SIZE - 1)
 
+#define KASAN_FREE_PAGE 0xFF  /* page was freed */
 #define KASAN_SHADOW_GAP0xF9  /* address belongs to shadow memory */
 
 struct access_info {
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 7f559b4..bfe3a31 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -57,6 +57,9 @@ static void print_error_description(struct access_info *info)
case 0 ... KASAN_SHADOW_SCALE_SIZE - 1:
bug_type = out of bounds access;
break;
+   case KASAN_FREE_PAGE:
+   bug_type = use after free;
+   break;
case KASAN_SHADOW_GAP:
bug_type = wild memory access;
break;
@@ -75,6 +78,10 @@ static void print_address_description(struct access_info 
*info)
page = virt_to_head_page((void *)info-access_addr);
 
switch (shadow_val) {
+   case KASAN_FREE_PAGE:
+   dump_page(page, kasan error);
+   dump_stack();
+   break;
case KASAN_SHADOW_GAP:
pr_err(No metainfo is available for this access.\n);
dump_stack();
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index fa94263..9ae7d0e 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -59,6 +59,7 @@
 #include linux/page-debug-flags.h
 #include linux/hugetlb.h
 #include linux/sched/rt.h
+#include linux/kasan.h
 
 #include asm/sections.h
 #include asm/tlbflush.h
@@ -759,6 +760,7 @@ static bool free_pages_prepare(struct page *page, unsigned 
int order)
 
trace_mm_page_free(page, order);
kmemcheck_free_shadow(page, order);
+   kasan_free_pages(page, order);
 
if (PageAnon(page))
page-mapping = NULL;
@@ -945,6 +947,7 @@ static int prep_new_page(struct page *page, unsigned int 
order, gfp_t gfp_flags)
 
arch_alloc_page(page, order);
kernel_map_pages(page, 1  order, 1);
+   kasan_alloc_pages(page, order);
 
if (gfp_flags  __GFP_ZERO

[PATCH v6 03/11] x86_64: add KASan support

2014-11-05 Thread Andrey Ryabinin
This patch adds arch specific code for kernel address sanitizer.

16TB of virtual addressed used for shadow memory.
It's located in range [0xd900 - 0xe900]
which belongs to vmalloc area.

At early stage we map whole shadow region with zero page.
Latter, after pages mapped to direct mapping address range
we unmap zero pages from corresponding shadow (see kasan_map_shadow())
and allocate and map a real shadow memory reusing vmemmap_populate()
function.

Also replace __pa with __pa_nodebug before shadow initialized.
__pa with CONFIG_DEBUG_VIRTUAL=y make external function call (__phys_addr)
__phys_addr is instrumented, so __asan_load could be called before
shadow area initialized.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 arch/x86/Kconfig  |  1 +
 arch/x86/boot/Makefile|  2 +
 arch/x86/boot/compressed/Makefile |  2 +
 arch/x86/include/asm/kasan.h  | 27 
 arch/x86/kernel/Makefile  |  2 +
 arch/x86/kernel/dumpstack.c   |  5 ++-
 arch/x86/kernel/head64.c  |  9 +++-
 arch/x86/kernel/head_64.S | 28 +
 arch/x86/mm/Makefile  |  3 ++
 arch/x86/mm/init.c|  3 ++
 arch/x86/mm/kasan_init_64.c   | 87 +++
 arch/x86/realmode/Makefile|  2 +-
 arch/x86/realmode/rm/Makefile |  1 +
 arch/x86/vdso/Makefile|  1 +
 lib/Kconfig.kasan |  2 +
 15 files changed, 171 insertions(+), 4 deletions(-)
 create mode 100644 arch/x86/include/asm/kasan.h
 create mode 100644 arch/x86/mm/kasan_init_64.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 6115af9..ba56207 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -138,6 +138,7 @@ config X86
select HAVE_ACPI_APEI_NMI if ACPI
select ACPI_LEGACY_TABLES_LOOKUP if ACPI
select X86_FEATURE_NAMES if PROC_FS
+   select HAVE_ARCH_KASAN if X86_64
 
 config INSTRUCTION_DECODER
def_bool y
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 5b016e2..1ef2724 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -14,6 +14,8 @@
 # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
 # The number is the same as you would ordinarily press at bootup.
 
+KASAN_SANITIZE := n
+
 SVGA_MODE  := -DSVGA_MODE=NORMAL_VGA
 
 targets:= vmlinux.bin setup.bin setup.elf bzImage
diff --git a/arch/x86/boot/compressed/Makefile 
b/arch/x86/boot/compressed/Makefile
index 704f58a..21faab6b7 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -4,6 +4,8 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
+KASAN_SANITIZE := n
+
 targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma 
\
vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
 
diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
new file mode 100644
index 000..056c943
--- /dev/null
+++ b/arch/x86/include/asm/kasan.h
@@ -0,0 +1,27 @@
+#ifndef _ASM_X86_KASAN_H
+#define _ASM_X86_KASAN_H
+
+#define KASAN_SHADOW_START 0xd900UL
+#define KASAN_SHADOW_END   0xe900UL
+
+#ifndef __ASSEMBLY__
+
+extern pte_t zero_pte[];
+extern pte_t zero_pmd[];
+extern pte_t zero_pud[];
+
+extern pte_t poisoned_pte[];
+extern pte_t poisoned_pmd[];
+extern pte_t poisoned_pud[];
+
+#ifdef CONFIG_KASAN
+void __init kasan_map_zero_shadow(pgd_t *pgd);
+void __init kasan_map_shadow(void);
+#else
+static inline void kasan_map_zero_shadow(pgd_t *pgd) { }
+static inline void kasan_map_shadow(void) { }
+#endif
+
+#endif
+
+#endif
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 8f1e774..9d46ee8 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -16,6 +16,8 @@ CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
 
+KASAN_SANITIZE_head$(BITS).o := n
+
 CFLAGS_irq.o := -I$(src)/../include/asm/trace
 
 obj-y  := process_$(BITS).o signal.o entry_$(BITS).o
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index b74ebc7..cf3df1d 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -265,7 +265,10 @@ int __die(const char *str, struct pt_regs *regs, long err)
printk(SMP );
 #endif
 #ifdef CONFIG_DEBUG_PAGEALLOC
-   printk(DEBUG_PAGEALLOC);
+   printk(DEBUG_PAGEALLOC );
+#endif
+#ifdef CONFIG_KASAN
+   printk(KASAN);
 #endif
printk(\n);
if (notify_die(DIE_OOPS, str, regs, err,
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index eda1a86..b9e4e50 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -27,6 +27,7 @@
 #include asm/bios_ebda.h
 #include asm/bootparam_utils.h
 #include asm/microcode.h
+#include asm/kasan.h
 
 /*
  * Manage page tables very early on.
@@ -46,7 +47,7 @@ static void __init reset_early_page_tables(void)
 
next_early_pgt

[PATCH v6 01/11] Add kernel address sanitizer infrastructure.

2014-11-05 Thread Andrey Ryabinin
Kernel Address sanitizer (KASan) is a dynamic memory error detector. It provides
fast and comprehensive solution for finding use-after-free and out-of-bounds 
bugs.

KASAN uses compile-time instrumentation for checking every memory access,
therefore GCC = v4.9.2 required.

This patch only adds infrastructure for kernel address sanitizer. It's not
available for use yet. The idea and some code was borrowed from [1].

Basic idea:
The main idea of KASAN is to use shadow memory to record whether each byte of 
memory
is safe to access or not, and use compiler's instrumentation to check the 
shadow memory
on each memory access.

Address sanitizer uses 1/8 of the memory addressable in kernel for shadow memory
and uses direct mapping with a scale and offset to translate a memory
address to its corresponding shadow address.

Here is function to translate address to corresponding shadow address:

 unsigned long kasan_mem_to_shadow(unsigned long addr)
 {
return (addr  KASAN_SHADOW_SCALE_SHIFT) + KASAN_SHADOW_OFFSET;
 }
where KASAN_SHADOW_SCALE_SHIFT = 3.

So for every 8 bytes there is one corresponding byte of shadow memory.
The following encoding used for each shadow byte: 0 means that all 8 bytes of 
the
corresponding memory region are valid for access; k (1 = k = 7) means that
the first k bytes are valid for access, and other (8 - k) bytes are not;
Any negative value indicates that the entire 8-bytes are inaccessible.
Different negative values used to distinguish between different kinds of
inaccessible memory (redzones, freed memory) (see mm/kasan/kasan.h).

To be able to detect accesses to bad memory we need a special compiler.
Such compiler inserts a specific function calls (__asan_load*(addr), 
__asan_store*(addr))
before each memory access of size 1, 2, 4, 8 or 16.

These functions check whether memory region is valid to access or not by 
checking
corresponding shadow memory. If access is not valid an error printed.

[1] https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel

Based on work by Andrey Konovalov adech...@gmail.com

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 Documentation/kasan.txt   | 169 
 Makefile  |  23 ++-
 drivers/firmware/efi/libstub/Makefile |   1 +
 include/linux/kasan.h |  42 
 include/linux/sched.h |   3 +
 lib/Kconfig.debug |   2 +
 lib/Kconfig.kasan |  43 
 mm/Makefile   |   1 +
 mm/kasan/Makefile |   7 +
 mm/kasan/kasan.c  | 362 ++
 mm/kasan/kasan.h  |  49 +
 mm/kasan/report.c | 206 +++
 scripts/Makefile.lib  |  10 +
 13 files changed, 916 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/kasan.txt
 create mode 100644 include/linux/kasan.h
 create mode 100644 lib/Kconfig.kasan
 create mode 100644 mm/kasan/Makefile
 create mode 100644 mm/kasan/kasan.c
 create mode 100644 mm/kasan/kasan.h
 create mode 100644 mm/kasan/report.c

diff --git a/Documentation/kasan.txt b/Documentation/kasan.txt
new file mode 100644
index 000..d532f91
--- /dev/null
+++ b/Documentation/kasan.txt
@@ -0,0 +1,169 @@
+Kernel address sanitizer
+
+
+0. Overview
+===
+
+Kernel Address sanitizer (KASan) is a dynamic memory error detector. It 
provides
+a fast and comprehensive solution for finding use-after-free and out-of-bounds
+bugs.
+
+KASan uses compile-time instrumentation for checking every memory access,
+therefore you will need a certain version of GCC = 4.9.2
+
+Currently KASan is supported only for x86_64 architecture and requires that the
+kernel be built with the SLUB allocator.
+
+1. Usage
+=
+
+To enable KASAN configure kernel with:
+
+ CONFIG_KASAN = y
+
+and choose between CONFIG_KASAN_OUTLINE and CONFIG_KASAN_INLINE. Outline/inline
+is compiler instrumentation types. The former produces smaller binary the
+latter is 1.1 - 2 times faster. Inline instrumentation requires GCC 5.0 or
+latter.
+
+Currently KASAN works only with the SLUB memory allocator.
+For better bug detection and nicer report, enable CONFIG_STACKTRACE and put
+at least 'slub_debug=U' in the boot cmdline.
+
+To disable instrumentation for specific files or directories, add a line
+similar to the following to the respective kernel Makefile:
+
+For a single file (e.g. main.o):
+KASAN_SANITIZE_main.o := n
+
+For all files in one directory:
+KASAN_SANITIZE := n
+
+1.1 Error reports
+==
+
+A typical out of bounds access report looks like this:
+
+==
+BUG: AddressSanitizer: out of bounds access in kmalloc_oob_right+0x65/0x75 
[test_kasan] at addr 8800693bc5d3

[PATCH v6 10/11] kmemleak: disable kasan instrumentation for kmemleak

2014-11-05 Thread Andrey Ryabinin
kmalloc internally round up allocation size, and kmemleak
uses rounded up size as object's size. This makes kasan
to complain while kmemleak scans memory or calculates of object's
checksum. The simplest solution here is to disable kasan.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 mm/kmemleak.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 3cda50c..9bda1b3 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -98,6 +98,7 @@
 #include asm/processor.h
 #include linux/atomic.h
 
+#include linux/kasan.h
 #include linux/kmemcheck.h
 #include linux/kmemleak.h
 #include linux/memory_hotplug.h
@@ -1113,7 +1114,10 @@ static bool update_checksum(struct kmemleak_object 
*object)
if (!kmemcheck_is_obj_initialized(object-pointer, object-size))
return false;
 
+   kasan_disable_local();
object-checksum = crc32(0, (void *)object-pointer, object-size);
+   kasan_enable_local();
+
return object-checksum != old_csum;
 }
 
@@ -1164,7 +1168,9 @@ static void scan_block(void *_start, void *_end,
  BYTES_PER_POINTER))
continue;
 
+   kasan_disable_local();
pointer = *ptr;
+   kasan_enable_local();
 
object = find_and_get_object(pointer, 1);
if (!object)
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] mm: slub: fix format mismatches in slab_err() callers

2014-11-05 Thread Andrey Ryabinin
Adding __printf(3, 4) to slab_err exposed following:

mm/slub.c: In function ‘check_slab’:
mm/slub.c:852:4: warning: format ‘%u’ expects argument of type ‘unsigned int’, 
but argument 4 has type ‘const char *’ [-Wformat=]
s-name, page-objects, maxobj);
^
mm/slub.c:852:4: warning: too many arguments for format [-Wformat-extra-args]
mm/slub.c:857:4: warning: format ‘%u’ expects argument of type ‘unsigned int’, 
but argument 4 has type ‘const char *’ [-Wformat=]
s-name, page-inuse, page-objects);
^
mm/slub.c:857:4: warning: too many arguments for format [-Wformat-extra-args]

mm/slub.c: In function ‘on_freelist’:
mm/slub.c:905:4: warning: format ‘%d’ expects argument of type ‘int’, but 
argument 5 has type ‘long unsigned int’ [-Wformat=]
should be %d, page-objects, max_objects);

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
Cc: Christoph Lameter c...@linux.com
Cc: Pekka Enberg penb...@kernel.org
Cc: David Rientjes rient...@google.com
Cc: Joonsoo Kim iamjoonsoo@lge.com
---
 mm/slub.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mm/slub.c b/mm/slub.c
index 80c170e..850a94a 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -849,12 +849,12 @@ static int check_slab(struct kmem_cache *s, struct page 
*page)
maxobj = order_objects(compound_order(page), s-size, s-reserved);
if (page-objects  maxobj) {
slab_err(s, page, objects %u  max %u,
-   s-name, page-objects, maxobj);
+   page-objects, maxobj);
return 0;
}
if (page-inuse  page-objects) {
slab_err(s, page, inuse %u  max %u,
-   s-name, page-inuse, page-objects);
+   page-inuse, page-objects);
return 0;
}
/* Slab_pad_check fixes things up after itself */
@@ -902,7 +902,7 @@ static int on_freelist(struct kmem_cache *s, struct page 
*page, void *search)
 
if (page-objects != max_objects) {
slab_err(s, page, Wrong number of objects. Found %d but 
-   should be %d, page-objects, max_objects);
+   should be %ld, page-objects, max_objects);
page-objects = max_objects;
slab_fix(s, Number of objects adjusted.);
}
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2] mm: slub: fix format mismatches in slab_err() callers

2014-11-06 Thread Andrey Ryabinin
Adding __printf(3, 4) to slab_err exposed following:

mm/slub.c: In function ‘check_slab’:
mm/slub.c:852:4: warning: format ‘%u’ expects argument of type ‘unsigned int’, 
but argument 4 has type ‘const char *’ [-Wformat=]
s-name, page-objects, maxobj);
^
mm/slub.c:852:4: warning: too many arguments for format [-Wformat-extra-args]
mm/slub.c:857:4: warning: format ‘%u’ expects argument of type ‘unsigned int’, 
but argument 4 has type ‘const char *’ [-Wformat=]
s-name, page-inuse, page-objects);
^
mm/slub.c:857:4: warning: too many arguments for format [-Wformat-extra-args]

mm/slub.c: In function ‘on_freelist’:
mm/slub.c:905:4: warning: format ‘%d’ expects argument of type ‘int’, but 
argument 5 has type ‘long unsigned int’ [-Wformat=]
should be %d, page-objects, max_objects);

Fix first two warnings by removing redundant s-name.
Fix the last by changing type of max_object from unsigned long to int.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
Cc: Christoph Lameter c...@linux.com
Cc: Pekka Enberg penb...@kernel.org
Cc: David Rientjes rient...@google.com
Cc: Joonsoo Kim iamjoonsoo@lge.com
---

Changes since v1:
  - To fix the last warning change the type of max_objects instead of changing 
format string (David)
  - Slightly update changelog

 mm/slub.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mm/slub.c b/mm/slub.c
index 80c170e..ed816f8 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -849,12 +849,12 @@ static int check_slab(struct kmem_cache *s, struct page 
*page)
maxobj = order_objects(compound_order(page), s-size, s-reserved);
if (page-objects  maxobj) {
slab_err(s, page, objects %u  max %u,
-   s-name, page-objects, maxobj);
+   page-objects, maxobj);
return 0;
}
if (page-inuse  page-objects) {
slab_err(s, page, inuse %u  max %u,
-   s-name, page-inuse, page-objects);
+   page-inuse, page-objects);
return 0;
}
/* Slab_pad_check fixes things up after itself */
@@ -871,7 +871,7 @@ static int on_freelist(struct kmem_cache *s, struct page 
*page, void *search)
int nr = 0;
void *fp;
void *object = NULL;
-   unsigned long max_objects;
+   int max_objects;
 
fp = page-freelist;
while (fp  nr = page-objects) {
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 00/12] Kernel address sanitizer - runtime memory debugger.

2014-11-27 Thread Andrey Ryabinin
://gcc.gnu.org/ml/gcc-patches/2014-10/msg02510.html

- Updated GCC version requirements in doc (GCC kasan patches were 
backported into 4.9 branch)

- Dropped last patch with inline instrumentation support. At first let's 
wait for merging GCC patches.

Changes since v3:

- rebased on last mm
- Added comment about rcu slabs.
- Removed useless kasan_free_slab_pages().
- Removed __asan_init_v*() stub. GCC doesn't generate this call anymore:
   https://gcc.gnu.org/ml/gcc-patches/2014-10/msg00269.html
- Replaced CALL_KASAN_REPORT define with inline function

Changes since v2:

- Shadow moved to vmalloc area.
- Added posion page. This page mapped to shadow correspondig to
  shadow region itself:
   [kasan_mem_to_shadow(KASAN_SHADOW_START) - 
kasan_mem_to_shadow(KASAN_SHADOW_END)]
  It used to catch memory access to shadow outside mm/kasan/.

- Fixed boot with CONFIG_DEBUG_VIRTUAL=y
- Fixed boot with KASan and stack protector enabled
 (patch x86_64: load_percpu_segment: read irq_stack_union.gs_base 
before load_segment)

- Fixed build with CONFIG_EFI_STUB=y
- Some slub specific stuf moved from mm/slab.h to include/linux/slub_def.h
- Fixed Kconfig dependency. CONFIG_KASAN depends on CONFIG_SLUB_DEBUG.
- Optimizations of __asan_load/__asan_store.
- Spelling fixes from Randy.
- Misc minor cleanups in different places.


- Added inline instrumentation in last patch. This will require two not
 yet-in-trunk-patches for GCC:
 https://gcc.gnu.org/ml/gcc-patches/2014-09/msg00452.html
 https://gcc.gnu.org/ml/gcc-patches/2014-09/msg00605.html

Changes since v1:

- The main change is in shadow memory laoyut.
  Now for shadow memory we reserve 1/8 of all virtual addresses available 
for kernel.
  16TB on x86_64 to cover all 128TB of kernel's address space.
  At early stage we map whole shadow region with zero page.
  Latter, after physical memory mapped to direct mapping address range
  we unmap zero pages from corresponding shadow and allocate and map a real
  memory.

 - Since per-arch work is much bigger now, support for arm/x86_32 platforms 
was dropped.

 - CFLAGS was change from -fsanitize=address with different --params to 
-fsanitize=kernel-address

 - If compiler doesn't support -fsanitize=kernel-address warning printed 
and build continues without -fsanitize

 - Removed kasan_memset/kasan_memcpy/kasan_memmove hooks. It turned out 
that this hooks are not needed. Compiler
   already instrument memset/memcpy/memmove (inserts 
__asan_load/__asan_store call before mem*() calls).

 - branch profiling disabled for mm/kasan/kasan.c to avoid recursion 
(__asan_load - ftrace_likely_update - __asan_load - ...)

 - kasan hooks for buddy allocator moved to right places


Andrey Ryabinin (12):
  Add kernel address sanitizer infrastructure.
  x86_64: load_percpu_segment: read irq_stack_union.gs_base before
load_segment
  x86_64: add KASan support
  mm: page_alloc: add kasan hooks on alloc and free paths
  mm: slub: introduce virt_to_obj function.
  mm: slub: share slab_err and object_err functions
  mm: slub: introduce metadata_access_enable()/metadata_access_disable()
  mm: slub: add kernel address sanitizer support for slub allocator
  fs: dcache: manually unpoison dname after allocation to shut up
kasan's reports
  kmemleak: disable kasan instrumentation for kmemleak
  lib: add kasan test module
  x86_64: kasan: add interceptors for memset/memmove/memcpy functions

 Documentation/kasan.txt| 169 +++
 Makefile   |  23 +-
 arch/x86/Kconfig   |   1 +
 arch/x86/boot/Makefile |   2 +
 arch/x86/boot/compressed/Makefile  |   2 +
 arch/x86/boot/compressed/eboot.c   |   3 +-
 arch/x86/boot/compressed/misc.h|   1 +
 arch/x86/include/asm/kasan.h   |  27 ++
 arch/x86/include/asm/string_64.h   |  18 +-
 arch/x86/kernel/Makefile   |   2 +
 arch/x86/kernel/cpu/common.c   |   4 +-
 arch/x86/kernel/dumpstack.c|   5 +-
 arch/x86/kernel/head64.c   |   9 +-
 arch/x86/kernel/head_64.S  |  28 ++
 arch/x86/kernel/setup.c|   3 +
 arch/x86/kernel/x8664_ksyms_64.c   |  10 +-
 arch/x86/lib/memcpy_64.S   |   6 +-
 arch/x86/lib/memmove_64.S  |   4 +
 arch/x86/lib/memset_64.S   |  10 +-
 arch/x86/mm/Makefile   |   3 +
 arch/x86/mm/kasan_init_64.c| 108 +++
 arch/x86/realmode/Makefile |   2 +-
 arch/x86/realmode/rm/Makefile  |   1 +
 arch/x86/vdso/Makefile |   1 +
 drivers/firmware/efi/libstub/Makefile  |   1 +
 drivers/firmware/efi/libstub/efistub.h |   4 +
 fs/dcache.c|   6 +
 include/linux/kasan.h  |  69 +
 include/linux/sched.h

[PATCH v8 04/12] mm: page_alloc: add kasan hooks on alloc and free paths

2014-11-27 Thread Andrey Ryabinin
Add kernel address sanitizer hooks to mark allocated page's addresses
as accessible in corresponding shadow region.
Mark freed pages as inaccessible.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/kasan.h |  6 ++
 mm/compaction.c   |  2 ++
 mm/kasan/kasan.c  | 14 ++
 mm/kasan/kasan.h  |  1 +
 mm/kasan/report.c |  7 +++
 mm/page_alloc.c   |  3 +++
 6 files changed, 33 insertions(+)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 01c99fe..9714fba 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -30,6 +30,9 @@ static inline void kasan_disable_local(void)
 
 void kasan_unpoison_shadow(const void *address, size_t size);
 
+void kasan_alloc_pages(struct page *page, unsigned int order);
+void kasan_free_pages(struct page *page, unsigned int order);
+
 #else /* CONFIG_KASAN */
 
 static inline void kasan_unpoison_shadow(const void *address, size_t size) {}
@@ -37,6 +40,9 @@ static inline void kasan_unpoison_shadow(const void *address, 
size_t size) {}
 static inline void kasan_enable_local(void) {}
 static inline void kasan_disable_local(void) {}
 
+static inline void kasan_alloc_pages(struct page *page, unsigned int order) {}
+static inline void kasan_free_pages(struct page *page, unsigned int order) {}
+
 #endif /* CONFIG_KASAN */
 
 #endif /* LINUX_KASAN_H */
diff --git a/mm/compaction.c b/mm/compaction.c
index 546e571..12f2c7d 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -16,6 +16,7 @@
 #include linux/sysfs.h
 #include linux/balloon_compaction.h
 #include linux/page-isolation.h
+#include linux/kasan.h
 #include internal.h
 
 #ifdef CONFIG_COMPACTION
@@ -61,6 +62,7 @@ static void map_pages(struct list_head *list)
list_for_each_entry(page, list, lru) {
arch_alloc_page(page, 0);
kernel_map_pages(page, 1, 1);
+   kasan_alloc_pages(page, 0);
}
 }
 
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index f77be01..b336073 100644
--- a/mm/kasan/kasan.c
+++ b/mm/kasan/kasan.c
@@ -247,6 +247,20 @@ static __always_inline void check_memory_region(unsigned 
long addr,
kasan_report(addr, size, write);
 }
 
+void kasan_alloc_pages(struct page *page, unsigned int order)
+{
+   if (likely(!PageHighMem(page)))
+   kasan_unpoison_shadow(page_address(page), PAGE_SIZE  order);
+}
+
+void kasan_free_pages(struct page *page, unsigned int order)
+{
+   if (likely(!PageHighMem(page)))
+   kasan_poison_shadow(page_address(page),
+   PAGE_SIZE  order,
+   KASAN_FREE_PAGE);
+}
+
 void __asan_load1(unsigned long addr)
 {
check_memory_region(addr, 1, false);
diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h
index 6da1d78..2a6a961 100644
--- a/mm/kasan/kasan.h
+++ b/mm/kasan/kasan.h
@@ -6,6 +6,7 @@
 #define KASAN_SHADOW_SCALE_SIZE (1UL  KASAN_SHADOW_SCALE_SHIFT)
 #define KASAN_SHADOW_MASK   (KASAN_SHADOW_SCALE_SIZE - 1)
 
+#define KASAN_FREE_PAGE 0xFF  /* page was freed */
 #define KASAN_SHADOW_GAP0xF9  /* address belongs to shadow memory */
 
 struct access_info {
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 56a2089..8ac3b6b 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -57,6 +57,9 @@ static void print_error_description(struct access_info *info)
case 0 ... KASAN_SHADOW_SCALE_SIZE - 1:
bug_type = out of bounds access;
break;
+   case KASAN_FREE_PAGE:
+   bug_type = use after free;
+   break;
case KASAN_SHADOW_GAP:
bug_type = wild memory access;
break;
@@ -78,6 +81,10 @@ static void print_address_description(struct access_info 
*info)
page = virt_to_head_page((void *)info-access_addr);
 
switch (shadow_val) {
+   case KASAN_FREE_PAGE:
+   dump_page(page, kasan error);
+   dump_stack();
+   break;
case KASAN_SHADOW_GAP:
pr_err(No metainfo is available for this access.\n);
dump_stack();
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 0b2f5a6..4ea0e33 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -25,6 +25,7 @@
 #include linux/compiler.h
 #include linux/kernel.h
 #include linux/kmemcheck.h
+#include linux/kasan.h
 #include linux/module.h
 #include linux/suspend.h
 #include linux/pagevec.h
@@ -804,6 +805,7 @@ static bool free_pages_prepare(struct page *page, unsigned 
int order)
 
trace_mm_page_free(page, order);
kmemcheck_free_shadow(page, order);
+   kasan_free_pages(page, order);
 
if (PageAnon(page))
page-mapping = NULL;
@@ -982,6 +984,7 @@ static int prep_new_page(struct page *page, unsigned int 
order, gfp_t gfp_flags)
 
arch_alloc_page(page, order);
kernel_map_pages(page, 1  order, 1);
+   kasan_alloc_pages(page, order);
 
if (gfp_flags

[PATCH v8 07/12] mm: slub: introduce metadata_access_enable()/metadata_access_disable()

2014-11-27 Thread Andrey Ryabinin
Wrap access to object's metadata in external functions with
metadata_access_enable()/metadata_access_disable() function calls.

This hooks separates payload accesses from metadata accesses
which might be useful for different checkers (e.g. KASan).

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 mm/slub.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/mm/slub.c b/mm/slub.c
index 0c01584..88ad8b8 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -467,13 +467,23 @@ static int slub_debug;
 static char *slub_debug_slabs;
 static int disable_higher_order_debug;
 
+static inline void metadata_access_enable(void)
+{
+}
+
+static inline void metadata_access_disable(void)
+{
+}
+
 /*
  * Object debugging
  */
 static void print_section(char *text, u8 *addr, unsigned int length)
 {
+   metadata_access_enable();
print_hex_dump(KERN_ERR, text, DUMP_PREFIX_ADDRESS, 16, 1, addr,
length, 1);
+   metadata_access_disable();
 }
 
 static struct track *get_track(struct kmem_cache *s, void *object,
@@ -503,7 +513,9 @@ static void set_track(struct kmem_cache *s, void *object,
trace.max_entries = TRACK_ADDRS_COUNT;
trace.entries = p-addrs;
trace.skip = 3;
+   metadata_access_enable();
save_stack_trace(trace);
+   metadata_access_disable();
 
/* See rant in lockdep.c */
if (trace.nr_entries != 0 
@@ -677,7 +689,9 @@ static int check_bytes_and_report(struct kmem_cache *s, 
struct page *page,
u8 *fault;
u8 *end;
 
+   metadata_access_enable();
fault = memchr_inv(start, value, bytes);
+   metadata_access_disable();
if (!fault)
return 1;
 
@@ -770,7 +784,9 @@ static int slab_pad_check(struct kmem_cache *s, struct page 
*page)
if (!remainder)
return 1;
 
+   metadata_access_enable();
fault = memchr_inv(end - remainder, POISON_INUSE, remainder);
+   metadata_access_disable();
if (!fault)
return 1;
while (end  fault  end[-1] == POISON_INUSE)
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 10/12] kmemleak: disable kasan instrumentation for kmemleak

2014-11-27 Thread Andrey Ryabinin
kmalloc internally round up allocation size, and kmemleak
uses rounded up size as object's size. This makes kasan
to complain while kmemleak scans memory or calculates of object's
checksum. The simplest solution here is to disable kasan.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 mm/kmemleak.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 3cda50c..9bda1b3 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -98,6 +98,7 @@
 #include asm/processor.h
 #include linux/atomic.h
 
+#include linux/kasan.h
 #include linux/kmemcheck.h
 #include linux/kmemleak.h
 #include linux/memory_hotplug.h
@@ -1113,7 +1114,10 @@ static bool update_checksum(struct kmemleak_object 
*object)
if (!kmemcheck_is_obj_initialized(object-pointer, object-size))
return false;
 
+   kasan_disable_local();
object-checksum = crc32(0, (void *)object-pointer, object-size);
+   kasan_enable_local();
+
return object-checksum != old_csum;
 }
 
@@ -1164,7 +1168,9 @@ static void scan_block(void *_start, void *_end,
  BYTES_PER_POINTER))
continue;
 
+   kasan_disable_local();
pointer = *ptr;
+   kasan_enable_local();
 
object = find_and_get_object(pointer, 1);
if (!object)
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 12/12] x86_64: kasan: add interceptors for memset/memmove/memcpy functions

2014-11-27 Thread Andrey Ryabinin
Recently instrumentation of builtin functions calls was removed from GCC 5.0.
To check the memory accessed by such functions, userspace asan always uses
interceptors for them.

So now we should do this as well. This patch declares memset/memmove/memcpy
as weak symbols. In mm/kasan/kasan.c we have our own implementation
of those functions which checks memory before accessing it.

Default memset/memmove/memcpy now now always have aliases with '__' prefix.
For files that built without kasan instrumentation (e.g. mm/slub.c)
original mem* replaced (via #define) with prefixed variants,
cause we don't want to check memory accesses there.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 arch/x86/boot/compressed/eboot.c   |  3 +--
 arch/x86/boot/compressed/misc.h|  1 +
 arch/x86/include/asm/string_64.h   | 18 +-
 arch/x86/kernel/x8664_ksyms_64.c   | 10 --
 arch/x86/lib/memcpy_64.S   |  6 --
 arch/x86/lib/memmove_64.S  |  4 
 arch/x86/lib/memset_64.S   | 10 ++
 drivers/firmware/efi/libstub/efistub.h |  4 
 mm/kasan/kasan.c   | 31 ++-
 9 files changed, 75 insertions(+), 12 deletions(-)

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index 92b9a5f..ef17683 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -13,8 +13,7 @@
 #include asm/setup.h
 #include asm/desc.h
 
-#undef memcpy  /* Use memcpy from misc.c */
-
+#include ../string.h
 #include eboot.h
 
 static efi_system_table_t *sys_table;
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 24e3e56..04477d6 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -7,6 +7,7 @@
  * we just keep it from happening
  */
 #undef CONFIG_PARAVIRT
+#undef CONFIG_KASAN
 #ifdef CONFIG_X86_32
 #define _ASM_X86_DESC_H 1
 #endif
diff --git a/arch/x86/include/asm/string_64.h b/arch/x86/include/asm/string_64.h
index 19e2c46..e466119 100644
--- a/arch/x86/include/asm/string_64.h
+++ b/arch/x86/include/asm/string_64.h
@@ -27,11 +27,12 @@ static __always_inline void *__inline_memcpy(void *to, 
const void *from, size_t
function. */
 
 #define __HAVE_ARCH_MEMCPY 1
+extern void *__memcpy(void *to, const void *from, size_t len);
+
 #ifndef CONFIG_KMEMCHECK
 #if (__GNUC__ == 4  __GNUC_MINOR__ = 3) || __GNUC__  4
 extern void *memcpy(void *to, const void *from, size_t len);
 #else
-extern void *__memcpy(void *to, const void *from, size_t len);
 #define memcpy(dst, src, len)  \
 ({ \
size_t __len = (len);   \
@@ -53,9 +54,11 @@ extern void *__memcpy(void *to, const void *from, size_t 
len);
 
 #define __HAVE_ARCH_MEMSET
 void *memset(void *s, int c, size_t n);
+void *__memset(void *s, int c, size_t n);
 
 #define __HAVE_ARCH_MEMMOVE
 void *memmove(void *dest, const void *src, size_t count);
+void *__memmove(void *dest, const void *src, size_t count);
 
 int memcmp(const void *cs, const void *ct, size_t count);
 size_t strlen(const char *s);
@@ -63,6 +66,19 @@ char *strcpy(char *dest, const char *src);
 char *strcat(char *dest, const char *src);
 int strcmp(const char *cs, const char *ct);
 
+#if defined(CONFIG_KASAN)  !defined(__SANITIZE_ADDRESS__)
+
+/*
+ * For files that not instrumented (e.g. mm/slub.c) we
+ * should use not instrumented version of mem* functions.
+ */
+
+#undef memcpy
+#define memcpy(dst, src, len) __memcpy(dst, src, len)
+#define memmove(dst, src, len) __memmove(dst, src, len)
+#define memset(s, c, n) __memset(s, c, n)
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_X86_STRING_64_H */
diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c
index 0406819..37d8fa4 100644
--- a/arch/x86/kernel/x8664_ksyms_64.c
+++ b/arch/x86/kernel/x8664_ksyms_64.c
@@ -50,13 +50,19 @@ EXPORT_SYMBOL(csum_partial);
 #undef memset
 #undef memmove
 
+extern void *__memset(void *, int, __kernel_size_t);
+extern void *__memcpy(void *, const void *, __kernel_size_t);
+extern void *__memmove(void *, const void *, __kernel_size_t);
 extern void *memset(void *, int, __kernel_size_t);
 extern void *memcpy(void *, const void *, __kernel_size_t);
-extern void *__memcpy(void *, const void *, __kernel_size_t);
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+EXPORT_SYMBOL(__memset);
+EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(__memmove);
 
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(__memcpy);
 EXPORT_SYMBOL(memmove);
 
 #ifndef CONFIG_DEBUG_VIRTUAL
diff --git a/arch/x86/lib/memcpy_64.S b/arch/x86/lib/memcpy_64.S
index 56313a3..89b53c9 100644
--- a/arch/x86/lib/memcpy_64.S
+++ b/arch/x86/lib/memcpy_64.S
@@ -53,6 +53,8 @@
 .Lmemcpy_e_e:
.previous
 
+.weak memcpy
+
 ENTRY(__memcpy)
 ENTRY(memcpy

[PATCH v8 11/12] lib: add kasan test module

2014-11-27 Thread Andrey Ryabinin
This is a test module doing various nasty things like
out of bounds accesses, use after free. It is useful for testing
kernel debugging features like kernel address sanitizer.

It mostly concentrates on testing of slab allocator, but we
might want to add more different stuff here in future (like
stack/global variables out of bounds accesses and so on).

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 lib/Kconfig.kasan |   8 ++
 lib/Makefile  |   1 +
 lib/test_kasan.c  | 254 ++
 3 files changed, 263 insertions(+)
 create mode 100644 lib/test_kasan.c

diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index 1fa4fe8..8548646 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -43,4 +43,12 @@ config KASAN_INLINE
 
 endchoice
 
+config TEST_KASAN
+   tristate Module for testing kasan for bug detection
+   depends on m  KASAN
+   help
+ This is a test module doing various nasty things like
+ out of bounds accesses, use after free. It is useful for testing
+ kernel debugging features like kernel address sanitizer.
+
 endif
diff --git a/lib/Makefile b/lib/Makefile
index c47f092..4a562a6 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_TEST_LKM) += test_module.o
 obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
 obj-$(CONFIG_TEST_BPF) += test_bpf.o
 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
+obj-$(CONFIG_TEST_KASAN) += test_kasan.o
 
 ifeq ($(CONFIG_DEBUG_KOBJECT),y)
 CFLAGS_kobject.o += -DDEBUG
diff --git a/lib/test_kasan.c b/lib/test_kasan.c
new file mode 100644
index 000..896dee5
--- /dev/null
+++ b/lib/test_kasan.c
@@ -0,0 +1,254 @@
+/*
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ * Author: Andrey Ryabinin a.ryabi...@samsung.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#define pr_fmt(fmt) kasan test: %s  fmt, __func__
+
+#include linux/kernel.h
+#include linux/printk.h
+#include linux/slab.h
+#include linux/string.h
+#include linux/module.h
+
+static noinline void __init kmalloc_oob_right(void)
+{
+   char *ptr;
+   size_t size = 123;
+
+   pr_info(out-of-bounds to right\n);
+   ptr = kmalloc(size, GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 'x';
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_oob_left(void)
+{
+   char *ptr;
+   size_t size = 15;
+
+   pr_info(out-of-bounds to left\n);
+   ptr = kmalloc(size, GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   *ptr = *(ptr - 1);
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_node_oob_right(void)
+{
+   char *ptr;
+   size_t size = 4096;
+
+   pr_info(kmalloc_node(): out-of-bounds to right\n);
+   ptr = kmalloc_node(size, GFP_KERNEL, 0);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 0;
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_large_oob_rigth(void)
+{
+   char *ptr;
+   size_t size = KMALLOC_MAX_CACHE_SIZE + 10;
+
+   pr_info(kmalloc large allocation: out-of-bounds to right\n);
+   ptr = kmalloc(size, GFP_KERNEL);
+   if (!ptr) {
+   pr_err(Allocation failed\n);
+   return;
+   }
+
+   ptr[size] = 0;
+   kfree(ptr);
+}
+
+static noinline void __init kmalloc_oob_krealloc_more(void)
+{
+   char *ptr1, *ptr2;
+   size_t size1 = 17;
+   size_t size2 = 19;
+
+   pr_info(out-of-bounds after krealloc more\n);
+   ptr1 = kmalloc(size1, GFP_KERNEL);
+   ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1);
+   return;
+   }
+
+   ptr2[size2] = 'x';
+   kfree(ptr2);
+}
+
+static noinline void __init kmalloc_oob_krealloc_less(void)
+{
+   char *ptr1, *ptr2;
+   size_t size1 = 17;
+   size_t size2 = 15;
+
+   pr_info(out-of-bounds after krealloc less\n);
+   ptr1 = kmalloc(size1, GFP_KERNEL);
+   ptr2 = krealloc(ptr1, size2, GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1);
+   return;
+   }
+   ptr2[size1] = 'x';
+   kfree(ptr2);
+}
+
+static noinline void __init kmalloc_oob_16(void)
+{
+   struct {
+   u64 words[2];
+   } *ptr1, *ptr2;
+
+   pr_info(kmalloc out-of-bounds for 16-bytes access\n);
+   ptr1 = kmalloc(sizeof(*ptr1) - 3, GFP_KERNEL);
+   ptr2 = kmalloc(sizeof(*ptr2), GFP_KERNEL);
+   if (!ptr1 || !ptr2) {
+   pr_err(Allocation failed\n);
+   kfree(ptr1

[PATCH v8 09/12] fs: dcache: manually unpoison dname after allocation to shut up kasan's reports

2014-11-27 Thread Andrey Ryabinin
We need to manually unpoison rounded up allocation size for dname
to avoid kasan's reports in dentry_string_cmp().
When CONFIG_DCACHE_WORD_ACCESS=y dentry_string_cmp may access
few bytes beyound requested in kmalloc() size.

dentry_string_cmp() relates on that fact that dentry allocated
using kmalloc and kmalloc internally round up allocation size.
So this is not a bug, but this makes kasan to complain about
such accesses.
To avoid such reports we mark rounded up allocation size in
shadow as accessible.

Reported-by: Dmitry Vyukov dvyu...@google.com
Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 fs/dcache.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/fs/dcache.c b/fs/dcache.c
index e368d4f..81561c8 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -38,6 +38,8 @@
 #include linux/prefetch.h
 #include linux/ratelimit.h
 #include linux/list_lru.h
+#include linux/kasan.h
+
 #include internal.h
 #include mount.h
 
@@ -1430,6 +1432,10 @@ struct dentry *__d_alloc(struct super_block *sb, const 
struct qstr *name)
}
atomic_set(p-u.count, 1);
dname = p-name;
+#ifdef CONFIG_DCACHE_WORD_ACCESS
+   kasan_unpoison_shadow(dname,
+   round_up(name-len + 1, sizeof(unsigned long)));
+#endif
} else  {
dname = dentry-d_iname;
}   
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 08/12] mm: slub: add kernel address sanitizer support for slub allocator

2014-11-27 Thread Andrey Ryabinin
With this patch kasan will be able to catch bugs in memory allocated
by slub.
Initially all objects in newly allocated slab page, marked as free.
Later, when allocation of slub object happens, requested by caller
number of bytes marked as accessible, and the rest of the object
(including slub's metadata) marked as redzone (inaccessible).

We also mark object as accessible if ksize was called for this object.
There is some places in kernel where ksize function is called to inquire
size of really allocated area. Such callers could validly access whole
allocated memory, so it should be marked as accessible.

Code in slub.c and slab_common.c files could validly access to object's
metadata, so instrumentation for this files are disabled.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/kasan.h | 21 
 include/linux/slab.h  | 11 --
 lib/Kconfig.kasan |  1 +
 mm/Makefile   |  3 ++
 mm/kasan/kasan.c  | 92 +++
 mm/kasan/kasan.h  |  4 +++
 mm/kasan/report.c | 25 ++
 mm/slab_common.c  |  5 ++-
 mm/slub.c | 36 ++--
 9 files changed, 192 insertions(+), 6 deletions(-)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index 9714fba..0463b90 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -32,6 +32,16 @@ void kasan_unpoison_shadow(const void *address, size_t size);
 
 void kasan_alloc_pages(struct page *page, unsigned int order);
 void kasan_free_pages(struct page *page, unsigned int order);
+void kasan_mark_slab_padding(struct kmem_cache *s, void *object,
+   struct page *page);
+
+void kasan_kmalloc_large(const void *ptr, size_t size);
+void kasan_kfree_large(const void *ptr);
+void kasan_kmalloc(struct kmem_cache *s, const void *object, size_t size);
+void kasan_krealloc(const void *object, size_t new_size);
+
+void kasan_slab_alloc(struct kmem_cache *s, void *object);
+void kasan_slab_free(struct kmem_cache *s, void *object);
 
 #else /* CONFIG_KASAN */
 
@@ -42,6 +52,17 @@ static inline void kasan_disable_local(void) {}
 
 static inline void kasan_alloc_pages(struct page *page, unsigned int order) {}
 static inline void kasan_free_pages(struct page *page, unsigned int order) {}
+static inline void kasan_mark_slab_padding(struct kmem_cache *s, void *object,
+   struct page *page) {}
+
+static inline void kasan_kmalloc_large(void *ptr, size_t size) {}
+static inline void kasan_kfree_large(const void *ptr) {}
+static inline void kasan_kmalloc(struct kmem_cache *s, const void *object,
+   size_t size) {}
+static inline void kasan_krealloc(const void *object, size_t new_size) {}
+
+static inline void kasan_slab_alloc(struct kmem_cache *s, void *object) {}
+static inline void kasan_slab_free(struct kmem_cache *s, void *object) {}
 
 #endif /* CONFIG_KASAN */
 
diff --git a/include/linux/slab.h b/include/linux/slab.h
index 8a2457d..5dc0d69 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -104,6 +104,7 @@
(unsigned long)ZERO_SIZE_PTR)
 
 #include linux/kmemleak.h
+#include linux/kasan.h
 
 struct mem_cgroup;
 /*
@@ -326,7 +327,10 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
 static __always_inline void *kmem_cache_alloc_trace(struct kmem_cache *s,
gfp_t flags, size_t size)
 {
-   return kmem_cache_alloc(s, flags);
+   void *ret = kmem_cache_alloc(s, flags);
+
+   kasan_kmalloc(s, ret, size);
+   return ret;
 }
 
 static __always_inline void *
@@ -334,7 +338,10 @@ kmem_cache_alloc_node_trace(struct kmem_cache *s,
  gfp_t gfpflags,
  int node, size_t size)
 {
-   return kmem_cache_alloc_node(s, gfpflags, node);
+   void *ret = kmem_cache_alloc_node(s, gfpflags, node);
+
+   kasan_kmalloc(s, ret, size);
+   return ret;
 }
 #endif /* CONFIG_TRACING */
 
diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan
index 386cc8b..1fa4fe8 100644
--- a/lib/Kconfig.kasan
+++ b/lib/Kconfig.kasan
@@ -6,6 +6,7 @@ if HAVE_ARCH_KASAN
 config KASAN
bool AddressSanitizer: runtime memory debugger
depends on !MEMORY_HOTPLUG
+   depends on SLUB_DEBUG
help
  Enables address sanitizer - runtime memory debugger,
  designed to find out-of-bounds accesses and use-after-free bugs.
diff --git a/mm/Makefile b/mm/Makefile
index 930b52d..088c68e 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -2,6 +2,9 @@
 # Makefile for the linux memory manager.
 #
 
+KASAN_SANITIZE_slab_common.o := n
+KASAN_SANITIZE_slub.o := n
+
 mmu-y  := nommu.o
 mmu-$(CONFIG_MMU)  := gup.o highmem.o memory.o mincore.o \
   mlock.o mmap.o mprotect.o mremap.o msync.o rmap.o \
diff --git a/mm/kasan/kasan.c b/mm/kasan/kasan.c
index b336073..7bb20ad 100644
--- a/mm/kasan/kasan.c
+++ b/mm

[PATCH v8 01/12] Add kernel address sanitizer infrastructure.

2014-11-27 Thread Andrey Ryabinin
Socket Socket  Message  Elapsed
Size   SizeSize Time Throughput
bytes  bytes   bytessecs.10^6bits/sec

no debug:   87380  16384  1638430.0041624.72

kasan inline:   87380  16384  1638430.0012870.54

kasan outline:  87380  16384  1638430.0010586.39

kmemcheck:  87380  16384  1638430.03  20.23

- Also kmemcheck couldn't work on several CPUs. It always sets number 
of CPUs to 1.
  KASan doesn't have such limitation.

DEBUG_PAGEALLOC:
- KASan is slower than DEBUG_PAGEALLOC, but KASan works on sub-page
  granularity level, so it able to find more bugs.

SLUB_DEBUG (poisoning, redzones):
- SLUB_DEBUG has lower overhead than KASan.

- SLUB_DEBUG in most cases are not able to detect bad reads,
  KASan able to detect both reads and writes.

- In some cases (e.g. redzone overwritten) SLUB_DEBUG detect
  bugs only on allocation/freeing of object. KASan catch
  bugs right before it will happen, so we always know exact
  place of first bad read/write.

[1] https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel
[2] https://code.google.com/p/address-sanitizer/wiki/FoundBugs
[3] https://code.google.com/p/thread-sanitizer/wiki/FoundBugs
[4] https://code.google.com/p/memory-sanitizer/wiki/FoundBugs
[5] 
https://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel#Trophies

Based on work by Andrey Konovalov adech...@gmail.com

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 Documentation/kasan.txt   | 169 +++
 Makefile  |  23 ++-
 drivers/firmware/efi/libstub/Makefile |   1 +
 include/linux/kasan.h |  42 
 include/linux/sched.h |   3 +
 lib/Kconfig.debug |   2 +
 lib/Kconfig.kasan |  43 
 mm/Makefile   |   1 +
 mm/kasan/Makefile |   8 +
 mm/kasan/kasan.c  | 374 ++
 mm/kasan/kasan.h  |  49 +
 mm/kasan/report.c | 205 +++
 scripts/Makefile.lib  |  10 +
 13 files changed, 928 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/kasan.txt
 create mode 100644 include/linux/kasan.h
 create mode 100644 lib/Kconfig.kasan
 create mode 100644 mm/kasan/Makefile
 create mode 100644 mm/kasan/kasan.c
 create mode 100644 mm/kasan/kasan.h
 create mode 100644 mm/kasan/report.c

diff --git a/Documentation/kasan.txt b/Documentation/kasan.txt
new file mode 100644
index 000..a3a9009
--- /dev/null
+++ b/Documentation/kasan.txt
@@ -0,0 +1,169 @@
+Kernel address sanitizer
+
+
+0. Overview
+===
+
+Kernel Address sanitizer (KASan) is a dynamic memory error detector. It 
provides
+a fast and comprehensive solution for finding use-after-free and out-of-bounds
+bugs.
+
+KASan uses compile-time instrumentation for checking every memory access,
+therefore you will need a certain version of GCC = 4.9.2
+
+Currently KASan is supported only for x86_64 architecture and requires that the
+kernel be built with the SLUB allocator.
+
+1. Usage
+=
+
+To enable KASAN configure kernel with:
+
+ CONFIG_KASAN = y
+
+and choose between CONFIG_KASAN_OUTLINE and CONFIG_KASAN_INLINE. Outline/inline
+is compiler instrumentation types. The former produces smaller binary the
+latter is 1.1 - 2 times faster. Inline instrumentation requires GCC 5.0 or
+latter.
+
+Currently KASAN works only with the SLUB memory allocator.
+For better bug detection and nicer report, enable CONFIG_STACKTRACE and put
+at least 'slub_debug=U' in the boot cmdline.
+
+To disable instrumentation for specific files or directories, add a line
+similar to the following to the respective kernel Makefile:
+
+For a single file (e.g. main.o):
+KASAN_SANITIZE_main.o := n
+
+For all files in one directory:
+KASAN_SANITIZE := n
+
+1.1 Error reports
+==
+
+A typical out of bounds access report looks like this:
+
+==
+BUG: AddressSanitizer: out of bounds access in kmalloc_oob_right+0x65/0x75 
[test_kasan] at addr 8800693bc5d3
+Write of size 1 by task modprobe/1689
+=
+BUG kmalloc-128 (Not tainted): kasan error
+-
+
+Disabling lock debugging due to kernel taint
+INFO: Allocated in kmalloc_oob_right+0x3d/0x75 [test_kasan] age=0 cpu=0 
pid=1689
+ __slab_alloc+0x4b4/0x4f0
+ kmem_cache_alloc_trace+0x10b/0x190
+ kmalloc_oob_right+0x3d/0x75 [test_kasan]
+ init_module+0x9/0x47 [test_kasan]
+ do_one_initcall+0x99/0x200
+ load_module+0x2cb3/0x3b20
+ SyS_finit_module+0x76/0x80

[PATCH v8 06/12] mm: slub: share slab_err and object_err functions

2014-11-27 Thread Andrey Ryabinin
Remove static and add function declarations to mm/slab.h so they
could be used by kernel address sanitizer.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 include/linux/slub_def.h | 5 +
 mm/slub.c| 4 ++--
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index c75bc1d..144b5cb 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -115,4 +115,9 @@ static inline void *virt_to_obj(struct kmem_cache *s, void 
*slab_page, void *x)
return x - ((x - slab_page) % s-size);
 }
 
+__printf(3, 4)
+void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...);
+void object_err(struct kmem_cache *s, struct page *page,
+   u8 *object, char *reason);
+
 #endif /* _LINUX_SLUB_DEF_H */
diff --git a/mm/slub.c b/mm/slub.c
index 95d2142..0c01584 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -629,14 +629,14 @@ static void print_trailer(struct kmem_cache *s, struct 
page *page, u8 *p)
dump_stack();
 }
 
-static void object_err(struct kmem_cache *s, struct page *page,
+void object_err(struct kmem_cache *s, struct page *page,
u8 *object, char *reason)
 {
slab_bug(s, %s, reason);
print_trailer(s, page, object);
 }
 
-static void slab_err(struct kmem_cache *s, struct page *page,
+void slab_err(struct kmem_cache *s, struct page *page,
const char *fmt, ...)
 {
va_list args;
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 05/12] mm: slub: introduce virt_to_obj function.

2014-11-27 Thread Andrey Ryabinin
virt_to_obj takes kmem_cache address, address of slab page,
address x pointing somewhere inside slab object,
and returns address of the begging of object.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
Acked-by: Christoph Lameter c...@linux.com
---
 include/linux/slub_def.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index d82abd4..c75bc1d 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -110,4 +110,9 @@ static inline void sysfs_slab_remove(struct kmem_cache *s)
 }
 #endif
 
+static inline void *virt_to_obj(struct kmem_cache *s, void *slab_page, void *x)
+{
+   return x - ((x - slab_page) % s-size);
+}
+
 #endif /* _LINUX_SLUB_DEF_H */
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v8 03/12] x86_64: add KASan support

2014-11-27 Thread Andrey Ryabinin
This patch adds arch specific code for kernel address sanitizer.

16TB of virtual addressed used for shadow memory.
It's located in range [0xd900 - 0xe900]
which belongs to vmalloc area.

At early stage we map whole shadow region with zero page.
Latter, after pages mapped to direct mapping address range
we unmap zero pages from corresponding shadow (see kasan_map_shadow())
and allocate and map a real shadow memory reusing vmemmap_populate()
function.

Also replace __pa with __pa_nodebug before shadow initialized.
__pa with CONFIG_DEBUG_VIRTUAL=y make external function call (__phys_addr)
__phys_addr is instrumented, so __asan_load could be called before
shadow area initialized.

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 arch/x86/Kconfig  |   1 +
 arch/x86/boot/Makefile|   2 +
 arch/x86/boot/compressed/Makefile |   2 +
 arch/x86/include/asm/kasan.h  |  27 ++
 arch/x86/kernel/Makefile  |   2 +
 arch/x86/kernel/dumpstack.c   |   5 +-
 arch/x86/kernel/head64.c  |   9 +++-
 arch/x86/kernel/head_64.S |  28 ++
 arch/x86/kernel/setup.c   |   3 ++
 arch/x86/mm/Makefile  |   3 ++
 arch/x86/mm/kasan_init_64.c   | 108 ++
 arch/x86/realmode/Makefile|   2 +-
 arch/x86/realmode/rm/Makefile |   1 +
 arch/x86/vdso/Makefile|   1 +
 lib/Kconfig.kasan |   2 +
 15 files changed, 192 insertions(+), 4 deletions(-)
 create mode 100644 arch/x86/include/asm/kasan.h
 create mode 100644 arch/x86/mm/kasan_init_64.c

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index da51602..f761193 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -84,6 +84,7 @@ config X86
select HAVE_CMPXCHG_LOCAL
select HAVE_CMPXCHG_DOUBLE
select HAVE_ARCH_KMEMCHECK
+   select HAVE_ARCH_KASAN if X86_64
select HAVE_USER_RETURN_NOTIFIER
select ARCH_BINFMT_ELF_RANDOMIZE_PIE
select HAVE_ARCH_JUMP_LABEL
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index 5b016e2..1ef2724 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -14,6 +14,8 @@
 # Set it to -DSVGA_MODE=NORMAL_VGA if you just want the EGA/VGA mode.
 # The number is the same as you would ordinarily press at bootup.
 
+KASAN_SANITIZE := n
+
 SVGA_MODE  := -DSVGA_MODE=NORMAL_VGA
 
 targets:= vmlinux.bin setup.bin setup.elf bzImage
diff --git a/arch/x86/boot/compressed/Makefile 
b/arch/x86/boot/compressed/Makefile
index d999398..0bf4d9f 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -16,6 +16,8 @@
 #  (see scripts/Makefile.lib size_append)
 #  compressed vmlinux.bin.all + u32 size of vmlinux.bin.all
 
+KASAN_SANITIZE := n
+
 targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma 
\
vmlinux.bin.xz vmlinux.bin.lzo vmlinux.bin.lz4
 
diff --git a/arch/x86/include/asm/kasan.h b/arch/x86/include/asm/kasan.h
new file mode 100644
index 000..47e0d42
--- /dev/null
+++ b/arch/x86/include/asm/kasan.h
@@ -0,0 +1,27 @@
+#ifndef _ASM_X86_KASAN_H
+#define _ASM_X86_KASAN_H
+
+#define KASAN_SHADOW_START 0xd900UL
+#define KASAN_SHADOW_END   0xe900UL
+
+#ifndef __ASSEMBLY__
+
+extern pte_t zero_pte[];
+extern pte_t zero_pmd[];
+extern pte_t zero_pud[];
+
+extern pte_t poisoned_pte[];
+extern pte_t poisoned_pmd[];
+extern pte_t poisoned_pud[];
+
+#ifdef CONFIG_KASAN
+void __init kasan_map_zero_shadow(pgd_t *pgd);
+void __init kasan_init(void);
+#else
+static inline void kasan_map_zero_shadow(pgd_t *pgd) { }
+static inline void kasan_init(void) { }
+#endif
+
+#endif
+
+#endif
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 5d4502c..74d3f3e 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -16,6 +16,8 @@ CFLAGS_REMOVE_ftrace.o = -pg
 CFLAGS_REMOVE_early_printk.o = -pg
 endif
 
+KASAN_SANITIZE_head$(BITS).o := n
+
 CFLAGS_irq.o := -I$(src)/../include/asm/trace
 
 obj-y  := process_$(BITS).o signal.o entry_$(BITS).o
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c
index b74ebc7..cf3df1d 100644
--- a/arch/x86/kernel/dumpstack.c
+++ b/arch/x86/kernel/dumpstack.c
@@ -265,7 +265,10 @@ int __die(const char *str, struct pt_regs *regs, long err)
printk(SMP );
 #endif
 #ifdef CONFIG_DEBUG_PAGEALLOC
-   printk(DEBUG_PAGEALLOC);
+   printk(DEBUG_PAGEALLOC );
+#endif
+#ifdef CONFIG_KASAN
+   printk(KASAN);
 #endif
printk(\n);
if (notify_die(DIE_OOPS, str, regs, err,
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index eda1a86..b9e4e50 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -27,6 +27,7 @@
 #include asm/bios_ebda.h
 #include asm/bootparam_utils.h
 #include asm/microcode.h
+#include asm/kasan.h
 
 /*
  * Manage page tables very early on.
@@ -46,7

[PATCH v8 02/12] x86_64: load_percpu_segment: read irq_stack_union.gs_base before load_segment

2014-11-27 Thread Andrey Ryabinin
Reading irq_stack_union.gs_base after load_segment creates troubles for kasan.
Compiler inserts __asan_load in between load_segment and wrmsrl. If kernel
built with stackprotector this will result in boot failure because __asan_load
has stackprotector.

To avoid this irq_stack_union.gs_base stored to temporary variable before
load_segment, so __asan_load will be called before load_segment().

There are two alternative ways to fix this:
 a) Add __attribute__((no_sanitize_address)) to load_percpu_segment(),
which tells compiler to not instrument this function. However this
will result in build failure with CONFIG_KASAN=y and 
CONFIG_OPTIMIZE_INLINING=y.

 b) Add -fno-stack-protector for mm/kasan/kasan.c

Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 arch/x86/kernel/cpu/common.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 5475f67..1291d69 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -391,8 +391,10 @@ void load_percpu_segment(int cpu)
 #ifdef CONFIG_X86_32
loadsegment(fs, __KERNEL_PERCPU);
 #else
+   void *gs_base = per_cpu(irq_stack_union.gs_base, cpu);
+
loadsegment(gs, 0);
-   wrmsrl(MSR_GS_BASE, (unsigned long)per_cpu(irq_stack_union.gs_base, 
cpu));
+   wrmsrl(MSR_GS_BASE, (unsigned long)gs_base);
 #endif
load_stack_canary_segment();
 }
-- 
2.1.3

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] kernel: sysctl: use 'unsigned long' type for 'zero' variable

2014-12-04 Thread Andrey Ryabinin
On 12/04/2014 03:19 AM, Andrew Morton wrote:
 On Wed, 3 Dec 2014 15:25:24 -0800 Andrew Morton a...@linux-foundation.org 
 wrote:
 
 On Wed, 03 Dec 2014 15:41:21 +0300 Andrey Ryabinin a.ryabi...@samsung.com 
 wrote:


 Use the 'unsigned long' type for 'zero' variable to fix this.
 Changing type to 'unsigned long' shouldn't affect any other users
 of this variable.

 Reported-by: Dmitry Vyukov dvyu...@google.com
 Fixes: ed4d4902ebdd (mm, hugetlb: remove hugetlb_zero and 
 hugetlb_infinity)
 Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
 ---
  kernel/sysctl.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/kernel/sysctl.c b/kernel/sysctl.c
 index 15f2511..45c45c9 100644
 --- a/kernel/sysctl.c
 +++ b/kernel/sysctl.c
 @@ -120,7 +120,7 @@ static int sixty = 60;
  
  static int __maybe_unused neg_one = -1;
  
 -static int zero;
 +static unsigned long zero;
  static int __maybe_unused one = 1;
  static int __maybe_unused two = 2;
  static int __maybe_unused four = 4;

 Yeah, this is ghastly.

 Look at 

  {
  .procname   = numa_balancing,
  .data   = NULL, /* filled in by handler */
  .maxlen = sizeof(unsigned int),
  .mode   = 0644,
  .proc_handler   = sysctl_numa_balancing,
  .extra1 = zero,
  .extra2 = one,
  },

 Now extra1 points at a long and extra2 points at an int. 
 sysctl_numa_balancing() calls proc_dointvec_minmax() and I think your
 patch just broke big-endian 64-bit machines.  sched_autogroup_enabled
 breaks as well.
 
 Taking another look at this...
 
 numa_balancing will continue to work on big-endian because of course
 zero is still zero when byteswapped.  But that's such a hack, isn't
 documented and doesn't work for one, sixty, etc.
 

Yeah, I agree it's a bit hacky.

 I'm thinking a better fix here is to switch hugetlb_sysctl_handler to
 use `int's.  2^32 hugepages is enough for anybody.
 

It's 8 petabytes for 2MB pages, so yeah should be enough.
Perhaps it also makes sense to change types for counters in 'struct hstate' 
from longs to ints.



 hugetlb_overcommit_handler() will need conversion also.
 
 Perhaps auditing all the proc_doulongvec_minmax callsites is the way to
 attack this.
 

I've looked through this yesterday and didn't found anything obviously wrong.
Though I could easily miss something.


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [rtc-linux] [PATCH] rtc: s5m: terminate s5m_rtc_id array with empty element

2015-01-22 Thread Andrey Ryabinin
On 01/22/2015 12:37 PM, Krzysztof Kozlowski wrote:
 2015-01-21 16:06 GMT+01:00 Andrey Ryabinin a.ryabi...@samsung.com:
 Array of platform_device_id elements should be terminated
 with empty element.

 Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
 ---
  drivers/rtc/rtc-s5m.c | 1 +
  1 file changed, 1 insertion(+)
 
 
 Right, good catch.
 
 Reviewed-by: Krzysztof Kozlowski k.kozlow...@samsung.com
 
 Maybe also cc stable for fixing 5bccae6ec458 (rtc: s5m-rtc: add
 real-time clock driver for s5m8767)?
 

Probably. I didn't add stable tag because, I have no idea what are runtime
effects of this bug, so I don't know whether this worth for stable or not.

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH] net/9p: fix format string in p9_mount_tag_show()

2015-01-26 Thread Andrey Ryabinin
Using %s for non-NULL terminated string is quite
dangerous, since this causes reading out of bounds.
chan-tag is non-NULL terminated, so precision
must be specified for printing it.

Fixes: 86c8437383ac (net/9p: Add sysfs mount_tag file for virtio 9P device)
Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
---
 net/9p/trans_virtio.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
index daa749c..f0d5f90 100644
--- a/net/9p/trans_virtio.c
+++ b/net/9p/trans_virtio.c
@@ -504,7 +504,8 @@ static ssize_t p9_mount_tag_show(struct device *dev,
vdev = dev_to_virtio(dev);
chan = vdev-priv;
 
-   return snprintf(buf, chan-tag_len + 1, %s, chan-tag);
+   return snprintf(buf, chan-tag_len + 1, %.*s,
+   chan-tag_len, chan-tag);
 }
 
 static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL);
-- 
2.2.2

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] net/9p: fix format string in p9_mount_tag_show()

2015-01-26 Thread Andrey Ryabinin
On 01/26/2015 08:04 PM, David Laight wrote:
 From: Andrey Ryabinin
 Using %s for non-NULL terminated string is quite
 dangerous, since this causes reading out of bounds.
 chan-tag is non-NULL terminated, so precision
 must be specified for printing it.

 Fixes: 86c8437383ac (net/9p: Add sysfs mount_tag file for virtio 9P device)
 Signed-off-by: Andrey Ryabinin a.ryabi...@samsung.com
 ---
  net/9p/trans_virtio.c | 3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

 diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c
 index daa749c..f0d5f90 100644
 --- a/net/9p/trans_virtio.c
 +++ b/net/9p/trans_virtio.c
 @@ -504,7 +504,8 @@ static ssize_t p9_mount_tag_show(struct device *dev,
  vdev = dev_to_virtio(dev);
  chan = vdev-priv;

 -return snprintf(buf, chan-tag_len + 1, %s, chan-tag);
 
 Note the 'buffer length' passed to snprintf().

Yes, but 'buffer length' is length of buf, not chan-tag.
The problem with %s is that vsnprintf expects to chan-tag to be 
NULL-terminated,
so it calls strnlen(chan-tag, -1).
Thus we read beyond of allocated memory range:

==
BUG: AddressSanitizer: out of bounds access in strnlen+0xa7/0xb0 at addr 
88006b882d79
Read of size 1 by task cat/669
=
BUG kmalloc-16 (Not tainted): kasan: bad access detected
-

Disabling lock debugging due to kernel taint
INFO: Allocated in p9_virtio_probe+0x523/0x11d0 age=7711 cpu=1 pid=1
__slab_alloc.constprop.16+0x765/0x1220
__kmalloc+0x380/0x630
p9_virtio_probe+0x523/0x11d0
virtio_dev_probe+0x739/0x11e0
really_probe+0x204/0xd10
__driver_attach+0x2c1/0x470
bus_for_each_dev+0x16c/0x280
driver_attach+0x48/0x80
bus_add_driver+0x490/0x970
driver_register+0x274/0x620
register_virtio_driver+0x97/0x140
p9_virtio_init+0x31/0x33
do_one_initcall+0x1fb/0x3a0
kernel_init_freeable+0x40d/0x4b1
kernel_init+0xe/0xf0
ret_from_fork+0x7c/0xb0
INFO: Slab 0xea0001ae2080 objects=23 used=23 fp=0x  (null) 
flags=0x40004080
INFO: Object 0x88006b882d70 @offset=3440 fp=0x88006b882ec8

Bytes b4 88006b882d60: 00 00 00 00 00 00 00 00 5a 5a 5a 5a 5a 5a 5a 5a  

Object 88006b882d70: 2f 64 65 76 2f 72 6f 6f 74 6b 6b 6b 6b 6b 6b a5  
/dev/rootkk.
Redzone 88006b882d80: cc cc cc cc cc cc cc cc  

Padding 88006b882ec0: 5a 5a 5a 5a 5a 5a 5a 5a  

CPU: 3 PID: 669 Comm: cat Tainted: GB  3.19.0-rc5+ #168
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 
rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
 88006b882d70 880069b8f6e8 82101090 0053
 88006c807a80 880069b8f748 8152b231 880069b8f758
 880069b8f708 880069b8f738 88006d19dd60 8237bac4
Call Trace:
 [82101090] dump_stack+0x45/0x57
 [8152b231] print_trailer+0x221/0x4b0
 [8153b30a] object_err+0x3a/0x50
 [8153fee2] kasan_report_error+0x3a2/0x9c0
 [812ce570] ? get_ksymbol+0x1b80/0x1b80
 [8153efb6] ? kasan_unpoison_shadow+0x36/0x70
 [8153efb6] ? kasan_unpoison_shadow+0x36/0x70
 [81540561] __asan_report_load1_noabort+0x61/0x80
 [81878657] ? strnlen+0xa7/0xb0
 [81878657] strnlen+0xa7/0xb0
 [81197824] ? __kernel_text_address+0x94/0xc0
 [8188197f] string.isra.2+0x3f/0x2f0
 [81888dc2] vsnprintf+0x392/0x23b0
 [814221f0] ? __rmqueue+0x24c0/0x24c0
 [81888a30] ? pointer.isra.17+0xd80/0xd80
 [8152b537] ? check_bytes_and_report+0x77/0x290
 [81531d91] ? deactivate_slab+0x4d1/0x1f00
 [820e1f00] ? p9_virtio_close+0xd0/0xd0
 [8188af95] snprintf+0x85/0xa0
 [8188af10] ? vsprintf+0x20/0x20
 [81534970] ? alloc_debug_processing+0x1e0/0x4a0
 [820e1fe8] p9_mount_tag_show+0xe8/0x180
 [81b49295] dev_attr_show+0x75/0x170
 [8153f20c] ? memset+0x2c/0x40
 [817157de] sysfs_kf_seq_show+0x3fe/0xe80
 [810144d0] ? dump_trace+0x230/0x920
 [817153e0] ? sysfs_remove_files+0xd0/0xd0
 [8153efb6] ? kasan_unpoison_shadow+0x36/0x70
 [8153f063] ? kasan_kmalloc+0x73/0x90
 [8170d849] kernfs_seq_show+0x1b9/0x330
 [815ff75e] seq_read+0x3be/0x1f30
 [814c3656] ? handle_mm_fault+0xe86/0x2340
 [815ff3a0] ? traverse+0x1000/0x1000
 [814cdeb1] ? find_vma+0x21/0x210
 [810f582b] ? __do_page_fault+0x2bb/0xea0
 [817109ae] kernfs_fop_read+0x38e/0x6f0
 [810f5570] ? mm_fault_error+0x410/0x410
 [81710620] ? kernfs_vma_page_mkwrite+0x390/0x390
 [8156441b] __vfs_read+0xbb/0x320
 [815647a3

Re: [PATCH v10 15/17] kernel: add support for .init_array.* constructors

2015-01-30 Thread Andrey Ryabinin
On 01/30/2015 02:13 AM, Andrew Morton wrote:
 On Thu, 29 Jan 2015 18:11:59 +0300 Andrey Ryabinin a.ryabi...@samsung.com 
 wrote:
 
 KASan uses constructors for initializing redzones for global
 variables. Actually KASan doesn't need priorities for constructors,
 so they were removed from GCC 5.0, but GCC 4.9.2 still generates
 constructors with priorities.
 
 I don't understand this changelog either.  What's wrong with priorities
 and what is the patch doing about it?  More details, please.
 

Currently kernel ignore constructors with priorities (e.g. .init_array.00099).
Kernel understand only constructors with default priority ( .init_array ).

This patch adds support for constructors with priorities.

For kernel image we put pointers to constructors between 
__ctors_start/__ctors_end
and do_ctors() will call them.

For modules  - .init_array.* sections merged into .init_array section.
Module code properly handles constructors in .init_array section.


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v10 01/17] Add kernel address sanitizer infrastructure.

2015-01-30 Thread Andrey Ryabinin
On 01/30/2015 02:12 AM, Andrew Morton wrote:
 On Thu, 29 Jan 2015 18:11:45 +0300 Andrey Ryabinin a.ryabi...@samsung.com 
 wrote:
 
 Kernel Address sanitizer (KASan) is a dynamic memory error detector. It 
 provides
 fast and comprehensive solution for finding use-after-free and out-of-bounds 
 bugs.

 KASAN uses compile-time instrumentation for checking every memory access,
 therefore GCC = v4.9.2 required.

 ...

 Based on work by Andrey Konovalov adech...@gmail.com
 
 Can we obtain Andrey's signed-off-by: please?
  

I'll ask.

...

 +static __always_inline bool memory_is_poisoned_1(unsigned long addr)
 
 What's with all the __always_inline in this file?  When I remove them
 all, kasan.o .text falls from 8294 bytes down to 4543 bytes.  That's
 massive, and quite possibly faster.
 
 If there's some magical functional reason for this then can we please
 get a nice prominent comment into this code apologetically explaining
 it?
 

The main reason is performance. __always_inline especially needed for 
check_memory_region()
and memory_is_poisoned() to optimize away switch in memory_is_poisoned():

if (__builtin_constant_p(size)) {
switch (size) {
case 1:
return memory_is_poisoned_1(addr);
case 2:
return memory_is_poisoned_2(addr);
case 4:
return memory_is_poisoned_4(addr);
case 8:
return memory_is_poisoned_8(addr);
case 16:
return memory_is_poisoned_16(addr);
default:
BUILD_BUG();
}
}

Always inlining memory_is_poisoned_x() gives additionally about 7%-10%.

According to my simple testing __always_inline gives about 20% versus
not inlined version of kasan.c


...

 +
 +void __asan_loadN(unsigned long addr, size_t size)
 +{
 +check_memory_region(addr, size, false);
 +}
 +EXPORT_SYMBOL(__asan_loadN);
 +
 +__attribute__((alias(__asan_loadN)))
 
 Maybe we need a __alias.  Like __packed and various other helpers.
 

Ok.



 +
 +static __always_inline void kasan_report(unsigned long addr,
 +size_t size,
 +bool is_write)
 
 Again, why the inline?  This is presumably not a hotpath and
 kasan_report has sixish call sites.
 

The reason of __always_inline here is to get correct _RET_IP_.
I could pass it from above and drop always inline here.

 
 +{
 +struct access_info info;
 +
 +if (likely(!kasan_enabled()))
 +return;
 +
 +info.access_addr = addr;
 +info.access_size = size;
 +info.is_write = is_write;
 +info.ip = _RET_IP_;
 +kasan_report_error(info);
 +}

...

 +
 +static void print_address_description(struct access_info *info)
 +{
 +dump_stack();
 +}
 
 dump_stack() uses KERN_INFO but the callers or
 print_address_description() use KERN_ERR.  This means that at some
 settings of `dmesg -n', the kasan output will have large missing
 chunks.
 
 Please test this and deide how bad it is.  A proper fix will be
 somewhat messy (new_dump_stack(KERN_ERR)).
 

This new_dump_stack() could be useful in other places.
E.g. object_err()/slab_err() in SLUB also use pr_err() + dump_stack() 
combination.



--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v10 02/17] x86_64: add KASan support

2015-01-30 Thread Andrey Ryabinin
On 01/30/2015 02:12 AM, Andrew Morton wrote:
 On Thu, 29 Jan 2015 18:11:46 +0300 Andrey Ryabinin a.ryabi...@samsung.com 
 wrote:
 
 This patch adds arch specific code for kernel address sanitizer.

 16TB of virtual addressed used for shadow memory.
 It's located in range [ec00 - fc00]
 between vmemmap and %esp fixup stacks.

 At early stage we map whole shadow region with zero page.
 Latter, after pages mapped to direct mapping address range
 we unmap zero pages from corresponding shadow (see kasan_map_shadow())
 and allocate and map a real shadow memory reusing vmemmap_populate()
 function.

 Also replace __pa with __pa_nodebug before shadow initialized.
 __pa with CONFIG_DEBUG_VIRTUAL=y make external function call (__phys_addr)
 __phys_addr is instrumented, so __asan_load could be called before
 shadow area initialized.

 ...

 --- a/lib/Kconfig.kasan
 +++ b/lib/Kconfig.kasan
 @@ -5,6 +5,7 @@ if HAVE_ARCH_KASAN
  
  config KASAN
  bool AddressSanitizer: runtime memory debugger
 +depends on !MEMORY_HOTPLUG
  help
Enables address sanitizer - runtime memory debugger,
designed to find out-of-bounds accesses and use-after-free bugs.
 
 That's a significant restriction.  It has obvious runtime implications.
 It also means that `make allmodconfig' and `make allyesconfig' don't
 enable kasan, so compile coverage will be impacted.
 
 This wasn't changelogged.  What's the reasoning and what has to be done
 to fix it?
 

Yes, this is runtime dependency. Hot adding memory won't work.
Since we don't have shadow for hotplugged memory, kernel will crash on the 
first access to it.
To fix this we need to allocate shadow for new memory.

Perhaps it would be better to have a runtime warning instead of Kconfig 
dependecy?


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v10 06/17] mm: slub: introduce metadata_access_enable()/metadata_access_disable()

2015-01-30 Thread Andrey Ryabinin
On 01/30/2015 02:12 AM, Andrew Morton wrote:
 On Thu, 29 Jan 2015 18:11:50 +0300 Andrey Ryabinin a.ryabi...@samsung.com 
 wrote:
 
 Wrap access to object's metadata in external functions with
 metadata_access_enable()/metadata_access_disable() function calls.

 This hooks separates payload accesses from metadata accesses
 which might be useful for different checkers (e.g. KASan).

 --- a/mm/slub.c
 +++ b/mm/slub.c
 @@ -467,13 +467,23 @@ static int slub_debug;
  static char *slub_debug_slabs;
  static int disable_higher_order_debug;
  
 +static inline void metadata_access_enable(void)
 +{
 +}
 +
 +static inline void metadata_access_disable(void)
 +{
 +}
 
 Some code comments here would be useful.  What they do, why they exist,
 etc.  The next patch fills them in with
 kasan_disable_local/kasan_enable_local but that doesn't help the reader
 to understand what's going on.  The fact that
 kasan_disable_local/kasan_enable_local are also undocumented doesn't
 help.
 

Ok, How about this?

/*
 * This hooks separate payload access from metadata access.
 * Useful for memory checkers that have to know when slub
 * accesses metadata.
 */


--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


<    1   2   3   4   5   6   7   8   9   10   >