[Bug 49093] New: Relocation of 32-bit PE builtin 'ntoskrnl.exe' causes kernel driver load failures (imports fixup recursion in load_driver_module)

WineHQ Bugzilla wine-bugs at winehq.org
Sun May 3 15:30:27 CDT 2020


https://bugs.winehq.org/show_bug.cgi?id=49093

            Bug ID: 49093
           Summary: Relocation of 32-bit PE builtin 'ntoskrnl.exe' causes
                    kernel driver load failures (imports fixup recursion
                    in load_driver_module)
           Product: Wine
           Version: 5.7
          Hardware: x86
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: ntoskrnl
          Assignee: wine-bugs at winehq.org
          Reporter: focht at gmx.net
      Distribution: ---

Hello folks,

encountered while revisiting some old kernel driver bug reports. Turns out it
can be reproduced with clean 32-bit WINEPREFIX as well. Apparently no one tests
'WINEARCH=win32' anymore ;-)

--- snip ---
$ export WINEARCH=win32

$ rm -rf ~/.wine

$ wineboot
...
0084:err:seh:setup_exception_record stack overflow 1504 bytes in thread 0084
eip f7bb05ed esp 00cf0d50 stack 0xcf0000-0xcf1000-0xdf0000
003c:err:service:process_send_command service protocol error - failed to read
pipe r = 0  count = 0!
003c:fixme:service:scmdatabase_autostart_services Auto-start service
L"SASDIFSV" failed to start: 1053
0098:err:seh:setup_exception_record stack overflow 1504 bytes in thread 0098
eip f7c615ed esp 00cf0d50 stack 0xcf0000-0xcf1000-0xdf0000
003c:err:service:process_send_command service protocol error - failed to read
pipe r = 0  count = 0!
003c:fixme:service:scmdatabase_autostart_services Auto-start service
L"SASKUTIL" failed to start: 1053
00ac:err:seh:setup_exception_record stack overflow 1600 bytes in thread 00ac
eip f7bad5ed esp 00cf0cf0 stack 0xcf0000-0xcf1000-0xdf0000
003c:err:service:process_send_command service protocol error - failed to read
pipe r = 0  count = 0!
003c:fixme:service:scmdatabase_autostart_services Auto-start service L"winebus"
failed to start: 1053
003c:err:service:process_send_start_message pipe connect failed
003c:fixme:service:scmdatabase_autostart_services Auto-start service L"wineusb"
failed to start: 1053
--- snip ---

More detailed trace log, but with an app installed kernel driver (from bug
21061):

