forked from torvalds/linux
- Notifications
You must be signed in to change notification settings - Fork 5
Closed
Labels
[ARCH-done] x86_32Finished on the 32-bit x86 architecture (ARCH=i386)Finished on the 32-bit x86 architecture (ARCH=i386)[Compiler-done] ClangAn issue in Clang itself has been finishedAn issue in Clang itself has been finished[Linux] v6.10Released in Linux kernel v6.10Released in Linux kernel v6.10[PATCH] AcceptedA submitted patch has been accepted upstreamA submitted patch has been accepted upstream
Description
Seen here: https://gitlab.freedesktop.org/drm/amd/-/issues/3323
Appeared under Clang 17 on ARCH=i386.
BUG: kernel NULL pointer dereference, address: 00000404 #PF: supervisor write access in kernel mode #PF: error_code(0x0002) - not-present page *pdpt = 0000000003723001 *pde = 0000000000000000 Oops: 0002 [#1] SMP DEBUG_PAGEALLOC PTI CPU: 1 PID: 187 Comm: (udev-worker) Not tainted 6.9.0-rc3-P3 #1 Hardware name: LENOVO 2007F2G/2007F2G, BIOS 79ETE7WW (2.27 ) 03/21/2011 EIP: __ubsan_handle_out_of_bounds+0x30/0x7c Code: 83 ec 28 89 c6 64 a1 40 65 02 d4 83 b8 f0 04 00 00 00 75 1e 89 d7 8d 5d cc 89 d8 ba ff 00 00 00 b9 28 00 00 00 e8 3c 9d 31 00 <f0> 0f ba 6e 04 1f 73 0e 83 c4 28 5e 5f 5b 5d 31 c0 31 c9 31 d2 c3 EAX: c351d8b0 EBX: c351d8b0 ECX: 00000000 EDX: 00000000 ESI: 00000400 EDI: 00000010 EBP: c351d8e4 ESP: c351d8b0 DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 EFLAGS: 00210246 CR0: 80050033 CR2: 00000404 CR3: 01c44000 CR4: 000006f0 The Code disassembles to:
0: 83 ec 28 sub esp,0x28 3: 89 c6 mov esi,eax 5: 64 a1 40 65 02 d4 mov eax,fs:0xd4026540 b: 83 b8 f0 04 00 00 00 cmp DWORD PTR [eax+0x4f0],0x0 12: 75 1e jne 0x32 14: 89 5d cc mov DWORD PTR [ebp-0x34],ebx 17: 89 d8 mov eax,ebx 19: ba ff 00 00 00 mov edx,0xff 1e: b9 28 00 00 00 mov ecx,0x28 23: e8 3c 9d 31 00 call 0x319d64 28: f0 0f ba 6e 04 1f lock bts DWORD PTR [esi+0x4],0x1fThe NULL deref (actually offset NULL + 1028) happened during the bts above, which maps to the test_and_set_bit() below:
static bool was_reported(struct source_location *location) { return test_and_set_bit(REPORTED_BIT, &location->reported); } static bool suppress_report(struct source_location *loc) { return current->in_ubsan || was_reported(loc); } ... void __ubsan_handle_out_of_bounds(void *_data, void *index) { struct out_of_bounds_data *data = _data; char index_str[VALUE_LENGTH]; if (suppress_report(&data->location)) return; ...This should be impossible, though. struct out_of_bounds_data contains location as the first struct:
struct source_location { const char *file_name; union { unsigned long reported; struct { u32 line; u32 column; }; }; }; struct out_of_bounds_data { struct source_location location; ...So data->location.report should be offset _data + sizeof(void *) (here, 4). This matches the assembly: DWORD PTR [esi+0x4], but %esi is 0x400.
Having a base address of 1024 seems like either a special value, a per-cpu variable, or some failed relocation?
Metadata
Metadata
Assignees
Labels
[ARCH-done] x86_32Finished on the 32-bit x86 architecture (ARCH=i386)Finished on the 32-bit x86 architecture (ARCH=i386)[Compiler-done] ClangAn issue in Clang itself has been finishedAn issue in Clang itself has been finished[Linux] v6.10Released in Linux kernel v6.10Released in Linux kernel v6.10[PATCH] AcceptedA submitted patch has been accepted upstreamA submitted patch has been accepted upstream