[PATCH v2 6/8] arm64: Import latest memcpy()/memmove() implementation

Robin Murphy robin.murphy at arm.com
Fri Sep 10 04:42:16 PDT 2021


On 2021-09-10 01:35, Peter Collingbourne wrote:
> Hi Robin,
> 
> (apologies for breaking the threading, I wasn't subscribed to
> linux-arm-kernel when you sent this)
> 
> It looks like this patch breaks the KASAN unit tests when running in
> HW tags mode. You can construct a config that reproduces the problem
> with something like:
> 
> make O=out defconfig
> scripts/config --file out/.config -e CONFIG_KUNIT -e CONFIG_KASAN -e
> CONFIG_KASAN_HW_TAGS -e CONFIG_KASAN_KUNIT_TEST
> yes '' | make O=out syncconfig
> 
> With that the "kmalloc_memmove_invalid_size" test fails and causes the
> kernel panic below.
> 
> What appears to be going on is that whereas the old memcpy
> implementation ends up returning early after not copying very much
> data if supplied a "negative" size as a side effect of using
> conditional branches that implement signed comparisons (e.g. b.ge on
> line 75), the new implementation does not exit early and attempts to
> copy a large amount of data backwards 4 bytes (after having disabled
> MTE early on as a result of a tag mismatch) until it hits a read-only
> page and causes a panic.

If the test depends on the implementation of memmove() being buggy, it's 
clearly not a very good test :/

> I'm not sure what the correct fix should be. It seems that at least
> when KASAN is enabled we should be able to catch these invalid memcpys
> somehow, print an error report and ideally abort the entire operation.
> But we should do so without causing a performance impact in the usual
> case.

Not sure I follow - the top of the log below clearly shows that KASASN 
*is* detecting and reporting a bad access. The fact that code intended 
to deliberately corrupt memory goes on to corrupt memory doesn't seem 
particularly surprising to me. A bug exists (intentionally or otherwise) 
which led to that invalid access being attempted, and KASAN can't 
magically change that.

Robin.

