Multiple fingerprinting mitigations: Apply canvas fingerprinting noise to tiny readbacks

Canvas readbacks smaller than 8x8 can still expose deterministic rendering
differences. Apply the canvas fingerprinting mitigation to those surfaces as
well, while bounding pixel selection to the SkPixmap dimensions to avoid
out-of-range coordinates.
This commit is contained in:
Carmelo Messina
2026-07-10 13:37:37 +02:00
parent 4751fc6afc
commit 7a53b69f4b
@@ -32,21 +32,21 @@ License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
.../blink/renderer/core/dom/document.cc | 19 +++
.../blink/renderer/core/dom/document.h | 7 +
.../html/canvas/canvas_async_blob_creator.cc | 4 +
.../renderer/core/html/canvas/text_metrics.cc | 18 ++
.../renderer/core/html/canvas/text_metrics.cc | 18 +++
.../renderer/core/html/canvas/text_metrics.h | 2 +
.../core/svg/svg_text_content_element.cc | 28 +++-
.../canvas2d/base_rendering_context_2d.cc | 24 ++-
.../canvas2d/base_rendering_context_2d.cc | 24 +++-
third_party/blink/renderer/platform/BUILD.gn | 5 +-
.../platform/exported/web_runtime_features.cc | 8 +
.../platform/graphics/image_data_buffer.cc | 8 +
.../platform/graphics/static_bitmap_image.cc | 154 ++++++++++++++++++
.../platform/exported/web_runtime_features.cc | 8 ++
.../platform/graphics/image_data_buffer.cc | 8 ++
.../platform/graphics/static_bitmap_image.cc | 134 ++++++++++++++++++
.../platform/graphics/static_bitmap_image.h | 2 +
.../platform/runtime_enabled_features.json5 | 6 +
third_party/skia/include/core/SkPixmap.h | 16 +-
third_party/skia/include/core/SkPixmap.h | 16 +--
third_party/ungoogled/BUILD.gn | 10 ++
third_party/ungoogled/ungoogled_switches.cc | 15 ++
third_party/ungoogled/ungoogled_switches.h | 17 ++
25 files changed, 355 insertions(+), 16 deletions(-)
third_party/ungoogled/ungoogled_switches.h | 17 +++
25 files changed, 335 insertions(+), 16 deletions(-)
create mode 100755 cromite_flags/chrome/browser/about_flags_cc/Multiple-fingerprinting-mitigations.inc
create mode 100644 third_party/ungoogled/BUILD.gn
create mode 100644 third_party/ungoogled/ungoogled_switches.cc
@@ -512,7 +512,7 @@ diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
namespace blink {
scoped_refptr<StaticBitmapImage> StaticBitmapImage::Create(
@@ -114,4 +119,153 @@ void StaticBitmapImage::DrawHelper(cc::PaintCanvas* canvas,
@@ -114,4 +119,133 @@ void StaticBitmapImage::DrawHelper(cc::PaintCanvas* canvas,
ToSkiaRectConstraint(draw_options.clamping_mode));
}
@@ -524,20 +524,16 @@ diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
+ const SkImageInfo& info = src_data.info();
+ auto w = info.width() - srcX, h = info.height() - srcY;
+
+ // skip tiny images; info.width()/height() can also be 0
+ if ((w < 8) || (h < 8)) {
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ // generate the first random number here
+ double shuffleX = base::RandDouble();
+
+ // cap maximum pixels to change
+ auto pixels = (w + h) / 8;
+ if (pixels > 100) {
+ pixels = 100;
+ } else if (pixels < 2) {
+ pixels = 2;
+ } else if (pixels < 1) {
+ pixels = 1;
+ }
+
+ auto colorType = info.colorType();
@@ -545,13 +541,9 @@ diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
+
+ DLOG(INFO) << "BRM: ShuffleSubchannelColorData() w=" << w << " h=" << h << " colorType=" << colorType << " fRowBytes=" << fRowBytes;
+
+ // second random number (for y/height)
+ double shuffleY = base::RandDouble();
+
+ // calculate random coordinates using bisection
+ auto currentW = w, currentH = h;
+ for(;pixels >= 0; pixels--) {
+ int x = currentW * shuffleX, y = currentH * shuffleY;
+ for (; pixels > 0; pixels--) {
+ int x = base::RandInt(0, w - 1);
+ int y = base::RandInt(0, h - 1);
+
+ // calculate randomisation amounts for each RGB component
+ uint8_t shuffleR = base::RandInt(0, 4);
@@ -648,18 +640,6 @@ diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image.cc
+ LOG(WARNING) << "BRM: ShuffleSubchannelColorData(): Ignoring pixel format";
+ return;
+ }
+
+ // keep bisecting or reset current width/height as needed
+ if (x == 0) {
+ currentW = w;
+ } else {
+ currentW = x;
+ }
+ if (y == 0) {
+ currentH = h;
+ } else {
+ currentH = y;
+ }
+ }
+}
+