aboutsummaryrefslogtreecommitdiffstats
path: root/mm/slub.c
diff options
context:
space:
mode:
authorAndrey Ryabinin <a.ryabinin@samsung.com>2015-02-13 17:39:38 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-02-14 00:21:41 -0500
commita79316c6178ca419e35feef47d47f50b4e0ee9f2 (patch)
tree970f49f49f93abbd388d9ff8e6607c7b86a13fde /mm/slub.c
parent75c66def8d815201aa0386ecc7c66a5c8dbca1ee (diff)
mm: slub: introduce metadata_access_enable()/metadata_access_disable()
It's ok for slub to access memory that marked by kasan as inaccessible (object's metadata). Kasan shouldn't print report in that case because these accesses are valid. Disabling instrumentation of slub.c code is not enough to achieve this because slub passes pointer to object's metadata into external functions like memchr_inv(). We don't want to disable instrumentation for memchr_inv() because this is quite generic function, and we don't want to miss bugs. metadata_access_enable/metadata_access_disable used to tell KASan where accesses to metadata starts/end, so we could temporarily disable KASan reports. Signed-off-by: Andrey Ryabinin <a.ryabinin@samsung.com> Cc: Dmitry Vyukov <dvyukov@google.com> Cc: Konstantin Serebryany <kcc@google.com> Cc: Dmitry Chernenkov <dmitryc@google.com> Signed-off-by: Andrey Konovalov <adech.fo@gmail.com> Cc: Yuri Gribov <tetra2005@gmail.com> Cc: Konstantin Khlebnikov <koct9i@gmail.com> Cc: Sasha Levin <sasha.levin@oracle.com> Cc: Christoph Lameter <cl@linux.com> Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Christoph Lameter <cl@linux.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: David Rientjes <rientjes@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/slub.c')
-rw-r--r--mm/slub.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/mm/slub.c b/mm/slub.c
index 6833b73ef6b3..37555ad8894d 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -20,6 +20,7 @@
20#include <linux/proc_fs.h> 20#include <linux/proc_fs.h>
21#include <linux/notifier.h> 21#include <linux/notifier.h>
22#include <linux/seq_file.h> 22#include <linux/seq_file.h>
23#include <linux/kasan.h>
23#include <linux/kmemcheck.h> 24#include <linux/kmemcheck.h>
24#include <linux/cpu.h> 25#include <linux/cpu.h>
25#include <linux/cpuset.h> 26#include <linux/cpuset.h>
@@ -468,12 +469,30 @@ static char *slub_debug_slabs;
468static int disable_higher_order_debug; 469static int disable_higher_order_debug;
469 470
470/* 471/*
472 * slub is about to manipulate internal object metadata. This memory lies
473 * outside the range of the allocated object, so accessing it would normally
474 * be reported by kasan as a bounds error. metadata_access_enable() is used
475 * to tell kasan that these accesses are OK.
476 */
477static inline void metadata_access_enable(void)
478{
479 kasan_disable_current();
480}
481
482static inline void metadata_access_disable(void)
483{
484 kasan_enable_current();
485}
486
487/*
471 * Object debugging 488 * Object debugging
472 */ 489 */
473static void print_section(char *text, u8 *addr, unsigned int length) 490static void print_section(char *text, u8 *addr, unsigned int length)
474{ 491{
492 metadata_access_enable();
475 print_hex_dump(KERN_ERR, text, DUMP_PREFIX_ADDRESS, 16, 1, addr, 493 print_hex_dump(KERN_ERR, text, DUMP_PREFIX_ADDRESS, 16, 1, addr,
476 length, 1); 494 length, 1);
495 metadata_access_disable();
477} 496}
478 497
479static struct track *get_track(struct kmem_cache *s, void *object, 498static struct track *get_track(struct kmem_cache *s, void *object,
@@ -503,7 +522,9 @@ static void set_track(struct kmem_cache *s, void *object,
503 trace.max_entries = TRACK_ADDRS_COUNT; 522 trace.max_entries = TRACK_ADDRS_COUNT;
504 trace.entries = p->addrs; 523 trace.entries = p->addrs;
505 trace.skip = 3; 524 trace.skip = 3;
525 metadata_access_enable();
506 save_stack_trace(&trace); 526 save_stack_trace(&trace);
527 metadata_access_disable();
507 528
508 /* See rant in lockdep.c */ 529 /* See rant in lockdep.c */
509 if (trace.nr_entries != 0 && 530 if (trace.nr_entries != 0 &&
@@ -677,7 +698,9 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
677 u8 *fault; 698 u8 *fault;
678 u8 *end; 699 u8 *end;
679 700
701 metadata_access_enable();
680 fault = memchr_inv(start, value, bytes); 702 fault = memchr_inv(start, value, bytes);
703 metadata_access_disable();
681 if (!fault) 704 if (!fault)
682 return 1; 705 return 1;
683 706
@@ -770,7 +793,9 @@ static int slab_pad_check(struct kmem_cache *s, struct page *page)
770 if (!remainder) 793 if (!remainder)
771 return 1; 794 return 1;
772 795
796 metadata_access_enable();
773 fault = memchr_inv(end - remainder, POISON_INUSE, remainder); 797 fault = memchr_inv(end - remainder, POISON_INUSE, remainder);
798 metadata_access_disable();
774 if (!fault) 799 if (!fault)
775 return 1; 800 return 1;
776 while (end > fault && end[-1] == POISON_INUSE) 801 while (end > fault && end[-1] == POISON_INUSE)