Summary: | redirectCount returns 0 when using a Service Worker | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Product: | WebKit | Reporter: | Daniel Schulz <daniel.schulz> | ||||||||||||||
Component: | Service Workers | Assignee: | youenn fablet <youennf> | ||||||||||||||
Status: | RESOLVED FIXED | ||||||||||||||||
Severity: | Minor | CC: | achristensen, bfulgham, cdumez, cgarcia, ews-feeder, webkit-bug-importer, youennf | ||||||||||||||
Priority: | P2 | Keywords: | InRadar | ||||||||||||||
Version: | WebKit Local Build | ||||||||||||||||
Hardware: | Mac (Apple Silicon) | ||||||||||||||||
OS: | macOS 12 | ||||||||||||||||
Attachments: |
|
Description
Daniel Schulz
2022-01-27 06:19:47 PST
Amendment: My reported return values of step 3) and 4) are swapped. Sorry for the inconvenience. Is supposed to be: 3) Repeat step 1) - performance.navigation.redirectCount // still returns 0 4) Uninstall Service Worker, Repeat 1) - performance.navigation.redirectCount // returns 1 again Created attachment 454462 [details]
Patch
Created attachment 454480 [details]
Patch
@kal, gtk is crashing with the following trace: Thread 1 (Thread 0x7fc96cd06e80 (LWP 322757)): #0 0x00007fc975f1136b in WTF::Vector<WTF::String, 0ul, WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>::~Vector() () at /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 #1 0x00007fc975f113db in WebCore::ResourceRequestBase::~ResourceRequestBase() () at /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 #2 0x00007fc9760ce0a6 in WebKit::NetworkLoad::~NetworkLoad() () at /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 #3 0x00007fc9760ce379 in WebKit::NetworkLoad::~NetworkLoad() () at /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 #4 0x00007fc9761a0997 in WebKit::ServiceWorkerNavigationPreloader::didComplete() () at /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 #5 0x00007fc9760cdc8b in WebKit::NetworkLoad::willPerformHTTPRedirection(WebCore::ResourceResponse&&, WebCore::ResourceRequest&&, WTF::CompletionHandler<void (WebCore::ResourceRequest&&)>&&) () at /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 #6 0x00007fc976215857 in WebKit::NetworkDataTaskSoup::continueHTTPRedirection() () at /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 Any idea what might be the issue? (In reply to youenn fablet from comment #5) > @kal, gtk is crashing with the following trace: > Thread 1 (Thread 0x7fc96cd06e80 (LWP 322757)): > #0 0x00007fc975f1136b in WTF::Vector<WTF::String, 0ul, > WTF::CrashOnOverflow, 16ul, WTF::FastMalloc>::~Vector() () at > /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 > #1 0x00007fc975f113db in > WebCore::ResourceRequestBase::~ResourceRequestBase() () at > /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 > #2 0x00007fc9760ce0a6 in WebKit::NetworkLoad::~NetworkLoad() () at > /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 > #3 0x00007fc9760ce379 in WebKit::NetworkLoad::~NetworkLoad() () at > /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 > #4 0x00007fc9761a0997 in > WebKit::ServiceWorkerNavigationPreloader::didComplete() () at > /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 > #5 0x00007fc9760cdc8b in > WebKit::NetworkLoad::willPerformHTTPRedirection(WebCore::ResourceResponse&&, > WebCore::ResourceRequest&&, WTF::CompletionHandler<void > (WebCore::ResourceRequest&&)>&&) () at > /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 > #6 0x00007fc976215857 in > WebKit::NetworkDataTaskSoup::continueHTTPRedirection() () at > /app/webkit/WebKitBuild/Release/lib/libwebkit2gtk-4.1.so.0 > > Any idea what might be the issue? Nope, let me debug it. Making this a security bug, because the problem I found is an UAF that I think it's in current code, but I'm not sure it can happen without this patch, so feel free to make it public again if there's not a security problem. The problem is that NetworkLoad destructor is called twice because ServiceWorkerNavigationPreloader is used after being freed. This is the sequence: 1.- ServiceWorkerFetchTask::loadResponseFromPreloader: starts the preloader load 2.- ServiceWorkerNavigationPreloader::loadFromNetwork: creates a NetworkLoad and starts loading. Redirection happens. 3.- ServiceWorkerNavigationPreloader::willSendRedirectedRequest: didReceiveResponse is called 3.1.- NetworkResourceLoader processes the response and finishes the load calling NetworkResourceLoader::didFinishWithRedirectResponse 3.2.- ServiceWorkerFetchTask::~ServiceWorkerFetchTask: calls cancelPreloadIfNecessary and sets m_preloader = nullptr; 3.3.- ServiceWorkerNavigationPreloader::cancel: this cancels the NetworkLoad 3.4.- ServiceWorkerNavigationPreloader::~ServiceWorkerNavigationPreloader: this destructor destroys the NetworkLoad. 4.- ServiceWorkerNavigationPreloader::willSendRedirectedRequest: continues and calls didComplete(), but this is already destroyed at this point. 4.- ServiceWorkerNavigationPreloader::didComplete: makes m_networkLoad = nullptr, calling the NetworkLoad destructor again. So, we need to make WeakPtr before calling didReceiveResponse() in 3. and check it before calling didComplete(). I'll update the patch to confirm it fixes in the crashes in EWS too. Created attachment 454586 [details]
Patch
(In reply to Carlos Garcia Campos from comment #8) > The problem is that NetworkLoad destructor is called twice because > ServiceWorkerNavigationPreloader is used after being freed. This is the > sequence: > > 1.- ServiceWorkerFetchTask::loadResponseFromPreloader: starts the preloader > load > 2.- ServiceWorkerNavigationPreloader::loadFromNetwork: creates a NetworkLoad > and starts loading. Redirection happens. > 3.- ServiceWorkerNavigationPreloader::willSendRedirectedRequest: > didReceiveResponse is called > 3.1.- NetworkResourceLoader processes the response and finishes the load > calling NetworkResourceLoader::didFinishWithRedirectResponse > 3.2.- ServiceWorkerFetchTask::~ServiceWorkerFetchTask: calls > cancelPreloadIfNecessary and sets m_preloader = nullptr; > 3.3.- ServiceWorkerNavigationPreloader::cancel: this cancels the NetworkLoad > 3.4.- ServiceWorkerNavigationPreloader::~ServiceWorkerNavigationPreloader: > this destructor destroys the NetworkLoad. > 4.- ServiceWorkerNavigationPreloader::willSendRedirectedRequest: continues > and calls didComplete(), but this is already destroyed at this point. > 4.- ServiceWorkerNavigationPreloader::didComplete: makes m_networkLoad = > nullptr, calling the NetworkLoad destructor again. > > So, we need to make WeakPtr before calling didReceiveResponse() in 3. and > check it before calling didComplete(). I'll update the patch to confirm it > fixes in the crashes in EWS too. Good catch! I am not sure the bug can happen in the current code path since all we are doing before the patch when receiving a redirect is to send it to WebProcess. After the patch, we are going through NetworkResourceLoader which can either send it to WebProcess (no problem) or cancel the load (leading tho this problem). Comment on attachment 454586 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=454586&action=review > Source/WebKit/NetworkProcess/ServiceWorker/ServiceWorkerNavigationPreloader.cpp:160 > + return; It might be better to call didComplete inside the didReceiveResponse lambda which would catch the weak pointer. Will upload this variant. Created attachment 454599 [details]
Patch
Comment on attachment 454599 [details] Patch View in context: https://bugs.webkit.org/attachment.cgi?id=454599&action=review > Source/WebKit/NetworkProcess/NetworkResourceLoader.h:247 > + enum class IsFromServiceWorker { No, Yes }; : bool > Source/WebKit/NetworkProcess/NetworkResourceLoader.h:249 > + std::optional<WebCore::NetworkLoadMetrics> computeResponseMetrics(const WebCore::ResourceResponse&); Ideally this function would be marked as const. Created attachment 454815 [details]
Patch for landing
Committed r291340 (248479@main): <https://commits.webkit.org/248479@main> All reviewed patches have been landed. Closing bug and clearing flags on attachment 454815 [details]. |