> 
> Peter
> 
> [    7.726311] ==================================================================
> [    7.726817] BUG: KASAN: invalid-access in __memcpy+0x1a0/0x230
> [    7.727310] Read at addr f8ff000002650ef2 by task kunit_try_catch/117
> [    7.727828] Pointer tag: [f8], memory tag: [fe]
> [    7.728209]
> [    7.728419] CPU: 0 PID: 117 Comm: kunit_try_catch Tainted: G    B
>            5.14.0-rc3-00011-g7a062ce31807-dirty #1
> [    7.729186] Hardware name: linux,dummy-virt (DT)
> [    7.729568] Call trace:
> [    7.729817]  dump_backtrace+0x0/0x1cc
> [    7.730191]  show_stack+0x18/0x24
> [    7.730543]  dump_stack_lvl+0x64/0x7c
> [    7.730917]  print_address_description+0x7c/0x1e0
> [    7.731336]  __kasan_report+0x228/0x30c
> [    7.731718]  kasan_report+0x44/0x70
> [    7.732076]  __do_kernel_fault+0xbc/0x248
> [    7.732464]  do_tag_check_fault+0x38/0xfc
> [    7.732862]  do_mem_abort+0x40/0xb4
> [    7.733223]  el1_abort+0x40/0x60
> [    7.733568]  el1h_64_sync_handler+0x5c/0x98
> [    7.733964]  el1h_64_sync+0x78/0x7c
> [    7.734327]  __memcpy+0x1a0/0x230
> [    7.734684]  kunit_try_run_case+0x48/0x108
> [    7.735073]  kunit_generic_run_threadfn_adapter+0x20/0x2c
> [    7.735536]  kthread+0x170/0x330
> [    7.735888]  ret_from_fork+0x10/0x18
> [    7.736264]
> [    7.736462] Allocated by task 116:
> [    7.736780]  ____kasan_kmalloc+0x108/0x130
> [    7.737163]  __kasan_kmalloc+0x10/0x1c
> [    7.737527]  kthread+0x6c/0x330
> [    7.737861]  ret_from_fork+0x10/0x18
> [    7.738217]
> [    7.738413] Freed by task 115:
> [    7.738713]  kasan_set_track+0x3c/0x74
> [    7.739080]  kasan_set_free_info+0x20/0x2c
> [    7.739461]  ____kasan_slab_free+0x214/0x218
> [    7.739847]  __kasan_slab_free+0x14/0x24
> [    7.740223]  kfree+0x140/0x3bc
> [    7.740553]  free_kthread_struct+0x28/0x4c
> [    7.740935]  __put_task_struct+0x138/0x1b8
> [    7.741326]  delayed_put_task_struct+0x4c/0x88
> [    7.741728]  rcu_do_batch+0x130/0x3ec
> [    7.742092]  rcu_core+0x1f0/0x344
> [    7.742446]  rcu_core_si+0x10/0x1c
> [    7.742796]  __do_softirq+0xd8/0x260
> [    7.743152]
> [    7.743348] The buggy address belongs to the object at ffff000002650e00
> [    7.743348]  which belongs to the cache kmalloc-128 of size 128
> [    7.744152] The buggy address is located 114 bytes to the right of
> [    7.744152]  128-byte region [ffff000002650e00, ffff000002650e80)
> [    7.744971] The buggy address belongs to the page:
> [    7.745345] page:fffffc0000099400 refcount:1 mapcount:0
> mapping:0000000000000000 index:0x0 pfn:0x42650
> [    7.746004] flags:
> 0x3fffc0000000200(slab|node=0|zone=0|lastcpupid=0xffff|kasantag=0x0)
> [    7.746680] raw: 03fffc0000000200 0000000000000000 0000000100000001
> fdff000002401200
> [    7.747276] raw: 0000000000000000 0000000080100010 00000001ffffffff
> 0000000000000000
> [    7.747775] page dumped because: kasan: bad access detected
> [    7.748190]
> [    7.748383] Memory state around the buggy address:
> [    7.748767]  ffff000002650c00: f8 f8 fe fe fe fe fe fe fe fe fe fe
> fe fe fe fe
> [    7.749303]  ffff000002650d00: f8 f8 f8 f8 f8 f8 f8 fe fe fe fe fe
> fe fe fe fe
> [    7.749831] >ffff000002650e00: fa fa fa fa fa fa fa fe fe fe fe fe
> fe fe fe fe
> [    7.750345]                                                                 ^
> [    7.750853]  ffff000002650f00: f8 f8 f8 f8 fe fe fe fe fe fe fe fe
> fe fe fe fe
> [    7.751388]  ffff000002651000: fc fc fc fc fc fc fc fc fe fb fb fb
> fb fb fb fb
> [    7.751914] ==================================================================
> [    7.754424] Unable to handle kernel write to read-only memory at
> virtual address f8ff000002573ff0
> [    7.760818] Mem abort info:
> [    7.761074]   ESR = 0x9600004f
> [    7.761392]   EC = 0x25: DABT (current EL), IL = 32 bits
> [    7.761819]   SET = 0, FnV = 0
> [    7.762086]   EA = 0, S1PTW = 0
> [    7.762374]   FSC = 0x0f: level 3 permission fault
> [    7.763350] Data abort info:
> [    7.763600]   ISV = 0, ISS = 0x0000004f
> [    7.763954]   CM = 0, WnR = 1
> [    7.764282] swapper pgtable: 4k pages, 48-bit VAs, pgdp=000000004193c000
> [    7.764760] [f8ff000002573ff0] pgd=180000005fff7003,
> p4d=180000005fff7003, pud=180000005fff6003, pmd=180000005ffed003,
> pte=0060000042573f87
> [    7.766996] Internal error: Oops: 9600004f [#1] PREEMPT SMP
> [    7.767561] Modules linked in:
> [    7.768138] CPU: 0 PID: 117 Comm: kunit_try_catch Tainted: G    B
>            5.14.0-rc3-00011-g7a062ce31807-dirty #1
> [    7.768948] Hardware name: linux,dummy-virt (DT)
> [    7.769444] pstate: a0400005 (NzCv daif +PAN -UAO -TCO BTYPE=--)
> [    7.769987] pc : __memcpy+0x1e8/0x230
> [    7.771029] lr : kmalloc_memmove_invalid_size+0x148/0x1cc
> [    7.771457] sp : ffff80001023bd60
> [    7.771740] x29: ffff80001023bdb0 x28: 0000000000000000 x27: f8ff000002650d40
> [    7.772450] x26: f3ff000002d64600 x25: ffffc63e374bdf48 x24: ffffc63e3901c50c
> [    7.773109] x23: 000001e700000001 x22: ffffc63e3905f000 x21: ffffc63e38587294
> [    7.773768] x20: ffff80001000bb70 x19: f8ff000002650f00 x18: ffffffffffffffff
> [    7.774422] x17: 0000000000000000 x16: 0000000000000118 x15: 0000000000000004
> [    7.775067] x14: 000000000000000e x13: 42573f83d4202000 x12: d4202000d4202000
> [    7.775722] x11: d4202000d4202000 x10: d4202000d4202000 x9 : d4202000d4202000
> [    7.776397] x8 : d4202000d4202000 x7 : d4202000d4202000 x6 : d4202000d4202000
> [    7.777040] x5 : f8ff000002574030 x4 : f8ff000002573ff4 x3 : 0000000000000000
> [    7.777687] x2 : fffffffffff230b0 x1 : f8ff000002650f04 x0 : f8ff000002650f00
> [    7.778441] Call trace:
> [    7.778714]  __memcpy+0x1e8/0x230
> [    7.779064]  kunit_try_run_case+0x48/0x108
> [    7.779409]  kunit_generic_run_threadfn_adapter+0x20/0x2c
> [    7.779818]  kthread+0x170/0x330
> [    7.780125]  ret_from_fork+0x10/0x18
> [    7.780771] Code: a93e24a8 a97e2488 a93d2caa a97d2c8a (a9bc34ac)
> [    7.781490] ---[ end trace e570c3a10375543e ]---
> [    7.783261] Unable to handle kernel paging request at virtual
> address 00650d50f8fefff8
> [    7.783766] Mem abort info:
> [    7.784002]   ESR = 0x96000004
> [    7.784255]   EC = 0x25: DABT (current EL), IL = 32 bits
> [    7.784637]   SET = 0, FnV = 0
> [    7.784892]   EA = 0, S1PTW = 0
> [    7.785150]   FSC = 0x04: level 0 translation fault
> [    7.785495] Data abort info:
> [    7.785724]   ISV = 0, ISS = 0x00000004
> [    7.786013]   CM = 0, WnR = 0
> [    7.786268] [00650d50f8fefff8] address between user and kernel address ranges
> [    7.786743] Internal error: Oops: 96000004 [#2] PREEMPT SMP
> [    7.787122] Modules linked in:
> [    7.787423] CPU: 0 PID: 117 Comm: kunit_try_catch Tainted: G    B D
>            5.14.0-rc3-00011-g7a062ce31807-dirty #1
> [    7.788099] Hardware name: linux,dummy-virt (DT)
> [    7.788419] pstate: 004000c5 (nzcv daIF +PAN -UAO -TCO BTYPE=--)
> [    7.788855] pc : swake_up_locked+0x1c/0x48
> [    7.789197] lr : complete+0x44/0x64
> [    7.789508] sp : ffff80001023b910
> [    7.789773] x29: ffff80001023b910 x28: f3ff000002d64600 x27: f3ff000002d64600
> [    7.790425] x26: f3ff000002d64600 x25: ffffc63e374bdf48 x24: ffffc63e374efbf8
> [    7.791069] x23: ffff80001023baa4 x22: 0000000000000000 x21: 0000000000000000
> [    7.791733] x20: f8ff000002650d40 x19: 02650d50f8ff0000 x18: ffffffffffffffff
> [    7.792380] x17: 0000000000000000 x16: 0000000000000118 x15: 0000000000000004
> [    7.793031] x14: 0000000000000fff x13: ffffc63e38d4aa08 x12: 0000000000000003
> [    7.793683] x11: 0000000000000000 x10: 0000000000000002 x9 : 0000000000000000
> [    7.794341] x8 : 0000000000000001 x7 : 205d303934313837 x6 : 372e37202020205b
> [    7.794977] x5 : ffffc63e39041f58 x4 : 0000000000000001 x3 : 0000000000000000
> [    7.795622] x2 : 0000000000000001 x1 : 0000000000000000 x0 : f8ff000002650d50
> [    7.796272] Call trace:
> [    7.796503]  swake_up_locked+0x1c/0x48
> [    7.796836]  complete+0x44/0x64
> [    7.797133]  mm_release+0xd4/0xec
> [    7.797437]  exit_mm_release+0x28/0x38
> [    7.797775]  exit_mm+0x3c/0x214
> [    7.798074]  do_exit+0x180/0x778
> [    7.798379]  die+0x2ac/0x2b0
> [    7.798669]  __do_kernel_fault+0x1bc/0x248
> [    7.799020]  do_page_fault+0x4c/0x3c4
> [    7.799343]  do_mem_abort+0x40/0xb4
> [    7.799661]  el1_abort+0x40/0x60
> [    7.799968]  el1h_64_sync_handler+0x5c/0x98
> [    7.800318]  el1h_64_sync+0x78/0x7c
> [    7.800639]  __memcpy+0x1e8/0x230
> [    7.800948]  kunit_try_run_case+0x48/0x108
> [    7.801297]  kunit_generic_run_threadfn_adapter+0x20/0x2c
> [    7.801697]  kthread+0x170/0x330
> [    7.801993]  ret_from_fork+0x10/0x18
> [    7.802383] Code: 910003fd f8408c13 eb00027f 54000100 (f85f8260)
> [    7.802810] ---[ end trace e570c3a10375543f ]---
> [    7.803154] note: kunit_try_catch[117] exited with preempt_count 2
> [    7.803596] Fixing recursive fault but reboot is needed!
> [   10.659826] Unable to handle kernel paging request at virtual
> address ffff39c2e762363e
> [   10.661382] Mem abort info:
> [   10.662059]   ESR = 0x96000004
> [   10.662795]   EC = 0x25: DABT (current EL), IL = 32 bits
> [   10.663887]   SET = 0, FnV = 0
> [   10.664634]   EA = 0, S1PTW = 0
> [   10.665390]   FSC = 0x04: level 0 translation fault
> [   10.666379] Data abort info:
> [   10.667043]   ISV = 0, ISS = 0x00000004
> [   10.667879]   CM = 0, WnR = 0
> [   10.668605] swapper pgtable: 4k pages, 48-bit VAs, pgdp=000000004193c000
> [   10.669507] [ffff39c2e762363e] pgd=0000000000000000, p4d=0000000000000000
> [   10.670636] Internal error: Oops: 96000004 [#3] PREEMPT SMP
> [   10.671425] Modules linked in:
> [   10.671998] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G    B D
>    5.14.0-rc3-00011-g7a062ce31807-dirty #1
> [   10.673281] Hardware name: linux,dummy-virt (DT)
> [   10.673958] pstate: 604000c5 (nZCv daIF +PAN -UAO -TCO BTYPE=--)
> [   10.674844] pc : __queue_work+0x1f4/0x408
> [   10.675536] lr : __queue_work+0x38/0x408
> [   10.676205] sp : ffff800010003d80
> [   10.676739] x29: ffff800010003d80 x28: ffff39c2e762363e x27: dead000000000122
> [   10.678061] x26: 0000000000000000 x25: ffffc63e38d1d768 x24: 000000007fffffff
> [   10.679392] x23: ffffc63e388a9638 x22: 0000000000000014 x21: 0000000000000100
> [   10.680286] x20: f9ff0000025f8c00 x19: f8ff000002fcc5b0 x18: 0000000000000000
> [   10.681183] x17: 0000000000000000 x16: 0000000000000001 x15: 0000000000000000
> [   10.682071] x14: 0000000000200000 x13: f8ff000002fcc588 x12: ffff00001fecd258
> [   10.682959] x11: ffffffffc0000040 x10: ffffc63e3889f000 x9 : ffff39c1e7627000
> [   10.683867] x8 : 000000007fffffff x7 : 00001e8480000000 x6 : 0000000000000000
> [   10.684763] x5 : 0000000000000000 x4 : 0000000000000000 x3 : 0000000000000069
> [   10.685642] x2 : f8ff000002fcc5b0 x1 : f9ff0000025f8c00 x0 : ffffc63e3901c250
> [   10.686511] Call trace:
> [   10.686832]  __queue_work+0x1f4/0x408
> [   10.687287]  queue_work_on+0x54/0x8c
> [   10.687736]  blk_rq_timed_out_timer+0x20/0x2c
> [   10.688225]  __run_timers+0x1d8/0x2fc
> [   10.688682]  run_timer_softirq+0x24/0x48
> [   10.689154]  __do_softirq+0xd8/0x260
> [   10.689592]  __irq_exit_rcu+0xf4/0xf8
> [   10.689954]  irq_exit+0x10/0x20
> [   10.690265]  handle_domain_irq+0x60/0x88
> [   10.690609]  gic_handle_irq+0x68/0xe0
> [   10.690944]  call_on_irq_stack+0x2c/0x54
> [   10.691284]  el1_interrupt+0x60/0xa4
> [   10.691633]  el1h_64_irq_handler+0x18/0x24
> [   10.691994]  el1h_64_irq+0x78/0x7c
> [   10.692316]  arch_cpu_idle+0x18/0x28
> [   10.692651]  cpuidle_idle_call+0x70/0x250
> [   10.693011]  do_idle+0xb0/0xfc
> [   10.693317]  cpu_startup_entry+0x24/0x28
> [   10.693662]  rest_init+0xe4/0xf4
> [   10.693976]  arch_call_rest_init+0x10/0x1c
> [   10.694343]  start_kernel+0x328/0x43c
> [   10.694679]  __primary_switched+0xc0/0xc8
> [   10.695101] Code: eb14013f 54000280 aa1b03e0 9439f6fb (f9400380)
> [   10.695897] ---[ end trace e570c3a103755440 ]---
> [   10.696360] Kernel panic - not syncing: Oops: Fatal exception in interrupt
> [   10.697132] Kernel Offset: 0x463e27000000 from 0xffff800010000000
> [   10.697565] PHYS_OFFSET: 0x40000000
> [   10.697857] CPU features: 0x000003d9,4d330c5f
> [   10.698416] Memory Limit: none
> [   10.698918] ---[ end Kernel panic - not syncing: Oops: Fatal
> exception in interrupt ]---
> 



More information about the linux-arm-kernel mailing list