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.