diff mbox series

arm64: kasan: fix phys_to_virt() false positive on tag-based kasan

Message ID 20190819114420.2535-1-walter-zh.wu@mediatek.com (mailing list archive)
State New, archived
Headers show
Series arm64: kasan: fix phys_to_virt() false positive on tag-based kasan | expand

Commit Message

Walter Wu Aug. 19, 2019, 11:44 a.m. UTC
__arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
but it will modify pointer tag into 0xff, so there is a false positive.

When enable tag-based kasan, phys_to_virt() function need to rewrite
its original pointer tag in order to avoid kasan report an incorrect
memory corruption.

BUG: KASAN: double-free or invalid-free in __arm_v7s_unmap+0x720/0xda4
Pointer tag: [ff], memory tag: [c1]

Call trace:
 dump_backtrace+0x0/0x1d4
 show_stack+0x14/0x1c
 dump_stack+0xe8/0x140
 print_address_description+0x80/0x2f0
 kasan_report_invalid_free+0x58/0x74
 __kasan_slab_free+0x1e4/0x220
 kasan_slab_free+0xc/0x18
 kmem_cache_free+0xfc/0x884
 __arm_v7s_unmap+0x720/0xda4
 __arm_v7s_map+0xc8/0x774
 arm_v7s_map+0x80/0x158
 mtk_iommu_map+0xb4/0xe0
 iommu_map+0x154/0x450
 iommu_map_sg+0xe4/0x150
 iommu_dma_map_sg+0x214/0x4ec
 __iommu_map_sg_attrs+0xf0/0x110
 ion_map_dma_buf+0xe8/0x114
 dma_buf_map_attachment+0x4c/0x80
 disp_sync_prepare_buf+0x378/0x820
 _ioctl_prepare_buffer+0x130/0x870
 mtk_disp_mgr_ioctl+0x5c4/0xab0
 do_vfs_ioctl+0x8e0/0x15a4
 __arm64_sys_ioctl+0x8c/0xb4
 el0_svc_common+0xe4/0x1e0
 el0_svc_handler+0x30/0x3c
 el0_svc+0x8/0xc

Signed-off-by: Walter Wu <walter-zh.wu@mediatek.com>
---
 arch/arm64/include/asm/kasan.h  |  1 -
 arch/arm64/include/asm/memory.h | 10 ++++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

Comments

Will Deacon Aug. 19, 2019, 12:56 p.m. UTC | #1
On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
> __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
> but it will modify pointer tag into 0xff, so there is a false positive.
> 
> When enable tag-based kasan, phys_to_virt() function need to rewrite
> its original pointer tag in order to avoid kasan report an incorrect
> memory corruption.

Hmm. Which tree did you see this on? We've recently queued a load of fixes
in this area, but I /thought/ they were only needed after the support for
52-bit virtual addressing in the kernel.

Will
Mark Rutland Aug. 19, 2019, 1:23 p.m. UTC | #2
On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
> On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
> > __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
> > but it will modify pointer tag into 0xff, so there is a false positive.
> > 
> > When enable tag-based kasan, phys_to_virt() function need to rewrite
> > its original pointer tag in order to avoid kasan report an incorrect
> > memory corruption.
> 
> Hmm. Which tree did you see this on? We've recently queued a load of fixes
> in this area, but I /thought/ they were only needed after the support for
> 52-bit virtual addressing in the kernel.

I'm seeing similar issues in the virtio blk code (splat below), atop of
the arm64 for-next/core branch. I think this is a latent issue, and
people are only just starting to test with KASAN_SW_TAGS.

It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
virt->page->virt, losing the per-object tag in the process.

Our page_to_virt() seems to get a per-page tag, but this only makes
sense if you're dealing with the page allocator, rather than something
like SLUB which carves a page into smaller objects giving each object a
distinct tag.

Any round-trip of a pointer from SLUB is going to lose the per-object
tag.

Thanks,
Mark.

==================================================================
BUG: KASAN: double-free or invalid-free in virtblk_request_done+0x128/0x1d8 drivers/block/virtio_blk.c:215
Pointer tag: [ff], memory tag: [a8]

CPU: 0 PID: 19116 Comm: syz-executor.0 Not tainted 5.3.0-rc3-00075-gcb38552 #1
Hardware name: linux,dummy-virt (DT)
Call trace:
 dump_backtrace+0x0/0x3c0 arch/arm64/include/asm/stacktrace.h:166
 show_stack+0x24/0x30 arch/arm64/kernel/traps.c:138
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x138/0x1f4 lib/dump_stack.c:113
 print_address_description+0x7c/0x328 mm/kasan/report.c:351
 kasan_report_invalid_free+0x80/0xe0 mm/kasan/report.c:444
 __kasan_slab_free+0x1a8/0x208 mm/kasan/common.c:56
 kasan_slab_free+0xc/0x18 mm/kasan/common.c:457
 slab_free_hook mm/slub.c:1423 [inline]
 slab_free_freelist_hook mm/slub.c:1474 [inline]
 slab_free mm/slub.c:3016 [inline]
 kfree+0x254/0x9dc mm/slub.c:3957
 virtblk_request_done+0x128/0x1d8 drivers/block/virtio_blk.c:215
 blk_done_softirq+0x3dc/0x49c block/blk-softirq.c:37
 __do_softirq+0xa90/0x1504 kernel/softirq.c:292
 do_softirq_own_stack include/linux/interrupt.h:549 [inline]
 invoke_softirq kernel/softirq.c:380 [inline]
 irq_exit+0x3b0/0x4f8 kernel/softirq.c:413
 __handle_domain_irq+0x150/0x250 kernel/irq/irqdesc.c:671
 atomic_read include/asm-generic/atomic-instrumented.h:26 [inline]
 static_key_count include/linux/jump_label.h:254 [inline]
 cpus_have_const_cap arch/arm64/include/asm/cpufeature.h:410 [inline]
 gic_read_iar drivers/irqchip/irq-gic-v3.c:152 [inline]
 gic_handle_irq+0x244/0x4ac drivers/irqchip/irq-gic-v3.c:490
 el1_irq+0xbc/0x140 arch/arm64/kernel/entry.S:670
 ktime_add_safe kernel/time/hrtimer.c:321 [inline]
 hrtimer_set_expires_range_ns include/linux/hrtimer.h:235 [inline]
 hrtimer_nanosleep kernel/time/hrtimer.c:1732 [inline]
 __do_sys_nanosleep kernel/time/hrtimer.c:1767 [inline]
 __se_sys_nanosleep kernel/time/hrtimer.c:1754 [inline]
 __arm64_sys_nanosleep+0x344/0x554 kernel/time/hrtimer.c:1754
 __invoke_syscall arch/arm64/kernel/syscall.c:36 [inline]
 invoke_syscall arch/arm64/kernel/syscall.c:48 [inline]
 el0_svc_common arch/arm64/kernel/syscall.c:114 [inline]
 el0_svc_handler+0x300/0x540 arch/arm64/kernel/syscall.c:160
 el0_svc+0x8/0xc arch/arm64/kernel/entry.S:1006

