Skip to content

Commit

Permalink
Merge pull request #8831 from brave/mpilgrim_webgl_extensions
Browse files Browse the repository at this point in the history
Implement new WebGL extensions blocking logic
  • Loading branch information
pilgrim-brave authored May 25, 2021
2 parents cc872e6 + 337c93f commit daa84af
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 31 deletions.
77 changes: 61 additions & 16 deletions browser/farbling/brave_webgl_farbling_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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 change: 1 addition & 0 deletions chromium_src/third_party/blink/renderer/DEPS
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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_
Original file line number Diff line number Diff line change
@@ -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(
Expand Down Expand Up @@ -122,55 +122,47 @@ 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());
+ BRAVE_WEBGL_RENDERING_CONTEXT_BASE_SCRIPT_VALUE
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());
+ BRAVE_WEBGL_RENDERING_CONTEXT_BASE_SCRIPT_VALUE
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;
+ BRAVE_WEBGL_RENDERING_CONTEXT_BASE_NULLPTR
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());
+ BRAVE_WEBGL_RENDERING_CONTEXT_BASE_SCRIPT_VALUE
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;
+ BRAVE_WEBGL_RENDERING_CONTEXT_BASE_ZERO
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;
Expand Down
21 changes: 21 additions & 0 deletions test/data/webgl/getExtension.html
Original file line number Diff line number Diff line change
@@ -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>

}
16 changes: 16 additions & 0 deletions test/data/webgl/getSupportedExtensions.html
Original file line number Diff line number Diff line change
@@ -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>

0 comments on commit daa84af

Please sign in to comment.