On Thu, Feb 14, 2019 at 1:25 AM Andrey Konovalov <[email protected]> wrote: > > 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. > > Signed-off-by: Andrey Konovalov <[email protected]>
Reported-by: Qian Cai <[email protected]> > --- > mm/slub.c | 13 ++++++++++++- > 1 file changed, 12 insertions(+), 1 deletion(-) > > diff --git a/mm/slub.c b/mm/slub.c > index 80da3a40b74d..c80e6699357c 100644 > --- a/mm/slub.c > +++ b/mm/slub.c > @@ -249,7 +249,18 @@ static inline void *freelist_ptr(const struct kmem_cache > *s, void *ptr, > unsigned long ptr_addr) > { > #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 > return ptr; > #endif > -- > 2.20.1.791.gb4d0f1c61a-goog >

