Re: [PATCH v4 1/2] m68k: Handle __generic_copy_to_user faults more carefully

Finn Thain
2024-08-07T08:14:39Z

On Mon, 29 Apr 2024, Michael Schmitz wrote:

> As mentioned by Finn Thain in his patch to improve put_user
> exception handling on 040, a similar problem exists on 030
> processors.
>
> A moves instruction that crosses a page boundary from a
> mapped page into an unmapped one will cause a mid-instruction
> bus error exception (frame format b), with the PC pointing
> (usually) two instructions past the faulting movesl instruction.
>
> Our exception handling in __generic_copy_to_user only covers
> the instruction immediately following the faulting one. As
> a result, fixup_exception in send_fault_sig does not detect
> this case, and cause send_fault_sig to oops.
>
> Extend the exception table to cover one additional instruction
> beyond the moves[lwb] instructions.
>
> Tested on 68030 (Atari Falcon 030) with transfers beginning
> at one to six bytes offset from the end of a mapped page,
> followed by further bytes on an unmapped page (testcase
> derived from stress-ng sysbadaddr stressor by Finn Thain).
>
> Tested on 68040 (Mac Quadra) and 68030 (Mac IIci) by Finn Thain.
>
> A similar problem is present in __clear_user(); modify the
> exception table for that function in the same way (tested by
> Finn Thain).
>

Well, that __clear_user() bug is no longer theoretical. I accidentally
bumped into it when I sent a ^C to a shell script I wrote to test some
mac_scsi driver patches...

[ 0.000000] Linux version 6.10.0-mac-00011-gd1d490afeb2a (fthain@nippy) (m68k-unknown-linux-musl-gcc (Gentoo 13.2.1_p20240210 p14) 13.2.1 20240210, GNU ld (Gentoo 2.40 p7) 2.40.0) #39 Sat Aug 3 19:57:43 AEST 2024

...

root@(none):/# bash scsi-test.sh /dev/sda5
bs=512k count=1
[ 130.090000] sd 0:0:0:0: [sda] tag#9 PDMA fixup: DRQ timeout
[ 130.090000] sd 0:0:0:0: [sda] tag#9 switching to slow handshake
[ 130.180000] sd 0:0:0:0: Power-on or device reset occurred
1+0 records in
1+0 records out
524288 bytes (524 kB, 512 KiB) copied, 5.13732 s, 102 kB/s
[ 136.030000] bash (57): drop_caches: 3
^C
root@(none):/# bash scsi-test.sh /dev/sdb5
bs=512k count=1
1+0 records in
1+0 records out
524288 bytes (524 kB, 512 KiB) copied, 1.1273 s, 465 kB/s
[ 160.440000] bash (61): drop_caches: 3
1+0 records in
1+0 records out
524288 bytes (524 kB, 512 KiB) copied, 1.12763 s, 465 kB/s
[ 171.920000] bash (61): drop_caches: 3

bs=64k count=8
8+0 records in
8+0 records out
524288 bytes (524 kB, 512 KiB) copied, 1.03469 s, 507 kB/s
[ 184.480000] bash (61): drop_caches: 3
8+0 records in
8+0 records out
524288 bytes (524 kB, 512 KiB) copied, 1.03221 s, 508 kB/s
[ 196.340000] bash (61): drop_caches: 3

bs=4k count=128
128+0 records in
128+0 records out
524288 bytes (524 kB, 512 KiB) copied, 1.13089 s, 464 kB/s
[ 208.860000] bash (61): drop_caches: 3
128+0 records in
128+0 records out
524288 bytes (524 kB, 512 KiB) copied, 1.13089 s, 464 kB/s
[ 220.850000] bash (61): drop_caches: 3

bs=512 count=1k
1024+0 records in
1024+0 records out
524288 bytes (524 kB, 512 KiB) copied, 3.69678 s, 142 kB/s
[ 236.020000] bash (61): drop_caches: 3
1024+0 records in
1024+0 records out
524288 bytes (524 kB, 512 KiB) copied, 3.68874 s, 142 kB/s
[ 250.570000] bash (61): drop_caches: 3

