https://bugs.winehq.org/show_bug.cgi?id=49225
Bug ID: 49225 Summary: FreeBSD "regression" causes assertion failure in (at least) applications using Gecko plugin Product: Wine Version: 5.9 Hardware: x86 OS: FreeBSD Status: NEW Severity: normal Priority: P2 Component: -unknown Assignee: wine-bugs@winehq.org Reporter: damjan.jov@gmail.com
My commit to get DLLs loading at correct addresses caused a regression where Wine crashes with an assertion failure when the ieframe component is loaded, eg. run 7-zip file manager, and click on Help -> Contents:
---snip--- Assertion failed: (view->protect & VPROT_SYSTEM), function create_view, file virtual.c, line 863. wine: Assertion failed at address 6235FCA3 (thread 0024), starting debugger... ---snip---
Starting the debugger fails due to permissions, but even if you do: sudo sysctl security.bsd.unprivileged_proc_debug=1 it deadlocks instead, so no stack trace is available.
This was the offending commit, by me, which exposed this bug for some applications, while fixing others:
commit 55ba3648379d90642f174e74809b84130d6d1ddc Author: Damjan Jovanovic damjan.jov@gmail.com Date: Mon May 18 21:04:58 2020 +0200
libwine: Add support for mmap at fixed start addresses on FreeBSD.
The way to implement MAP_TRYFIXED on FreeBSD is call mmap() with MAP_FIXED | MAP_EXCL, which will allocate the mapping from the exact starting address if possible, and if that fails, call mmap() again without them. This gets PE DLLs loading at their correct base addresses, and fixes a FreeBSD-specific problem with Cygwin's fork() caused by cygwin1.dll loading at different base addresses in the parent and child.
Signed-off-by: Damjan Jovanovic damjan.jov@gmail.com Signed-off-by: Alexandre Julliard julliard@winehq.org
M libs/wine/mmap.c
https://bugs.winehq.org/show_bug.cgi?id=49225
Damjan Jovanovic damjan.jov@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Regression SHA1| |55ba3648379d90642f174e74809 | |b84130d6d1ddc URL| |https://www.7-zip.org/a/7z9 | |20.exe Keywords| |download, regression, | |source
https://bugs.winehq.org/show_bug.cgi?id=49225
--- Comment #1 from Damjan Jovanovic damjan.jov@gmail.com --- The error is from this code snippet in dlls/ntdll/virtual.c function create_view():
---snip--- /* Check for overlapping views. This can happen if the previous view * was a system view that got unmapped behind our back. In that case * we recover by simply deleting it. */
while ((view = find_view_range( base, size ))) { TRACE( "overlapping view %p-%p for %p-%p\n", view->base, (char *)view->base + view->size, base, (char *)base + size ); assert( view->protect & VPROT_SYSTEM ); delete_view( view ); } ---snip---
which, when changed to FIXME, logs:
0024:fixme:virtual:create_view overlapping view 0x69e40000-0x6db71000 for 0x6b840000-0x6ba58000
What's at 0x69e40000-0x6db71000? Check /proc/<pid>/map:
---snip--- 0x69e40000 0x69e41000 1 0 0xfffff80271eae800 r-x 1 0 0x3000 COW NC vnode /usr/home/dj/.wine/drive_c/windows/system32/gecko/2.47.1/wine_gecko/xul.dll CH 1003 0x69e41000 0x6d061000 12832 0 0xfffff803e21bd800 r-x 1 0 0x2000 COW NC default - CH 1003 0x6d061000 0x6d0b8000 87 0 0xfffff802cf9fb600 rwx 1 0 0x2000 COW NC default - CH 1003 0x6d0b8000 0x6d944000 2188 0 0xfffff803cfecd000 r-x 1 0 0x2000 COW NC default - CH 1003 0x6d944000 0x6d945000 1 0 0xfffff8037d3a8d00 rwx 1 0 0x3000 COW NC default - CH 1003 0x6d945000 0x6d976000 1 0 0xfffff800750c0800 rwx 1 0 0x3000 COW NC default - CH 1003 0x6d976000 0x6d979000 3 0 0xfffff803e2e4d100 r-x 1 0 0x3000 COW NC vnode /usr/home/dj/.wine/drive_c/windows/system32/gecko/2.47.1/wine_gecko/xul.dll CH 1003 0x6d979000 0x6d988000 15 0 0xfffff80336ed4e00 rwx 1 0 0x3000 COW NC default - CH 1003 0x6d988000 0x6d989000 1 0 0xfffff803a4d7d400 rwx 1 0 0x3000 COW NC vnode /usr/home/dj/.wine/drive_c/windows/system32/gecko/2.47.1/wine_gecko/xul.dll CH 1003 0x6d989000 0x6db71000 488 0 0xfffff80315811800 r-x 1 0 0x3000 COW NC default - CH 1003 ---snip---
Multiple mappings from xul.dll.
https://bugs.winehq.org/show_bug.cgi?id=49225
--- Comment #2 from Damjan Jovanovic damjan.jov@gmail.com --- /* per-mapping protection flags */ #define VPROT_SYSTEM 0x0200 /* system view (underlying mmap not under our control) */
So Wine finds a "view", and expects it to be a system view that's been unmapped behind its back, but it isn't, thus the assertion error. What's interesting is that xul.dll is:
---snip--- .wine/drive_c/windows/system32/gecko/2.47.1/wine_gecko/xul.dll: PE32 executable (DLL) (GUI) Intel 80386 (stripped to external PDB), for MS Windows ---snip---
a Windows DLL; Wine should know about it and its memory mappings. How did it slip through the cracks?
Where do the views find_view_range() is searching come from, and where is create_view() called from that it wants the overlapping range?
find_view_range() searched the red-black tree in the "views_tree" variable for a range that neither starts after its given range, not ends before it. It correctly detects the range for xul.dll is there, and returns it. But why is it a problem that the range is there?
https://bugs.winehq.org/show_bug.cgi?id=49225
--- Comment #3 from Damjan Jovanovic damjan.jov@gmail.com --- It seems that create_view() is called after the memory is allocated by another function such as map_view(), in order to store the mapping. Thus if there is a range collision, it is a serious problem, because memory was allocated when it shouldn't have been.
Where is create_view called from and why?
create_view() map_view() allocate_dos_memory() map_image() virtual_map_section() virtual_alloc_thread_stack() virtual_alloc() allocate_dos_memory() virtual_alloc() NtAllocateVirtualMemory() virtual_alloc_first_teb() ... virtual_alloc_teb() ... ... virtual_create_builtin_view() ... virtual_alloc_thread_stack() RtlCreateUserStack() ...
That's a lot of searching. Let's assume the view got the right range previously, and only the call which results in the overlapping range is wrong. Where did that call come from?
https://bugs.winehq.org/show_bug.cgi?id=49225
--- Comment #4 from Damjan Jovanovic damjan.jov@gmail.com --- Further logging of calls (as there is no stack trace possible) gave the following chain of calls:
create_view() map_view() map_image() virtual_map_section() NtMapViewOfSection()
The 0x6b840000 address from the bad range that causes the assertion came from .wine/drive_c/windows/system32/gecko/2.47.1/wine_gecko/nss3.dll while the range it wants to get mapped into was from .wine/drive_c/windows/system32/gecko/2.47.1/wine_gecko/xul.dll
It is normal for a DLLs to have the a base address that's inside the range of a previously loaded DLL; nss3.dll is allowed to want a range overlapping xul.dll. The question is, why does map_view() not see the range is taken by xul.dll and relocate nss3.dll elsewhere, but allocate it over the xul.dll range instead?
https://bugs.winehq.org/show_bug.cgi?id=49225
--- Comment #5 from Damjan Jovanovic damjan.jov@gmail.com --- map_view() sees "base" is non-NULL, and calls map_fixed_area(), which calls unix_funcs->mmap_is_in_reserved_area() and takes this case in the switch statement:
case 0: /* not in a reserved area, do a normal allocation */
There, the bad pointer is returned from:
if ((ptr = wine_anon_mmap( base, size, VIRTUAL_GetUnixProt(vprot), 0 )) == (void *)-1)
https://bugs.winehq.org/show_bug.cgi?id=49225
Damjan Jovanovic damjan.jov@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Component|-unknown |winelib
--- Comment #6 from Damjan Jovanovic damjan.jov@gmail.com --- The regression was in my own commit, I wasn't checking the return value from mmap() properly.
Patch sent: https://source.winehq.org/patches/data/185684
https://bugs.winehq.org/show_bug.cgi?id=49225
Damjan Jovanovic damjan.jov@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Summary|FreeBSD "regression" causes |FreeBSD assertion failure / |assertion failure in (at |memory corruption |least) applications using |regression from not |Gecko plugin |checking mmap() return | |value correctly
https://bugs.winehq.org/show_bug.cgi?id=49225
Gerald Pfeifer gerald@pfeifer.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |gerald@pfeifer.com
https://bugs.winehq.org/show_bug.cgi?id=49225
Damjan Jovanovic damjan.jov@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Fixed by SHA1| |e0138c4a6a7a87f1d25badd43e0 | |5490e706bc666 Status|NEW |RESOLVED Resolution|--- |FIXED
--- Comment #7 from Damjan Jovanovic damjan.jov@gmail.com --- Patch committed, resolving fixed.
https://bugs.winehq.org/show_bug.cgi?id=49225
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #8 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 5.11.