mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 06:02:05 +00:00
kasan, slub: fix more conflicts with CONFIG_SLAB_FREELIST_HARDENED
When CONFIG_KASAN_SW_TAGS is enabled, ptr_addr might be tagged. Normally, this doesn't cause any issues, as both set_freepointer() and get_freepointer() are called with a pointer with the same tag. However, there are some issues with CONFIG_SLUB_DEBUG code. For example, when __free_slub() iterates over objects in a cache, it passes untagged pointers to check_object(). check_object() in turns calls get_freepointer() with an untagged pointer, which causes the freepointer to be restored incorrectly. Add kasan_reset_tag to freelist_ptr(). Also add a detailed comment. Link: http://lkml.kernel.org/r/bf858f26ef32eb7bd24c665755b3aee4bc58d0e4.1550103861.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov <andreyknvl@google.com> Reported-by: Qian Cai <cai@lca.pw> Tested-by: Qian Cai <cai@lca.pw> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Cc: Alexander Potapenko <glider@google.com> Cc: Dmitry Vyukov <dvyukov@google.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
18e5066102
commit
d36a63a943
13
mm/slub.c
13
mm/slub.c
@ -249,7 +249,18 @@ static inline void *freelist_ptr(const struct kmem_cache *s, void *ptr,
|
|||||||
unsigned long ptr_addr)
|
unsigned long ptr_addr)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_SLAB_FREELIST_HARDENED
|
#ifdef CONFIG_SLAB_FREELIST_HARDENED
|
||||||
return (void *)((unsigned long)ptr ^ s->random ^ ptr_addr);
|
/*
|
||||||
|
* When CONFIG_KASAN_SW_TAGS is enabled, ptr_addr might be tagged.
|
||||||
|
* Normally, this doesn't cause any issues, as both set_freepointer()
|
||||||
|
* and get_freepointer() are called with a pointer with the same tag.
|
||||||
|
* However, there are some issues with CONFIG_SLUB_DEBUG code. For
|
||||||
|
* example, when __free_slub() iterates over objects in a cache, it
|
||||||
|
* passes untagged pointers to check_object(). check_object() in turns
|
||||||
|
* calls get_freepointer() with an untagged pointer, which causes the
|
||||||
|
* freepointer to be restored incorrectly.
|
||||||
|
*/
|
||||||
|
return (void *)((unsigned long)ptr ^ s->random ^
|
||||||
|
(unsigned long)kasan_reset_tag((void *)ptr_addr));
|
||||||
#else
|
#else
|
||||||
return ptr;
|
return ptr;
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user