bs=512k count=1
1+0 records in
1+0 records out
524288 bytes (524 kB, 512 KiB) copied, 1.12338 s, 467 kB/s
[ 263.120000] bash (61): drop_caches: 3
1+0 records in
1+0 records out
524288 bytes (524 kB, 512 KiB) copied, 1.12665 s, 465 kB/s
[ 275.110000] bash (61): drop_caches: 3

bs=64k count=8
8+0 records in
8+0 records out
524288 bytes (524 kB, 512 KiB) copied, 1.08861 s, 482 kB/s
[ 287.610000] bash (61): drop_caches: 3
8+0 records in
8+0 records out
524288 bytes (524 kB, 512 KiB) copied, 1.03319 s, 507 kB/s
[ 299.510000] bash (61): drop_caches: 3
^C[ 303.190000] Unable to handle kernel access at virtual address d7d17fd7
[ 303.200000] Oops: 00000000
[ 303.210000] Modules linked in:
[ 303.220000] PC: [<004301fe>] __clear_user+0x22/0x40
[ 303.240000] SR: 2000 SP: 4841d159 a2: 00b78590
[ 303.250000] d0: 000003ab d1: 00000000 d2: 00000000 d3: 8000c150
[ 303.260000] d4: 00002000 d5: 00000000 a0: 8000c154 a1: 009bdb3c
[ 303.280000] Process cmp (pid: 92, task=7d95deea)
[ 303.290000] Frame format=B ssw=0709 isc=0801 isb=0001 daddr=8000c150 dobuf=00000000
[ 303.310000] baddr=00430202 dibuf=8000c150 ver=f
[ 303.320000] Stack from 0149de8c:
[ 303.320000] 8001c2c4 0149deb8 00139904 8000c150 00000eb0 00983c00 00000000 00000003
[ 303.320000] 00000003 8000bf00 00983a00 0149df40 0013a1fa 00912480 8000bf00 00983c60
[ 303.320000] 00000003 00000012 00000000 fffffff8 00000006 d012f728 00000000 00983a5a
[ 303.320000] 00000004 00983a00 000579d4 0052b7e8 009125a0 00912480 00983a5a 80000034
[ 303.320000] 000d1704 014994c0 80008864 80000000 00000000 80008864 80008864 00000000
[ 303.320000] 01497800 00000000 00000034 fffffff8 fffffff8 0149df7c 000e9296 00983a00
[ 303.380000] Call Trace: [<00139904>] elf_load+0x192/0x1da
[ 303.390000] [<0013a1fa>] load_elf_binary+0x8ae/0xe46
[ 303.400000] [<000579d4>] try_module_get+0x0/0x48
[ 303.410000] [<000d1704>] kfree+0x0/0x160
[ 303.420000] [<000e9296>] bprm_execve+0x134/0x416
[ 303.430000] [<000e9daa>] copy_string_kernel+0x0/0x184
[ 303.440000] [<000e9fa4>] copy_strings+0x0/0x310
[ 303.460000] [<000ea3f6>] do_execveat_common+0x142/0x1d2
[ 303.480000] [<000eb128>] sys_execve+0x2a/0x36
[ 303.490000] [<0000275e>] syscall+0x8/0xc
[ 303.510000] [<0008c010>] do_read_cache_folio+0xde/0x2c8
[ 303.520000]
[ 303.520000] Code: 206e 0008 4282 4a80 6708 0e98 2800 5380 <66f8> 0801 0001 6704 0e58 2800 0801 0000 6704 0e10 2800 241f 4e5e 4e75 4e75 4e56
[ 303.560000] Disabling lock debugging due to kernel taint

root@(none):/#

Also, it appears that the patch Michael posted in this thread would have
prevented that oops because the "jne 1b" at __clear_user+0x22 would have
been found in the exception table.