Allocated by task 170:
 save_stack mm/kasan/common.c:69 [inline]
 set_track mm/kasan/common.c:77 [inline]
 __kasan_kmalloc+0x114/0x1d0 mm/kasan/common.c:487
 kasan_kmalloc+0x10/0x18 mm/kasan/common.c:501
 __kmalloc+0x1f0/0x48c mm/slub.c:3811
 kmalloc_array include/linux/slab.h:676 [inline]
 virtblk_setup_discard_write_zeroes drivers/block/virtio_blk.c:188 [inline]
 virtio_queue_rq+0x948/0xe48 drivers/block/virtio_blk.c:322
 blk_mq_dispatch_rq_list+0x914/0x16fc block/blk-mq.c:1257
 blk_mq_do_dispatch_sched+0x374/0x4d8 block/blk-mq-sched.c:115
 blk_mq_sched_dispatch_requests+0x4d0/0x68c block/blk-mq-sched.c:216
 __blk_mq_run_hw_queue+0x22c/0x35c block/blk-mq.c:1387
 blk_mq_run_work_fn+0x64/0x78 block/blk-mq.c:1620
 process_one_work+0x10bc/0x1df0 kernel/workqueue.c:2269
 worker_thread+0x1124/0x17bc kernel/workqueue.c:2415
 kthread+0x3c0/0x3d0 kernel/kthread.c:255
 ret_from_fork+0x10/0x18 arch/arm64/kernel/entry.S:1164

Freed by task 17121:
 save_stack mm/kasan/common.c:69 [inline]
 set_track mm/kasan/common.c:77 [inline]
 __kasan_slab_free+0x138/0x208 mm/kasan/common.c:449
 kasan_slab_free+0xc/0x18 mm/kasan/common.c:457
 slab_free_hook mm/slub.c:1423 [inline]
 slab_free_freelist_hook mm/slub.c:1474 [inline]
 slab_free mm/slub.c:3016 [inline]
 kfree+0x254/0x9dc mm/slub.c:3957
 kvfree+0x54/0x60 mm/util.c:488
 __vunmap+0xa3c/0xafc mm/vmalloc.c:2255
 __vfree mm/vmalloc.c:2299 [inline]
 vfree+0xe4/0x1c4 mm/vmalloc.c:2329
 copy_entries_to_user net/ipv6/netfilter/ip6_tables.c:883 [inline]
 get_entries net/ipv6/netfilter/ip6_tables.c:1041 [inline]
 do_ip6t_get_ctl+0xf78/0x1804 net/ipv6/netfilter/ip6_tables.c:1709
 nf_sockopt net/netfilter/nf_sockopt.c:104 [inline]
 nf_getsockopt+0x238/0x258 net/netfilter/nf_sockopt.c:122
 ipv6_getsockopt+0x3374/0x40c4 net/ipv6/ipv6_sockglue.c:1400
 tcp_getsockopt+0x214/0x54e0 net/ipv4/tcp.c:3662
 sock_common_getsockopt+0xc8/0xf4 net/core/sock.c:3089
 __sys_getsockopt net/socket.c:2129 [inline]
 __do_sys_getsockopt net/socket.c:2144 [inline]
 __se_sys_getsockopt net/socket.c:2141 [inline]
 __arm64_sys_getsockopt+0x240/0x308 net/socket.c:2141
 __invoke_syscall arch/arm64/kernel/syscall.c:36 [inline]
 invoke_syscall arch/arm64/kernel/syscall.c:48 [inline]
 el0_svc_common arch/arm64/kernel/syscall.c:114 [inline]
 el0_svc_handler+0x300/0x540 arch/arm64/kernel/syscall.c:160
 el0_svc+0x8/0xc arch/arm64/kernel/entry.S:1006

The buggy address belongs to the object at ffff00005338eb80
 which belongs to the cache kmalloc-128 of size 128
The buggy address is located 0 bytes inside of
 128-byte region [ffff00005338eb80, ffff00005338ec00)
The buggy address belongs to the page:
page:ffffffdffff4ce00 refcount:1 mapcount:0 mapping:e5ff0000576b0480 index:0x29ff000053388f00
flags: 0xffffff000000200(slab)
raw: 0ffffff000000200 ffffffdffff00108 5eff0000576afd40 e5ff0000576b0480
raw: 29ff000053388f00 000000000066005d 00000001ffffffff 0000000000000000
page dumped because: kasan: bad access detected

Memory state around the buggy address:
 ffff00005338e900: 34 34 34 34 34 34 34 34 fe fe fe fe fe fe fe fe
 ffff00005338ea00: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
>ffff00005338eb00: fe fe fe fe fe fe fe fe a8 fe fe fe fe fe fe fe
                                           ^
 ffff00005338ec00: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
 ffff00005338ed00: fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe fe
