|
@@ -20,6 +20,7 @@
|
|
|
#include <linux/proc_fs.h>
|
|
|
#include <linux/notifier.h>
|
|
|
#include <linux/seq_file.h>
|
|
|
+#include <linux/kasan.h>
|
|
|
#include <linux/kmemcheck.h>
|
|
|
#include <linux/cpu.h>
|
|
|
#include <linux/cpuset.h>
|
|
@@ -467,13 +468,31 @@ static int slub_debug;
|
|
|
static char *slub_debug_slabs;
|
|
|
static int disable_higher_order_debug;
|
|
|
|
|
|
+/*
|
|
|
+ * slub is about to manipulate internal object metadata. This memory lies
|
|
|
+ * outside the range of the allocated object, so accessing it would normally
|
|
|
+ * be reported by kasan as a bounds error. metadata_access_enable() is used
|
|
|
+ * to tell kasan that these accesses are OK.
|
|
|
+ */
|
|
|
+static inline void metadata_access_enable(void)
|
|
|
+{
|
|
|
+ kasan_disable_current();
|
|
|
+}
|
|
|
+
|
|
|
+static inline void metadata_access_disable(void)
|
|
|
+{
|
|
|
+ kasan_enable_current();
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* 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 +522,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 +698,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 +793,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)
|