SLAB support for KASAN
Subsystems (20)
Alexander Potapenko
reviewercover SLAB support for KASAN
This patch set implements SLAB support for KASAN
Unlike SLUB, SLAB doesn't store allocation/deallocation stacks for heap objects, therefore we reimplement this feature in mm/kasan/stackdepot.c. The intention is to ultimately switch SLUB to use this implementation as well, which will remove the dependency on SLUB_DEBUG.
Also neither SLUB nor SLAB delay the reuse of freed memory chunks, which is necessary for better detection of use-after-free errors. We introduce memory quarantine (mm/kasan/quarantine.c), which allows delayed reuse of deallocated memory.
Alexander Potapenko (8):
kasan: Change the behavior of kmalloc_large_oob_right test mm, kasan: SLAB support
mm, kasan: Added GFP flags to KASAN API
arch, ftrace: For KASAN put hard/soft IRQ entries into separate
sections
mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
kasan: Test fix: Warn if the UAF could not be detected in kmalloc_uaf2
kasan: Changed kmalloc_large_oob_right, added
kmalloc_pagealloc_oob_right
mm: kasan: Initial memory quarantine implementation
Documentation/kasan.txt | 5 +- arch/arm/kernel/vmlinux.lds.S | 1 + arch/arm64/kernel/vmlinux.lds.S | 1 + arch/blackfin/kernel/vmlinux.lds.S | 1 + arch/c6x/kernel/vmlinux.lds.S | 1 + arch/metag/kernel/vmlinux.lds.S | 1 + arch/microblaze/kernel/vmlinux.lds.S | 1 + arch/mips/kernel/vmlinux.lds.S | 1 + arch/nios2/kernel/vmlinux.lds.S | 1 + arch/openrisc/kernel/vmlinux.lds.S | 1 + arch/parisc/kernel/vmlinux.lds.S | 1 + arch/powerpc/kernel/vmlinux.lds.S | 1 + arch/s390/kernel/vmlinux.lds.S | 1 + arch/sh/kernel/vmlinux.lds.S | 1 + arch/sparc/kernel/vmlinux.lds.S | 1 + arch/tile/kernel/vmlinux.lds.S | 1 + arch/x86/kernel/Makefile | 1 + arch/x86/kernel/vmlinux.lds.S | 1 + include/asm-generic/vmlinux.lds.h | 12 +- include/linux/ftrace.h | 31 ++-- include/linux/kasan.h | 63 +++++--- include/linux/slab.h | 6 + include/linux/slab_def.h | 14 ++ include/linux/slub_def.h | 11 ++ kernel/softirq.c | 3 +- lib/Kconfig.kasan | 4 +- lib/test_kasan.c | 66 +++++++- mm/Makefile | 1 + mm/kasan/Makefile | 3 + mm/kasan/kasan.c | 221 +++++++++++++++++++++++++-- mm/kasan/kasan.h | 52 +++++++ mm/kasan/quarantine.c | 284 +++++++++++++++++++++++++++++++++++ mm/kasan/report.c | 68 +++++++-- mm/kasan/stackdepot.c | 236 +++++++++++++++++++++++++++++ mm/mempool.c | 23 +-- mm/page_alloc.c | 2 +- mm/slab.c | 56 ++++++- mm/slab.h | 4 + mm/slab_common.c | 8 +- mm/slub.c | 21 +-- 40 files changed, 1122 insertions(+), 89 deletions(-) create mode 100644 mm/kasan/quarantine.c create mode 100644 mm/kasan/stackdepot.c
Signature · 7 lines
2.7.0.rc3.207.g0ac5344 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerPATCH 1/8 kasan: Change the behavior of kmalloc_large_oob_right test
depending on which allocator (SLAB or SLUB) is being used
--- lib/test_kasan.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
lib/test_kasan.c +16 -1
@@ -68,7 +68,22 @@ static noinline void __init kmalloc_node_oob_right(void) static noinline void __init kmalloc_large_oob_right(void) {char *ptr; -size_t size =KMALLOC_MAX_CACHE_SIZE +10 ; +size_t size; + +if (KMALLOC_MAX_CACHE_SIZE ==KMALLOC_MAX_SIZE ) { +/* +* We're using the SLAB allocator. Allocate a chunk that fits +* into a slab. +*/ + size =KMALLOC_MAX_CACHE_SIZE -256 ; + }else { +/* +* KMALLOC_MAX_SIZE > KMALLOC_MAX_CACHE_SIZE. +* We're using the SLUB allocator. Allocate a chunk that does +* not fit into a slab to trigger the page allocator. +*/ + size =KMALLOC_MAX_CACHE_SIZE +10 ; + }pr_info ("kmalloc large allocation: out-of-bounds to right\n" ); ptr =kmalloc (size,GFP_KERNEL );
Signature · 7 lines
2.7.0.rc3.207.g0ac5344 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerRe: [PATCH v1 1/8] kasan: Change the behavior of kmalloc_large_oob_right test
Quoted 17 lines · On Wed, 27 Jan 2016 19:25:06 +0100 Alexander Potapenko <[email protected]>…
depending on which allocator (SLAB or SLUB) is being used
...
lib/test_kasan.c +6
-1@@ -68,7 +68,22 @@ static noinline void __init kmalloc_node_oob_right(void) static noinline void __init kmalloc_large_oob_right(void) {char *ptr; -size_t size =KMALLOC_MAX_CACHE_SIZE +10 ; +size_t size; + +if (KMALLOC_MAX_CACHE_SIZE ==KMALLOC_MAX_SIZE ) { +/* +* We're using the SLAB allocator. Allocate a chunk that fits +* into a slab.
lib/test_kasan.c static noinline void __init kmalloc_node_oob_right(void) · line 86
Quoted 10 lines
lib/test_kasan.c +10
-0+*/ + size =KMALLOC_MAX_CACHE_SIZE -256 ; + }else { +/* +* KMALLOC_MAX_SIZE > KMALLOC_MAX_CACHE_SIZE. +* We're using the SLUB allocator. Allocate a chunk that does +* not fit into a slab to trigger the page allocator. +*/ + size =KMALLOC_MAX_CACHE_SIZE +10 ; + }
This seems a weird way of working out whether we're using SLAB or SLUB.
Can't we use, umm, #ifdef CONFIG_SLAB? If not that then let's cook up something standardized rather than a weird just-happens-to-work like this.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrey Ryabinin
maintainerRe: [PATCH v1 1/8] kasan: Change the behavior of kmalloc_large_oob_right test
Quoted 32 lines · Andrew Morton
Quoted 17 lines · On Wed, 27 Jan 2016 19:25:06 +0100 Alexander Potapenko <[email protected]>…
depending on which allocator (SLAB or SLUB) is being used
...
lib/test_kasan.c +6
-1@@ -68,7 +68,22 @@ static noinline void __init kmalloc_node_oob_right(void) static noinline void __init kmalloc_large_oob_right(void) {char *ptr; -size_t size =KMALLOC_MAX_CACHE_SIZE +10 ; +size_t size; + +if (KMALLOC_MAX_CACHE_SIZE ==KMALLOC_MAX_SIZE ) { +/* +* We're using the SLAB allocator. Allocate a chunk that fits +* into a slab. lib/test_kasan.c static noinline void __init kmalloc_node_oob_right(void) · line 86
Quoted 10 lines
lib/test_kasan.c +10
-0+*/ + size =KMALLOC_MAX_CACHE_SIZE -256 ; + }else { +/* +* KMALLOC_MAX_SIZE > KMALLOC_MAX_CACHE_SIZE. +* We're using the SLUB allocator. Allocate a chunk that does +* not fit into a slab to trigger the page allocator. +*/ + size =KMALLOC_MAX_CACHE_SIZE +10 ; + }This seems a weird way of working out whether we're using SLAB or SLUB.
Quoted 4 lines
Can't we use, umm, #ifdef
CONFIG_SLAB? If not that then let's cook up something standardized rather than a weird just-happens-to-work like this.
Actually it would be simpler to not use KMALLOC_MAX_CACHE_SIZE at all. Simply replace it with 2 or 3 PAGE_SIZEs.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 1/8] kasan: Change the behavior of kmalloc_large_oob_right test
The intention was to detect the situation in which a new allocator appears for which we don't know how it behaves if we allocate more than KMALLOC_MAX_CACHE_SIZE.
I agree this makes little sense and we can just stick to CONFIG_SLAB/CONFIG_SLUB cases.
However I think it's better to keep 'size = KMALLOC_MAX_CACHE_SIZE + something' to keep this code working in the case the value of KMALLOC_MAX_CACHE_SIZE changes.
Quoted 42 lines · Andrey Ryabinin
Quoted 32 lines · Andrew Morton
Quoted 17 lines · On Wed, 27 Jan 2016 19:25:06 +0100 Alexander Potapenko <[email protected]>…
depending on which allocator (SLAB or SLUB) is being used
...
lib/test_kasan.c +6
-1@@ -68,7 +68,22 @@ static noinline void __init kmalloc_node_oob_right(void) static noinline void __init kmalloc_large_oob_right(void) {char *ptr; -size_t size =KMALLOC_MAX_CACHE_SIZE +10 ; +size_t size; + +if (KMALLOC_MAX_CACHE_SIZE ==KMALLOC_MAX_SIZE ) { +/* +* We're using the SLAB allocator. Allocate a chunk that fits +* into a slab. lib/test_kasan.c static noinline void __init kmalloc_node_oob_right(void) · line 86
Quoted 10 lines
lib/test_kasan.c +10
-0+*/ + size =KMALLOC_MAX_CACHE_SIZE -256 ; + }else { +/* +* KMALLOC_MAX_SIZE > KMALLOC_MAX_CACHE_SIZE. +* We're using the SLUB allocator. Allocate a chunk that does +* not fit into a slab to trigger the page allocator. +*/ + size =KMALLOC_MAX_CACHE_SIZE +10 ; + }This seems a weird way of working out whether we're using SLAB or SLUB.
Quoted 4 lines
Can't we use, umm, #ifdef
CONFIG_SLAB? If not that then let's cook up something standardized rather than a weird just-happens-to-work like this.Actually it would be simpler to not use
KMALLOC_MAX_CACHE_SIZEat all. Simply replace it with 2 or 3PAGE_SIZEs.
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 1/8] kasan: Change the behavior of kmalloc_large_oob_right test
Turns out I've actually overintellectualized this test. I've reworked this patch so that kmalloc_pagealloc_oob_right() allocates a big chunk of memory from the page allocator (and therefore is enabled only under CONFIG_SLUB). kmalloc_large_oob_right() now allocates KMALLOC_MAX_CACHE_SIZE - 256 in both SLAB and SLUB modes.
I'll send the updated patch set later today.
Quoted 73 lines · Alexander Potapenko
The intention was to detect the situation in which a new allocator appears for which we don't know how it behaves if we allocate more than
KMALLOC_MAX_CACHE_SIZE.
I agree this makes little sense and we can just stick to CONFIG_SLAB/CONFIG_SLUB cases.However I think it's better to keep 'size =
KMALLOC_MAX_CACHE_SIZE+ something' to keep this code working in the case the value ofKMALLOC_MAX_CACHE_SIZEchanges.Quoted 35 lines · Andrey Ryabinin
Quoted 32 lines · Andrew Morton
Quoted 17 lines · On Wed, 27 Jan 2016 19:25:06 +0100 Alexander Potapenko <[email protected]>…
depending on which allocator (SLAB or SLUB) is being used
...
lib/test_kasan.c +6
-1@@ -68,7 +68,22 @@ static noinline void __init kmalloc_node_oob_right(void) static noinline void __init kmalloc_large_oob_right(void) {char *ptr; -size_t size =KMALLOC_MAX_CACHE_SIZE +10 ; +size_t size; + +if (KMALLOC_MAX_CACHE_SIZE ==KMALLOC_MAX_SIZE ) { +/* +* We're using the SLAB allocator. Allocate a chunk that fits +* into a slab. lib/test_kasan.c static noinline void __init kmalloc_node_oob_right(void) · line 86
Quoted 10 lines
lib/test_kasan.c +10
-0+*/ + size =KMALLOC_MAX_CACHE_SIZE -256 ; + }else { +/* +* KMALLOC_MAX_SIZE > KMALLOC_MAX_CACHE_SIZE. +* We're using the SLUB allocator. Allocate a chunk that does +* not fit into a slab to trigger the page allocator. +*/ + size =KMALLOC_MAX_CACHE_SIZE +10 ; + }This seems a weird way of working out whether we're using SLAB or SLUB.
Quoted 7 lines
Quoted 4 lines
Can't we use, umm, #ifdef
CONFIG_SLAB? If not that then let's cook up something standardized rather than a weird just-happens-to-work like this.Actually it would be simpler to not use
KMALLOC_MAX_CACHE_SIZEat all. Simply replace it with 2 or 3PAGE_SIZEs.--
Alexander Potapenko
Software EngineerGoogle Germany GmbH
Erika-Mann-Straße, 33
80636 MünchenGeschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks.
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerPATCH 2/8 mm, kasan: SLAB support
In reply to Alexander PotapenkoThis patch adds KASAN hooks to SLAB allocator.
This patch is based on the "mm: kasan: unified support for SLUB and SLAB allocators" patch originally prepared by Dmitry Chernenkov.
--- Documentation/kasan.txt | 5 ++- include/linux/kasan.h | 12 +++++++ include/linux/slab.h | 6 ++++ include/linux/slab_def.h | 14 ++++++++ include/linux/slub_def.h | 11 ++++++ lib/Kconfig.kasan | 4 ++- mm/Makefile | 1 + mm/kasan/kasan.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++ mm/kasan/kasan.h | 34 ++++++++++++++++++ mm/kasan/report.c | 59 +++++++++++++++++++++++++------ mm/slab.c | 46 +++++++++++++++++++++--- mm/slab_common.c | 2 +- 12 files changed, 264 insertions(+), 21 deletions(-)
Documentation/kasan.txt +2 -3
@@ -12,8 +12,7 @@ KASAN uses compile-time instrumentation for checking every memory access, therefore you will need a GCC version 4.9.2 or later. GCC 5.0 or later is required for detection of out-of-bounds accesses to stack or global variables. -Currently KASAN is supported only for x86_64 architecture and requires the -kernel to be built with the SLUB allocator. +Currently KASAN is supported only for x86_64 architecture. 1. Usage ========
@@ -27,7 +26,7 @@ inline are compiler instrumentation types. The former produces smaller binary the latter is 1.1 - 2 times faster. Inline instrumentation requires a GCC version 5.0 or later. -Currently KASAN works only with the SLUB memory allocator. +KASAN works with both SLUB and SLAB memory allocators. For better bug detection and nicer reporting, enable CONFIG_STACKTRACE. To disable instrumentation for specific files or directories, add a line
include/linux/kasan.h +12 -0
@@ -46,6 +46,9 @@ 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_cache_create (struct kmem_cache *cache,size_t *size, +unsigned long *flags); +void kasan_poison_slab (struct page *page);void kasan_unpoison_object_data (struct kmem_cache *cache,void *object);void kasan_poison_object_data (struct kmem_cache *cache,void *object);
@@ -59,6 +62,11 @@ 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); +struct kasan_cache { +int alloc_meta_offset; +int free_meta_offset; +}; +int kasan_module_alloc (void *addr,size_t size);void kasan_free_shadow (const struct vm_struct *vm);
@@ -72,6 +80,10 @@ static inline void kasan_disable_current(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_cache_create (struct kmem_cache *cache, +size_t *size, +unsigned long *flags) {} +static inline void kasan_poison_slab (struct page *page) {}static inline void kasan_unpoison_object_data (struct kmem_cache *cache,void *object) {}
include/linux/slab.h +6 -0
@@ -92,6 +92,12 @@# define SLAB_ACCOUNT 0x00000000UL#endif +#ifdef CONFIG_KASAN +#define SLAB_KASAN 0x08000000UL +#else +#define SLAB_KASAN 0x00000000UL +#endif +/* The following flags affect the page allocator grouping pages by mobility */ #define SLAB_RECLAIM_ACCOUNT 0x00020000UL/* Objects are reclaimable */ #define SLAB_TEMPORARY SLAB_RECLAIM_ACCOUNT/* Objects are short-lived */
include/linux/slab_def.h +14 -0
@@ -72,8 +72,22 @@ struct kmem_cache {#ifdef CONFIG_MEMCG_KMEM struct memcg_cache_params memcg_params;#endif +#ifdef CONFIG_KASAN +struct kasan_cache kasan_info; +#endif struct kmem_cache_node *node[MAX_NUMNODES]; }; +static inline void *nearest_obj (struct kmem_cache *cache,struct page *page, +void *x) { +void *object = x - (x - page->s_mem) % cache->size; +void *last_object = page->s_mem + (cache->num -1 ) * cache->size; + +if (unlikely (object > last_object)) +return last_object; +else +return object; +} +#endif /* _LINUX_SLAB_DEF_H */
include/linux/slub_def.h +11 -0
@@ -129,4 +129,15 @@ static inline void *virt_to_obj(struct kmem_cache *s,void object_err (struct kmem_cache *s,struct page *page,u8 *object,char *reason); +static inline void *nearest_obj (struct kmem_cache *cache,struct page *page, +void *x) { +void *object = x - (x -page_address (page)) % cache->size; +void *last_object =page_address (page) + + (page->objects -1 ) * cache->size; +if (unlikely (object > last_object)) +return last_object; +else +return object; +} +#endif /* _LINUX_SLUB_DEF_H */
lib/Kconfig.kasan +3 -1
@@ -5,7 +5,7 @@ if HAVE_ARCH_KASAN config KASAN bool "KASan: runtime memory debugger" - depends on SLUB_DEBUG + depends on SLUB_DEBUG || (SLAB && !DEBUG_SLAB) select CONSTRUCTORS help Enables kernel address sanitizer - runtime memory debugger,
@@ -16,6 +16,8 @@ config KASAN This feature consumes about 1/8 of available memory and brings about ~x3 performance slowdown. For better error detection enable CONFIG_STACKTRACE. + Currently CONFIG_KASAN doesn't work with CONFIG_DEBUG_SLAB + (the resulting kernel does not boot). choice prompt "Instrumentation type"
mm/Makefile +1 -0
@@ -3,6 +3,7 @@ # KASAN_SANITIZE_slab_common.o := n +KASAN_SANITIZE_slab.o := n KASAN_SANITIZE_slub.o := n mmu-y := nommu.o
mm/kasan/kasan.c +91 -0
111 lines not on this page · raw message
mm/kasan/kasan.h +34 -0
@@ -54,6 +54,40 @@ struct kasan_global {#endif }; +/** +* Structures to keep alloc and free tracks * +*/ + +enum kasan_state { +KASAN_STATE_INIT , +KASAN_STATE_ALLOC , +KASAN_STATE_FREE +}; + +struct kasan_track { +u64 cpu :6 ;/* for NR_CPUS = 64 */ +u64 pid :16 ;/* 65536 processes */ +u64 when :42 ;/* ~140 years */ +}; + +struct kasan_alloc_meta { +u32 state :2 ;/* enum kasan_state */ +u32 alloc_size :30 ; +struct kasan_track track; +}; + +struct kasan_free_meta { +/* Allocator freelist pointer, unused by KASAN. */ +void **freelist; +struct kasan_track track; +}; + +struct kasan_alloc_meta *get_alloc_info (struct kmem_cache *cache, +const void *object); +struct kasan_free_meta *get_free_info (struct kmem_cache *cache, +const void *object); + +static inline const void *kasan_shadow_to_mem (const void *shadow_addr) { return (void *)(((unsigned long)shadow_addr - KASAN_SHADOW_OFFSET)
mm/kasan/report.c +48 -11
85 lines not on this page · raw message
mm/slab.c +41 -5
127 lines not on this page · raw message
mm/slab_common.c +1 -1
@@ -35,7 +35,7 @@ struct kmem_cache *kmem_cache;*/ #define SLAB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \ SLAB_TRACE | SLAB_DESTROY_BY_RCU | SLAB_NOLEAKTRACE | \ - SLAB_FAILSLAB) + SLAB_FAILSLAB | SLAB_KASAN)#define SLAB_MERGE_SAME (SLAB_RECLAIM_ACCOUNT | SLAB_CACHE_DMA | \ SLAB_NOTRACK | SLAB_ACCOUNT)
Signature · 7 lines
2.7.0.rc3.207.g0ac5344 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 2/8] mm, kasan: SLAB support
Quoted 8 lines · Alexander Potapenko
This patch adds KASAN hooks to SLAB allocator.
This patch is based on the "mm: kasan: unified support for SLUB and SLAB allocators" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- Documentation/kasan.txt | 5 ++-
...
mm/kasan/kasan.c void kasan_poison_object_data(struct kmem_cache *cache, void *object) · line 415
Quoted 13 lines
mm/kasan/kasan.c +13
-0+#ifdef CONFIG_SLAB +struct kasan_alloc_meta *get_alloc_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.alloc_meta_offset; +} + +struct kasan_free_meta *get_free_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.free_meta_offset; +} +#endif
I cannot find the place to store stack info for free. get_free_info() isn't used except print_object(). Plese let me know where.
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 2/8] mm, kasan: SLAB support
Quoted 13 lines · Joonsoo Kim
Quoted 8 lines · Alexander Potapenko
This patch adds KASAN hooks to SLAB allocator.
This patch is based on the "mm: kasan: unified support for SLUB and SLAB allocators" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- Documentation/kasan.txt | 5 ++-...
Quoted 16 lines
mm/kasan/kasan.c void kasan_poison_object_data(struct kmem_cache *cache, void *object) · line 415
Quoted 13 lines
mm/kasan/kasan.c +13
-0+#ifdef CONFIG_SLAB +struct kasan_alloc_meta *get_alloc_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.alloc_meta_offset; +} + +struct kasan_free_meta *get_free_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.free_meta_offset; +} +#endif I cannot find the place to store stack info for free.
get_free_info()isn't used exceptprint_object(). Plese let me know where.
This is covered by other patches in this patchset.
Quoted 1 line
Thanks.
Alexander Potapenko
reviewerRe: [PATCH v1 2/8] mm, kasan: SLAB support
Quoted 32 lines · Alexander Potapenko
Quoted 13 lines · Joonsoo Kim
Quoted 8 lines · Alexander Potapenko
This patch adds KASAN hooks to SLAB allocator.
This patch is based on the "mm: kasan: unified support for SLUB and SLAB allocators" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- Documentation/kasan.txt | 5 ++-...
Quoted 16 lines
mm/kasan/kasan.c void kasan_poison_object_data(struct kmem_cache *cache, void *object) · line 415
Quoted 13 lines
mm/kasan/kasan.c +13
-0+#ifdef CONFIG_SLAB +struct kasan_alloc_meta *get_alloc_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.alloc_meta_offset; +} + +struct kasan_free_meta *get_free_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.free_meta_offset; +} +#endif I cannot find the place to store stack info for free.
get_free_info()isn't used exceptprint_object(). Plese let me know where.
Quoted 3 lines
This is covered by other patches in this patchset.
Quoted 1 line
Thanks.
(resending to linux-kernel@ because the previous mail bounced)
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 2/8] mm, kasan: SLAB support
Quoted 33 lines · Alexander Potapenko
Quoted 32 lines · Alexander Potapenko
Quoted 29 lines · Joonsoo Kim
Quoted 8 lines · Alexander Potapenko
This patch adds KASAN hooks to SLAB allocator.
This patch is based on the "mm: kasan: unified support for SLUB and SLAB allocators" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- Documentation/kasan.txt | 5 ++-...
mm/kasan/kasan.c void kasan_poison_object_data(struct kmem_cache *cache, void *object) · line 415
Quoted 13 lines
mm/kasan/kasan.c +13
-0+#ifdef CONFIG_SLAB +struct kasan_alloc_meta *get_alloc_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.alloc_meta_offset; +} + +struct kasan_free_meta *get_free_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.free_meta_offset; +} +#endif I cannot find the place to store stack info for free.
get_free_info()isn't used exceptprint_object(). Plese let me know where.
Quoted 1 line
Quoted 1 line
This is covered by other patches in this patchset.
This should be covered by this patch. Stroing and printing free_info is already done on SLUB and it is meaningful without quarantain.
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 2/8] mm, kasan: SLAB support
However this info is meaningless without saved stack traces, which are only introduced in the stackdepot patch (see "[PATCH v1 5/8] mm,
kasan: Stackdepot implementation. Enable stackdepot for SLAB")
Quoted 40 lines · Joonsoo Kim
Quoted 33 lines · Alexander Potapenko
Quoted 32 lines · Alexander Potapenko
Quoted 29 lines · Joonsoo Kim
Quoted 8 lines · Alexander Potapenko
This patch adds KASAN hooks to SLAB allocator.
This patch is based on the "mm: kasan: unified support for SLUB and SLAB allocators" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- Documentation/kasan.txt | 5 ++-...
mm/kasan/kasan.c void kasan_poison_object_data(struct kmem_cache *cache, void *object) · line 415
Quoted 13 lines
mm/kasan/kasan.c +13
-0+#ifdef CONFIG_SLAB +struct kasan_alloc_meta *get_alloc_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.alloc_meta_offset; +} + +struct kasan_free_meta *get_free_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.free_meta_offset; +} +#endif I cannot find the place to store stack info for free.
get_free_info()isn't used exceptprint_object(). Plese let me know where.Quoted 1 line
Quoted 1 line
This is covered by other patches in this patchset.
This should be covered by this patch. Stroing and printing
free_infois already done on SLUB and it is meaningful without quarantain.Thanks.
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 2/8] mm, kasan: SLAB support
Quoted 35 lines · Joonsoo Kim
Quoted 34 lines · Alexander Potapenko
Quoted 33 lines · Alexander Potapenko
Quoted 32 lines · Joonsoo Kim
Quoted 29 lines · Alexander Potapenko
Quoted 8 lines
This patch adds KASAN hooks to SLAB allocator.
This patch is based on the "mm: kasan: unified support for SLUB and SLAB allocators" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- Documentation/kasan.txt | 5 ++-...
mm/kasan/kasan.c void kasan_poison_object_data(struct kmem_cache *cache, void *object) · line 415
Quoted 13 lines
mm/kasan/kasan.c +13
-0+#ifdef CONFIG_SLAB +struct kasan_alloc_meta *get_alloc_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.alloc_meta_offset; +} + +struct kasan_free_meta *get_free_info (struct kmem_cache *cache, +const void *object) +{ +return (void *)object + cache->kasan_info.free_meta_offset; +} +#endif I cannot find the place to store stack info for free.
get_free_info()isn't used exceptprint_object(). Plese let me know where.
Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Quoted 1 line
This is covered by other patches in this patchset.
This should be covered by this patch. Stroing and printing
free_infois already done on SLUB and it is meaningful without quarantain.
2016-02-18 21:58 GMT+09:00 Alexander Potapenko <[email protected]>:
Quoted 3 lines
However this info is meaningless without saved stack traces, which are only introduced in the stackdepot patch (see "[PATCH v1 5/8] mm,
kasan: Stackdepot implementation. Enable stackdepot for SLAB")
Not meaningless. You already did it for allocation caller without saved stack traces. What makes difference between alloc/free?
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 2/8] mm, kasan: SLAB support
Ah, yes, I see.
This patch was indeed missing the following bits in kasan_slab_free():
#ifdef CONFIG_SLAB
if (cache->flags & SLAB_KASAN) {
struct kasan_free_meta *free_info =
get_free_info(cache, object);
struct kasan_alloc_meta *alloc_info =
get_alloc_info(cache, object);
alloc_info->state = KASAN_STATE_FREE;
set_track(&free_info->track);
}
#endif
I'll include them in the next round of patches.
Quoted 49 lines · Joonsoo Kim
Quoted 35 lines · Joonsoo Kim
Quoted 34 lines · Alexander Potapenko
Quoted 33 lines · Alexander Potapenko
Quoted 32 lines · Joonsoo Kim
Quoted 29 lines · Alexander Potapenko
Quoted 8 lines
This patch adds KASAN hooks to SLAB allocator.
This patch is based on the "mm: kasan: unified support for SLUB and SLAB allocators" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- Documentation/kasan.txt | 5 ++-...
Review
Quoted 13 lines
(quoted diff) +13
-0+#ifdef CONFIG_SLAB +struct kasan_alloc_meta *get_alloc_info(struct kmem_cache *cache, + const void *object) +{ + return (void *)object + cache->kasan_info.alloc_meta_offset; +} + +struct kasan_free_meta *get_free_info(struct kmem_cache *cache, + const void *object) +{ + return (void *)object + cache->kasan_info.free_meta_offset; +} +#endifI cannot find the place to store stack info for free.
get_free_info()isn't used exceptprint_object(). Plese let me know where.Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Quoted 1 line
This is covered by other patches in this patchset.
This should be covered by this patch. Stroing and printing
free_infois already done on SLUB and it is meaningful without quarantain.2016-02-18 21:58 GMT+09:00 Alexander Potapenko <[email protected]>:
Quoted 3 lines
However this info is meaningless without saved stack traces, which are only introduced in the stackdepot patch (see "[PATCH v1 5/8] mm,
kasan: Stackdepot implementation. Enable stackdepot for SLAB")Not meaningless. You already did it for allocation caller without saved stack traces. What makes difference between alloc/free?
Thanks.
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerPATCH 3/8 mm, kasan: Added GFP flags to KASAN API
In reply to Alexander PotapenkoAdd GFP flags to KASAN hooks for future patches to use.
This patch is based on the "mm: kasan: unified support for SLUB and SLAB allocators" patch originally prepared by Dmitry Chernenkov.
--- include/linux/kasan.h | 19 +++++++++++-------- mm/kasan/kasan.c | 15 ++++++++------- mm/mempool.c | 16 ++++++++-------- mm/slab.c | 14 +++++++------- mm/slab_common.c | 4 ++-- mm/slub.c | 17 +++++++++-------- 6 files changed, 45 insertions(+), 40 deletions(-)
include/linux/kasan.h +11 -8
@@ -53,13 +53,14 @@ void kasan_poison_slab(struct page *page);void kasan_unpoison_object_data (struct kmem_cache *cache,void *object);void kasan_poison_object_data (struct kmem_cache *cache,void *object); -void kasan_kmalloc_large (const void *ptr,size_t size); +void kasan_kmalloc_large (const void *ptr,size_t size,gfp_t flags);void kasan_kfree_large (const void *ptr);void kasan_kfree (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_kmalloc (struct kmem_cache *s,const void *object,size_t size, +gfp_t flags); +void kasan_krealloc (const void *object,size_t new_size,gfp_t flags); -void kasan_slab_alloc (struct kmem_cache *s,void *object); +void kasan_slab_alloc (struct kmem_cache *s,void *object,gfp_t flags);void kasan_slab_free (struct kmem_cache *s,void *object);struct kasan_cache {
@@ -90,14 +91,16 @@ static inline void kasan_unpoison_object_data(struct kmem_cache *cache,static inline void kasan_poison_object_data (struct kmem_cache *cache,void *object) {} -static inline void kasan_kmalloc_large (void *ptr,size_t size) {} +static inline void kasan_kmalloc_large (void *ptr,size_t size,gfp_t flags) {}static inline void kasan_kfree_large (const void *ptr) {}static inline void kasan_kfree (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) {} +size_t size,gfp_t flags) {} +static inline void kasan_krealloc (const void *object,size_t new_size, +gfp_t flags) {} -static inline void kasan_slab_alloc (struct kmem_cache *s,void *object) {} +static inline void kasan_slab_alloc (struct kmem_cache *s,void *object, +gfp_t flags) {}static inline void kasan_slab_free (struct kmem_cache *s,void *object) {}static inline int kasan_module_alloc (void *addr,size_t size) {return 0 ; }
mm/kasan/kasan.c +8 -7
@@ -414,9 +414,9 @@ struct kasan_free_meta *get_free_info(struct kmem_cache *cache, }#endif -void kasan_slab_alloc (struct kmem_cache *cache,void *object) +void kasan_slab_alloc (struct kmem_cache *cache,void *object,gfp_t flags) { -kasan_kmalloc (cache, object, cache->object_size); +kasan_kmalloc (cache, object, cache->object_size, flags); }void kasan_slab_free (struct kmem_cache *cache,void *object)
@@ -431,7 +431,8 @@ void kasan_slab_free(struct kmem_cache *cache, void *object)kasan_poison_shadow (object, rounded_up_size,KASAN_KMALLOC_FREE ); } -void kasan_kmalloc (struct kmem_cache *cache,const void *object,size_t size) +void kasan_kmalloc (struct kmem_cache *cache,const void *object,size_t size, +gfp_t flags) {unsigned long redzone_start;unsigned long redzone_end;
@@ -460,7 +461,7 @@ void kasan_kmalloc(struct kmem_cache *cache, const void *object, size_t size) }EXPORT_SYMBOL (kasan_kmalloc); -void kasan_kmalloc_large (const void *ptr,size_t size) +void kasan_kmalloc_large (const void *ptr,size_t size,gfp_t flags) {struct page *page;unsigned long redzone_start;
@@ -479,7 +480,7 @@ void kasan_kmalloc_large(const void *ptr, size_t size) KASAN_PAGE_REDZONE); } -void kasan_krealloc (const void *object,size_t size) +void kasan_krealloc (const void *object,size_t size,gfp_t flags) {struct page *page;
@@ -489,9 +490,9 @@ void kasan_krealloc(const void *object, size_t size) page =virt_to_head_page (object);if (unlikely (!PageSlab (page))) -kasan_kmalloc_large (object, size); +kasan_kmalloc_large (object, size, flags);else -kasan_kmalloc (page->slab_cache, object, size); +kasan_kmalloc (page->slab_cache, object, size, flags); }void kasan_kfree (void *ptr)
mm/mempool.c +8 -8
@@ -112,12 +112,12 @@ static void kasan_poison_element(mempool_t *pool, void *element)kasan_free_pages (element, (unsigned long )pool->pool_data); } -static void kasan_unpoison_element (mempool_t *pool,void *element) +static void kasan_unpoison_element (mempool_t *pool,void *element,gfp_t flags) {if (pool->alloc == mempool_alloc_slab) -kasan_slab_alloc (pool->pool_data, element); +kasan_slab_alloc (pool->pool_data, element, flags);if (pool->alloc == mempool_kmalloc) -kasan_krealloc (element, (size_t )pool->pool_data); +kasan_krealloc (element, (size_t )pool->pool_data, flags);if (pool->alloc == mempool_alloc_pages)kasan_alloc_pages (element, (unsigned long )pool->pool_data); }
@@ -130,13 +130,13 @@ static void add_element(mempool_t *pool, void *element) pool->elements[pool->curr_nr++] = element; } -static void *remove_element (mempool_t *pool) +static void *remove_element (mempool_t *pool,gfp_t flags) {void *element = pool->elements[--pool->curr_nr];BUG_ON (pool->curr_nr <0 );check_element (pool, element); -kasan_unpoison_element (pool, element); +kasan_unpoison_element (pool, element, flags);return element; }
@@ -154,7 +154,7 @@ void mempool_destroy(mempool_t *pool)return ;while (pool->curr_nr) { -void *element =remove_element (pool); +void *element =remove_element (pool,GFP_KERNEL ); pool->free (element, pool->pool_data); }kfree (pool->elements);
@@ -250,7 +250,7 @@ int mempool_resize(mempool_t *pool, int new_min_nr)spin_lock_irqsave (&pool->lock, flags);if (new_min_nr <= pool->min_nr) {while (new_min_nr < pool->curr_nr) { - element =remove_element (pool); + element =remove_element (pool,GFP_KERNEL );spin_unlock_irqrestore (&pool->lock, flags); pool->free (element, pool->pool_data);spin_lock_irqsave (&pool->lock, flags);
@@ -336,7 +336,7 @@ repeat_alloc:spin_lock_irqsave (&pool->lock, flags);if (likely (pool->curr_nr)) { - element =remove_element (pool); + element =remove_element (pool, gfp_temp);spin_unlock_irqrestore (&pool->lock, flags);/* paired with rmb in mempool_free(), read comment there */ smp_wmb ();
mm/slab.c +7 -7
@@ -3417,7 +3417,7 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags) {void *ret =slab_alloc (cachep, flags, _RET_IP_);if (ret) -kasan_slab_alloc (cachep, ret); +kasan_slab_alloc (cachep, ret, flags);trace_kmem_cache_alloc (_RET_IP_, ret, cachep->object_size, cachep->size, flags);
@@ -3448,7 +3448,7 @@ kmem_cache_alloc_trace(struct kmem_cache *cachep, gfp_t flags, size_t size) ret =slab_alloc (cachep, flags, _RET_IP_);if (ret) -kasan_kmalloc (cachep, ret, size); +kasan_kmalloc (cachep, ret, size, flags);trace_kmalloc (_RET_IP_, ret, size, cachep->size, flags);return ret;
@@ -3473,7 +3473,7 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)void *ret =slab_alloc_node (cachep, flags, nodeid, _RET_IP_);if (ret) -kasan_slab_alloc (cachep, ret); +kasan_slab_alloc (cachep, ret, flags);trace_kmem_cache_alloc_node (_RET_IP_, ret, cachep->object_size, cachep->size, flags, nodeid);
@@ -3493,7 +3493,7 @@ void *kmem_cache_alloc_node_trace(struct kmem_cache *cachep, ret =slab_alloc_node (cachep, flags, nodeid, _RET_IP_);if (ret) -kasan_kmalloc (cachep, ret, size); +kasan_kmalloc (cachep, ret, size, flags);trace_kmalloc_node (_RET_IP_, ret, size, cachep->size, flags, nodeid);
@@ -3513,7 +3513,7 @@ __do_kmalloc_node(size_t size, gfp_t flags, int node, unsigned long caller)return cachep; ret =kmem_cache_alloc_node_trace (cachep, flags, node, size);if (ret) -kasan_kmalloc (cachep, ret, size); +kasan_kmalloc (cachep, ret, size, flags);return ret; }
@@ -3550,7 +3550,7 @@ static __always_inline void *__do_kmalloc(size_t size, gfp_t flags, ret =slab_alloc (cachep, flags, caller);if (ret) -kasan_kmalloc (cachep, ret, size); +kasan_kmalloc (cachep, ret, size, flags);trace_kmalloc (caller, ret, size, cachep->size, flags);
@@ -4278,7 +4278,7 @@ size_t ksize(const void *objp)/* We assume that ksize callers could use whole allocated area, * so we need to unpoison this area. */ -kasan_krealloc (objp, size); +kasan_krealloc (objp, size,GFP_NOWAIT );return size; }
mm/slab_common.c +2 -2
@@ -1008,7 +1008,7 @@ void *kmalloc_order(size_t size, gfp_t flags, unsigned int order) page =alloc_kmem_pages (flags, order); ret = page ?page_address (page) :NULL ;kmemleak_alloc (ret, size,1 , flags); -kasan_kmalloc_large (ret, size); +kasan_kmalloc_large (ret, size, flags);return ret; }EXPORT_SYMBOL (kmalloc_order);
@@ -1189,7 +1189,7 @@ static __always_inline void *__do_krealloc(const void *p, size_t new_size, ks =ksize (p);if (ks >= new_size) { -kasan_krealloc ((void *)p, new_size); +kasan_krealloc ((void *)p, new_size, flags);return (void *)p; }
mm/slub.c +9 -8
@@ -1272,7 +1272,7 @@ static inline void dec_slabs_node(struct kmem_cache *s, int node,static inline void kmalloc_large_node_hook (void *ptr,size_t size,gfp_t flags) {kmemleak_alloc (ptr, size,1 , flags); -kasan_kmalloc_large (ptr, size); +kasan_kmalloc_large (ptr, size, flags); }static inline void kfree_hook (const void *x)
@@ -1306,7 +1306,7 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,kmemcheck_slab_alloc (s, flags, object,slab_ksize (s));kmemleak_alloc_recursive (object, s->object_size,1 , s->flags, flags); -kasan_slab_alloc (s, object); +kasan_slab_alloc (s, object, flags); }memcg_kmem_put_cache (s); }
@@ -2590,7 +2590,7 @@ void *kmem_cache_alloc_trace(struct kmem_cache *s, gfp_t gfpflags, size_t size) {void *ret =slab_alloc (s, gfpflags, _RET_IP_);trace_kmalloc (_RET_IP_, ret, size, s->size, gfpflags); -kasan_kmalloc (s, ret, size); +kasan_kmalloc (s, ret, size, gfpflags);return ret; }EXPORT_SYMBOL (kmem_cache_alloc_trace);
@@ -2618,7 +2618,7 @@ void *kmem_cache_alloc_node_trace(struct kmem_cache *s,trace_kmalloc_node (_RET_IP_, ret, size, s->size, gfpflags, node); -kasan_kmalloc (s, ret, size); +kasan_kmalloc (s, ret, size, gfpflags);return ret; }EXPORT_SYMBOL (kmem_cache_alloc_node_trace);
@@ -3162,7 +3162,8 @@ static void early_kmem_cache_node_alloc(int node)init_object (kmem_cache_node, n,SLUB_RED_ACTIVE );init_tracking (kmem_cache_node, n);#endif -kasan_kmalloc (kmem_cache_node, n,sizeof (struct kmem_cache_node )); +kasan_kmalloc (kmem_cache_node, n,sizeof (struct kmem_cache_node ), +GFP_KERNEL );init_kmem_cache_node (n);inc_slabs_node (kmem_cache_node, node, page->objects);
@@ -3535,7 +3536,7 @@ void *__kmalloc(size_t size, gfp_t flags)trace_kmalloc (_RET_IP_, ret, size, s->size, flags); -kasan_kmalloc (s, ret, size); +kasan_kmalloc (s, ret, size, flags);return ret; }
@@ -3580,7 +3581,7 @@ void *__kmalloc_node(size_t size, gfp_t flags, int node)trace_kmalloc_node (_RET_IP_, ret, size, s->size, flags, node); -kasan_kmalloc (s, ret, size); +kasan_kmalloc (s, ret, size, flags);return ret; }
@@ -3609,7 +3610,7 @@ size_t ksize(const void *object)size_t size =__ksize (object);/* We assume that ksize callers could use whole allocated area, so we need unpoison this area. */ -kasan_krealloc (object, size); +kasan_krealloc (object, size,GFP_NOWAIT );return size; }EXPORT_SYMBOL (ksize);
Signature · 7 lines
2.7.0.rc3.207.g0ac5344 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerPATCH 4/8 arch, ftrace: For KASAN put hard/soft IRQ entries into separate sections
In reply to Alexander PotapenkoKASAN needs to know whether the allocation happens in an IRQ handler. This lets us strip everything below the IRQ entry point to reduce the number of unique stack traces needed to be stored.
--- arch/arm/kernel/vmlinux.lds.S | 1 + arch/arm64/kernel/vmlinux.lds.S | 1 + arch/blackfin/kernel/vmlinux.lds.S | 1 + arch/c6x/kernel/vmlinux.lds.S | 1 + arch/metag/kernel/vmlinux.lds.S | 1 + arch/microblaze/kernel/vmlinux.lds.S | 1 + arch/mips/kernel/vmlinux.lds.S | 1 + arch/nios2/kernel/vmlinux.lds.S | 1 + arch/openrisc/kernel/vmlinux.lds.S | 1 + arch/parisc/kernel/vmlinux.lds.S | 1 + arch/powerpc/kernel/vmlinux.lds.S | 1 + arch/s390/kernel/vmlinux.lds.S | 1 + arch/sh/kernel/vmlinux.lds.S | 1 + arch/sparc/kernel/vmlinux.lds.S | 1 + arch/tile/kernel/vmlinux.lds.S | 1 + arch/x86/kernel/vmlinux.lds.S | 1 + include/asm-generic/vmlinux.lds.h | 12 +++++++++++- include/linux/ftrace.h | 31 ++++++++++++++++++++----------- kernel/softirq.c | 3 ++- 19 files changed, 49 insertions(+), 13 deletions(-)
arch/arm/kernel/vmlinux.lds.S +1 -0
@@ -105,6 +105,7 @@ SECTIONS *(.exception.text) __exception_text_end = .; IRQENTRY_TEXT + SOFTIRQENTRY_TEXT TEXT_TEXT SCHED_TEXT LOCK_TEXT
arch/arm64/kernel/vmlinux.lds.S +1 -0
@@ -102,6 +102,7 @@ SECTIONS *(.exception.text) __exception_text_end = .; IRQENTRY_TEXT + SOFTIRQENTRY_TEXT TEXT_TEXT SCHED_TEXT LOCK_TEXT
arch/blackfin/kernel/vmlinux.lds.S +1 -0
@@ -35,6 +35,7 @@ SECTIONS #endif LOCK_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT KPROBES_TEXT #ifdef CONFIG_ROMKERNEL __sinittext = .;
arch/c6x/kernel/vmlinux.lds.S +1 -0
@@ -72,6 +72,7 @@ SECTIONS SCHED_TEXT LOCK_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT KPROBES_TEXT *(.fixup) *(.gnu.warning)
arch/metag/kernel/vmlinux.lds.S +1 -0
@@ -24,6 +24,7 @@ SECTIONS LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT *(.text.*) *(.gnu.warning) }
arch/microblaze/kernel/vmlinux.lds.S +1 -0
@@ -36,6 +36,7 @@ SECTIONS { LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT . = ALIGN (4) ; _etext = . ; }
arch/mips/kernel/vmlinux.lds.S +1 -0
@@ -58,6 +58,7 @@ SECTIONS LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT *(.text.*) *(.fixup) *(.gnu.warning)
arch/nios2/kernel/vmlinux.lds.S +1 -0
@@ -39,6 +39,7 @@ SECTIONS SCHED_TEXT LOCK_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT KPROBES_TEXT } =0 _etext = .;
arch/openrisc/kernel/vmlinux.lds.S +1 -0
@@ -50,6 +50,7 @@ SECTIONS LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT *(.fixup) *(.text.__*) _etext = .;
arch/parisc/kernel/vmlinux.lds.S +1 -0
@@ -72,6 +72,7 @@ SECTIONS LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT *(.text.do_softirq) *(.text.sys_exit) *(.text.do_sigaltstack)
arch/powerpc/kernel/vmlinux.lds.S +1 -0
@@ -55,6 +55,7 @@ SECTIONS LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT #ifdef CONFIG_PPC32 *(.got1)
arch/s390/kernel/vmlinux.lds.S +1 -0
@@ -28,6 +28,7 @@ SECTIONS LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT *(.fixup) *(.gnu.warning) } :text = 0x0700
arch/sh/kernel/vmlinux.lds.S +1 -0
@@ -39,6 +39,7 @@ SECTIONS LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT *(.fixup) *(.gnu.warning) _etext = .; /* End of text section */
arch/sparc/kernel/vmlinux.lds.S +1 -0
@@ -48,6 +48,7 @@ SECTIONS LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT *(.gnu.warning) } = 0 _etext = .;
arch/tile/kernel/vmlinux.lds.S +1 -0
@@ -45,6 +45,7 @@ SECTIONS LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT __fix_text_end = .; /* tile-cpack won't rearrange before this */ ALIGN_FUNCTION(); *(.hottext*)
arch/x86/kernel/vmlinux.lds.S +1 -0
@@ -102,6 +102,7 @@ SECTIONS KPROBES_TEXT ENTRY_TEXT IRQENTRY_TEXT + SOFTIRQENTRY_TEXT *(.fixup) *(.gnu.warning) /* End of text section */
include/asm-generic/vmlinux.lds.h +11 -1
@@ -456,7 +456,7 @@ *(.entry.text) \ VMLINUX_SYMBOL(__entry_text_end) = .; -#ifdef CONFIG_FUNCTION_GRAPH_TRACER +#if defined(CONFIG_FUNCTION_GRAPH_TRACER ) || defined(CONFIG_KASAN )#define IRQENTRY_TEXT \ ALIGN_FUNCTION(); \ VMLINUX_SYMBOL(__irqentry_text_start) = .; \
@@ -466,6 +466,16 @@#define IRQENTRY_TEXT #endif +#if defined(CONFIG_FUNCTION_GRAPH_TRACER ) || defined(CONFIG_KASAN ) +#define SOFTIRQENTRY_TEXT \ + ALIGN_FUNCTION(); \ + VMLINUX_SYMBOL(__softirqentry_text_start) = .; \ + *(.softirqentry.text) \ + VMLINUX_SYMBOL(__softirqentry_text_end) = .; +#else +#define SOFTIRQENTRY_TEXT +#endif +/* Section used for early init (in .S files) */ #define HEAD_TEXT *(.head.text)
include/linux/ftrace.h +20 -11
@@ -762,6 +762,26 @@ struct ftrace_graph_ret {typedef void (*trace_func_graph_ret_t )(struct ftrace_graph_ret *);/* return */ typedef int (*trace_func_graph_ent_t )(struct ftrace_graph_ent *);/* entry */ +#if defined(CONFIG_FUNCTION_GRAPH_TRACER ) || defined(CONFIG_KASAN ) +/* +* We want to know which function is an entrypoint of a hardirq. +*/ +#define __irq_entry __attribute__((__section__(".irqentry.text"))) +#define __softirq_entry \ + __attribute__((__section__(".softirqentry.text"))) + +/* Limits of hardirq entrypoints */ +extern char __irqentry_text_start[]; +extern char __irqentry_text_end[]; +/* Limits of softirq entrypoints */ +extern char __softirqentry_text_start[]; +extern char __softirqentry_text_end[]; + +#else +#define __irq_entry +#define __softirq_entry +#endif +#ifdef CONFIG_FUNCTION_GRAPH_TRACER /* for init task */
@@ -798,16 +818,6 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func, int *depth,*/ #define __notrace_funcgraph notrace -/* -* We want to which function is an entrypoint of a hardirq. -* That will help us to put a signal on output. -*/ -#define __irq_entry __attribute__((__section__(".irqentry.text"))) - -/* Limits of hardirq entrypoints */ -extern char __irqentry_text_start[]; -extern char __irqentry_text_end[]; -#define FTRACE_NOTRACE_DEPTH 65536#define FTRACE_RETFUNC_DEPTH 50#define FTRACE_RETSTACK_ALLOC_SIZE 32
@@ -844,7 +854,6 @@ static inline void unpause_graph_tracing(void)#else /* !CONFIG_FUNCTION_GRAPH_TRACER */ #define __notrace_funcgraph -#define __irq_entry#define INIT_FTRACE_GRAPH static inline void ftrace_graph_init_task (struct task_struct *t) { }
kernel/softirq.c +2 -1
@@ -11,6 +11,7 @@#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt#include <linux/export.h> +#include <linux/ftrace.h> #include <linux/kernel_stat.h> #include <linux/interrupt.h> #include <linux/init.h>
@@ -227,7 +228,7 @@ static inline bool lockdep_softirq_start(void) { return false; }static inline void lockdep_softirq_end (bool in_hardirq) { }#endif -asmlinkage __visible void __do_softirq(void) +asmlinkage __visible void __softirq_entry __do_softirq(void) {unsigned long end = jiffies +MAX_SOFTIRQ_TIME ;unsigned long old_flags = current->flags;
Signature · 7 lines
2.7.0.rc3.207.g0ac5344 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Steven Rostedt
maintainerRe: [PATCH v1 4/8] arch, ftrace: For KASAN put hard/soft IRQ entries into separate sections
Quoted 19 lines · On Wed, 27 Jan 2016 19:25:09 +0100 Alexander Potapenko <[email protected]>…
include/linux/ftrace.h +13
-0@@ -762,6 +762,26 @@ struct ftrace_graph_ret {typedef void (*trace_func_graph_ret_t )(struct ftrace_graph_ret *);/* return */ typedef int (*trace_func_graph_ent_t )(struct ftrace_graph_ent *);/* entry */ +#if defined(CONFIG_FUNCTION_GRAPH_TRACER ) || defined(CONFIG_KASAN ) +/* +* We want to know which function is an entrypoint of a hardirq. +*/ +#define __irq_entry __attribute__((__section__(".irqentry.text"))) +#define __softirq_entry \ + __attribute__((__section__(".softirqentry.text"))) + +/* Limits of hardirq entrypoints */ +extern char __irqentry_text_start[]; +extern char __irqentry_text_end[]; +/* Limits of softirq entrypoints */ +extern char __softirqentry_text_start[];
include/linux/ftrace.h struct ftrace_graph_ret { · line 787
Quoted 10 lines
include/linux/ftrace.h +7
-0+extern char __softirqentry_text_end[]; + +#else +#define __irq_entry +#define __softirq_entry +#endif +#ifdef CONFIG_FUNCTION_GRAPH_TRACER /* for init task */
Since this is no longer just used for function tracing, perhaps the code should be moved to include/linux/irq.h or something.
-- Steve
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 4/8] arch, ftrace: For KASAN put hard/soft IRQ entries into separate sections
Agreed. Once I receive more comments I will make a new patch set and include this change as well.
Quoted 38 lines · Steven Rostedt
Quoted 19 lines · On Wed, 27 Jan 2016 19:25:09 +0100 Alexander Potapenko <[email protected]>…
include/linux/ftrace.h +13
-0@@ -762,6 +762,26 @@ struct ftrace_graph_ret {typedef void (*trace_func_graph_ret_t )(struct ftrace_graph_ret *);/* return */ typedef int (*trace_func_graph_ent_t )(struct ftrace_graph_ent *);/* entry */ +#if defined(CONFIG_FUNCTION_GRAPH_TRACER ) || defined(CONFIG_KASAN ) +/* +* We want to know which function is an entrypoint of a hardirq. +*/ +#define __irq_entry __attribute__((__section__(".irqentry.text"))) +#define __softirq_entry \ + __attribute__((__section__(".softirqentry.text"))) + +/* Limits of hardirq entrypoints */ +extern char __irqentry_text_start[]; +extern char __irqentry_text_end[]; +/* Limits of softirq entrypoints */ +extern char __softirqentry_text_start[];include/linux/ftrace.h struct ftrace_graph_ret { · line 787
Quoted 10 lines
include/linux/ftrace.h +7
-0+extern char __softirqentry_text_end[]; + +#else +#define __irq_entry +#define __softirq_entry +#endif +#ifdef CONFIG_FUNCTION_GRAPH_TRACER /* for init task */ Since this is no longer just used for function tracing, perhaps the code should be moved to
include/linux/irq.hor something.-- Steve
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 4/8] arch, ftrace: For KASAN put hard/soft IRQ entries into separate sections
On the other hand, this will require including <linux/irq.h> into various files that currently use __irq_section.
But that header has a comment saying:
/*
* Please do not include this file in generic code. There is currently
* no requirement for any architecture to implement anything held
* within this file.
*
* Thanks. --rmk
*/
Do we really want to put anything into that header?
Quoted 62 lines · Alexander Potapenko
Agreed. Once I receive more comments I will make a new patch set and include this change as well.
Quoted 31 lines · Steven Rostedt
Quoted 28 lines · On Wed, 27 Jan 2016 19:25:09 +0100 Alexander Potapenko <[email protected]>…
include/linux/ftrace.h +20
-0@@ -762,6 +762,26 @@ struct ftrace_graph_ret {typedef void (*trace_func_graph_ret_t )(struct ftrace_graph_ret *);/* return */ typedef int (*trace_func_graph_ent_t )(struct ftrace_graph_ent *);/* entry */ +#if defined(CONFIG_FUNCTION_GRAPH_TRACER ) || defined(CONFIG_KASAN ) +/* +* We want to know which function is an entrypoint of a hardirq. +*/ +#define __irq_entry __attribute__((__section__(".irqentry.text"))) +#define __softirq_entry \ + __attribute__((__section__(".softirqentry.text"))) + +/* Limits of hardirq entrypoints */ +extern char __irqentry_text_start[]; +extern char __irqentry_text_end[]; +/* Limits of softirq entrypoints */ +extern char __softirqentry_text_start[]; +extern char __softirqentry_text_end[]; + +#else +#define __irq_entry +#define __softirq_entry +#endif +#ifdef CONFIG_FUNCTION_GRAPH_TRACER Quoted 7 lines
include/linux/ftrace.h struct ftrace_graph_ret { · line 787
Quoted 1 line
include/linux/ftrace.h +0
-0/* for init task */ Since this is no longer just used for function tracing, perhaps the code should be moved to
include/linux/irq.hor something.-- Steve
--
Alexander Potapenko
Software EngineerGoogle Germany GmbH
Erika-Mann-Straße, 33
80636 MünchenGeschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks.
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Steven Rostedt
maintainerRe: [PATCH v1 4/8] arch, ftrace: For KASAN put hard/soft IRQ entries into separate sections
Quoted 12 lines · On Fri, 29 Jan 2016 12:59:13 +0100 Alexander Potapenko <[email protected]>…
On the other hand, this will require including <
linux/irq.h> into various files that currently use__irq_section.
But that header has a comment saying:/*
* Please do not include this file in generic code. There is currently
* no requirement for any architecture to implement anything held
* within this file.
*
* Thanks. --rmk
*/
Quoted 2 lines
Do we really want to put anything into that header?
What about interrupt.h?
It's just weird to have KSAN needing to pull in ftrace.h for irq work.
-- Steve
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 4/8] arch, ftrace: For KASAN put hard/soft IRQ entries into separate sections
Ok, interrupt.h sounds good.
Quoted 23 lines · Steven Rostedt
Quoted 12 lines · On Fri, 29 Jan 2016 12:59:13 +0100 Alexander Potapenko <[email protected]>…
On the other hand, this will require including <
linux/irq.h> into various files that currently use__irq_section.
But that header has a comment saying:/*
* Please do not include this file in generic code. There is currently
* no requirement for any architecture to implement anything held
* within this file.
*
* Thanks. --rmk
*/Quoted 2 lines
Do we really want to put anything into that header?
What about
interrupt.h?It's just weird to have KSAN needing to pull in
ftrace.hfor irq work.-- Steve
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerPATCH 5/8 mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
In reply to Alexander PotapenkoStack depot will allow KASAN store allocation/deallocation stack traces for memory chunks. The stack traces are stored in a hash table and referenced by handles which reside in the kasan_alloc_meta and kasan_free_meta structures in the allocated memory chunks.
IRQ stack traces are cut below the IRQ entry point to avoid unnecessary duplication.
Right now stackdepot support is only enabled in SLAB allocator. Once KASAN features in SLAB are on par with those in SLUB we can switch SLUB to stackdepot as well, thus removing the dependency on SLUB_DEBUG.
This patch is based on the "mm: kasan: stack depots" patch originally prepared by Dmitry Chernenkov.
--- arch/x86/kernel/Makefile | 1 + mm/kasan/Makefile | 3 + mm/kasan/kasan.c | 51 +++++++++- mm/kasan/kasan.h | 11 +++ mm/kasan/report.c | 8 ++ mm/kasan/stackdepot.c | 236 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 307 insertions(+), 3 deletions(-)
arch/x86/kernel/Makefile +1 -0
@@ -19,6 +19,7 @@ endif KASAN_SANITIZE_head$(BITS).o := n KASAN_SANITIZE_dumpstack.o := n KASAN_SANITIZE_dumpstack_$(BITS).o := n +KASAN_SANITIZE_stacktrace.o := n CFLAGS_irq.o := -I$(src)/../include/asm/trace
mm/kasan/Makefile +3 -0
@@ -6,3 +6,6 @@ CFLAGS_REMOVE_kasan.o = -pg CFLAGS_kasan.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector) obj-y := kasan.o report.o kasan_init.o +ifdef CONFIG_SLAB + obj-y += stackdepot.o +endif
mm/kasan/kasan.c +48 -3
92 lines not on this page · raw message
mm/kasan/kasan.h +11 -0
@@ -64,10 +64,15 @@ enum kasan_state {KASAN_STATE_FREE }; +#define KASAN_STACK_DEPTH 64 +#define KASAN_STACK_BITS (32)/* up to 16GB of stack storage */ +typedef u32 kasan_stack_handle ; +struct kasan_track {u64 cpu :6 ;/* for NR_CPUS = 64 */ u64 pid :16 ;/* 65536 processes */ u64 when :42 ;/* ~140 years */ +kasan_stack_handle stack :KASAN_STACK_BITS ; };struct kasan_alloc_meta {
@@ -102,4 +107,10 @@ static inline bool kasan_report_enabled(void)void kasan_report (unsigned long addr,size_t size,bool is_write,unsigned long ip); +struct stack_trace ; + +kasan_stack_handle kasan_save_stack (struct stack_trace *trace,gfp_t flags); + +void kasan_fetch_stack (kasan_stack_handle handle,struct stack_trace *trace); +#endif
mm/kasan/report.c +8 -0
@@ -119,6 +119,14 @@ static void print_track(struct kasan_track *track) {pr_err ("PID = %lu, CPU = %lu, timestamp = %lu\n" , track->pid, track->cpu, track->when); +if (track->stack) { +struct stack_trace trace; + +kasan_fetch_stack (track->stack, &trace); +print_stack_trace (&trace,0 ); + }else { +pr_err ("(stack is not available)\n" ); + } }static void print_object (struct kmem_cache *cache,void *object)
mm/kasan/stackdepot.c new file +236 -0
236 lines not on this page · raw message
Signature · 7 lines
2.7.0.rc3.207.g0ac5344 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 5/8] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
Hello,
Quoted 4 lines · Alexander Potapenko
Stack depot will allow KASAN store allocation/deallocation stack traces for memory chunks. The stack traces are stored in a hash table and referenced by handles which reside in the
kasan_alloc_metaandkasan_free_metastructures in the allocated memory chunks.
Looks really nice!
Could it be more generalized to be used by other feature that need to store stack trace such as tracepoint or page owner?
If it could be, there is one more requirement.
I understand the fact that entry is never removed from depot makes things very simpler, but, for general usecases, it's better to use reference count and allow to remove. Is it possible?
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 5/8] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
Quoted 9 lines · Joonsoo Kim
Hello,
Quoted 4 lines · Alexander Potapenko
Stack depot will allow KASAN store allocation/deallocation stack traces for memory chunks. The stack traces are stored in a hash table and referenced by handles which reside in the
kasan_alloc_metaandkasan_free_metastructures in the allocated memory chunks.
Quoted 4 lines
Looks really nice!
Could it be more generalized to be used by other feature that need to store stack trace such as tracepoint or page owner?
Certainly yes, but see below.
Quoted 3 lines
If it could be, there is one more requirement.
I understand the fact that entry is never removed from depot makes things very simpler, but, for general usecases, it's better to use reference
count
Quoted 1 line
and allow to remove. Is it possible?
For our use case reference counting is not really necessary, and it would introduce unwanted contention.
There are two possible options, each having its advantages and drawbacks:
we can let the clients store the refcounters directly in their stacks (more universal, but harder to use for the clients), or keep the counters in the depot but add an API that does not change them (easier for the clients, but potentially error-prone).
I'd say it's better to actually find at least one more user for the stack depot in order to understand the requirements, and refactor the code after that.
Quoted 2 lines
Thanks.
Alexander Potapenko
reviewerRe: [PATCH v1 5/8] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
Quoted 30 lines · Alexander Potapenko
Quoted 9 lines · Joonsoo Kim
Hello,
Quoted 4 lines · Alexander Potapenko
Stack depot will allow KASAN store allocation/deallocation stack traces for memory chunks. The stack traces are stored in a hash table and referenced by handles which reside in the
kasan_alloc_metaandkasan_free_metastructures in the allocated memory chunks.Quoted 4 lines
Looks really nice!
Could it be more generalized to be used by other feature that need to store stack trace such as tracepoint or page owner?
Certainly yes, but see below.
Quoted 5 lines
If it could be, there is one more requirement.
I understand the fact that entry is never removed from depot makes things very simpler, but, for general usecases, it's better to use reference count
and allow to remove. Is it possible?For our use case reference counting is not really necessary, and it would introduce unwanted contention.
There are two possible options, each having its advantages and drawbacks: we can let the clients store the refcounters directly in their stacks (more universal, but harder to use for the clients), or keep the counters in the depot but add an API that does not change them (easier for the clients, but potentially error-prone).
Quoted 5 lines
I'd say it's better to actually find at least one more user for the stack depot in order to understand the requirements, and refactor the code after that.
Quoted 2 lines
Thanks.
(resending to linux-kernel@ because the previous mail bounced)
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 5/8] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
Quoted 18 lines · Alexander Potapenko
Quoted 17 lines · Alexander Potapenko
Quoted 9 lines · Joonsoo Kim
Hello,
Quoted 4 lines · Alexander Potapenko
Stack depot will allow KASAN store allocation/deallocation stack traces for memory chunks. The stack traces are stored in a hash table and referenced by handles which reside in the
kasan_alloc_metaandkasan_free_metastructures in the allocated memory chunks.Quoted 4 lines
Looks really nice!
Could it be more generalized to be used by other feature that need to store stack trace such as tracepoint or page owner?
Certainly yes, but see below.
Quoted 7 lines
Quoted 7 lines
Quoted 5 lines
If it could be, there is one more requirement.
I understand the fact that entry is never removed from depot makes things very simpler, but, for general usecases, it's better to use reference count
and allow to remove. Is it possible?For our use case reference counting is not really necessary, and it would introduce unwanted contention.
Okay.
Quoted 8 lines
Quoted 8 lines
There are two possible options, each having its advantages and drawbacks: we can let the clients store the refcounters directly in their stacks (more universal, but harder to use for the clients), or keep the counters in the depot but add an API that does not change them (easier for the clients, but potentially error-prone).
I'd say it's better to actually find at least one more user for the stack depot in order to understand the requirements, and refactor the code after that.
I re-think the page owner case and it also may not need refcount. For now, just moving this stuff to /lib would be helpful for other future user.
BTW, is there any performance number? I guess that it could affect the performance.
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 5/8] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
Quoted 38 lines · Joonsoo Kim
Quoted 18 lines · Alexander Potapenko
Quoted 17 lines · Alexander Potapenko
Quoted 9 lines · Joonsoo Kim
Hello,
Quoted 4 lines · Alexander Potapenko
Stack depot will allow KASAN store allocation/deallocation stack traces for memory chunks. The stack traces are stored in a hash table and referenced by handles which reside in the
kasan_alloc_metaandkasan_free_metastructures in the allocated memory chunks.Quoted 4 lines
Looks really nice!
Could it be more generalized to be used by other feature that need to store stack trace such as tracepoint or page owner?
Certainly yes, but see below.
Quoted 7 lines
Quoted 7 lines
Quoted 5 lines
If it could be, there is one more requirement.
I understand the fact that entry is never removed from depot makes things very simpler, but, for general usecases, it's better to use reference count
and allow to remove. Is it possible?For our use case reference counting is not really necessary, and it would introduce unwanted contention.
Okay.
Quoted 8 lines
Quoted 8 lines
There are two possible options, each having its advantages and drawbacks: we can let the clients store the refcounters directly in their stacks (more universal, but harder to use for the clients), or keep the counters in the depot but add an API that does not change them (easier for the clients, but potentially error-prone).
I'd say it's better to actually find at least one more user for the stack depot in order to understand the requirements, and refactor the code after that.
Quoted 2 lines
I re-think the page owner case and it also may not need refcount. For now, just moving this stuff to /lib would be helpful for other future user.
I agree this code may need to be moved to /lib someday, but I wouldn't hurry with that.
Right now it is quite KASAN-specific, and it's unclear yet whether anyone else is going to use it.
I suggest we keep it in mm/kasan for now, and factor the common parts into /lib when the need arises.
Quoted 2 lines
BTW, is there any performance number? I guess that it could affect the performance.
I've compared the performance of KASAN with SLAB allocator on a small synthetic benchmark in two modes: with stack depot enabled and with kasan_save_stack() unconditionally returning 0.
In the former case 8% more time was spent in the kernel than in the latter case.
If I am not mistaking, for SLUB allocator the bookkeeping (enabled with the slub_debug=UZ boot options) take only 1.5 time, so the difference is worth looking into (at least before we switch SLUB to stack depot).
Quoted 1 line
Thanks.
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 5/8] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
Quoted 55 lines · Alexander Potapenko
Quoted 38 lines · Joonsoo Kim
Quoted 18 lines · Alexander Potapenko
Quoted 17 lines · Alexander Potapenko
Quoted 9 lines · Joonsoo Kim
Hello,
Quoted 4 lines · Alexander Potapenko
Stack depot will allow KASAN store allocation/deallocation stack traces for memory chunks. The stack traces are stored in a hash table and referenced by handles which reside in the
kasan_alloc_metaandkasan_free_metastructures in the allocated memory chunks.Quoted 4 lines
Looks really nice!
Could it be more generalized to be used by other feature that need to store stack trace such as tracepoint or page owner?
Certainly yes, but see below.
Quoted 7 lines
Quoted 7 lines
Quoted 5 lines
If it could be, there is one more requirement.
I understand the fact that entry is never removed from depot makes things very simpler, but, for general usecases, it's better to use reference count
and allow to remove. Is it possible?For our use case reference counting is not really necessary, and it would introduce unwanted contention.
Okay.
Quoted 8 lines
Quoted 8 lines
There are two possible options, each having its advantages and drawbacks: we can let the clients store the refcounters directly in their stacks (more universal, but harder to use for the clients), or keep the counters in the depot but add an API that does not change them (easier for the clients, but potentially error-prone).
I'd say it's better to actually find at least one more user for the stack depot in order to understand the requirements, and refactor the code after that.Quoted 2 lines
I re-think the page owner case and it also may not need refcount. For now, just moving this stuff to /lib would be helpful for other future user.
I agree this code may need to be moved to /lib someday, but I wouldn't hurry with that.
Right now it is quite KASAN-specific, and it's unclear yet whether anyone else is going to use it.
I suggest we keep it in mm/kasan for now, and factor the common parts into /lib when the need arises.Quoted 2 lines
BTW, is there any performance number? I guess that it could affect the performance.
I've compared the performance of KASAN with SLAB allocator on a small synthetic benchmark in two modes: with stack depot enabled and with
kasan_save_stack()unconditionally returning 0.
In the former case 8% more time was spent in the kernel than in the latter case.
Quoted 4 lines
If I am not mistaking, for SLUB allocator the bookkeeping (enabled with the slub_debug=UZ boot options) take only 1.5 time, so the difference is worth looking into (at least before we switch SLUB to stack depot).
I've made additional measurements.
Previously I had been using a userspace benchmark that created and destroyed pipes in a loop
(https://github.com/google/sanitizers/blob/master/address-sanitizer/kernel_buildbot/slave/bench_pipes.c).
Now I've made a kernel module that allocated and deallocated memory chunks of different sizes in a loop.
There were two modes of operation:
1) all the allocations were made from the same function, therefore all allocation/deallocation stacks were similar and there always was a hit in the stackdepot hashtable
2) The allocations were made from 2^16 different stacks.
In the first case SLAB+stackdepot turned out to be 13% faster than SLUB+slub_debug, in the second SLAB was 11% faster.
Note that in both cases and for both allocators most of the time (more than 90%) was spent in the x86 stack unwinder, which is common for both approaches.
Yet another observation regarding stackdepot: under a heavy load (running Trinity for a hour, 101M allocations) the depot saturates at around 20K records with the hashtable miss rate of 0.02%. That said, I still cannot justify the results of the userspace benchmark, but the slowdown of the stackdepot approach for SLAB sounds acceptable, especially given the memory gain compared to SLUB bookkeeping (which requires 128 bytes per memory allocation) and the fact we'll be dealing with the fast path most of the time.
It will certainly be nice to compare SLUB+slub_debug to SLUB+stackdepot once we start switching SLUB to stackdepot.
Quoted 22 lines
Quoted 2 lines
Thanks.
--
Alexander Potapenko
Software EngineerGoogle Germany GmbH
Erika-Mann-Straße, 33
80636 MünchenGeschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks.
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 5/8] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
2016-02-18 3:29 GMT+09:00 Alexander Potapenko <[email protected]>:
Quoted 74 lines · Alexander Potapenko
Quoted 55 lines · Joonsoo Kim
Quoted 38 lines · Alexander Potapenko
Quoted 18 lines · Alexander Potapenko
Quoted 17 lines · Joonsoo Kim
Quoted 9 lines
Hello,
Quoted 4 lines · Alexander Potapenko
Stack depot will allow KASAN store allocation/deallocation stack traces for memory chunks. The stack traces are stored in a hash table and referenced by handles which reside in the
kasan_alloc_metaandkasan_free_metastructures in the allocated memory chunks.Quoted 4 lines
Looks really nice!
Could it be more generalized to be used by other feature that need to store stack trace such as tracepoint or page owner?
Certainly yes, but see below.
Quoted 7 lines
Quoted 7 lines
Quoted 5 lines
If it could be, there is one more requirement.
I understand the fact that entry is never removed from depot makes things very simpler, but, for general usecases, it's better to use reference count
and allow to remove. Is it possible?For our use case reference counting is not really necessary, and it would introduce unwanted contention.
Okay.
Quoted 8 lines
Quoted 8 lines
There are two possible options, each having its advantages and drawbacks: we can let the clients store the refcounters directly in their stacks (more universal, but harder to use for the clients), or keep the counters in the depot but add an API that does not change them (easier for the clients, but potentially error-prone).
I'd say it's better to actually find at least one more user for the stack depot in order to understand the requirements, and refactor the code after that.Quoted 2 lines
I re-think the page owner case and it also may not need refcount. For now, just moving this stuff to /lib would be helpful for other future user.
I agree this code may need to be moved to /lib someday, but I wouldn't hurry with that.
Right now it is quite KASAN-specific, and it's unclear yet whether anyone else is going to use it.
I suggest we keep it in mm/kasan for now, and factor the common parts into /lib when the need arises.Quoted 2 lines
BTW, is there any performance number? I guess that it could affect the performance.
I've compared the performance of KASAN with SLAB allocator on a small synthetic benchmark in two modes: with stack depot enabled and with
kasan_save_stack()unconditionally returning 0.
In the former case 8% more time was spent in the kernel than in the latter case.Quoted 4 lines
If I am not mistaking, for SLUB allocator the bookkeeping (enabled with the slub_debug=UZ boot options) take only 1.5 time, so the difference is worth looking into (at least before we switch SLUB to stack depot).
I've made additional measurements.
Previously I had been using a userspace benchmark that created and destroyed pipes in a loop
(https://github.com/google/sanitizers/blob/master/address-sanitizer/kernel_buildbot/slave/bench_pipes.c).Now I've made a kernel module that allocated and deallocated memory chunks of different sizes in a loop.
There were two modes of operation:
1) all the allocations were made from the same function, therefore all allocation/deallocation stacks were similar and there always was a hit in the stackdepot hashtable
2) The allocations were made from 2^16 different stacks.
Quoted 2 lines
In the first case SLAB+stackdepot turned out to be 13% faster than SLUB+slub_debug, in the second SLAB was 11% faster.
I don't know what version of kernel you tested but, until recently, slub_debug=UZ has a side effect not to using fastpath of SLUB. So, comparison between them isn't appropriate. Today's linux-next branch would have some improvements on this area so use it to compare them.
Quoted 3 lines
Note that in both cases and for both allocators most of the time (more than 90%) was spent in the x86 stack unwinder, which is common for both approaches.
If more than 90% time is spent in stack unwinder which is common for both cases, how something is better than the other by 13%?
Quoted 8 lines
Yet another observation regarding stackdepot: under a heavy load (running Trinity for a hour, 101M allocations) the depot saturates at around 20K records with the hashtable miss rate of 0.02%. That said, I still cannot justify the results of the userspace benchmark, but the slowdown of the stackdepot approach for SLAB sounds acceptable, especially given the memory gain compared to SLUB bookkeeping (which requires 128 bytes per memory allocation) and the fact we'll be dealing with the fast path most of the time.
In fact, I don't have much concern about performance because saving memory has enough merit to be merged. Anyway, it looks acceptable even for performance.
Quoted 2 lines
It will certainly be nice to compare SLUB+slub_debug to SLUB+stackdepot once we start switching SLUB to stackdepot.
Okay.
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 5/8] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
Quoted 75 lines · Joonsoo Kim
2016-02-18 3:29 GMT+09:00 Alexander Potapenko <[email protected]>:
Quoted 74 lines · Alexander Potapenko
Quoted 55 lines · Joonsoo Kim
Quoted 38 lines · Alexander Potapenko
Quoted 18 lines · Alexander Potapenko
Quoted 17 lines · Joonsoo Kim
Quoted 9 lines
Hello,
Quoted 4 lines · Alexander Potapenko
Stack depot will allow KASAN store allocation/deallocation stack traces for memory chunks. The stack traces are stored in a hash table and referenced by handles which reside in the
kasan_alloc_metaandkasan_free_metastructures in the allocated memory chunks.Quoted 4 lines
Looks really nice!
Could it be more generalized to be used by other feature that need to store stack trace such as tracepoint or page owner?
Certainly yes, but see below.
Quoted 7 lines
Quoted 7 lines
Quoted 5 lines
If it could be, there is one more requirement.
I understand the fact that entry is never removed from depot makes things very simpler, but, for general usecases, it's better to use reference count
and allow to remove. Is it possible?For our use case reference counting is not really necessary, and it would introduce unwanted contention.
Okay.
Quoted 8 lines
Quoted 8 lines
There are two possible options, each having its advantages and drawbacks: we can let the clients store the refcounters directly in their stacks (more universal, but harder to use for the clients), or keep the counters in the depot but add an API that does not change them (easier for the clients, but potentially error-prone).
I'd say it's better to actually find at least one more user for the stack depot in order to understand the requirements, and refactor the code after that.Quoted 2 lines
I re-think the page owner case and it also may not need refcount. For now, just moving this stuff to /lib would be helpful for other future user.
I agree this code may need to be moved to /lib someday, but I wouldn't hurry with that.
Right now it is quite KASAN-specific, and it's unclear yet whether anyone else is going to use it.
I suggest we keep it in mm/kasan for now, and factor the common parts into /lib when the need arises.Quoted 2 lines
BTW, is there any performance number? I guess that it could affect the performance.
I've compared the performance of KASAN with SLAB allocator on a small synthetic benchmark in two modes: with stack depot enabled and with
kasan_save_stack()unconditionally returning 0.
In the former case 8% more time was spent in the kernel than in the latter case.Quoted 4 lines
If I am not mistaking, for SLUB allocator the bookkeeping (enabled with the slub_debug=UZ boot options) take only 1.5 time, so the difference is worth looking into (at least before we switch SLUB to stack depot).
I've made additional measurements.
Previously I had been using a userspace benchmark that created and destroyed pipes in a loop
(https://github.com/google/sanitizers/blob/master/address-sanitizer/kernel_buildbot/slave/bench_pipes.c).Now I've made a kernel module that allocated and deallocated memory chunks of different sizes in a loop.
There were two modes of operation:
1) all the allocations were made from the same function, therefore all allocation/deallocation stacks were similar and there always was a hit in the stackdepot hashtable
2) The allocations were made from 2^16 different stacks.
Quoted 8 lines
Quoted 2 lines
In the first case SLAB+stackdepot turned out to be 13% faster than SLUB+slub_debug, in the second SLAB was 11% faster.
I don't know what version of kernel you tested but, until recently, slub_debug=UZ has a side effect not to using fastpath of SLUB. So, comparison between them isn't appropriate. Today's linux-next branch would have some improvements on this area so use it to compare them.
That's good to know.
I've been using https://github.com/torvalds/linux.git, which probably didn't have those improvements.
Quoted 6 lines
Quoted 3 lines
Note that in both cases and for both allocators most of the time (more than 90%) was spent in the x86 stack unwinder, which is common for both approaches.
If more than 90% time is spent in stack unwinder which is common for both cases, how something is better than the other by 13%?
On the second glance, this number (90%) may be inaccurate, because I measured the stack unwinding times separately, which could have introduced deviation (not to mention it was incorrect for SLUB). Yet we're talking about a significant amount of time spent in the unwinder. My numbers were 26.111 seconds for 1024K SLAB allocation/deallocation pairs and 30.278 seconds for 1024K alloc/dealloc pairs with SLUB. When measured separately in the same routine that did the allocations, 2048K calls to save_stack_trace() took 25.487 seconds.
Quoted 19 lines
Quoted 8 lines
Yet another observation regarding stackdepot: under a heavy load (running Trinity for a hour, 101M allocations) the depot saturates at around 20K records with the hashtable miss rate of 0.02%. That said, I still cannot justify the results of the userspace benchmark, but the slowdown of the stackdepot approach for SLAB sounds acceptable, especially given the memory gain compared to SLUB bookkeeping (which requires 128 bytes per memory allocation) and the fact we'll be dealing with the fast path most of the time.
In fact, I don't have much concern about performance because saving memory has enough merit to be merged. Anyway, it looks acceptable even for performance.
Quoted 2 lines
It will certainly be nice to compare SLUB+slub_debug to SLUB+stackdepot once we start switching SLUB to stackdepot.
Okay.
Thanks.
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 5/8] mm, kasan: Stackdepot implementation. Enable stackdepot for SLAB
In reply to Alexander Potapenko2016-02-17 3:37 GMT+09:00 Alexander Potapenko <[email protected]>:
Quoted 39 lines · Joonsoo Kim
Quoted 38 lines · Alexander Potapenko
Quoted 18 lines · Alexander Potapenko
Quoted 17 lines · Joonsoo Kim
Quoted 9 lines
Hello,
Quoted 4 lines · Alexander Potapenko
Stack depot will allow KASAN store allocation/deallocation stack traces for memory chunks. The stack traces are stored in a hash table and referenced by handles which reside in the
kasan_alloc_metaandkasan_free_metastructures in the allocated memory chunks.Quoted 4 lines
Looks really nice!
Could it be more generalized to be used by other feature that need to store stack trace such as tracepoint or page owner?
Certainly yes, but see below.
Quoted 7 lines
Quoted 7 lines
Quoted 5 lines
If it could be, there is one more requirement.
I understand the fact that entry is never removed from depot makes things very simpler, but, for general usecases, it's better to use reference count
and allow to remove. Is it possible?For our use case reference counting is not really necessary, and it would introduce unwanted contention.
Okay.
Quoted 8 lines
Quoted 8 lines
There are two possible options, each having its advantages and drawbacks: we can let the clients store the refcounters directly in their stacks (more universal, but harder to use for the clients), or keep the counters in the depot but add an API that does not change them (easier for the clients, but potentially error-prone).
I'd say it's better to actually find at least one more user for the stack depot in order to understand the requirements, and refactor the code after that.
Quoted 8 lines
Quoted 2 lines
I re-think the page owner case and it also may not need refcount. For now, just moving this stuff to /lib would be helpful for other future user.
I agree this code may need to be moved to /lib someday, but I wouldn't hurry with that.
Right now it is quite KASAN-specific, and it's unclear yet whether anyone else is going to use it.
I suggest we keep it in mm/kasan for now, and factor the common parts into /lib when the need arises.
Please consider it one more time. I really have a plan to use it on page owner, because using page owner requires too many memory for stack trace and it changes system behaviour a lot.
Page owner uses following structure to store stack trace.
struct page_ext {
unsigned long flags;
#ifdef CONFIG_PAGE_OWNER
unsigned int order;
gfp_t gfp_mask;
unsigned int nr_entries;
int last_migrate_reason;
unsigned long trace_entries[8];#endif
};
Using stack depot in page owner would be straight forward if stack depot is in /lib. It is possible to move it when needed but it requires moving a file and it would not be desirable.
Quoted 11 lines
Quoted 2 lines
BTW, is there any performance number? I guess that it could affect the performance.
I've compared the performance of KASAN with SLAB allocator on a small synthetic benchmark in two modes: with stack depot enabled and with
kasan_save_stack()unconditionally returning 0.
In the former case 8% more time was spent in the kernel than in the latter case.If I am not mistaking, for SLUB allocator the bookkeeping (enabled with the slub_debug=UZ boot options) take only 1.5 time, so the difference is worth looking into (at least before we switch SLUB to stack depot).
Okay.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerPATCH 6/8 kasan: Test fix: Warn if the UAF could not be detected in kmalloc_uaf2
In reply to Alexander Potapenko--- lib/test_kasan.c | 2 ++ 1 file changed, 2 insertions(+)
lib/test_kasan.c +2 -0
@@ -286,6 +286,8 @@ static noinline void __init kmalloc_uaf2(void) } ptr1[40 ] ='x' ; +if (ptr1 == ptr2) +pr_err ("Could not detect use-after-free: ptr1 == ptr2\n" );kfree (ptr2); }
Signature · 7 lines
2.7.0.rc3.207.g0ac5344 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerPATCH 7/8 kasan: Changed kmalloc_large_oob_right, added kmalloc_pagealloc_oob_right
In reply to Alexander Potapenko--- lib/test_kasan.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-)
lib/test_kasan.c +17 -1
@@ -65,7 +65,8 @@ static noinline void __init kmalloc_node_oob_right(void)kfree (ptr); } -static noinline void __init kmalloc_large_oob_right(void) +#ifdef CONFIG_SLUB +static noinline void __init kmalloc_pagealloc_oob_right(void) {char *ptr;size_t size;
@@ -85,6 +86,18 @@ static noinline void __init kmalloc_large_oob_right(void) size = KMALLOC_MAX_CACHE_SIZE + 10; } + ptr[size] =0 ; +kfree (ptr); +} +#endif + +static noinline void __init kmalloc_large_oob_right(void) +{ +char *ptr; +size_t size =KMALLOC_MAX_CACHE_SIZE -256 ; +/* Allocate a chunk that is large enough, but still fits into a slab +* and does not trigger the page allocator fallback in SLUB. +*/ pr_info ("kmalloc large allocation: out-of-bounds to right\n" ); ptr =kmalloc (size,GFP_KERNEL );if (!ptr) {
@@ -341,6 +354,9 @@ static int __init kmalloc_tests_init(void)kmalloc_oob_right ();kmalloc_oob_left ();kmalloc_node_oob_right (); +#ifdef CONFIG_SLUB +kmalloc_pagealloc_oob_right (); +#endif kmalloc_large_oob_right ();kmalloc_oob_krealloc_more ();kmalloc_oob_krealloc_less ();
Signature · 7 lines
2.7.0.rc3.207.g0ac5344 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerPATCH 8/8 mm: kasan: Initial memory quarantine implementation
In reply to Alexander PotapenkoQuarantine isolates freed objects in a separate queue. The objects are returned to the allocator later, which helps to detect use-after-free errors.
Freed objects are first added to per-cpu quarantine queues. When a cache is destroyed or memory shrinking is requested, the objects are moved into the global quarantine queue. Whenever a kmalloc call allows memory reclaiming, the oldest objects are popped out of the global queue until the total size of objects in quarantine is less than 3/4 of the maximum quarantine size (which is a fraction of installed physical memory).
Right now quarantine support is only enabled in SLAB allocator. Unification of KASAN features in SLAB and SLUB will be done later.
This patch is based on the "mm: kasan: quarantine" patch originally prepared by Dmitry Chernenkov.
--- include/linux/kasan.h | 30 ++++-- lib/test_kasan.c | 29 ++++++ mm/kasan/Makefile | 2 +- mm/kasan/kasan.c | 68 +++++++++++- mm/kasan/kasan.h | 11 +- mm/kasan/quarantine.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++ mm/kasan/report.c | 3 +- mm/mempool.c | 7 +- mm/page_alloc.c | 2 +- mm/slab.c | 12 ++- mm/slab.h | 4 + mm/slab_common.c | 2 + mm/slub.c | 4 +- 13 files changed, 435 insertions(+), 23 deletions(-)
include/linux/kasan.h +22 -8
@@ -44,24 +44,29 @@ static inline void kasan_disable_current(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); +void kasan_poison_free_pages (struct page *page,unsigned int order);void kasan_cache_create (struct kmem_cache *cache,size_t *size,unsigned long *flags); +void kasan_cache_shrink (struct kmem_cache *cache); +void kasan_cache_destroy (struct kmem_cache *cache);void kasan_poison_slab (struct page *page);void kasan_unpoison_object_data (struct kmem_cache *cache,void *object);void kasan_poison_object_data (struct kmem_cache *cache,void *object);void kasan_kmalloc_large (const void *ptr,size_t size,gfp_t flags); -void kasan_kfree_large (const void *ptr); -void kasan_kfree (void *ptr); +void kasan_poison_kfree_large (const void *ptr); +void kasan_poison_kfree (void *ptr);void kasan_kmalloc (struct kmem_cache *s,const void *object,size_t size,gfp_t flags);void kasan_krealloc (const void *object,size_t new_size,gfp_t flags);void kasan_slab_alloc (struct kmem_cache *s,void *object,gfp_t flags); -void kasan_slab_free (struct kmem_cache *s,void *object); +/* kasan_slab_free() returns true if the object has been put into quarantine. +*/ +bool kasan_slab_free (struct kmem_cache *s,void *object); +void kasan_poison_slab_free (struct kmem_cache *s,void *object);struct kasan_cache {int alloc_meta_offset;
@@ -79,11 +84,14 @@ static inline void kasan_enable_current(void) {}static inline void kasan_disable_current (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_poison_free_pages (struct page *page, +unsigned int order) {}static inline void kasan_cache_create (struct kmem_cache *cache,size_t *size,unsigned long *flags) {} +static inline void kasan_cache_shrink (struct kmem_cache *cache) {} +static inline void kasan_cache_destroy (struct kmem_cache *cache) {}static inline void kasan_poison_slab (struct page *page) {} static inline void kasan_unpoison_object_data(struct kmem_cache *cache,
@@ -92,8 +100,8 @@ static inline void kasan_poison_object_data(struct kmem_cache *cache, void *object) {}static inline void kasan_kmalloc_large (void *ptr,size_t size,gfp_t flags) {} -static inline void kasan_kfree_large (const void *ptr) {} -static inline void kasan_kfree (void *ptr) {} +static inline void kasan_poison_kfree_large (const void *ptr) {} +static inline void kasan_poison_kfree (void *ptr) {}static inline void kasan_kmalloc (struct kmem_cache *s,const void *object,size_t size,gfp_t flags) {} static inline void kasan_krealloc(const void *object, size_t new_size,
@@ -101,7 +109,13 @@ static inline void kasan_krealloc(const void *object, size_t new_size,static inline void kasan_slab_alloc (struct kmem_cache *s,void *object,gfp_t flags) {} -static inline void kasan_slab_free (struct kmem_cache *s,void *object) {} +/* kasan_slab_free() returns true if the object has been put into quarantine. +*/ +static inline bool kasan_slab_free (struct kmem_cache *s,void *object) +{ +return false; +} +static inline void kasan_poison_slab_free (struct kmem_cache *s,void *object) {}static inline int kasan_module_alloc (void *addr,size_t size) {return 0 ; }static inline void kasan_free_shadow (const struct vm_struct *vm) {}
lib/test_kasan.c +29 -0
@@ -349,6 +349,32 @@ static noinline void __init kasan_stack_oob(void) *(volatile char *)p; } +#ifdef CONFIG_SLAB +static noinline void __init kasan_quarantine_cache(void) +{ +struct kmem_cache *cache =kmem_cache_create ( +"test" ,137 ,8 ,GFP_KERNEL ,NULL ); +int i; + +for (i =0 ; i <100 ; i++) { +void *p =kmem_cache_alloc (cache,GFP_KERNEL ); + +kmem_cache_free (cache, p); + p =kmalloc (sizeof (u64),GFP_KERNEL ); +kfree (p); + } +kmem_cache_shrink (cache); +for (i =0 ; i <100 ; i++) { +u64 *p =kmem_cache_alloc (cache,GFP_KERNEL ); + +kmem_cache_free (cache, p); + p =kmalloc (sizeof (u64),GFP_KERNEL ); +kfree (p); + } +kmem_cache_destroy (cache); +} +#endif +static int __init kmalloc_tests_init (void ) {kmalloc_oob_right ();
@@ -372,6 +398,9 @@ static int __init kmalloc_tests_init(void)kmem_cache_oob ();kasan_stack_oob ();kasan_global_oob (); +#ifdef CONFIG_SLAB +kasan_quarantine_cache (); +#endif return -EAGAIN ; }
mm/kasan/Makefile +1 -1
@@ -7,5 +7,5 @@ CFLAGS_kasan.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector) obj-y := kasan.o report.o kasan_init.o ifdef CONFIG_SLAB - obj-y += stackdepot.o + obj-y += stackdepot.o quarantine.o endif
mm/kasan/kasan.c +64 -4
116 lines not on this page · raw message
mm/kasan/kasan.h +9 -2
@@ -61,6 +61,7 @@ struct kasan_global {enum kasan_state {KASAN_STATE_INIT ,KASAN_STATE_ALLOC , +KASAN_STATE_QUARANTINE ,KASAN_STATE_FREE };
@@ -82,8 +83,10 @@ struct kasan_alloc_meta { };struct kasan_free_meta { -/* Allocator freelist pointer, unused by KASAN. */ -void **freelist; +/* This field is used while the object is in the quarantine. +* Otherwise it might be used for the allocator freelist. +*/ +void **quarantine_link;struct kasan_track track; };
@@ -113,4 +116,8 @@ kasan_stack_handle kasan_save_stack(struct stack_trace *trace, gfp_t flags);void kasan_fetch_stack (kasan_stack_handle handle,struct stack_trace *trace); +void quarantine_put (struct kasan_free_meta *info,struct kmem_cache *cache); +void quarantine_reduce (void ); +void quarantine_remove_cache (struct kmem_cache *cache); +#endif
mm/kasan/quarantine.c new file +284 -0
284 lines not on this page · raw message
mm/kasan/report.c +2 -1
@@ -148,7 +148,8 @@ static void print_object(struct kmem_cache *cache, void *object)print_track (&alloc_info->track);break ;case KASAN_STATE_FREE : -pr_err ("Object freed, allocated with size %u bytes\n" , +case KASAN_STATE_QUARANTINE : +pr_err ("Object freed, allocated with size %lu bytes\n" , alloc_info->alloc_size); free_info =get_free_info (cache, object);pr_err ("Allocation:\n" );
mm/mempool.c +4 -3
@@ -105,11 +105,12 @@ static inline void poison_element(mempool_t *pool, void *element)static void kasan_poison_element (mempool_t *pool,void *element) {if (pool->alloc == mempool_alloc_slab) -kasan_slab_free (pool->pool_data, element); +kasan_poison_slab_free (pool->pool_data, element);if (pool->alloc == mempool_kmalloc) -kasan_kfree (element); +kasan_poison_kfree (element);if (pool->alloc == mempool_alloc_pages) -kasan_free_pages (element, (unsigned long )pool->pool_data); +kasan_poison_free_pages (element, + (unsigned long )pool->pool_data); }static void kasan_unpoison_element (mempool_t *pool,void *element,gfp_t flags)
mm/page_alloc.c +1 -1
@@ -980,7 +980,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); +kasan_poison_free_pages (page, order);if (PageAnon (page)) page->mapping =NULL ;
mm/slab.c +11 -1
@@ -3374,9 +3374,19 @@ free_done:static inline void __cache_free (struct kmem_cache *cachep,void *objp,unsigned long caller) { +#ifdef CONFIG_KASAN +if (!kasan_slab_free (cachep, objp)) +/* The object has been put into the quarantine, don't touch it +* for now. +*/ + nokasan_free(cachep, objp, caller); +} + +void nokasan_free (struct kmem_cache *cachep,void *objp,unsigned long caller) +{ +#endif struct array_cache *ac; -kasan_slab_free (cachep, objp); ac =cpu_cache_get (cachep);check_irq_off ();
mm/slab.h +4 -0
@@ -372,4 +372,8 @@ void *slab_next(struct seq_file *m, void *p, loff_t *pos);void slab_stop (struct seq_file *m,void *p);int memcg_slab_show (struct seq_file *m,void *p); +#ifdef CONFIG_KASAN +void nokasan_free (struct kmem_cache *cache,void *x,unsigned long addr); +#endif +#endif /* MM_SLAB_H */
mm/slab_common.c +2 -0
@@ -710,6 +710,7 @@ void kmem_cache_destroy(struct kmem_cache *s)get_online_cpus ();get_online_mems (); +kasan_cache_destroy (s);mutex_lock (&slab_mutex); s->refcount--;
@@ -748,6 +749,7 @@ int kmem_cache_shrink(struct kmem_cache *cachep)get_online_cpus ();get_online_mems (); +kasan_cache_shrink (cachep); ret =__kmem_cache_shrink (cachep, false);put_online_mems ();put_online_cpus ();
mm/slub.c +2 -2
@@ -1278,7 +1278,7 @@ static inline void kmalloc_large_node_hook(void *ptr, size_t size, gfp_t flags)static inline void kfree_hook (const void *x) {kmemleak_free (x); -kasan_kfree_large (x); +kasan_poison_kfree_large (x); } static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,
@@ -1333,7 +1333,7 @@ static inline void slab_free_hook(struct kmem_cache *s, void *x)if (!(s->flags &SLAB_DEBUG_OBJECTS ))debug_check_no_obj_freed (x, s->object_size); -kasan_slab_free (s, x); +kasan_poison_slab_free (s, x); } static inline void slab_free_freelist_hook(struct kmem_cache *s,
Signature · 7 lines
2.7.0.rc3.207.g0ac5344 -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 8/8] mm: kasan: Initial memory quarantine implementation
Quoted 11 lines · Alexander Potapenko
Quarantine isolates freed objects in a separate queue. The objects are returned to the allocator later, which helps to detect use-after-free errors.
Freed objects are first added to per-cpu quarantine queues. When a cache is destroyed or memory shrinking is requested, the objects are moved into the global quarantine queue. Whenever a kmalloc call allows memory reclaiming, the oldest objects are popped out of the global queue until the total size of objects in quarantine is less than 3/4 of the maximum quarantine size (which is a fraction of installed physical memory).
Just wondering why not using time based approach rather than size based one. In heavy load condition, how much time do the object stay in quarantine?
Quoted 24 lines
Right now quarantine support is only enabled in SLAB allocator. Unification of KASAN features in SLAB and SLUB will be done later.
This patch is based on the "mm: kasan: quarantine" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- include/linux/kasan.h | 30 ++++-- lib/test_kasan.c | 29 ++++++ mm/kasan/Makefile | 2 +- mm/kasan/kasan.c | 68 +++++++++++- mm/kasan/kasan.h | 11 +- mm/kasan/quarantine.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++ mm/kasan/report.c | 3 +- mm/mempool.c | 7 +- mm/page_alloc.c | 2 +- mm/slab.c | 12 ++- mm/slab.h | 4 + mm/slab_common.c | 2 + mm/slub.c | 4 +- 13 files changed, 435 insertions(+), 23 deletions(-)
...
Quoted 7 lines
mm/kasan/kasan.c +7
-0+bool kasan_slab_free (struct kmem_cache *cache,void *object) +{ +#ifdef CONFIG_SLAB +/* RCU slabs could be legally used after free within the RCU period */ +if (unlikely (cache->flags &SLAB_DESTROY_BY_RCU )) +return false; +
mm/kasan/kasan.c void kasan_slab_free(struct kmem_cache *cache, void *object) · line 509
Quoted 10 lines
mm/kasan/kasan.c +10
-0+if (likely (cache->flags &SLAB_KASAN )) { +struct kasan_alloc_meta *alloc_info = +get_alloc_info (cache, object); +struct kasan_free_meta *free_info = +get_free_info (cache, object); + +switch (alloc_info->state) { +case KASAN_STATE_ALLOC : + alloc_info->state =KASAN_STATE_QUARANTINE ; +quarantine_put (free_info, cache);
quarantine_put() can be called regardless of SLAB_DESTROY_BY_RCU, although it's not much meaningful without poisoning. But, I have an idea to poison object on SLAB_DESTROY_BY_RCU cache.
quarantine_put() moves per cpu list to global queue when list size reaches QUARANTINE_PERCPU_SIZE. If we call synchronize_rcu() at that time, after then, we can poison objects. With appropriate size setup, it would not be intrusive.
mm/kasan/kasan.c void kasan_slab_free(struct kmem_cache *cache, void *object) · line 510
Quoted 1 line
mm/kasan/kasan.c +1
-0+set_track (&free_info->track,GFP_NOWAIT );
set_track() can be called regardless of SLAB_DESTROY_BY_RCU.
Quoted 18 lines
mm/kasan/kasan.c +18
-0+kasan_poison_slab_free (cache, object); +return true; +case KASAN_STATE_QUARANTINE : +case KASAN_STATE_FREE : +pr_err ("Double free" ); +dump_stack (); +break ; +default : + break; + } + } +return false; +#else +kasan_poison_slab_free (cache, object); +return false; +#endif +} +
...
Quoted 28 lines
mm/kasan/quarantine.c new file +28
-0+void quarantine_reduce(void) +{ + size_t new_quarantine_size; + unsigned long flags; + struct qlist to_free = QLIST_INIT; + size_t size_to_free = 0; + void **last; + + if (likely(ACCESS_ONCE(global_quarantine.bytes) <= + smp_load_acquire(&quarantine_size))) + return; + + spin_lock_irqsave(&quarantine_lock, flags); + + /* Update quarantine size in case of hotplug. Allocate a fraction of + * the installed memory to quarantine minus per-cpu queue limits. + */ + new_quarantine_size = (ACCESS_ONCE(totalram_pages) << PAGE_SHIFT) / + QUARANTINE_FRACTION; + new_quarantine_size -= QUARANTINE_PERCPU_SIZE * num_online_cpus(); + smp_store_release(&quarantine_size, new_quarantine_size); + + last = global_quarantine.head; + while (last) { + struct kmem_cache *cache = qlink_to_cache(last); + + size_to_free += cache->size; + if (!*last || size_to_free >
mm/kasan/quarantine.c line 230
Quoted 10 lines
mm/kasan/quarantine.c new file +10
-0+ global_quarantine.bytes - QUARANTINE_LOW_SIZE) + break; + last = (void **) *last; + } +qlist_move (&global_quarantine, last, &to_free, size_to_free); + +spin_unlock_irqrestore (&quarantine_lock, flags); + +qlist_free_all (&to_free,NULL ); +}
Isn't it better to call quarantine_reduce() in shrink_slab()? It will help to maximize quarantine time.
Quoted 37 lines
mm/kasan/quarantine.c new file +37
-0+ +static inline void qlist_move_cache (struct qlist *from, +struct qlist *to, +struct kmem_cache *cache) +{ +void ***prev; + +if (unlikely (empty_qlist (from))) +return ; + + prev = &from->head; +while (*prev) { +void **qlink = *prev; +struct kmem_cache *obj_cache =qlink_to_cache (qlink); + +if (obj_cache == cache) { +if (unlikely (from->tail == qlink)) + from->tail = (void **) prev; + *prev = (void **) *qlink; + from->bytes -= cache->size; +qlist_put (to, qlink, cache->size); + }else + prev = (void ***) *prev; + } +} + +static void per_cpu_remove_cache (void *arg) +{ +struct kmem_cache *cache = arg; +struct qlist to_free =QLIST_INIT ; +struct qlist *q; +unsigned long flags; + +local_irq_save (flags); + q =this_cpu_ptr (&cpu_quarantine); +qlist_move_cache (q, &to_free, cache); +local_irq_restore (flags);
mm/kasan/quarantine.c line 277
Quoted 10 lines
mm/kasan/quarantine.c new file +10
-0+ +qlist_free_all (&to_free, cache); +} + +void quarantine_remove_cache (struct kmem_cache *cache) +{ +unsigned long flags; +struct qlist to_free =QLIST_INIT ; + +on_each_cpu (per_cpu_remove_cache, cache,0 );
Should be called with wait = 1.
Quoted 63 lines
mm/kasan/quarantine.c new file +7
-0+ +spin_lock_irqsave (&quarantine_lock, flags); +qlist_move_cache (&global_quarantine, &to_free, cache); +spin_unlock_irqrestore (&quarantine_lock, flags); + +qlist_free_all (&to_free, cache); +}mm/kasan/report.c +2
-1@@ -148,7 +148,8 @@ static void print_object(struct kmem_cache *cache, void *object)print_track (&alloc_info->track);break ;case KASAN_STATE_FREE : -pr_err ("Object freed, allocated with size %u bytes\n" , +case KASAN_STATE_QUARANTINE : +pr_err ("Object freed, allocated with size %lu bytes\n" , alloc_info->alloc_size); free_info =get_free_info (cache, object);pr_err ("Allocation:\n" );mm/mempool.c +4
-3@@ -105,11 +105,12 @@ static inline void poison_element(mempool_t *pool, void *element)static void kasan_poison_element (mempool_t *pool,void *element) {if (pool->alloc == mempool_alloc_slab) -kasan_slab_free (pool->pool_data, element); +kasan_poison_slab_free (pool->pool_data, element);if (pool->alloc == mempool_kmalloc) -kasan_kfree (element); +kasan_poison_kfree (element);if (pool->alloc == mempool_alloc_pages) -kasan_free_pages (element, (unsigned long )pool->pool_data); +kasan_poison_free_pages (element, + (unsigned long )pool->pool_data); }static void kasan_unpoison_element (mempool_t *pool,void *element,gfp_t flags)mm/page_alloc.c +1
-1@@ -980,7 +980,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); +kasan_poison_free_pages (page, order);if (PageAnon (page)) page->mapping =NULL ;mm/slab.c +1
-0@@ -3374,9 +3374,19 @@ free_done:static inline void __cache_free (struct kmem_cache *cachep,void *objp,unsigned long caller) { +#ifdef CONFIG_KASAN
mm/slab.c free_done: · line 3387
Quoted 10 lines
mm/slab.c +10
-0+if (!kasan_slab_free (cachep, objp)) +/* The object has been put into the quarantine, don't touch it +* for now. +*/ + nokasan_free(cachep, objp, caller); +} + +void nokasan_free (struct kmem_cache *cachep,void *objp,unsigned long caller) +{ +#endif
It looks not good to me.
Converting __cache_free() to ____cache_free() and making __cache_free() call ____cache_free() if (!kasan_slab_free()) looks better to me and less error-prone.
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Alexander Potapenko
reviewerRe: [PATCH v1 8/8] mm: kasan: Initial memory quarantine implementation
Quoted 66 lines · Joonsoo Kim
Quoted 11 lines · Alexander Potapenko
Quarantine isolates freed objects in a separate queue. The objects are returned to the allocator later, which helps to detect use-after-free errors.
Freed objects are first added to per-cpu quarantine queues. When a cache is destroyed or memory shrinking is requested, the objects are moved into the global quarantine queue. Whenever a kmalloc call allows memory reclaiming, the oldest objects are popped out of the global queue until the total size of objects in quarantine is less than 3/4 of the maximum quarantine size (which is a fraction of installed physical memory).
Just wondering why not using time based approach rather than size based one. In heavy load condition, how much time do the object stay in quarantine?
Quoted 24 lines
Right now quarantine support is only enabled in SLAB allocator. Unification of KASAN features in SLAB and SLUB will be done later.
This patch is based on the "mm: kasan: quarantine" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- include/linux/kasan.h | 30 ++++-- lib/test_kasan.c | 29 ++++++ mm/kasan/Makefile | 2 +- mm/kasan/kasan.c | 68 +++++++++++- mm/kasan/kasan.h | 11 +- mm/kasan/quarantine.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++ mm/kasan/report.c | 3 +- mm/mempool.c | 7 +- mm/page_alloc.c | 2 +- mm/slab.c | 12 ++- mm/slab.h | 4 + mm/slab_common.c | 2 + mm/slub.c | 4 +- 13 files changed, 435 insertions(+), 23 deletions(-)...
Quoted 7 lines
mm/kasan/kasan.c +7
-0+bool kasan_slab_free (struct kmem_cache *cache,void *object) +{ +#ifdef CONFIG_SLAB +/* RCU slabs could be legally used after free within the RCU period */ +if (unlikely (cache->flags &SLAB_DESTROY_BY_RCU )) +return false; +mm/kasan/kasan.c void kasan_slab_free(struct kmem_cache *cache, void *object) · line 509
Quoted 10 lines
mm/kasan/kasan.c +10
-0+if (likely (cache->flags &SLAB_KASAN )) { +struct kasan_alloc_meta *alloc_info = +get_alloc_info (cache, object); +struct kasan_free_meta *free_info = +get_free_info (cache, object); + +switch (alloc_info->state) { +case KASAN_STATE_ALLOC : + alloc_info->state =KASAN_STATE_QUARANTINE ; +quarantine_put (free_info, cache);
quarantine_put()can be called regardless ofSLAB_DESTROY_BY_RCU, although it's not much meaningful without poisoning. But, I have an idea to poison object onSLAB_DESTROY_BY_RCUcache.
Quoted 5 lines
quarantine_put()moves per cpu list to global queue when list size reachesQUARANTINE_PERCPU_SIZE. If we callsynchronize_rcu()at that time, after then, we can poison objects. With appropriate size setup, it would not be intrusive.
Won't this slow the quarantine down unpredictably (e.g. in the case there're no RCU slabs in quarantine we'll still be waiting for synchronize_rcu())?
Yet this is something worth looking into. Do you want RCU to be handled in this patch set?
Quoted 3 lines
Quoted 1 line
+
set_track(&free_info->track, GFP_NOWAIT);
set_track()can be called regardless ofSLAB_DESTROY_BY_RCU.
Agreed, I can fix that if we decide to handle RCU in this patch (otherwise it will lead to confusion).
Quoted 55 lines
Quoted 19 lines
mm/kasan/kasan.c +18
-0+kasan_poison_slab_free (cache, object); +return true; +case KASAN_STATE_QUARANTINE : +case KASAN_STATE_FREE : +pr_err ("Double free" ); +dump_stack (); +break ; +default : + break; + } + } +return false; +#else +kasan_poison_slab_free (cache, object); +return false; +#endif +} +...
Quoted 33 lines
mm/kasan/quarantine.c new file +33
-0+void quarantine_reduce (void ) +{ +size_t new_quarantine_size; +unsigned long flags; +struct qlist to_free =QLIST_INIT ; +size_t size_to_free =0 ; +void **last; + +if (likely (ACCESS_ONCE (global_quarantine.bytes) <= +smp_load_acquire (&quarantine_size))) +return ; + +spin_lock_irqsave (&quarantine_lock, flags); + +/* Update quarantine size in case of hotplug. Allocate a fraction of +* the installed memory to quarantine minus per-cpu queue limits. +*/ + new_quarantine_size = (ACCESS_ONCE (totalram_pages) <<PAGE_SHIFT ) / +QUARANTINE_FRACTION ; + new_quarantine_size -=QUARANTINE_PERCPU_SIZE *num_online_cpus (); +smp_store_release (&quarantine_size, new_quarantine_size); + + last = global_quarantine.head; +while (last) { +struct kmem_cache *cache =qlink_to_cache (last); + + size_to_free += cache->size; +if (!*last || size_to_free > + global_quarantine.bytes -QUARANTINE_LOW_SIZE ) +break ; + last = (void **) *last; + } +qlist_move (&global_quarantine, last, &to_free, size_to_free);
Quoted 8 lines
mm/kasan/quarantine.c line 230
Quoted 5 lines
mm/kasan/quarantine.c new file +5
-0+ +spin_unlock_irqrestore (&quarantine_lock, flags); + +qlist_free_all (&to_free,NULL ); +}Isn't it better to call
quarantine_reduce()inshrink_slab()? It will help to maximize quarantine time.
This is true, however if we don't call quarantine_reduce() from kmalloc()/kfree() the size of the quarantine will be unpredictable. There's a tradeoff between efficiency and space here, and at least in some cases we may want to trade efficiency for space.
Quoted 42 lines
Quoted 42 lines
mm/kasan/quarantine.c new file +41
-0+ +static inline void qlist_move_cache (struct qlist *from, +struct qlist *to, +struct kmem_cache *cache) +{ +void ***prev; + +if (unlikely (empty_qlist (from))) +return ; + + prev = &from->head; +while (*prev) { +void **qlink = *prev; +struct kmem_cache *obj_cache =qlink_to_cache (qlink); + +if (obj_cache == cache) { +if (unlikely (from->tail == qlink)) + from->tail = (void **) prev; + *prev = (void **) *qlink; + from->bytes -= cache->size; +qlist_put (to, qlink, cache->size); + }else + prev = (void ***) *prev; + } +} + +static void per_cpu_remove_cache (void *arg) +{ +struct kmem_cache *cache = arg; +struct qlist to_free =QLIST_INIT ; +struct qlist *q; +unsigned long flags; + +local_irq_save (flags); + q =this_cpu_ptr (&cpu_quarantine); +qlist_move_cache (q, &to_free, cache); +local_irq_restore (flags); + +qlist_free_all (&to_free, cache); +} +
Quoted 8 lines
mm/kasan/quarantine.c line 277
Quoted 6 lines
mm/kasan/quarantine.c new file +6
-0+void quarantine_remove_cache (struct kmem_cache *cache) +{ +unsigned long flags; +struct qlist to_free =QLIST_INIT ; + +on_each_cpu (per_cpu_remove_cache, cache,0 );Should be called with wait = 1.
Agreed, thank you.
Quoted 70 lines
Quoted 70 lines
mm/kasan/quarantine.c new file +7
-0+ +spin_lock_irqsave (&quarantine_lock, flags); +qlist_move_cache (&global_quarantine, &to_free, cache); +spin_unlock_irqrestore (&quarantine_lock, flags); + +qlist_free_all (&to_free, cache); +}mm/kasan/report.c +2
-1@@ -148,7 +148,8 @@ static void print_object(struct kmem_cache *cache, void *object)print_track (&alloc_info->track);break ;case KASAN_STATE_FREE : -pr_err ("Object freed, allocated with size %u bytes\n" , +case KASAN_STATE_QUARANTINE : +pr_err ("Object freed, allocated with size %lu bytes\n" , alloc_info->alloc_size); free_info =get_free_info (cache, object);pr_err ("Allocation:\n" );mm/mempool.c +4
-3@@ -105,11 +105,12 @@ static inline void poison_element(mempool_t *pool, void *element)static void kasan_poison_element (mempool_t *pool,void *element) {if (pool->alloc == mempool_alloc_slab) -kasan_slab_free (pool->pool_data, element); +kasan_poison_slab_free (pool->pool_data, element);if (pool->alloc == mempool_kmalloc) -kasan_kfree (element); +kasan_poison_kfree (element);if (pool->alloc == mempool_alloc_pages) -kasan_free_pages (element, (unsigned long )pool->pool_data); +kasan_poison_free_pages (element, + (unsigned long )pool->pool_data); }static void kasan_unpoison_element (mempool_t *pool,void *element,gfp_t flags)mm/page_alloc.c +1
-1@@ -980,7 +980,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); +kasan_poison_free_pages (page, order);if (PageAnon (page)) page->mapping =NULL ;mm/slab.c +8
-0@@ -3374,9 +3374,19 @@ free_done:static inline void __cache_free (struct kmem_cache *cachep,void *objp,unsigned long caller) { +#ifdef CONFIG_KASAN +if (!kasan_slab_free (cachep, objp)) +/* The object has been put into the quarantine, don't touch it +* for now. +*/ + nokasan_free(cachep, objp, caller); +} +
Quoted 8 lines
mm/slab.c free_done: · line 3387
Quoted 3 lines
mm/slab.c +3
-0+void nokasan_free (struct kmem_cache *cachep,void *objp,unsigned long caller) +{ +#endif It looks not good to me.
Converting__cache_free()to____cache_free()and making__cache_free()call____cache_free()if (!kasan_slab_free()) looks better to me and less error-prone.
Fixed. Will upload the new patchset soonish.
Quoted 1 line
Thanks.
Signature · 22 lines
Alexander Potapenko Software Engineer Google Germany GmbH Erika-Mann-Straße, 33 80636 München Geschäftsführer: Matthew Scott Sucherman, Paul Terence Manicle Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Diese E-Mail ist vertraulich. Wenn Sie nicht der richtige Adressat sind, leiten Sie diese bitte nicht weiter, informieren Sie den Absender und löschen Sie die E-Mail und alle Anhänge. Vielen Dank. This e-mail is confidential. If you are not the right addressee please do not forward it, please inform the sender, and please erase this e-mail including any attachments. Thanks. -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 8/8] mm: kasan: Initial memory quarantine implementation
2016-02-18 23:06 GMT+09:00 Alexander Potapenko <[email protected]>:
Quoted 67 lines · Joonsoo Kim
Quoted 66 lines · Alexander Potapenko
Quoted 11 lines
Quarantine isolates freed objects in a separate queue. The objects are returned to the allocator later, which helps to detect use-after-free errors.
Freed objects are first added to per-cpu quarantine queues. When a cache is destroyed or memory shrinking is requested, the objects are moved into the global quarantine queue. Whenever a kmalloc call allows memory reclaiming, the oldest objects are popped out of the global queue until the total size of objects in quarantine is less than 3/4 of the maximum quarantine size (which is a fraction of installed physical memory).
Just wondering why not using time based approach rather than size based one. In heavy load condition, how much time do the object stay in quarantine?
Quoted 24 lines
Right now quarantine support is only enabled in SLAB allocator. Unification of KASAN features in SLAB and SLUB will be done later.
This patch is based on the "mm: kasan: quarantine" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- include/linux/kasan.h | 30 ++++-- lib/test_kasan.c | 29 ++++++ mm/kasan/Makefile | 2 +- mm/kasan/kasan.c | 68 +++++++++++- mm/kasan/kasan.h | 11 +- mm/kasan/quarantine.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++ mm/kasan/report.c | 3 +- mm/mempool.c | 7 +- mm/page_alloc.c | 2 +- mm/slab.c | 12 ++- mm/slab.h | 4 + mm/slab_common.c | 2 + mm/slub.c | 4 +- 13 files changed, 435 insertions(+), 23 deletions(-)...
Quoted 7 lines
mm/kasan/kasan.c +7
-0+bool kasan_slab_free (struct kmem_cache *cache,void *object) +{ +#ifdef CONFIG_SLAB +/* RCU slabs could be legally used after free within the RCU period */ +if (unlikely (cache->flags &SLAB_DESTROY_BY_RCU )) +return false; +mm/kasan/kasan.c void kasan_slab_free(struct kmem_cache *cache, void *object) · line 509
Quoted 10 lines
mm/kasan/kasan.c +10
-0+if (likely (cache->flags &SLAB_KASAN )) { +struct kasan_alloc_meta *alloc_info = +get_alloc_info (cache, object); +struct kasan_free_meta *free_info = +get_free_info (cache, object); + +switch (alloc_info->state) { +case KASAN_STATE_ALLOC : + alloc_info->state =KASAN_STATE_QUARANTINE ; +quarantine_put (free_info, cache);
quarantine_put()can be called regardless ofSLAB_DESTROY_BY_RCU, although it's not much meaningful without poisoning. But, I have an idea to poison object onSLAB_DESTROY_BY_RCUcache.
Quoted 8 lines
Quoted 5 lines
quarantine_put()moves per cpu list to global queue when list size reachesQUARANTINE_PERCPU_SIZE. If we callsynchronize_rcu()at that time, after then, we can poison objects. With appropriate size setup, it would not be intrusive.Won't this slow the quarantine down unpredictably (e.g. in the case there're no RCU slabs in quarantine we'll still be waiting for
synchronize_rcu())?
It could be handled by introducing one cpu variable.
Quoted 2 lines
Yet this is something worth looking into. Do you want RCU to be handled in this patch set?
No. It would be future work.
Quoted 69 lines
Quoted 3 lines
Quoted 1 line
+
set_track(&free_info->track, GFP_NOWAIT);
set_track()can be called regardless ofSLAB_DESTROY_BY_RCU.Agreed, I can fix that if we decide to handle RCU in this patch (otherwise it will lead to confusion).
Quoted 55 lines
Quoted 19 lines
mm/kasan/kasan.c +18
-0+kasan_poison_slab_free (cache, object); +return true; +case KASAN_STATE_QUARANTINE : +case KASAN_STATE_FREE : +pr_err ("Double free" ); +dump_stack (); +break ; +default : + break; + } + } +return false; +#else +kasan_poison_slab_free (cache, object); +return false; +#endif +} +...
Quoted 33 lines
mm/kasan/quarantine.c new file +33
-0+void quarantine_reduce (void ) +{ +size_t new_quarantine_size; +unsigned long flags; +struct qlist to_free =QLIST_INIT ; +size_t size_to_free =0 ; +void **last; + +if (likely (ACCESS_ONCE (global_quarantine.bytes) <= +smp_load_acquire (&quarantine_size))) +return ; + +spin_lock_irqsave (&quarantine_lock, flags); + +/* Update quarantine size in case of hotplug. Allocate a fraction of +* the installed memory to quarantine minus per-cpu queue limits. +*/ + new_quarantine_size = (ACCESS_ONCE (totalram_pages) <<PAGE_SHIFT ) / +QUARANTINE_FRACTION ; + new_quarantine_size -=QUARANTINE_PERCPU_SIZE *num_online_cpus (); +smp_store_release (&quarantine_size, new_quarantine_size); + + last = global_quarantine.head; +while (last) { +struct kmem_cache *cache =qlink_to_cache (last); + + size_to_free += cache->size; +if (!*last || size_to_free > + global_quarantine.bytes -QUARANTINE_LOW_SIZE ) +break ; + last = (void **) *last; + } +qlist_move (&global_quarantine, last, &to_free, size_to_free);Quoted 8 lines
mm/kasan/quarantine.c line 230
Quoted 5 lines
mm/kasan/quarantine.c new file +5
-0+ +spin_unlock_irqrestore (&quarantine_lock, flags); + +qlist_free_all (&to_free,NULL ); +}Isn't it better to call
quarantine_reduce()inshrink_slab()? It will help to maximize quarantine time.
Quoted 4 lines
This is true, however if we don't call
quarantine_reduce()from kmalloc()/kfree() the size of the quarantine will be unpredictable. There's a tradeoff between efficiency and space here, and at least in some cases we may want to trade efficiency for space.
size of the quarantine doesn't matter unless there is memory pressure. If memory pressure, shrink_slab() would be called and we can reduce size of quarantine. However, I don't think this is show stopper. We can do it when needed.
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Dmitry Vyukov
reviewerRe: [PATCH v1 8/8] mm: kasan: Initial memory quarantine implementation
Quoted 158 lines · Joonsoo Kim
2016-02-18 23:06 GMT+09:00 Alexander Potapenko <[email protected]>:
Quoted 67 lines · Joonsoo Kim
Quoted 66 lines · Alexander Potapenko
Quoted 11 lines
Quarantine isolates freed objects in a separate queue. The objects are returned to the allocator later, which helps to detect use-after-free errors.
Freed objects are first added to per-cpu quarantine queues. When a cache is destroyed or memory shrinking is requested, the objects are moved into the global quarantine queue. Whenever a kmalloc call allows memory reclaiming, the oldest objects are popped out of the global queue until the total size of objects in quarantine is less than 3/4 of the maximum quarantine size (which is a fraction of installed physical memory).
Just wondering why not using time based approach rather than size based one. In heavy load condition, how much time do the object stay in quarantine?
Quoted 24 lines
Right now quarantine support is only enabled in SLAB allocator. Unification of KASAN features in SLAB and SLUB will be done later.
This patch is based on the "mm: kasan: quarantine" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- include/linux/kasan.h | 30 ++++-- lib/test_kasan.c | 29 ++++++ mm/kasan/Makefile | 2 +- mm/kasan/kasan.c | 68 +++++++++++- mm/kasan/kasan.h | 11 +- mm/kasan/quarantine.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++ mm/kasan/report.c | 3 +- mm/mempool.c | 7 +- mm/page_alloc.c | 2 +- mm/slab.c | 12 ++- mm/slab.h | 4 + mm/slab_common.c | 2 + mm/slub.c | 4 +- 13 files changed, 435 insertions(+), 23 deletions(-)...
Quoted 7 lines
mm/kasan/kasan.c +7
-0+bool kasan_slab_free (struct kmem_cache *cache,void *object) +{ +#ifdef CONFIG_SLAB +/* RCU slabs could be legally used after free within the RCU period */ +if (unlikely (cache->flags &SLAB_DESTROY_BY_RCU )) +return false; +mm/kasan/kasan.c void kasan_slab_free(struct kmem_cache *cache, void *object) · line 509
Quoted 10 lines
mm/kasan/kasan.c +10
-0+if (likely (cache->flags &SLAB_KASAN )) { +struct kasan_alloc_meta *alloc_info = +get_alloc_info (cache, object); +struct kasan_free_meta *free_info = +get_free_info (cache, object); + +switch (alloc_info->state) { +case KASAN_STATE_ALLOC : + alloc_info->state =KASAN_STATE_QUARANTINE ; +quarantine_put (free_info, cache);
quarantine_put()can be called regardless ofSLAB_DESTROY_BY_RCU, although it's not much meaningful without poisoning. But, I have an idea to poison object onSLAB_DESTROY_BY_RCUcache.Quoted 8 lines
Quoted 5 lines
quarantine_put()moves per cpu list to global queue when list size reachesQUARANTINE_PERCPU_SIZE. If we callsynchronize_rcu()at that time, after then, we can poison objects. With appropriate size setup, it would not be intrusive.Won't this slow the quarantine down unpredictably (e.g. in the case there're no RCU slabs in quarantine we'll still be waiting for
synchronize_rcu())?It could be handled by introducing one cpu variable.
Quoted 2 lines
Yet this is something worth looking into. Do you want RCU to be handled in this patch set?
No. It would be future work.
Quoted 69 lines
Quoted 3 lines
Quoted 1 line
+
set_track(&free_info->track, GFP_NOWAIT);
set_track()can be called regardless ofSLAB_DESTROY_BY_RCU.Agreed, I can fix that if we decide to handle RCU in this patch (otherwise it will lead to confusion).
Quoted 55 lines
Quoted 19 lines
mm/kasan/kasan.c +18
-0+kasan_poison_slab_free (cache, object); +return true; +case KASAN_STATE_QUARANTINE : +case KASAN_STATE_FREE : +pr_err ("Double free" ); +dump_stack (); +break ; +default : + break; + } + } +return false; +#else +kasan_poison_slab_free (cache, object); +return false; +#endif +} +...
Quoted 33 lines
mm/kasan/quarantine.c new file +33
-0+void quarantine_reduce (void ) +{ +size_t new_quarantine_size; +unsigned long flags; +struct qlist to_free =QLIST_INIT ; +size_t size_to_free =0 ; +void **last; + +if (likely (ACCESS_ONCE (global_quarantine.bytes) <= +smp_load_acquire (&quarantine_size))) +return ; + +spin_lock_irqsave (&quarantine_lock, flags); + +/* Update quarantine size in case of hotplug. Allocate a fraction of +* the installed memory to quarantine minus per-cpu queue limits. +*/ + new_quarantine_size = (ACCESS_ONCE (totalram_pages) <<PAGE_SHIFT ) / +QUARANTINE_FRACTION ; + new_quarantine_size -=QUARANTINE_PERCPU_SIZE *num_online_cpus (); +smp_store_release (&quarantine_size, new_quarantine_size); + + last = global_quarantine.head; +while (last) { +struct kmem_cache *cache =qlink_to_cache (last); + + size_to_free += cache->size; +if (!*last || size_to_free > + global_quarantine.bytes -QUARANTINE_LOW_SIZE ) +break ; + last = (void **) *last; + } +qlist_move (&global_quarantine, last, &to_free, size_to_free);Quoted 8 lines
mm/kasan/quarantine.c line 230
Quoted 5 lines
mm/kasan/quarantine.c new file +5
-0+ +spin_unlock_irqrestore (&quarantine_lock, flags); + +qlist_free_all (&to_free,NULL ); +}Isn't it better to call
quarantine_reduce()inshrink_slab()? It will help to maximize quarantine time.Quoted 4 lines
This is true, however if we don't call
quarantine_reduce()from kmalloc()/kfree() the size of the quarantine will be unpredictable. There's a tradeoff between efficiency and space here, and at least in some cases we may want to trade efficiency for space.
Quoted 4 lines
size of the quarantine doesn't matter unless there is memory pressure. If memory pressure,
shrink_slab()would be called and we can reduce size of quarantine. However, I don't think this is show stopper. We can do it when needed.
No, this does not work. We've tried.
The problem is fragmentation. When all memory is occupied by slab, it's already too late to reclaim memory. Free objects are randomly scattered over memory, so if you have just 1% of live objects, the chances are that you won't be able to reclaim any single page.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 8/8] mm: kasan: Initial memory quarantine implementation
Quoted 5 lines · Dmitry Vyukov
No, this does not work. We've tried.
The problem is fragmentation. When all memory is occupied by slab, it's already too late to reclaim memory. Free objects are randomly scattered over memory, so if you have just 1% of live objects, the chances are that you won't be able to reclaim any single page.
Yes that is why slab objects *need* to be *movable*!!!
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [PATCH v1 8/8] mm: kasan: Initial memory quarantine implementation
In reply to Dmitry VyukovQuoted 165 lines · Dmitry Vyukov
Quoted 158 lines · Joonsoo Kim
2016-02-18 23:06 GMT+09:00 Alexander Potapenko <[email protected]>:
Quoted 67 lines · Joonsoo Kim
Quoted 66 lines · Alexander Potapenko
Quoted 11 lines
Quarantine isolates freed objects in a separate queue. The objects are returned to the allocator later, which helps to detect use-after-free errors.
Freed objects are first added to per-cpu quarantine queues. When a cache is destroyed or memory shrinking is requested, the objects are moved into the global quarantine queue. Whenever a kmalloc call allows memory reclaiming, the oldest objects are popped out of the global queue until the total size of objects in quarantine is less than 3/4 of the maximum quarantine size (which is a fraction of installed physical memory).
Just wondering why not using time based approach rather than size based one. In heavy load condition, how much time do the object stay in quarantine?
Quoted 24 lines
Right now quarantine support is only enabled in SLAB allocator. Unification of KASAN features in SLAB and SLUB will be done later.
This patch is based on the "mm: kasan: quarantine" patch originally prepared by Dmitry Chernenkov.
Signed-off-by Alexander Potapenko <[email protected]>--- include/linux/kasan.h | 30 ++++-- lib/test_kasan.c | 29 ++++++ mm/kasan/Makefile | 2 +- mm/kasan/kasan.c | 68 +++++++++++- mm/kasan/kasan.h | 11 +- mm/kasan/quarantine.c | 284 ++++++++++++++++++++++++++++++++++++++++++++++++++ mm/kasan/report.c | 3 +- mm/mempool.c | 7 +- mm/page_alloc.c | 2 +- mm/slab.c | 12 ++- mm/slab.h | 4 + mm/slab_common.c | 2 + mm/slub.c | 4 +- 13 files changed, 435 insertions(+), 23 deletions(-)...
Quoted 7 lines
mm/kasan/kasan.c +7
-0+bool kasan_slab_free (struct kmem_cache *cache,void *object) +{ +#ifdef CONFIG_SLAB +/* RCU slabs could be legally used after free within the RCU period */ +if (unlikely (cache->flags &SLAB_DESTROY_BY_RCU )) +return false; +mm/kasan/kasan.c void kasan_slab_free(struct kmem_cache *cache, void *object) · line 509
Quoted 10 lines
mm/kasan/kasan.c +10
-0+if (likely (cache->flags &SLAB_KASAN )) { +struct kasan_alloc_meta *alloc_info = +get_alloc_info (cache, object); +struct kasan_free_meta *free_info = +get_free_info (cache, object); + +switch (alloc_info->state) { +case KASAN_STATE_ALLOC : + alloc_info->state =KASAN_STATE_QUARANTINE ; +quarantine_put (free_info, cache);
quarantine_put()can be called regardless ofSLAB_DESTROY_BY_RCU, although it's not much meaningful without poisoning. But, I have an idea to poison object onSLAB_DESTROY_BY_RCUcache.Quoted 8 lines
Quoted 5 lines
quarantine_put()moves per cpu list to global queue when list size reachesQUARANTINE_PERCPU_SIZE. If we callsynchronize_rcu()at that time, after then, we can poison objects. With appropriate size setup, it would not be intrusive.Won't this slow the quarantine down unpredictably (e.g. in the case there're no RCU slabs in quarantine we'll still be waiting for
synchronize_rcu())?It could be handled by introducing one cpu variable.
Quoted 2 lines
Yet this is something worth looking into. Do you want RCU to be handled in this patch set?
No. It would be future work.
Quoted 69 lines
Quoted 3 lines
Quoted 1 line
+
set_track(&free_info->track, GFP_NOWAIT);
set_track()can be called regardless ofSLAB_DESTROY_BY_RCU.Agreed, I can fix that if we decide to handle RCU in this patch (otherwise it will lead to confusion).
Quoted 55 lines
Quoted 19 lines
mm/kasan/kasan.c +18
-0+kasan_poison_slab_free (cache, object); +return true; +case KASAN_STATE_QUARANTINE : +case KASAN_STATE_FREE : +pr_err ("Double free" ); +dump_stack (); +break ; +default : + break; + } + } +return false; +#else +kasan_poison_slab_free (cache, object); +return false; +#endif +} +...
Quoted 33 lines
mm/kasan/quarantine.c new file +33
-0+void quarantine_reduce (void ) +{ +size_t new_quarantine_size; +unsigned long flags; +struct qlist to_free =QLIST_INIT ; +size_t size_to_free =0 ; +void **last; + +if (likely (ACCESS_ONCE (global_quarantine.bytes) <= +smp_load_acquire (&quarantine_size))) +return ; + +spin_lock_irqsave (&quarantine_lock, flags); + +/* Update quarantine size in case of hotplug. Allocate a fraction of +* the installed memory to quarantine minus per-cpu queue limits. +*/ + new_quarantine_size = (ACCESS_ONCE (totalram_pages) <<PAGE_SHIFT ) / +QUARANTINE_FRACTION ; + new_quarantine_size -=QUARANTINE_PERCPU_SIZE *num_online_cpus (); +smp_store_release (&quarantine_size, new_quarantine_size); + + last = global_quarantine.head; +while (last) { +struct kmem_cache *cache =qlink_to_cache (last); + + size_to_free += cache->size; +if (!*last || size_to_free > + global_quarantine.bytes -QUARANTINE_LOW_SIZE ) +break ; + last = (void **) *last; + } +qlist_move (&global_quarantine, last, &to_free, size_to_free);Quoted 8 lines
mm/kasan/quarantine.c line 230
Quoted 5 lines
mm/kasan/quarantine.c new file +5
-0+ +spin_unlock_irqrestore (&quarantine_lock, flags); + +qlist_free_all (&to_free,NULL ); +}Isn't it better to call
quarantine_reduce()inshrink_slab()? It will help to maximize quarantine time.Quoted 4 lines
This is true, however if we don't call
quarantine_reduce()from kmalloc()/kfree() the size of the quarantine will be unpredictable. There's a tradeoff between efficiency and space here, and at least in some cases we may want to trade efficiency for space.Quoted 4 lines
size of the quarantine doesn't matter unless there is memory pressure. If memory pressure,
shrink_slab()would be called and we can reduce size of quarantine. However, I don't think this is show stopper. We can do it when needed.
Quoted 5 lines
No, this does not work. We've tried.
The problem is fragmentation. When all memory is occupied by slab, it's already too late to reclaim memory. Free objects are randomly scattered over memory, so if you have just 1% of live objects, the chances are that you won't be able to reclaim any single page.
Okay. Now, I got it.
Thanks.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>