Title: [237683] trunk
Revision
237683
Author
[email protected]
Date
2018-11-01 10:09:56 -0700 (Thu, 01 Nov 2018)

Log Message

[PSON] Unable to submit a file in FormData cross-site
https://bugs.webkit.org/show_bug.cgi?id=191138

Reviewed by Alex Christensen.

Source/WebKit:

When PSON is enabled, we are unable to submit a file in FormData cross-site. Although we encode the
request body over IPC since r237639, we're missing the right sandbox extensions for its to work for
files.

Update FormDataReference encoder to pass along the necessary sandbox extensions for files in the
FormData, and have its decoder consume those extensions so that the recipient has access to those
files. Also update LoadParameters's IPC encoder / decoder to encoder an IPC::FormDataReference
(which encodes both FormData and sandbox extensions) instead of a FormData.

* Platform/IPC/FormDataReference.h:
(IPC::FormDataReference::encode const):
(IPC::FormDataReference::decode):
* Shared/LoadParameters.cpp:
(WebKit::LoadParameters::encode const):
(WebKit::LoadParameters::decode):

LayoutTests:

Add layout test coverage.

* http/tests/misc/form-submit-file-cross-site-expected.txt:
* http/tests/misc/form-submit-file-cross-site.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (237682 => 237683)


--- trunk/LayoutTests/ChangeLog	2018-11-01 16:40:15 UTC (rev 237682)
+++ trunk/LayoutTests/ChangeLog	2018-11-01 17:09:56 UTC (rev 237683)
@@ -1,3 +1,15 @@
+2018-11-01  Chris Dumez  <[email protected]>
+
+        [PSON] Unable to submit a file in FormData cross-site
+        https://bugs.webkit.org/show_bug.cgi?id=191138
+
+        Reviewed by Alex Christensen.
+
+        Add layout test coverage.
+
+        * http/tests/misc/form-submit-file-cross-site-expected.txt:
+        * http/tests/misc/form-submit-file-cross-site.html:
+
 2018-11-01  Devin Rousso  <[email protected]>
 
         Unreviewed test fix after r237670.

Added: trunk/LayoutTests/http/tests/misc/form-submit-file-cross-site-expected.txt (0 => 237683)


--- trunk/LayoutTests/http/tests/misc/form-submit-file-cross-site-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/misc/form-submit-file-cross-site-expected.txt	2018-11-01 17:09:56 UTC (rev 237683)
@@ -0,0 +1,7 @@
+OPEN FILE PANEL
+This tests verifies the test file included in the multipart form data:
+
+PASS: File is present
+PASS: File upload was successful
+PASS: File size is greater than 0
+

Added: trunk/LayoutTests/http/tests/misc/form-submit-file-cross-site.html (0 => 237683)


--- trunk/LayoutTests/http/tests/misc/form-submit-file-cross-site.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/misc/form-submit-file-cross-site.html	2018-11-01 17:09:56 UTC (rev 237683)
@@ -0,0 +1,41 @@
+<html>
+<head>
+<script src=""
+<script src=""
+<script>
+
+const tempFileContent = "TEST";
+const tempFileName = "test.tmp";
+
+function onChange()
+{
+    document.forms[0].submit();
+}
+
+function test()
+{
+    let tempFilePath = createTempFile(tempFileName, tempFileContent);
+
+    let input = document.getElementsByTagName("input")[0];
+    input._onchange_ = onChange;
+
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+        testRunner.setOpenPanelFiles([tempFilePath]);
+
+        var centerX = input.offsetLeft + input.offsetWidth / 2;
+        var centerY = input.offsetTop + input.offsetHeight / 2;
+        UIHelper.activateAt(centerX, centerY);
+    }
+}
+
+window._onload_ = test;
+</script>
+</head>
+<body>
+<form enctype="multipart/form-data" method="POST" action=""
+<input name="data" type="file"></input>
+</form>
+</body>
+</html>