==================================================================
Will Deacon Aug. 19, 2019, 1:34 p.m. UTC | #3
On Mon, Aug 19, 2019 at 02:23:48PM +0100, Mark Rutland wrote:
> On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
> > On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
> > > __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
> > > but it will modify pointer tag into 0xff, so there is a false positive.
> > > 
> > > When enable tag-based kasan, phys_to_virt() function need to rewrite
> > > its original pointer tag in order to avoid kasan report an incorrect
> > > memory corruption.
> > 
> > Hmm. Which tree did you see this on? We've recently queued a load of fixes
> > in this area, but I /thought/ they were only needed after the support for
> > 52-bit virtual addressing in the kernel.
> 
> I'm seeing similar issues in the virtio blk code (splat below), atop of
> the arm64 for-next/core branch. I think this is a latent issue, and
> people are only just starting to test with KASAN_SW_TAGS.
> 
> It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
> virt->page->virt, losing the per-object tag in the process.
> 
> Our page_to_virt() seems to get a per-page tag, but this only makes
> sense if you're dealing with the page allocator, rather than something
> like SLUB which carves a page into smaller objects giving each object a
> distinct tag.
> 
> Any round-trip of a pointer from SLUB is going to lose the per-object
> tag.

Urgh, I wonder how this is supposed to work?

If we end up having to check the KASAN shadow for *_to_virt(), then why
do we need to store anything in the page flags at all? Andrey?

Will
Andrey Konovalov Aug. 19, 2019, 2:05 p.m. UTC | #4
On Mon, Aug 19, 2019 at 3:34 PM Will Deacon <will@kernel.org> wrote:
>
> On Mon, Aug 19, 2019 at 02:23:48PM +0100, Mark Rutland wrote:
> > On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
> > > On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
> > > > __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
> > > > but it will modify pointer tag into 0xff, so there is a false positive.
> > > >
> > > > When enable tag-based kasan, phys_to_virt() function need to rewrite
> > > > its original pointer tag in order to avoid kasan report an incorrect
> > > > memory corruption.
> > >
> > > Hmm. Which tree did you see this on? We've recently queued a load of fixes
> > > in this area, but I /thought/ they were only needed after the support for
> > > 52-bit virtual addressing in the kernel.
> >
> > I'm seeing similar issues in the virtio blk code (splat below), atop of
> > the arm64 for-next/core branch. I think this is a latent issue, and
> > people are only just starting to test with KASAN_SW_TAGS.
> >
> > It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
> > virt->page->virt, losing the per-object tag in the process.
> >
> > Our page_to_virt() seems to get a per-page tag, but this only makes
> > sense if you're dealing with the page allocator, rather than something
> > like SLUB which carves a page into smaller objects giving each object a
> > distinct tag.
> >
> > Any round-trip of a pointer from SLUB is going to lose the per-object
> > tag.
>
> Urgh, I wonder how this is supposed to work?
>
> If we end up having to check the KASAN shadow for *_to_virt(), then why
> do we need to store anything in the page flags at all? Andrey?