--- snip ---
...
0120:trace:ntoskrnl:load_driver loading driver L"C:\\Program
Files\\SUPERAntiSpyware\\SASKUTIL.SYS"
0120:Call KERNEL32.LoadLibraryW(00210f90 L"C:\\Program
Files\\SUPERAntiSpyware\\SASKUTIL.SYS") ret=003356f2
...
0120:trace:module:map_image mapped PE file at 0xf10000-0xf32000
0120:trace:module:map_image mapping section .text at 0xf11000 off 400 size c200
virt c078 flags 60000020
0120:trace:module:map_image clearing 0xf1d200 - 0xf1e000
0120:trace:module:map_image mapping section .rdata at 0xf1e000 off c600 size
e00 virt d4c flags 40000040
0120:trace:module:map_image clearing 0xf1ee00 - 0xf1f000
0120:trace:module:map_image mapping section .data at 0xf1f000 off d400 size 600
virt 10e48 flags c0000040
0120:trace:module:map_image clearing 0xf1f600 - 0xf20000
0120:trace:module:map_image mapping section .rsrc at 0xf30000 off da00 size 600
virt 588 flags 42000040
0120:trace:module:map_image clearing 0xf30600 - 0xf31000
0120:trace:module:map_image mapping section .reloc at 0xf31000 off e000 size
e00 virt d7e flags 42000040
0120:trace:module:map_image clearing 0xf31e00 - 0xf32000
...
0120:trace:module:load_native_dll Trying native dll L"\\??\\C:\\Program
Files\\SUPERAntiSpyware\\SASKUTIL.SYS"
0120:trace:module:perform_relocations relocating from 0x10000-0x32000 to
0xf10000-0xf32000
...
0120:trace:module:load_dll Found L"C:\\windows\\system32\\ntoskrnl.exe" for
L"ntoskrnl.exe" at 0x320000, count=-1
0120:trace:imports:import_dll --- IofCompleteRequest ntoskrnl.exe.480 =
0x327568
0120:trace:imports:import_dll --- KeBugCheck ntoskrnl.exe.498 = 0x328480
0120:trace:imports:import_dll --- PsGetCurrentProcessId ntoskrnl.exe.847 =
0x329500 
...
0120:trace:imports:import_dll --- ProbeForRead ntoskrnl.exe.832 = 0x329460
0120:trace:imports:import_dll --- ExFreePoolWithTag ntoskrnl.exe.78 = 0x327900
...
0120:trace:module:load_dll Found L"C:\\windows\\system32\\hal.dll" for
L"HAL.dll" at 0x3c0000, count=-1
0120:trace:imports:import_dll --- KfRaiseIrql HAL.dll.78 = 0x3c1a08
0120:trace:imports:import_dll --- KeGetCurrentIrql HAL.dll.64 = 0x3c1acc
0120:trace:imports:import_dll --- KfLowerIrql HAL.dll.77 = 0x3c19e4
0120:trace:loaddll:load_native_dll Loaded L"C:\\Program
Files\\SUPERAntiSpyware\\SASKUTIL.SYS" at 0xf10000: native
0120:trace:module:load_dll Loaded module L"\\??\\C:\\Program
Files\\SUPERAntiSpyware\\SASKUTIL.SYS" at 0xf10000
...
0120:Ret  KERNEL32.LoadLibraryW() retval=00f10000 ret=003356f2
0120:Call ntdll.RtlImageNtHeader(00f10000) ret=00335705
0120:Ret  ntdll.RtlImageNtHeader() retval=00f100d8 ret=00335705
0120:Call ntdll.NtQuerySystemInformation(00000000,00defb74,0000002c,00000000)
ret=00335723
0120:Ret  ntdll.NtQuerySystemInformation() retval=00000000 ret=00335723
0120:Call
ntdll.RtlImageDirectoryEntryToData(00f10000,00000001,00000001,00defbb0)
ret=00335966
0120:Ret  ntdll.RtlImageDirectoryEntryToData() retval=00f1e534 ret=00335966
0120:trace:ntoskrnl:load_driver_module name='ntoskrnl.exe', i=0
0120:Call KERNEL32.LoadLibraryW(00def9f4 L"ntoskrnl.exe") ret=003356f2
...
0120:trace:module:load_dll Found L"C:\\windows\\system32\\ntoskrnl.exe" for
L"ntoskrnl.exe" at 0x320000, count=-1
0120:Ret  ntdll.LdrLoadDll() retval=00000000 ret=7b016808
0120:Call ntdll.RtlReleasePath(00210ff8) ret=7b01683f
0120:Ret  ntdll.RtlReleasePath() retval=00000000 ret=7b01683f
0120:Ret  KERNEL32.LoadLibraryW() retval=00320000 ret=003356f2 
0120:Call ntdll.RtlImageNtHeader(00320000) ret=00335705
0120:Ret  ntdll.RtlImageNtHeader() retval=00320078 ret=00335705
0120:Call ntdll.NtQuerySystemInformation(00000000,00def994,0000002c,00000000)
ret=00335723
0120:Ret  ntdll.NtQuerySystemInformation() retval=00000000 ret=00335723
0120:Call
ntdll.RtlImageDirectoryEntryToData(00320000,00000001,00000001,00def9d0)
ret=00335966
0120:Ret  ntdll.RtlImageDirectoryEntryToData() retval=0034c260 ret=00335966 
...
0120:Call KERNEL32.LoadLibraryW(00def814 L"advapi32.dll") ret=003356f2
...
0120:Ret  KERNEL32.LoadLibraryW() retval=7e9f0000 ret=003356f2
0120:Call ntdll.RtlImageNtHeader(7e9f0000) ret=00335705
0120:Ret  ntdll.RtlImageNtHeader() retval=7e9f0060 ret=00335705
0120:Call KERNEL32.FreeLibrary(7e9f0000) ret=00335a08
...
0120:Ret  KERNEL32.FreeLibrary() retval=00000001 ret=00335a08
... 
0120:Call KERNEL32.LoadLibraryW(00def814 L"hal.dll") ret=003356f2 
...
0120:Ret  KERNEL32.LoadLibraryW() retval=003c0000 ret=003356f2
0120:Call ntdll.RtlImageNtHeader(003c0000) ret=00335705
0120:Ret  ntdll.RtlImageNtHeader() retval=003c0078 ret=00335705
0120:Call ntdll.NtQuerySystemInformation(00000000,00def7b4,0000002c,00000000)
ret=00335723
0120:Ret  ntdll.NtQuerySystemInformation() retval=00000000 ret=00335723
0120:Call
ntdll.RtlImageDirectoryEntryToData(003c0000,00000001,00000001,00def7f0)
ret=00335966
0120:Ret  ntdll.RtlImageDirectoryEntryToData() retval=003c3e2d ret=003359
...
0120:Call KERNEL32.LoadLibraryW(00def634 L"ntoskrnl.exe") ret=003356f2
...
0120:Ret  KERNEL32.LoadLibraryW() retval=00320000 ret=003356f2
0120:Call ntdll.RtlImageNtHeader(00320000) ret=00335705
0120:Ret  ntdll.RtlImageNtHeader() retval=00320078 ret=00335705
0120:Call ntdll.NtQuerySystemInformation(00000000,00def5d4,0000002c,00000000)
ret=00335723
0120:Ret  ntdll.NtQuerySystemInformation() retval=00000000 ret=00335723
0120:Call
ntdll.RtlImageDirectoryEntryToData(00320000,00000001,00000001,00def610)
ret=00335966
0120:Ret  ntdll.RtlImageDirectoryEntryToData() retval=0034c260 ret=00335966
0120:Call KERNEL32.LoadLibraryW(00def454 L"advapi32.dll") ret=003356f2 
...
<repeats until stack overflow>
--- snip ---

Relocation fixup sequence is like this:

--- snip ---
LoadLibraryW("SASKUTIL.SYS")
    FreeLibrary( LoadLibraryW("ntoskrnl.exe"))
        FreeLibrary( LoadLibraryW( "advapi32.dll"))
        FreeLibrary( LoadLibraryW("HAL.dll"))
            FreeLibrary( LoadLibraryW("ntoskrnl.exe"))
                FreeLibrary( LoadLibraryW( "advapi32.dll"))
                FreeLibrary( LoadLibraryW("HAL.dll"))
                    FreeLibrary( LoadLibraryW("ntoskrnl.exe"))
                        FreeLibrary( LoadLibraryW( "advapi32.dll"))
...
--- snip ---

The reason is the addition of builtin 'sechost.dll' in commit
https://source.winehq.org/git/wine.git/commitdiff/dedd5ccc88547529ffb1101045602aed59fa0170
("sechost: New stub DLL.").

Technically it's not a regresson - the problem was already present, it's just
triggered now.

'sechost.dll' is the first PE builtin which get mapped into 'winedevice'
hosting process, occupying the default load address for MinGW builtins ->
0x10000000.

--- snip ---
...
003c:trace:process:RtlCreateUserProcess
L"\\??\\C:\\windows\\system32\\winedevice.exe" image
L"C:\\windows\\system32\\winedevice.exe" cmdline
L"C:\\windows\\system32\\winedevice.exe" 
...
00a4:trace:module:build_so_dll_module loaded
L"\\??\\C:\\windows\\system32\\ntdll.dll" 0x1102a8 0x7bc30000 
...
003c:trace:process:CreateProcessInternalW started process pid 00a0 tid 00a4
...
00a4:trace:loaddll:load_native_dll Loaded
L"C:\\windows\\system32\\kernelbase.dll" at 0x7b000000: PE builtin 
...
00a4:trace:loaddll:load_so_dll Loaded L"C:\\windows\\system32\\kernel32.dll" at
0x7b420000: builtin 
...
00a4:trace:loaddll:load_native_dll Loaded
L"C:\\windows\\system32\\winedevice.exe" at 0x400000: PE builtin 
...
00a4:trace:loaddll:load_so_dll Loaded L"C:\\windows\\system32\\ucrtbase.dll" at
0x7e8f0000: builtin 
...
00a4:trace:loaddll:load_native_dll Loaded L"C:\\windows\\system32\\sechost.dll"
at 0x10000000: PE builtin 
...
00a4:trace:loaddll:load_so_dll Loaded L"C:\\windows\\system32\\advapi32.dll" at
0x7e9f0000: builtin 
...
00a4:trace:loaddll:load_native_dll Loaded L"C:\\windows\\system32\\hal.dll" at
0x3c0000: PE builtin 
...
00a4:trace:loaddll:load_so_dll Loaded L"C:\\windows\\system32\\msvcrt.dll" at
0x7e810000: builtin 
...
00a4:trace:loaddll:load_native_dll Loaded
L"C:\\windows\\system32\\ntoskrnl.exe" at 0x320000: PE builtin 
...
<rest doesn't matter>
--- snip ---

Previously this address was always taken by PE builtin 'ntoskrnl.exe' which
coincidentally avoided the relocation processing of the module.

Wine source:

https://source.winehq.org/git/wine.git/blob/d1f858e03da732c621504f90e349d5170ca3336e:/dlls/ntoskrnl.exe/ntoskrnl.c#l3453

--- snip ---
3453 /* load the driver module file */
3454 static HMODULE load_driver_module( const WCHAR *name )
3455 {
3456     IMAGE_NT_HEADERS *nt;
3457     const IMAGE_IMPORT_DESCRIPTOR *imports;
3458     SYSTEM_BASIC_INFORMATION info;
3459     int i;
3460     INT_PTR delta;
3461     ULONG size;
3462     DWORD old;
3463     NTSTATUS status;
3464     HMODULE module = LoadLibraryW( name );
3465 
3466     if (!module) return NULL;
3467     nt = RtlImageNtHeader( module );
3468 
3469     if (!(delta = (char *)module - (char *)nt->OptionalHeader.ImageBase))
return module;
3470 
3471     /* the loader does not apply relocations to non page-aligned binaries
or executables,
3472      * we have to do it ourselves */
3473 
3474     NtQuerySystemInformation( SystemBasicInformation, &info, sizeof(info),
NULL );
3475     if (nt->OptionalHeader.SectionAlignment < info.PageSize ||
3476         !(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
3477     {
3478         status = perform_relocations(module,
nt->OptionalHeader.SizeOfImage);
3479         if (status != STATUS_SUCCESS)
3480             goto error;
3481 
3482         /* make sure we don't try again */
3483         size = FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) +
nt->FileHeader.SizeOfOptionalHeader;
3484         VirtualProtect( nt, size, PAGE_READWRITE, &old );
3485        
nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0;
3486         VirtualProtect( nt, size, old, &old );
3487     }
3488 
3489     /* make sure imports are relocated too */
3490 
3491     if ((imports = RtlImageDirectoryEntryToData( module, TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
3492     {
3493         for (i = 0; imports[i].Name && imports[i].FirstThunk; i++)
3494         {
3495             char *name = (char *)module + imports[i].Name;
3496             WCHAR buffer[32], *p = buffer;
3497 
3498             while (p < buffer + 32) if (!(*p++ = *name++)) break;
3499             if (p <= buffer + 32) FreeLibrary( load_driver_module( buffer
) );
3500         }
3501     }
3502 
3503     return module;
3504 
3505 error:
3506     FreeLibrary( module );
3507     return NULL;
3508 }
--- snip ---

$ wine --version
wine-5.7-170-gd1f858e03d

Regards

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.



More information about the wine-bugs mailing list