Implement new WebGL extensions blocking logic

This commit is contained in:
Mark Pilgrim
2021-05-24 17:48:46 -04:00
parent c726e59e4a
commit 337c93fe4e
7 changed files with 164 additions and 31 deletions
@@ -29,7 +29,7 @@
using brave_shields::ControlType;
const char kEmbeddedTestServerDirectory[] = "webgl";
const char kTitleScript[] = "domAutomationController.send(document.title);";
const char kTitleScript[] = "document.title";
class BraveWebGLFarblingBrowserTest : public InProcessBrowserTest {
public:
@@ -80,13 +80,6 @@ class BraveWebGLFarblingBrowserTest : public InProcessBrowserTest {
embedded_test_server()->GetURL(domain, "/"));
}
template <typename T>
std::string ExecScriptGetStr(const std::string& script, T* frame) {
std::string value;
EXPECT_TRUE(ExecuteScriptAndExtractString(frame, script, &value));
return value;
}
content::WebContents* contents() {
return browser()->tab_strip_model()->GetActiveWebContents();
}
@@ -131,19 +124,20 @@ IN_PROC_BROWSER_TEST_F(BraveWebGLFarblingBrowserTest, FarbleGetParameterWebGL) {
// relation to original data
BlockFingerprinting(domain);
NavigateToURLUntilLoadStop(url);
EXPECT_EQ(ExecScriptGetStr(kTitleScript, contents()), kExpectedRandomString);
EXPECT_EQ(EvalJs(contents(), kTitleScript).ExtractString(),
kExpectedRandomString);
// second time, same as the first (tests that results are consistent for the
// lifetime of a session, and that the PRNG properly resets itself at the
// beginning of each calculation)
NavigateToURLUntilLoadStop(url);
EXPECT_EQ(ExecScriptGetStr(kTitleScript, contents()), kExpectedRandomString);
EXPECT_EQ(EvalJs(contents(), kTitleScript).ExtractString(),
kExpectedRandomString);
std::string actual;
// Farbling level: balanced (default)
// WebGL getParameter of restricted values: original data
SetFingerprintingDefault(domain);
NavigateToURLUntilLoadStop(url);
actual = ExecScriptGetStr(kTitleScript, contents());
std::string actual = EvalJs(contents(), kTitleScript).ExtractString();
// Farbling level: off
// WebGL getParameter of restricted values: original data
@@ -152,8 +146,8 @@ IN_PROC_BROWSER_TEST_F(BraveWebGLFarblingBrowserTest, FarbleGetParameterWebGL) {
// Since this value depends on the underlying hardware, we just test that the
// results for "off" are the same as the results for "balanced", and that
// they're different than the results for "maximum".
EXPECT_EQ(ExecScriptGetStr(kTitleScript, contents()), actual);
EXPECT_NE(kExpectedRandomString, actual);
EXPECT_EQ(EvalJs(contents(), kTitleScript).ExtractString(), actual);
EXPECT_NE(actual, kExpectedRandomString);
}
IN_PROC_BROWSER_TEST_F(BraveWebGLFarblingBrowserTest,
@@ -172,7 +166,7 @@ IN_PROC_BROWSER_TEST_F(BraveWebGLFarblingBrowserTest,
AllowFingerprinting(domain);
NavigateToURLUntilLoadStop(url);
std::vector<int64_t> real_values =
SplitStringAsInts(ExecScriptGetStr(kTitleScript, contents()));
SplitStringAsInts(EvalJs(contents(), kTitleScript).ExtractString());
ASSERT_EQ(real_values.size(), 12UL);
// Farbling level: default
@@ -181,8 +175,59 @@ IN_PROC_BROWSER_TEST_F(BraveWebGLFarblingBrowserTest,
SetFingerprintingDefault(domain);
NavigateToURLUntilLoadStop(url);
std::vector<int64_t> farbled_values =
SplitStringAsInts(ExecScriptGetStr(kTitleScript, contents()));
SplitStringAsInts(EvalJs(contents(), kTitleScript).ExtractString());
ASSERT_EQ(farbled_values.size(), 12UL);
ASSERT_EQ(DiffsAsString(real_values, farbled_values), expected_diff);
}
}
IN_PROC_BROWSER_TEST_F(BraveWebGLFarblingBrowserTest, GetSupportedExtensions) {
std::string domain = "a.com";
GURL url =
embedded_test_server()->GetURL(domain, "/getSupportedExtensions.html");
const std::string kSupportedExtensionsMax = "WEBGL_debug_renderer_info";
// Farbling level: maximum
// WebGL getSupportedExtensions returns abbreviated list
BlockFingerprinting(domain);
NavigateToURLUntilLoadStop(url);
EXPECT_EQ(EvalJs(contents(), kTitleScript).ExtractString(),
kSupportedExtensionsMax);
// Farbling level: off
// WebGL getSupportedExtensions is real
AllowFingerprinting(domain);
NavigateToURLUntilLoadStop(url);
std::string actual = EvalJs(contents(), kTitleScript).ExtractString();
EXPECT_NE(actual, kSupportedExtensionsMax);
// Farbling level: balanced (default)
// WebGL getSupportedExtensions is real
SetFingerprintingDefault(domain);
NavigateToURLUntilLoadStop(url);
EXPECT_EQ(EvalJs(contents(), kTitleScript).ExtractString(), actual);
}
IN_PROC_BROWSER_TEST_F(BraveWebGLFarblingBrowserTest, GetExtension) {
std::string domain = "a.com";
GURL url = embedded_test_server()->GetURL(domain, "/getExtension.html");
const std::string kExpectedExtensionListMax = "WEBGL_debug_renderer_info";
// Farbling level: maximum
// WebGL getExtension returns null for most names
BlockFingerprinting(domain);
NavigateToURLUntilLoadStop(url);
EXPECT_EQ(EvalJs(contents(), kTitleScript).ExtractString(),
kExpectedExtensionListMax);
// Farbling level: off
// WebGL getExtension returns real objects
AllowFingerprinting(domain);
NavigateToURLUntilLoadStop(url);
std::string actual = EvalJs(contents(), kTitleScript).ExtractString();
EXPECT_NE(actual, kExpectedExtensionListMax);
// Farbling level: balanced (default)
// WebGL getExtension returns real objects
SetFingerprintingDefault(domain);
NavigateToURLUntilLoadStop(url);
EXPECT_EQ(EvalJs(contents(), kTitleScript).ExtractString(), actual);
}
+1
View File
@@ -13,6 +13,7 @@ include_rules = [
"+../../../../../../../third_party/blink/renderer/modules/mediastream",
"+../../../../../../../third_party/blink/renderer/modules/quota",
"+../../../../../../../third_party/blink/renderer/modules/storage",
"+../../../../../../third_party/blink/renderer/modules/webgl",
"+../../../../../../../third_party/blink/renderer/modules/webaudio",
"+../../../../../../../../third_party/blink/renderer/modules/canvas/canvas2d",
"+../../../../../../../third_party/blink/renderer/platform/graphics",
@@ -3,6 +3,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
#include "third_party/blink/public/platform/web_content_settings_client.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -77,7 +78,42 @@ bool AllowFingerprintingForHost(blink::CanvasRenderingContextHost* host) {
*(Host()->GetTopExecutionContext())) \
.GenerateRandomString("UNMASKED_VENDOR_WEBGL", 8)));
#define getExtension getExtension_ChromiumImpl
#define getSupportedExtensions getSupportedExtensions_ChromiumImpl
#include "../../../../../../../third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc"
#undef getSupportedExtensions
#undef getExtension
namespace blink {
// If fingerprinting is disallowed, claim that the only supported extension is
// WebGLDebugRendererInfo.
base::Optional<Vector<String>>
WebGLRenderingContextBase::getSupportedExtensions() {
base::Optional<Vector<String>> real_extensions =
getSupportedExtensions_ChromiumImpl();
if (real_extensions == base::nullopt)
return real_extensions;
if (AllowFingerprintingForHost(Host()))
return real_extensions;
Vector<String> fake_extensions;
fake_extensions.push_back(WebGLDebugRendererInfo::ExtensionName());
return fake_extensions;
}
// If fingerprinting is disallowed and they're asking for information about any
// extension other than WebGLDebugRendererInfo, don't give it to them.
ScriptValue WebGLRenderingContextBase::getExtension(ScriptState* script_state,
const String& name) {
if (!AllowFingerprintingForHost(Host()))
if (name != WebGLDebugRendererInfo::ExtensionName())
return ScriptValue::CreateNull(script_state->GetIsolate());
return getExtension_ChromiumImpl(script_state, name);
}
} // namespace blink
#undef BRAVE_WEBGL_GET_PARAMETER_UNMASKED_RENDERER
#undef BRAVE_WEBGL_GET_PARAMETER_UNMASKED_VENDOR
#undef BRAVE_WEBGL_RENDERING_CONTEXT_BASE_STRING
@@ -0,0 +1,22 @@
/* Copyright (c) 2021 The Brave Authors. All rights reserved.
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at https://mozilla.org/MPL/2.0/. */
#ifndef BRAVE_CHROMIUM_SRC_THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_RENDERING_CONTEXT_BASE_H_
#define BRAVE_CHROMIUM_SRC_THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_RENDERING_CONTEXT_BASE_H_
#define getExtension \
getExtension_ChromiumImpl(ScriptState*, const String& name); \
ScriptValue getExtension
#define getSupportedExtensions \
getSupportedExtensions_ChromiumImpl(); \
base::Optional<Vector<String>> getSupportedExtensions
#include "../../../../../../third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h"
#undef getSupportedExtensions
#undef getExtension
#endif // BRAVE_CHROMIUM_SRC_THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGL_WEBGL_RENDERING_CONTEXT_BASE_H_
@@ -1,5 +1,5 @@
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 31a22fa48c001a07d1b848c107d22c7d1342c2a6..598a94a2cb71897c4ace95dbecfb8cd9bf57a51d 100644
index 31a22fa48c001a07d1b848c107d22c7d1342c2a6..70adc89b0c804f28d8c94e6217d9dd650f97a5ac 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -2920,6 +2920,7 @@ WebGLActiveInfo* WebGLRenderingContextBase::getActiveAttrib(
@@ -122,15 +122,7 @@ index 31a22fa48c001a07d1b848c107d22c7d1342c2a6..598a94a2cb71897c4ace95dbecfb8cd9
return EnsureNotNull(shader->Source());
}
@@ -3868,6 +3883,7 @@ base::Optional<Vector<String>>
WebGLRenderingContextBase::getSupportedExtensions() {
if (isContextLost())
return base::nullopt;
+ BRAVE_WEBGL_RENDERING_CONTEXT_BASE_NULLOPT
Vector<String> result;
@@ -3890,6 +3906,7 @@ ScriptValue WebGLRenderingContextBase::getTexParameter(
@@ -3890,6 +3905,7 @@ ScriptValue WebGLRenderingContextBase::getTexParameter(
GLenum pname) {
if (isContextLost())
return ScriptValue::CreateNull(script_state->GetIsolate());
@@ -138,7 +130,7 @@ index 31a22fa48c001a07d1b848c107d22c7d1342c2a6..598a94a2cb71897c4ace95dbecfb8cd9
if (!ValidateTextureBinding("getTexParameter", target))
return ScriptValue::CreateNull(script_state->GetIsolate());
switch (pname) {
@@ -3924,6 +3941,7 @@ ScriptValue WebGLRenderingContextBase::getUniform(
@@ -3924,6 +3940,7 @@ ScriptValue WebGLRenderingContextBase::getUniform(
const WebGLUniformLocation* uniform_location) {
if (!ValidateWebGLProgramOrShader("getUniform", program))
return ScriptValue::CreateNull(script_state->GetIsolate());
@@ -146,7 +138,7 @@ index 31a22fa48c001a07d1b848c107d22c7d1342c2a6..598a94a2cb71897c4ace95dbecfb8cd9
DCHECK(uniform_location);
if (uniform_location->Program() != program) {
SynthesizeGLError(GL_INVALID_OPERATION, "getUniform",
@@ -4183,6 +4201,7 @@ WebGLUniformLocation* WebGLRenderingContextBase::getUniformLocation(
@@ -4183,6 +4200,7 @@ WebGLUniformLocation* WebGLRenderingContextBase::getUniformLocation(
const String& name) {
if (!ValidateWebGLProgramOrShader("getUniformLocation", program))
return nullptr;
@@ -154,7 +146,7 @@ index 31a22fa48c001a07d1b848c107d22c7d1342c2a6..598a94a2cb71897c4ace95dbecfb8cd9
if (!ValidateLocationLength("getUniformLocation", name))
return nullptr;
if (!ValidateString("getUniformLocation", name))
@@ -4207,6 +4226,7 @@ ScriptValue WebGLRenderingContextBase::getVertexAttrib(
@@ -4207,6 +4225,7 @@ ScriptValue WebGLRenderingContextBase::getVertexAttrib(
GLenum pname) {
if (isContextLost())
return ScriptValue::CreateNull(script_state->GetIsolate());
@@ -162,7 +154,7 @@ index 31a22fa48c001a07d1b848c107d22c7d1342c2a6..598a94a2cb71897c4ace95dbecfb8cd9
if (index >= max_vertex_attribs_) {
SynthesizeGLError(GL_INVALID_VALUE, "getVertexAttrib",
"index out of range");
@@ -4284,6 +4304,7 @@ int64_t WebGLRenderingContextBase::getVertexAttribOffset(GLuint index,
@@ -4284,6 +4303,7 @@ int64_t WebGLRenderingContextBase::getVertexAttribOffset(GLuint index,
GLenum pname) {
if (isContextLost())
return 0;
@@ -170,7 +162,7 @@ index 31a22fa48c001a07d1b848c107d22c7d1342c2a6..598a94a2cb71897c4ace95dbecfb8cd9
GLvoid* result = nullptr;
// NOTE: If pname is ever a value that returns more than 1 element
// this will corrupt memory.
@@ -4631,6 +4652,7 @@ void WebGLRenderingContextBase::ReadPixelsHelper(GLint x,
@@ -4631,6 +4651,7 @@ void WebGLRenderingContextBase::ReadPixelsHelper(GLint x,
int64_t offset) {
if (isContextLost())
return;
+21
View File
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<title>WebGL getExtension() test</title>
<meta charset="utf-8">
</head>
<body>
<canvas id="test" width="8" height="8"></canvas>
<script>
var canvas = document.getElementById("test");
var gl = canvas.getContext("webgl");
var ext_list = [];
for (const [i, name] of Object.entries(gl.getSupportedExtensions())) {
ext_list = ext_list.concat(gl.getExtension(name) ? name : null);
}
document.title = ext_list.join("");
</script>
</body>
</html>
}
@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>WebGL getSupportedExtensions() test</title>
<meta charset="utf-8">
</head>
<body>
<canvas id="test" width="8" height="8"></canvas>
<script>
var canvas = document.getElementById("test");
var gl = canvas.getContext("webgl");
var ext_list = gl.getSupportedExtensions();
document.title = ext_list.join(",");
</script>
</body>
</html>