As per 2813b9c0 ("kasan, mm, arm64: tag non slab memory allocated via
pagealloc") we should only save a non-0xff tag in page flags for non
slab pages.

Could you share your .config so I can reproduce this?
Andrey Ryabinin Aug. 19, 2019, 2:06 p.m. UTC | #5
On 8/19/19 4:34 PM, Will Deacon wrote:
> On Mon, Aug 19, 2019 at 02:23:48PM +0100, Mark Rutland wrote:
>> On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
>>> On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
>>>> __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
>>>> but it will modify pointer tag into 0xff, so there is a false positive.
>>>>
>>>> When enable tag-based kasan, phys_to_virt() function need to rewrite
>>>> its original pointer tag in order to avoid kasan report an incorrect
>>>> memory corruption.
>>>
>>> Hmm. Which tree did you see this on? We've recently queued a load of fixes
>>> in this area, but I /thought/ they were only needed after the support for
>>> 52-bit virtual addressing in the kernel.
>>
>> I'm seeing similar issues in the virtio blk code (splat below), atop of
>> the arm64 for-next/core branch. I think this is a latent issue, and
>> people are only just starting to test with KASAN_SW_TAGS.
>>
>> It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
>> virt->page->virt, losing the per-object tag in the process.
>>
>> Our page_to_virt() seems to get a per-page tag, but this only makes
>> sense if you're dealing with the page allocator, rather than something
>> like SLUB which carves a page into smaller objects giving each object a
>> distinct tag.
>>
>> Any round-trip of a pointer from SLUB is going to lose the per-object
>> tag.
> 
> Urgh, I wonder how this is supposed to work?
> 

We supposed to ignore pointers with 0xff tags. We do ignore them when memory access checked,
but not in kfree() path.
This untested patch should fix the issue:



---
 mm/kasan/common.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 895dc5e2b3d5..0a81cc328049 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -407,7 +407,7 @@ static inline bool shadow_invalid(u8 tag, s8 shadow_byte)
 		return shadow_byte < 0 ||
 			shadow_byte >= KASAN_SHADOW_SCALE_SIZE;
 	else
-		return tag != (u8)shadow_byte;
+		return (tag != KASAN_TAG_KERNEL) && (tag != (u8)shadow_byte);
 }
 
 static bool __kasan_slab_free(struct kmem_cache *cache, void *object,
Walter Wu Aug. 19, 2019, 2:21 p.m. UTC | #6
On Mon, 2019-08-19 at 17:06 +0300, Andrey Ryabinin wrote:
> 
> On 8/19/19 4:34 PM, Will Deacon wrote:
> > On Mon, Aug 19, 2019 at 02:23:48PM +0100, Mark Rutland wrote:
> >> On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
> >>> On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
> >>>> __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
> >>>> but it will modify pointer tag into 0xff, so there is a false positive.
> >>>>
> >>>> When enable tag-based kasan, phys_to_virt() function need to rewrite
> >>>> its original pointer tag in order to avoid kasan report an incorrect
> >>>> memory corruption.
> >>>
> >>> Hmm. Which tree did you see this on? We've recently queued a load of fixes
> >>> in this area, but I /thought/ they were only needed after the support for
> >>> 52-bit virtual addressing in the kernel.
> >>
> >> I'm seeing similar issues in the virtio blk code (splat below), atop of
> >> the arm64 for-next/core branch. I think this is a latent issue, and
> >> people are only just starting to test with KASAN_SW_TAGS.
> >>
> >> It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
> >> virt->page->virt, losing the per-object tag in the process.
> >>
> >> Our page_to_virt() seems to get a per-page tag, but this only makes
> >> sense if you're dealing with the page allocator, rather than something
> >> like SLUB which carves a page into smaller objects giving each object a
> >> distinct tag.
> >>
> >> Any round-trip of a pointer from SLUB is going to lose the per-object
> >> tag.
> > 
> > Urgh, I wonder how this is supposed to work?
> > 
> 
> We supposed to ignore pointers with 0xff tags. We do ignore them when memory access checked,
> but not in kfree() path.
> This untested patch should fix the issue:
> 
> 
> 
> ---
>  mm/kasan/common.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> index 895dc5e2b3d5..0a81cc328049 100644
> --- a/mm/kasan/common.c
> +++ b/mm/kasan/common.c
> @@ -407,7 +407,7 @@ static inline bool shadow_invalid(u8 tag, s8 shadow_byte)
>  		return shadow_byte < 0 ||
>  			shadow_byte >= KASAN_SHADOW_SCALE_SIZE;
>  	else
> -		return tag != (u8)shadow_byte;
> +		return (tag != KASAN_TAG_KERNEL) && (tag != (u8)shadow_byte);
>  }
>  
>  static bool __kasan_slab_free(struct kmem_cache *cache, void *object,


Hi, Andrey,

Does it miss the double-free case after ignore pointer tag 0xff ?
and please help review my another patch about memory corruption
identification.

Thanks your respondence

Walter
Will Deacon Aug. 19, 2019, 2:22 p.m. UTC | #7
On Mon, Aug 19, 2019 at 04:05:22PM +0200, Andrey Konovalov wrote:
> On Mon, Aug 19, 2019 at 3:34 PM Will Deacon <will@kernel.org> wrote:
> >
> > On Mon, Aug 19, 2019 at 02:23:48PM +0100, Mark Rutland wrote:
> > > On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
> > > > On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
> > > > > __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
> > > > > but it will modify pointer tag into 0xff, so there is a false positive.
> > > > >
> > > > > When enable tag-based kasan, phys_to_virt() function need to rewrite
> > > > > its original pointer tag in order to avoid kasan report an incorrect
> > > > > memory corruption.
> > > >
> > > > Hmm. Which tree did you see this on? We've recently queued a load of fixes
> > > > in this area, but I /thought/ they were only needed after the support for
> > > > 52-bit virtual addressing in the kernel.
> > >
> > > I'm seeing similar issues in the virtio blk code (splat below), atop of
> > > the arm64 for-next/core branch. I think this is a latent issue, and
> > > people are only just starting to test with KASAN_SW_TAGS.
> > >
> > > It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
> > > virt->page->virt, losing the per-object tag in the process.
> > >
> > > Our page_to_virt() seems to get a per-page tag, but this only makes
> > > sense if you're dealing with the page allocator, rather than something
> > > like SLUB which carves a page into smaller objects giving each object a
> > > distinct tag.
> > >
> > > Any round-trip of a pointer from SLUB is going to lose the per-object
> > > tag.
> >
> > Urgh, I wonder how this is supposed to work?
> >
> > If we end up having to check the KASAN shadow for *_to_virt(), then why
> > do we need to store anything in the page flags at all? Andrey?
> 
> As per 2813b9c0 ("kasan, mm, arm64: tag non slab memory allocated via
> pagealloc") we should only save a non-0xff tag in page flags for non
> slab pages.

Thanks, that makes sense. Hopefully the patch from Andrey R will solve
both of the reported splats, since I'd not realised they were both on the
kfree() path.

> Could you share your .config so I can reproduce this?

This is in the iopgtable code, so it's probably pretty tricky to trigger
at runtime unless you have the write IOMMU hardware, unfortunately.

Will
Robin Murphy Aug. 19, 2019, 2:35 p.m. UTC | #8
On 19/08/2019 15:22, Will Deacon wrote:
> On Mon, Aug 19, 2019 at 04:05:22PM +0200, Andrey Konovalov wrote:
>> On Mon, Aug 19, 2019 at 3:34 PM Will Deacon <will@kernel.org> wrote:
>>>
>>> On Mon, Aug 19, 2019 at 02:23:48PM +0100, Mark Rutland wrote:
>>>> On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
>>>>> On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
>>>>>> __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
>>>>>> but it will modify pointer tag into 0xff, so there is a false positive.
>>>>>>
>>>>>> When enable tag-based kasan, phys_to_virt() function need to rewrite
>>>>>> its original pointer tag in order to avoid kasan report an incorrect
>>>>>> memory corruption.
>>>>>
>>>>> Hmm. Which tree did you see this on? We've recently queued a load of fixes
>>>>> in this area, but I /thought/ they were only needed after the support for
>>>>> 52-bit virtual addressing in the kernel.
>>>>
>>>> I'm seeing similar issues in the virtio blk code (splat below), atop of
>>>> the arm64 for-next/core branch. I think this is a latent issue, and
>>>> people are only just starting to test with KASAN_SW_TAGS.
>>>>
>>>> It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
>>>> virt->page->virt, losing the per-object tag in the process.
>>>>
>>>> Our page_to_virt() seems to get a per-page tag, but this only makes
>>>> sense if you're dealing with the page allocator, rather than something
>>>> like SLUB which carves a page into smaller objects giving each object a
>>>> distinct tag.
>>>>
>>>> Any round-trip of a pointer from SLUB is going to lose the per-object
>>>> tag.
>>>
>>> Urgh, I wonder how this is supposed to work?
>>>
>>> If we end up having to check the KASAN shadow for *_to_virt(), then why
>>> do we need to store anything in the page flags at all? Andrey?
>>
>> As per 2813b9c0 ("kasan, mm, arm64: tag non slab memory allocated via
>> pagealloc") we should only save a non-0xff tag in page flags for non
>> slab pages.
> 
> Thanks, that makes sense. Hopefully the patch from Andrey R will solve
> both of the reported splats, since I'd not realised they were both on the
> kfree() path.
> 
>> Could you share your .config so I can reproduce this?
> 
> This is in the iopgtable code, so it's probably pretty tricky to trigger
> at runtime unless you have the write IOMMU hardware, unfortunately.

If simply freeing any entry from the l2_tables cache is sufficient, then 
the short-descriptor selftest should do the job, and that ought to run 
on anything (modulo insane RAM layouts).

Robin.
Will Deacon Aug. 19, 2019, 2:43 p.m. UTC | #9
On Mon, Aug 19, 2019 at 03:35:16PM +0100, Robin Murphy wrote:
> On 19/08/2019 15:22, Will Deacon wrote:
> > On Mon, Aug 19, 2019 at 04:05:22PM +0200, Andrey Konovalov wrote:
> > > On Mon, Aug 19, 2019 at 3:34 PM Will Deacon <will@kernel.org> wrote:
> > > > 
> > > > On Mon, Aug 19, 2019 at 02:23:48PM +0100, Mark Rutland wrote:
> > > > > On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
> > > > > > On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
> > > > > > > __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
> > > > > > > but it will modify pointer tag into 0xff, so there is a false positive.
> > > > > > > 
> > > > > > > When enable tag-based kasan, phys_to_virt() function need to rewrite
> > > > > > > its original pointer tag in order to avoid kasan report an incorrect
> > > > > > > memory corruption.
> > > > > > 
> > > > > > Hmm. Which tree did you see this on? We've recently queued a load of fixes
> > > > > > in this area, but I /thought/ they were only needed after the support for
> > > > > > 52-bit virtual addressing in the kernel.
> > > > > 
> > > > > I'm seeing similar issues in the virtio blk code (splat below), atop of
> > > > > the arm64 for-next/core branch. I think this is a latent issue, and
> > > > > people are only just starting to test with KASAN_SW_TAGS.
> > > > > 
> > > > > It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
> > > > > virt->page->virt, losing the per-object tag in the process.
> > > > > 
> > > > > Our page_to_virt() seems to get a per-page tag, but this only makes
> > > > > sense if you're dealing with the page allocator, rather than something
> > > > > like SLUB which carves a page into smaller objects giving each object a
> > > > > distinct tag.
> > > > > 
> > > > > Any round-trip of a pointer from SLUB is going to lose the per-object
> > > > > tag.
> > > > 
> > > > Urgh, I wonder how this is supposed to work?
> > > > 
> > > > If we end up having to check the KASAN shadow for *_to_virt(), then why
> > > > do we need to store anything in the page flags at all? Andrey?
> > > 
> > > As per 2813b9c0 ("kasan, mm, arm64: tag non slab memory allocated via
> > > pagealloc") we should only save a non-0xff tag in page flags for non
> > > slab pages.
> > 
> > Thanks, that makes sense. Hopefully the patch from Andrey R will solve
> > both of the reported splats, since I'd not realised they were both on the
> > kfree() path.
> > 
> > > Could you share your .config so I can reproduce this?
> > 
> > This is in the iopgtable code, so it's probably pretty tricky to trigger
> > at runtime unless you have the write IOMMU hardware, unfortunately.
> 
> If simply freeing any entry from the l2_tables cache is sufficient, then the
> short-descriptor selftest should do the job, and that ought to run on
> anything (modulo insane RAM layouts).

Ok, so that would be defconfig + CONFIG_IOMMU_IO_PGTABLE_ARMV7S +
CONFIG_IOMMU_IO_PGTABLE_ARMV7S_SELFTEST + KASAN...

Will
Mark Rutland Aug. 19, 2019, 3:03 p.m. UTC | #10
On Mon, Aug 19, 2019 at 04:05:22PM +0200, Andrey Konovalov wrote:
> On Mon, Aug 19, 2019 at 3:34 PM Will Deacon <will@kernel.org> wrote:
> >
> > On Mon, Aug 19, 2019 at 02:23:48PM +0100, Mark Rutland wrote:
> > > On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
> > > > On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
> > > > > __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
> > > > > but it will modify pointer tag into 0xff, so there is a false positive.
> > > > >
> > > > > When enable tag-based kasan, phys_to_virt() function need to rewrite
> > > > > its original pointer tag in order to avoid kasan report an incorrect
> > > > > memory corruption.
> > > >
> > > > Hmm. Which tree did you see this on? We've recently queued a load of fixes
> > > > in this area, but I /thought/ they were only needed after the support for
> > > > 52-bit virtual addressing in the kernel.
> > >
> > > I'm seeing similar issues in the virtio blk code (splat below), atop of
> > > the arm64 for-next/core branch. I think this is a latent issue, and
> > > people are only just starting to test with KASAN_SW_TAGS.
> > >
> > > It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
> > > virt->page->virt, losing the per-object tag in the process.
> > >
> > > Our page_to_virt() seems to get a per-page tag, but this only makes
> > > sense if you're dealing with the page allocator, rather than something
> > > like SLUB which carves a page into smaller objects giving each object a
> > > distinct tag.
> > >
> > > Any round-trip of a pointer from SLUB is going to lose the per-object
> > > tag.
> >
> > Urgh, I wonder how this is supposed to work?
> >
> > If we end up having to check the KASAN shadow for *_to_virt(), then why
> > do we need to store anything in the page flags at all? Andrey?
> 
> As per 2813b9c0 ("kasan, mm, arm64: tag non slab memory allocated via
> pagealloc") we should only save a non-0xff tag in page flags for non
> slab pages.
> 
> Could you share your .config so I can reproduce this?

I wrote a test (below) to do so. :)

It fires with arm64 defconfig, + CONFIG_TEST_KASAN=m.

With Andrey Ryabinin's patch it works as expected with no KASAN splats
for the two new test cases.

Thanks,
Mark.

---->8----
From 7e8569b558fca21ad4e80fddae659591bc84ce1f Mon Sep 17 00:00:00 2001
From: Mark Rutland <mark.rutland@arm.com>
Date: Mon, 19 Aug 2019 15:39:32 +0100
Subject: [PATCH] lib/test_kasan: add roundtrip tests

In several places we needs to be able to operate on pointers which have
gone via a roundtrip:

	virt -> {phys,page} -> virt

With KASAN_SW_TAGS, we can't preserve the tag for SLUB objects, and the
{phys,page} -> virt conversion will use KASAN_TAG_KERNEL.

This patch adds tests to ensure that this works as expected, without
false positives.

Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Andrey Konovalov <andreyknvl@google.com>
Cc: Will Deacon <will.deacon@arm.com>
---
 lib/test_kasan.c | 40 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/lib/test_kasan.c b/lib/test_kasan.c
index b63b367a94e8..cf7b93f0d90c 100644
--- a/lib/test_kasan.c
+++ b/lib/test_kasan.c
@@ -19,6 +19,8 @@
 #include <linux/string.h>
 #include <linux/uaccess.h>
 
+#include <asm/page.h>
+
 /*
  * Note: test functions are marked noinline so that their names appear in
  * reports.
@@ -337,6 +339,42 @@ static noinline void __init kmalloc_uaf2(void)
 	kfree(ptr2);
 }
 
+static noinline void __init kfree_via_page(void)
+{
+	char *ptr;
+	size_t size = 8;
+	struct page *page;
+	unsigned long offset;
+
+	pr_info("invalid-free false positive (via page)\n");
+	ptr = kmalloc(size, GFP_KERNEL);
+	if (!ptr) {
+		pr_err("Allocation failed\n");
+		return;
+	}
+
+	page = virt_to_page(ptr);
+	offset = offset_in_page(ptr);
+	kfree(page_address(page) + offset);
+}
+
+static noinline void __init kfree_via_phys(void)
+{
+	char *ptr;
+	size_t size = 8;
+	phys_addr_t phys;
+
+	pr_info("invalid-free false positive (via phys)\n");
+	ptr = kmalloc(size, GFP_KERNEL);
+	if (!ptr) {
+		pr_err("Allocation failed\n");
+		return;
+	}
+
+	phys = virt_to_phys(ptr);
+	kfree(phys_to_virt(phys));
+}
+
 static noinline void __init kmem_cache_oob(void)
 {
 	char *p;
@@ -737,6 +775,8 @@ static int __init kmalloc_tests_init(void)
 	kmalloc_uaf();
 	kmalloc_uaf_memset();
 	kmalloc_uaf2();
+	kfree_via_page();
+	kfree_via_phys();
 	kmem_cache_oob();
 	memcg_accounted_kmem_cache();
 	kasan_stack_oob();
Andrey Konovalov Aug. 19, 2019, 3:37 p.m. UTC | #11
On Mon, Aug 19, 2019 at 5:03 PM Mark Rutland <mark.rutland@arm.com> wrote:
>
> On Mon, Aug 19, 2019 at 04:05:22PM +0200, Andrey Konovalov wrote:
> > On Mon, Aug 19, 2019 at 3:34 PM Will Deacon <will@kernel.org> wrote:
> > >
> > > On Mon, Aug 19, 2019 at 02:23:48PM +0100, Mark Rutland wrote:
> > > > On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
> > > > > On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
> > > > > > __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
> > > > > > but it will modify pointer tag into 0xff, so there is a false positive.
> > > > > >
> > > > > > When enable tag-based kasan, phys_to_virt() function need to rewrite
> > > > > > its original pointer tag in order to avoid kasan report an incorrect
> > > > > > memory corruption.
> > > > >
> > > > > Hmm. Which tree did you see this on? We've recently queued a load of fixes
> > > > > in this area, but I /thought/ they were only needed after the support for
> > > > > 52-bit virtual addressing in the kernel.
> > > >
> > > > I'm seeing similar issues in the virtio blk code (splat below), atop of
> > > > the arm64 for-next/core branch. I think this is a latent issue, and
> > > > people are only just starting to test with KASAN_SW_TAGS.
> > > >
> > > > It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
> > > > virt->page->virt, losing the per-object tag in the process.
> > > >
> > > > Our page_to_virt() seems to get a per-page tag, but this only makes
> > > > sense if you're dealing with the page allocator, rather than something
> > > > like SLUB which carves a page into smaller objects giving each object a
> > > > distinct tag.
> > > >
> > > > Any round-trip of a pointer from SLUB is going to lose the per-object
> > > > tag.
> > >
> > > Urgh, I wonder how this is supposed to work?
> > >
> > > If we end up having to check the KASAN shadow for *_to_virt(), then why
> > > do we need to store anything in the page flags at all? Andrey?
> >
> > As per 2813b9c0 ("kasan, mm, arm64: tag non slab memory allocated via
> > pagealloc") we should only save a non-0xff tag in page flags for non
> > slab pages.
> >
> > Could you share your .config so I can reproduce this?
>
> I wrote a test (below) to do so. :)
>
> It fires with arm64 defconfig, + CONFIG_TEST_KASAN=m.
>
> With Andrey Ryabinin's patch it works as expected with no KASAN splats
> for the two new test cases.

OK, Andrey's patch makes sense and fixes both Mark's test patch and
reports from CONFIG_IOMMU_IO_PGTABLE_ARMV7S_SELFTEST.

Tested-by: Andrey Konovalov <andreyknvl@google.com>
Reviewed-by: Andrey Konovalov <andreyknvl@google.com>

on both patches.

>
> Thanks,
> Mark.
>
> ---->8----
> From 7e8569b558fca21ad4e80fddae659591bc84ce1f Mon Sep 17 00:00:00 2001
> From: Mark Rutland <mark.rutland@arm.com>
> Date: Mon, 19 Aug 2019 15:39:32 +0100
> Subject: [PATCH] lib/test_kasan: add roundtrip tests
>
> In several places we needs to be able to operate on pointers which have

"needs" => "need"

> gone via a roundtrip:
>
>         virt -> {phys,page} -> virt
>
> With KASAN_SW_TAGS, we can't preserve the tag for SLUB objects, and the
> {phys,page} -> virt conversion will use KASAN_TAG_KERNEL.
>
> This patch adds tests to ensure that this works as expected, without
> false positives.
>
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
> Cc: Andrey Konovalov <andreyknvl@google.com>
> Cc: Will Deacon <will.deacon@arm.com>
> ---
>  lib/test_kasan.c | 40 ++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 40 insertions(+)
>
> diff --git a/lib/test_kasan.c b/lib/test_kasan.c
> index b63b367a94e8..cf7b93f0d90c 100644
> --- a/lib/test_kasan.c
> +++ b/lib/test_kasan.c
> @@ -19,6 +19,8 @@
>  #include <linux/string.h>
>  #include <linux/uaccess.h>
>
> +#include <asm/page.h>
> +
>  /*
>   * Note: test functions are marked noinline so that their names appear in
>   * reports.
> @@ -337,6 +339,42 @@ static noinline void __init kmalloc_uaf2(void)
>         kfree(ptr2);
>  }
>
> +static noinline void __init kfree_via_page(void)
> +{
> +       char *ptr;
> +       size_t size = 8;
> +       struct page *page;
> +       unsigned long offset;
> +
> +       pr_info("invalid-free false positive (via page)\n");
> +       ptr = kmalloc(size, GFP_KERNEL);
> +       if (!ptr) {
> +               pr_err("Allocation failed\n");
> +               return;
> +       }
> +
> +       page = virt_to_page(ptr);
> +       offset = offset_in_page(ptr);
> +       kfree(page_address(page) + offset);
> +}
> +
> +static noinline void __init kfree_via_phys(void)
> +{
> +       char *ptr;
> +       size_t size = 8;
> +       phys_addr_t phys;
> +
> +       pr_info("invalid-free false positive (via phys)\n");
> +       ptr = kmalloc(size, GFP_KERNEL);
> +       if (!ptr) {
> +               pr_err("Allocation failed\n");
> +               return;
> +       }
> +
> +       phys = virt_to_phys(ptr);
> +       kfree(phys_to_virt(phys));
> +}
> +
>  static noinline void __init kmem_cache_oob(void)
>  {
>         char *p;
> @@ -737,6 +775,8 @@ static int __init kmalloc_tests_init(void)
>         kmalloc_uaf();
>         kmalloc_uaf_memset();
>         kmalloc_uaf2();
> +       kfree_via_page();
> +       kfree_via_phys();
>         kmem_cache_oob();
>         memcg_accounted_kmem_cache();
>         kasan_stack_oob();
> --
> 2.11.0
>
Mark Rutland Aug. 19, 2019, 4:03 p.m. UTC | #12
On Mon, Aug 19, 2019 at 05:37:36PM +0200, Andrey Konovalov wrote:
> On Mon, Aug 19, 2019 at 5:03 PM Mark Rutland <mark.rutland@arm.com> wrote:
> >
> > On Mon, Aug 19, 2019 at 04:05:22PM +0200, Andrey Konovalov wrote:
> > > On Mon, Aug 19, 2019 at 3:34 PM Will Deacon <will@kernel.org> wrote:
> > > >
> > > > On Mon, Aug 19, 2019 at 02:23:48PM +0100, Mark Rutland wrote:
> > > > > On Mon, Aug 19, 2019 at 01:56:26PM +0100, Will Deacon wrote:
> > > > > > On Mon, Aug 19, 2019 at 07:44:20PM +0800, Walter Wu wrote:
> > > > > > > __arm_v7s_unmap() call iopte_deref() to translate pyh_to_virt address,
> > > > > > > but it will modify pointer tag into 0xff, so there is a false positive.
> > > > > > >
> > > > > > > When enable tag-based kasan, phys_to_virt() function need to rewrite
> > > > > > > its original pointer tag in order to avoid kasan report an incorrect
> > > > > > > memory corruption.
> > > > > >
> > > > > > Hmm. Which tree did you see this on? We've recently queued a load of fixes
> > > > > > in this area, but I /thought/ they were only needed after the support for
> > > > > > 52-bit virtual addressing in the kernel.
> > > > >
> > > > > I'm seeing similar issues in the virtio blk code (splat below), atop of
> > > > > the arm64 for-next/core branch. I think this is a latent issue, and
> > > > > people are only just starting to test with KASAN_SW_TAGS.
> > > > >
> > > > > It looks like the virtio blk code will round-trip a SLUB-allocated pointer from
> > > > > virt->page->virt, losing the per-object tag in the process.
> > > > >
> > > > > Our page_to_virt() seems to get a per-page tag, but this only makes
> > > > > sense if you're dealing with the page allocator, rather than something
> > > > > like SLUB which carves a page into smaller objects giving each object a
> > > > > distinct tag.
> > > > >
> > > > > Any round-trip of a pointer from SLUB is going to lose the per-object
> > > > > tag.
> > > >
> > > > Urgh, I wonder how this is supposed to work?
> > > >
> > > > If we end up having to check the KASAN shadow for *_to_virt(), then why
> > > > do we need to store anything in the page flags at all? Andrey?
> > >
> > > As per 2813b9c0 ("kasan, mm, arm64: tag non slab memory allocated via
> > > pagealloc") we should only save a non-0xff tag in page flags for non
> > > slab pages.
> > >
> > > Could you share your .config so I can reproduce this?
> >
> > I wrote a test (below) to do so. :)
> >
> > It fires with arm64 defconfig, + CONFIG_TEST_KASAN=m.
> >
> > With Andrey Ryabinin's patch it works as expected with no KASAN splats
> > for the two new test cases.
> 
> OK, Andrey's patch makes sense and fixes both Mark's test patch and
> reports from CONFIG_IOMMU_IO_PGTABLE_ARMV7S_SELFTEST.
> 
> Tested-by: Andrey Konovalov <andreyknvl@google.com>
> Reviewed-by: Andrey Konovalov <andreyknvl@google.com>
> 
> on both patches.
> 
> >
> > Thanks,
> > Mark.
> >
> > ---->8----
> > From 7e8569b558fca21ad4e80fddae659591bc84ce1f Mon Sep 17 00:00:00 2001
> > From: Mark Rutland <mark.rutland@arm.com>
> > Date: Mon, 19 Aug 2019 15:39:32 +0100
> > Subject: [PATCH] lib/test_kasan: add roundtrip tests
> >
> > In several places we needs to be able to operate on pointers which have
> 
> "needs" => "need"

Thanks! 

I'll spin a standalone v2 of this with that fixed and your tags folded
in.

Mark.

> 
> > gone via a roundtrip:
> >
> >         virt -> {phys,page} -> virt
> >
> > With KASAN_SW_TAGS, we can't preserve the tag for SLUB objects, and the
> > {phys,page} -> virt conversion will use KASAN_TAG_KERNEL.
> >
> > This patch adds tests to ensure that this works as expected, without
> > false positives.
> >
> > Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> > Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
> > Cc: Andrey Konovalov <andreyknvl@google.com>
> > Cc: Will Deacon <will.deacon@arm.com>
> > ---
> >  lib/test_kasan.c | 40 ++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 40 insertions(+)
> >
> > diff --git a/lib/test_kasan.c b/lib/test_kasan.c
> > index b63b367a94e8..cf7b93f0d90c 100644
> > --- a/lib/test_kasan.c
> > +++ b/lib/test_kasan.c
> > @@ -19,6 +19,8 @@
> >  #include <linux/string.h>
> >  #include <linux/uaccess.h>
> >
> > +#include <asm/page.h>
> > +
> >  /*
> >   * Note: test functions are marked noinline so that their names appear in
> >   * reports.
> > @@ -337,6 +339,42 @@ static noinline void __init kmalloc_uaf2(void)
> >         kfree(ptr2);
> >  }
> >
> > +static noinline void __init kfree_via_page(void)
> > +{
> > +       char *ptr;
> > +       size_t size = 8;
> > +       struct page *page;
> > +       unsigned long offset;
> > +
> > +       pr_info("invalid-free false positive (via page)\n");
> > +       ptr = kmalloc(size, GFP_KERNEL);
> > +       if (!ptr) {
> > +               pr_err("Allocation failed\n");
> > +               return;
> > +       }
> > +
> > +       page = virt_to_page(ptr);
> > +       offset = offset_in_page(ptr);
> > +       kfree(page_address(page) + offset);
> > +}
> > +
> > +static noinline void __init kfree_via_phys(void)
> > +{
> > +       char *ptr;
> > +       size_t size = 8;
> > +       phys_addr_t phys;
> > +
> > +       pr_info("invalid-free false positive (via phys)\n");
> > +       ptr = kmalloc(size, GFP_KERNEL);
> > +       if (!ptr) {
> > +               pr_err("Allocation failed\n");
> > +               return;
> > +       }
> > +
> > +       phys = virt_to_phys(ptr);
> > +       kfree(phys_to_virt(phys));
> > +}
> > +
> >  static noinline void __init kmem_cache_oob(void)
> >  {
> >         char *p;
> > @@ -737,6 +775,8 @@ static int __init kmalloc_tests_init(void)
> >         kmalloc_uaf();
> >         kmalloc_uaf_memset();
> >         kmalloc_uaf2();
> > +       kfree_via_page();
> > +       kfree_via_phys();
> >         kmem_cache_oob();
> >         memcg_accounted_kmem_cache();
> >         kasan_stack_oob();
> > --
> > 2.11.0
> >
diff mbox series

Patch

diff --git a/arch/arm64/include/asm/kasan.h b/arch/arm64/include/asm/kasan.h
index b52aacd2c526..59894cafad60 100644
--- a/arch/arm64/include/asm/kasan.h
+++ b/arch/arm64/include/asm/kasan.h
@@ -5,7 +5,6 @@ 
 #ifndef __ASSEMBLY__
 
 #include <linux/linkage.h>
-#include <asm/memory.h>
 #include <asm/pgtable-types.h>
 
 #define arch_kasan_set_tag(addr, tag)	__tag_set(addr, tag)
diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
index 8ffcf5a512bb..75af5ba9ff22 100644
--- a/arch/arm64/include/asm/memory.h
+++ b/arch/arm64/include/asm/memory.h
@@ -171,6 +171,7 @@ 
 
 #include <linux/bitops.h>
 #include <linux/mmdebug.h>
+#include <asm/kasan.h>
 
 extern s64			memstart_addr;
 /* PHYS_OFFSET - the physical address of the start of memory. */
@@ -282,7 +283,16 @@  static inline phys_addr_t virt_to_phys(const volatile void *x)
 #define phys_to_virt phys_to_virt
 static inline void *phys_to_virt(phys_addr_t x)
 {
+#ifdef CONFIG_KASAN_SW_TAGS
+	unsigned long addr = __phys_to_virt(x);
+	u8 *tag = (void *)(addr >> KASAN_SHADOW_SCALE_SHIFT)
+				+ KASAN_SHADOW_OFFSET;
+
+	addr = __tag_set(addr, *tag);
+	return (void *)addr;
+#else
 	return (void *)(__phys_to_virt(x));
+#endif
 }
 
 /*