Bug 218612 - [WPE] Crash if a view loads a blocked URL by a content filter
Summary: [WPE] Crash if a view loads a blocked URL by a content filter
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WPE WebKit (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-11-05 05:39 PST by Pablo Saavedra
Modified: 2021-02-04 02:06 PST (History)
1 user (show)

See Also:


Attachments
Test case (14.27 KB, text/x-csrc)
2020-11-05 05:39 PST, Pablo Saavedra
no flags Details
filters.json (553 bytes, application/json)
2020-11-05 05:49 PST, Pablo Saavedra
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Pablo Saavedra 2020-11-05 05:39:27 PST
Created attachment 413286 [details]
Test case

Crash happens in WPE when attempting to load a page blocked by the Content filters:

{{{
#0  0x00007f74fc23f310 in wl_connection_flush (connection=0x727574616e676973) at ../src/connection.c:297
#1  0x00007f750a07d220 in ViewBackend::releaseBuffer(wl_resource*) () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#2  0x00007f750a07c3aa in (anonymous namespace)::ClientBundleEGL::releaseImage(wpe_fdo_egl_exported_image*) () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#3  0x00007f750a07c649 in wpe_view_backend_exportable_fdo_egl_dispatch_release_exported_image () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#4  0x0000562f7d00bb4d in on_buffer_release (data=0x562f7f1ae770, buffer=0x562f7f1dbb10) at surface.c:173
#5  0x00007f74fc24f8ee in ffi_call_unix64 () at /usr/lib/x86_64-linux-gnu/libffi.so.6
#6  0x00007f74fc24f2bf in ffi_call () at /usr/lib/x86_64-linux-gnu/libffi.so.6
#7  0x00007f750a0a028d in wl_closure_invoke (closure=0x562f7f18f800, flags=1, target=<optimized out>, opcode=0, data=<optimized out>) at ../src/connection.c:1006
#8  0x00007f750a09cac9 in dispatch_event (display=display@entry=0x562f7eff0d90, queue=<optimized out>) at ../src/wayland-client.c:1427
#9  0x00007f750a09df94 in dispatch_queue (queue=0x562f7eff0e58, display=0x562f7eff0d90) at ../src/wayland-client.c:1573
#10 0x00007f750a09df94 in wl_display_dispatch_queue_pending (display=0x562f7eff0d90, queue=0x562f7eff0e58) at ../src/wayland-client.c:1815
#11 0x0000562f7d00bd23 in on_export_fdo_egl_image (data=0x0, image=0x562f7f1dfc40) at surface.c:213
#12 0x00007f750a07c47a in (anonymous namespace)::ClientBundleEGL::exportImage(wpe_fdo_egl_exported_image*) () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#13 0x00007f750a07c20d in (anonymous namespace)::ClientBundleEGL::exportBuffer(linux_dmabuf_buffer const*) () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#14 0x00007f750a07d0f2 in ViewBackend::exportLinuxDmabuf(linux_dmabuf_buffer const*) () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#15 0x00007f750a083314 in WS::ImplEGL::surfaceCommit(WS::Surface&) () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#16 0x00007f750a07ddfd in WS::{lambda(wl_client*, wl_resource*)#10}::operator()(wl_client*, wl_resource*) const () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#17 0x00007f750a07de25 in WS::{lambda(wl_client*, wl_resource*)#10}::_FUN(wl_client*, wl_resource*) () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#18 0x00007f74fc24f8ee in ffi_call_unix64 () at /usr/lib/x86_64-linux-gnu/libffi.so.6
#19 0x00007f74fc24f2bf in ffi_call () at /usr/lib/x86_64-linux-gnu/libffi.so.6
#20 0x00007f74fc240b2d in wl_closure_invoke (closure=closure@entry=0x562f7f1e0aa0, flags=flags@entry=2, target=<optimized out>, target@entry=0x562f7f1ad1e0, opcode=opcode@entry=6, data=<optimized out>, data@entry=0x562f7f195260)
    at ../src/connection.c:1006
#21 0x00007f74fc23d5a9 in wl_client_connection_data (fd=<optimized out>, mask=<optimized out>, data=0x562f7f195260) at ../src/wayland-server.c:420
#22 0x00007f74fc23eb72 in wl_event_loop_dispatch (loop=0x562f7f16b0f0, timeout=<optimized out>) at ../src/event-loop.c:641
#23 0x00007f750a07da25 in WS::ServerSource::{lambda(_GSource*, int (*)(void*), void*)#3}::operator()(_GSource*, int (*)(void*), void*) const () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#24 0x00007f750a07da8c in WS::ServerSource::{lambda(_GSource*, int (*)(void*), void*)#3}::_FUN(_GSource*, int (*)(void*), void*) () at /home/igalia/psaavedra/install/lib/libWPEBackend-fdo-1.0.so.1
#25 0x00007f74fdb10f2e in g_main_context_dispatch () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#26 0x00007f74fdb111c8 in  () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#27 0x00007f74fdb114c2 in g_main_loop_run () at /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0
#28 0x0000562f7d00c5e9 in main (argc=1, argv=0x7fffb7f511a8) at surface.c:445
}}}

AFAIK, what is happening is that the wl_client of the surface associated to the load request of the blocked content is being closed because an WL_EVENT_HANGUP (5). The UI-process doesn't knows about it and because it has its own copy of the wl_client pointer it keeps trying to operate over it during the release/dispatch actions even when the memory is or will be freed. The client is being freed in the wayland code when the error happens but the ViewBackend will never will know that its copy of the pointer is pointing to an area that it will be deleted.

The WL_EVENT_HANGUP happens immediately after that the content is blocked. If we are able to close the client and/or unregister the surface related to this request in a civilized way, we could avoid this situation.

Another possibility could be to add a wl_client_add_destroy_listener(). Something like this:
https://paste.debian.net/1170037/ to give the chance to the Surface to know if the client was being destroyed and avoid dispatching and/or releasing over that already closed client's connection. That patch works and acts immediately before to any other flush action but still doesn't address all the problems (for example: the wl_connection_flush() is also called in a close action invoked in in another non-located place).

HOW TO REPRODUCE:

The synthetic code to reproduce the crash is attached in the issue: launcher.c


* Build instructions:

```
# Set this variables to the right place where you have the WPE related libraries
# export PKG_CONFIG_PATH=/home/igalia/psaavedra/install/lib/pkgconfig/
# export LD_LIBRARY_PATH=/home/igalia/psaavedra/install/lib

filename="launcher"

CFLAGS="gtk+-3.0 wpe-webkit-1.0 wpebackend-fdo-1.0 egl"
LIBS="gtk+-3.0 wayland-client wpe-1.0 wpebackend-fdo-1.0 wpe-web-extension-1.0  wpe-webkit-1.0 egl"

gcc -g3 `pkg-config --cflags $CFLAGS` -o $filename $filename.c `pkg-config --libs $LIBS`
```

* Execution: 

```
export WAYLAND_DISPLAY=wayland-0
export XDG_RUNTIME_DIR=/xdg
export LD_LIBRARY_PATH=/home/igalia/psaavedra/install/lib
export WEBKIT_IGNORE_SSL_ERRORS=1
./launcher
```

The issue is reproducible in:

* WebKit: 2.28; 2.30; trunk
* libwpe: 1.6; 1.8
* Weston: 1.3; 5.0 
* Wayland-protocols: 1.13 and 1.17



ii  wayland-protocols                      1.17-1                              all          wayland compositor protocols
ii  weston                                 5.0.0-3                             amd64        reference implementation of a wayland compositor
Comment 1 Pablo Saavedra 2020-11-05 05:43:43 PST
Some relevant messages throw when the bloked page is being processed:


```
ERROR: 0x7f74f61a69a0 - ProvisionalPageProxy::didFailProvisionalLoadForFrame: pageProxyID=5 webPageID=13, frameID=3, navigationID=7
../Source/WebKit/UIProcess/ProvisionalPageProxy.cpp(269) : void WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame(WebCore::FrameIdentifier, WebKit::FrameInfoData&&, WebCore::ResourceRequest&&, uint64_t, const WTF::String&, const WebCore::ResourceError&, WebCore::WillContinueLoading, const WebKit::UserData&)
ERROR: 0x7f74afcf6000 - [pageProxyID=5, webPageID=6, PID=29633] WebPageProxy::didFailProvisionalLoadForFrame: frameID = 3, domain = WebKitPolicyError, code = 104
../Source/WebKit/UIProcess/WebPageProxy.cpp(4609) : void WebKit::WebPageProxy::didFailProvisionalLoadForFrameShared(WTF::Ref<WebKit::WebProcessProxy>&&, WebCore::FrameIdentifier, WebKit::FrameInfoData&&, WebCore::ResourceRequest&&, uint64_t, const WTF::String&, const WebCore::ResourceError&, WebCore::WillContinueLoading, const WebKit::UserData&)
```
Comment 2 Pablo Saavedra 2020-11-05 05:49:47 PST
Created attachment 413287 [details]
filters.json

Put this file in the same directory where the ./launcher launched.
Comment 3 Pablo Saavedra 2020-11-07 05:45:46 PST
Trying to address this issue by fixing the WPEbackend-fdo: https://github.com/Igalia/WPEBackend-fdo/pull/127
Comment 4 Pablo Saavedra 2021-02-04 02:06:48 PST
Fixed in WPEBackend-fdo: https://github.com/Igalia/WPEBackend-fdo/pull/127