diff options
-rw-r--r-- | mm/slub.c | 25 |
1 files changed, 25 insertions, 0 deletions
@@ -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; | |||
468 | static int disable_higher_order_debug; | 469 | static 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 | */ | ||
477 | static inline void metadata_access_enable(void) | ||
478 | { | ||
479 | kasan_disable_current(); | ||
480 | } | ||
481 | |||
482 | static inline void metadata_access_disable(void) | ||
483 | { | ||
484 | kasan_enable_current(); | ||
485 | } | ||
486 | |||
487 | /* | ||
471 | * Object debugging | 488 | * Object debugging |
472 | */ | 489 | */ |
473 | static void print_section(char *text, u8 *addr, unsigned int length) | 490 | static 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 | ||
479 | static struct track *get_track(struct kmem_cache *s, void *object, | 498 | static 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) |