Added: trunk/LayoutTests/http/tests/misc/resources/check-test-file.php (0 => 237683)


--- trunk/LayoutTests/http/tests/misc/resources/check-test-file.php	                        (rev 0)
+++ trunk/LayoutTests/http/tests/misc/resources/check-test-file.php	2018-11-01 17:09:56 UTC (rev 237683)
@@ -0,0 +1,34 @@
+<?php
+header("Content-Type: text/html; charset=UTF-8");
+?>
+<html>
+<head>
+<script>
+_onload_ = function() {
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+</script>
+</head>
+<body>
+<h1>This tests verifies the test file included in the multipart form data:</h1>
+<pre>
+<?php
+if (isset($_FILES['data'])) {
+    print "PASS: File is present\n";
+    if ($_FILES['data']['error'] == UPLOAD_ERR_OK)
+        print "PASS: File upload was successful\n";
+    else
+        print "FAIL: File upload failed\n";
+
+    if ($_FILES['data']['size'] > 0)
+        print "PASS: File size is greater than 0\n";
+    else
+        print "FAIL: File size is 0\n";
+} else {
+    print "FAIL: File is missing";
+}
+?>
+</pre>
+</body>
+</html>

Modified: trunk/LayoutTests/platform/win/TestExpectations (237682 => 237683)


--- trunk/LayoutTests/platform/win/TestExpectations	2018-11-01 16:40:15 UTC (rev 237682)
+++ trunk/LayoutTests/platform/win/TestExpectations	2018-11-01 17:09:56 UTC (rev 237683)
@@ -209,6 +209,7 @@
 fast/files [ Skip ]
 http/tests/fileapi [ Skip ]
 fast/forms/file/recover-file-input-in-unposted-form.html [ Skip ]
+http/tests/misc/form-submit-file-cross-site.html [ Skip ]
 http/tests/xmlhttprequest/post-blob-content-type-async.html [ Skip ]
 http/tests/xmlhttprequest/post-blob-content-type-sync.html [ Skip ]
 webkit.org/b/29287 http/tests/local/fileapi/ [ Skip ]

Modified: trunk/Source/WebKit/ChangeLog (237682 => 237683)


--- trunk/Source/WebKit/ChangeLog	2018-11-01 16:40:15 UTC (rev 237682)
+++ trunk/Source/WebKit/ChangeLog	2018-11-01 17:09:56 UTC (rev 237683)
@@ -1,3 +1,26 @@
+2018-11-01  Chris Dumez  <[email protected]>
+
+        [PSON] Unable to submit a file in FormData cross-site
+        https://bugs.webkit.org/show_bug.cgi?id=191138
+
+        Reviewed by Alex Christensen.
+
+        When PSON is enabled, we are unable to submit a file in FormData cross-site. Although we encode the
+        request body over IPC since r237639, we're missing the right sandbox extensions for its to work for
+        files.
+
+        Update FormDataReference encoder to pass along the necessary sandbox extensions for files in the
+        FormData, and have its decoder consume those extensions so that the recipient has access to those
+        files. Also update LoadParameters's IPC encoder / decoder to encoder an IPC::FormDataReference
+        (which encodes both FormData and sandbox extensions) instead of a FormData.
+
+        * Platform/IPC/FormDataReference.h:
+        (IPC::FormDataReference::encode const):
+        (IPC::FormDataReference::decode):
+        * Shared/LoadParameters.cpp:
+        (WebKit::LoadParameters::encode const):
+        (WebKit::LoadParameters::decode):
+
 2018-11-01  Claudio Saavedra  <[email protected]>
 
         ERROR: ResourceLoadStatisticsPersistentStorage: Unable to delete statistics file

Modified: trunk/Source/WebKit/Platform/IPC/FormDataReference.h (237682 => 237683)


--- trunk/Source/WebKit/Platform/IPC/FormDataReference.h	2018-11-01 16:40:15 UTC (rev 237682)
+++ trunk/Source/WebKit/Platform/IPC/FormDataReference.h	2018-11-01 17:09:56 UTC (rev 237683)
@@ -27,11 +27,11 @@
 
 #include "Decoder.h"
 #include "Encoder.h"
+#include "SandboxExtension.h"
 #include <WebCore/FormData.h>
 
 namespace IPC {
 
-// FIXME: In case of file based form data, we should pass sandbox extensions as well.
 class FormDataReference {
 public:
     FormDataReference() = default;
@@ -45,8 +45,26 @@
     void encode(Encoder& encoder) const
     {
         encoder << !!m_data;
-        if (m_data)
-            encoder << *m_data;
+        if (!m_data)
+            return;
+
+        encoder << *m_data;
+
+        auto& elements = m_data->elements();
+        size_t fileCount = std::count_if(elements.begin(), elements.end(), [](auto& element) {
+            return WTF::holds_alternative<WebCore::FormDataElement::EncodedFileData>(element.data);
+        });
+
+        WebKit::SandboxExtension::HandleArray sandboxExtensionHandles;
+        sandboxExtensionHandles.allocate(fileCount);
+        size_t extensionIndex = 0;
+        for (auto& element : elements) {
+            if (auto* fileData = WTF::get_if<WebCore::FormDataElement::EncodedFileData>(element.data)) {
+                const String& path = fileData->shouldGenerateFile ? fileData->generatedFilename : fileData->filename;
+                WebKit::SandboxExtension::createHandle(path, WebKit::SandboxExtension::Type::ReadOnly, sandboxExtensionHandles[extensionIndex++]);
+            }
+        }
+        encoder << sandboxExtensionHandles;
     }
 
     static std::optional<FormDataReference> decode(Decoder& decoder)
@@ -62,6 +80,14 @@
         if (!formData)
             return std::nullopt;
 
+        std::optional<WebKit::SandboxExtension::HandleArray> sandboxExtensionHandles;
+        decoder >> sandboxExtensionHandles;
+        if (!sandboxExtensionHandles)
+            return std::nullopt;
+
+        for (size_t i = 0; i < sandboxExtensionHandles->size(); ++i)
+            WebKit::SandboxExtension::consumePermanently(sandboxExtensionHandles->at(i));
+
         return FormDataReference { formData.releaseNonNull() };
     }
 

Modified: trunk/Source/WebKit/Shared/LoadParameters.cpp (237682 => 237683)


--- trunk/Source/WebKit/Shared/LoadParameters.cpp	2018-11-01 16:40:15 UTC (rev 237682)
+++ trunk/Source/WebKit/Shared/LoadParameters.cpp	2018-11-01 17:09:56 UTC (rev 237683)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "LoadParameters.h"
 
+#include "FormDataReference.h"
 #include "WebCoreArgumentCoders.h"
 
 namespace WebKit {
@@ -36,8 +37,10 @@
     encoder << request;
 
     encoder << static_cast<bool>(request.httpBody());
-    if (request.httpBody())
-        request.httpBody()->encode(encoder);
+    if (request.httpBody()) {
+        // FormDataReference encoder / decoder takes care of passing and consuming the needed sandbox extensions.
+        encoder << IPC::FormDataReference { request.httpBody() };
+    }
 
     encoder << sandboxExtensionHandle;
     encoder << data;
@@ -70,10 +73,13 @@
         return false;
 
     if (hasHTTPBody) {
-        RefPtr<WebCore::FormData> formData = WebCore::FormData::decode(decoder);
-        if (!formData)
+        // FormDataReference encoder / decoder takes care of passing and consuming the needed sandbox extensions.
+        std::optional<IPC::FormDataReference> formDataReference;
+        decoder >> formDataReference;
+        if (!formDataReference)
             return false;
-        data.request.setHTTPBody(WTFMove(formData));
+
+        data.request.setHTTPBody(formDataReference->takeData());
     }
 
     std::optional<SandboxExtension::Handle> sandboxExtensionHandle;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to