From 7d31c860a7e7239428587323308861df6a1ba3ea Mon Sep 17 00:00:00 2001 From: Rootkit404 <175176948+RKNF404@users.noreply.github.com> Date: Thu, 29 Aug 2024 15:41:33 -0400 Subject: [PATCH 1/4] Add newest Vanadium patches --- ...lementation-with-Cross-Partitioned-B.patch | 342 ++++++++++++++++++ ...cross-partition-blob-url-fetching-by.patch | 22 ++ ...-Support-restriction-of-dynamic-code.patch | 150 ++++++++ ...ynamic-code-execution-via-seccomp-bp.patch | 320 ++++++++++++++++ 4 files changed, 834 insertions(+) create mode 100644 vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch create mode 100644 vanadium_patches/0191-Enable-blocking-cross-partition-blob-url-fetching-by.patch create mode 100644 vanadium_patches/0192-Support-restriction-of-dynamic-code.patch create mode 100644 vanadium_patches/0193-Restriction-of-dynamic-code-execution-via-seccomp-bp.patch diff --git a/vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch b/vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch new file mode 100644 index 00000000..77ce044e --- /dev/null +++ b/vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch @@ -0,0 +1,342 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Janice Liu +Date: Wed, 21 Aug 2024 18:39:10 +0000 +Subject: [PATCH] Add Fetching Implementation with Cross-Partitioned Blob URL + +Bug: 357484649 +Change-Id: I074b15fd78114185f1d7bfddc2647e2dd76bbed7 +Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5762280 +Commit-Queue: Janice Liu +Reviewed-by: Ayu Ishii +Auto-Submit: Janice Liu +Reviewed-by: David Baron +Cr-Commit-Position: refs/heads/main@{#1344948} +--- + storage/browser/BUILD.gn | 2 + + storage/browser/blob/blob_url_store_impl.cc | 13 ++ + .../blob/blob_url_store_impl_unittest.cc | 160 ++++++++++++++++-- + storage/browser/blob/features.cc | 16 ++ + storage/browser/blob/features.h | 22 +++ + third_party/blink/web_tests/VirtualTestSuites | 10 ++ + .../README.md | 1 + + ...oss-partition.tentative.https-expected.txt | 3 + + 8 files changed, 211 insertions(+), 16 deletions(-) + create mode 100644 storage/browser/blob/features.cc + create mode 100644 storage/browser/blob/features.h + create mode 100644 third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/README.md + create mode 100644 third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/external/wpt/FileAPI/BlobURL/cross-partition.tentative.https-expected.txt + +diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn +index b52c014f46fcd..fb0c66e45a953 100644 +--- a/storage/browser/BUILD.gn ++++ b/storage/browser/BUILD.gn +@@ -47,6 +47,8 @@ component("browser") { + "blob/blob_url_store_impl.h", + "blob/blob_url_utils.cc", + "blob/blob_url_utils.h", ++ "blob/features.cc", ++ "blob/features.h", + "blob/mojo_blob_reader.cc", + "blob/mojo_blob_reader.h", + "blob/scoped_file.cc", +diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/blob_url_store_impl.cc +index d9a474d6c2439..bdd06f6230350 100644 +--- a/storage/browser/blob/blob_url_store_impl.cc ++++ b/storage/browser/blob/blob_url_store_impl.cc +@@ -14,6 +14,7 @@ + #include "storage/browser/blob/blob_url_loader_factory.h" + #include "storage/browser/blob/blob_url_registry.h" + #include "storage/browser/blob/blob_url_utils.h" ++#include "storage/browser/blob/features.h" + #include "url/url_util.h" + + namespace storage { +@@ -119,9 +120,21 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory( + std::move(callback).Run(std::nullopt, std::nullopt); + return; + } ++ if (base::FeatureList::IsEnabled( ++ features::kBlockCrossPartitionBlobUrlFetching) && ++ !registry_->IsUrlMapped(BlobUrlUtils::ClearUrlFragment(url), ++ storage_key_)) { ++ BlobURLLoaderFactory::Create(mojo::NullRemote(), url, std::move(receiver)); ++ std::move(callback).Run(std::nullopt, std::nullopt); ++ return; ++ } + + BlobURLLoaderFactory::Create(registry_->GetBlobFromUrl(url), url, + std::move(receiver)); ++ // When a fragment URL is present, registry_->GetUnsafeAgentClusterID(url) and ++ // registry_->GetUnsafeTopLevelSite(url) will return nullopt because their ++ // implementations don't remove the fragment and only support fragmentless ++ // URLs (crbug.com/40775506). + std::move(callback).Run(registry_->GetUnsafeAgentClusterID(url), + registry_->GetUnsafeTopLevelSite(url)); + } +diff --git a/storage/browser/blob/blob_url_store_impl_unittest.cc b/storage/browser/blob/blob_url_store_impl_unittest.cc +index bd3d6ed6fe3bb..e398d6bae304e 100644 +--- a/storage/browser/blob/blob_url_store_impl_unittest.cc ++++ b/storage/browser/blob/blob_url_store_impl_unittest.cc +@@ -21,6 +21,7 @@ + #include "storage/browser/blob/blob_impl.h" + #include "storage/browser/blob/blob_storage_context.h" + #include "storage/browser/blob/blob_url_registry.h" ++#include "storage/browser/blob/features.h" + #include "testing/gtest/include/gtest/gtest.h" + + using blink::mojom::BlobURLStore; +@@ -30,10 +31,9 @@ namespace storage { + namespace { + + enum class PartitionedBlobUrlTestCase { +- kPartitioningDisabledWithSupportDisabled, +- kPartitioningDisabledWithSupportEnabled, +- kPartitioningEnabledWithSupportDisabled, +- kPartitioningEnabledWithSupportEnabled, ++ kPartitioningDisabled, ++ kBlockCrossPartitionBlobUrlFetchingEnabled, ++ kBlockCrossPartitionBlobUrlFetchingDisabled, + }; + + class BlobURLStoreImplTestP +@@ -51,14 +51,17 @@ class BlobURLStoreImplTestP + &BlobURLStoreImplTestP::OnBadMessage, base::Unretained(this))); + } + +- void TearDown() override { +- mojo::SetDefaultProcessErrorHandler(base::NullCallback()); +- } +- + void InitializeScopedFeatureList() { + std::vector enabled_features{}; + std::vector disabled_features{}; + ++ if (BlockCrossPartitionBlobUrlFetchingEnabled()) { ++ enabled_features.push_back(features::kBlockCrossPartitionBlobUrlFetching); ++ } else { ++ disabled_features.push_back( ++ features::kBlockCrossPartitionBlobUrlFetching); ++ } ++ + if (StoragePartitioningEnabled()) { + enabled_features.push_back(net::features::kThirdPartyStoragePartitioning); + } else { +@@ -69,16 +72,26 @@ class BlobURLStoreImplTestP + scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); + } + +- bool StoragePartitioningEnabled() { ++ bool BlockCrossPartitionBlobUrlFetchingEnabled() { + switch (test_case_) { +- case PartitionedBlobUrlTestCase::kPartitioningEnabledWithSupportDisabled: +- case PartitionedBlobUrlTestCase::kPartitioningEnabledWithSupportEnabled: ++ case PartitionedBlobUrlTestCase:: ++ kBlockCrossPartitionBlobUrlFetchingDisabled: ++ case PartitionedBlobUrlTestCase:: ++ kBlockCrossPartitionBlobUrlFetchingEnabled: + return true; + default: + return false; + } + } + ++ bool StoragePartitioningEnabled() { ++ return test_case_ != PartitionedBlobUrlTestCase::kPartitioningDisabled; ++ } ++ ++ void TearDown() override { ++ mojo::SetDefaultProcessErrorHandler(base::NullCallback()); ++ } ++ + void OnBadMessage(const std::string& error) { + bad_messages_.push_back(error); + } +@@ -377,6 +390,110 @@ TEST_P(BlobURLStoreImplTestP, ResolveAsURLLoaderFactory) { + download_loop.Run(); + } + ++TEST_P(BlobURLStoreImplTestP, ++ ResolveAsURLLoaderFactoryWithSeparateStorageKeys) { ++ const blink::StorageKey kWrongStorageKey = blink::StorageKey::Create( ++ kOrigin, kWrongTopLevelSite, blink::mojom::AncestorChainBit::kCrossSite); ++ ++ mojo::PendingRemote blob = ++ CreateBlobFromString(kId, "hello world"); ++ ++ BlobURLStoreImpl url_store1(kStorageKey, kStorageKey.origin(), /*rph_id=*/0, ++ url_registry_.AsWeakPtr()); ++ BlobURLStoreImpl url_store2(kWrongStorageKey, kStorageKey.origin(), ++ /*rph_id=*/0, url_registry_.AsWeakPtr()); ++ ++ RegisterURL(&url_store1, std::move(blob), kValidUrl); ++ ++ mojo::Remote factory; ++ base::RunLoop resolve_loop; ++ url_store2.ResolveAsURLLoaderFactory( ++ kValidUrl, factory.BindNewPipeAndPassReceiver(), ++ base::BindLambdaForTesting( ++ [&](const std::optional& ++ unsafe_agent_cluster_id, ++ const std::optional& unsafe_top_level_site) { ++ if (BlockCrossPartitionBlobUrlFetchingEnabled()) { ++ EXPECT_FALSE(unsafe_agent_cluster_id.has_value()); ++ EXPECT_FALSE(unsafe_top_level_site.has_value()); ++ } else { ++ EXPECT_EQ(*unsafe_agent_cluster_id, agent_cluster_id_); ++ } ++ resolve_loop.Quit(); ++ })); ++ ++ resolve_loop.Run(); ++ auto request = std::make_unique(); ++ request->url = kValidUrl; ++ auto loader = network::SimpleURLLoader::Create(std::move(request), ++ TRAFFIC_ANNOTATION_FOR_TESTS); ++ base::RunLoop download_loop; ++ loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( ++ factory.get(), base::BindLambdaForTesting( ++ [&](std::unique_ptr response_body) { ++ download_loop.Quit(); ++ if (BlockCrossPartitionBlobUrlFetchingEnabled()) { ++ EXPECT_FALSE(response_body); ++ } else { ++ ASSERT_TRUE(response_body); ++ EXPECT_EQ("hello world", *response_body); ++ } ++ })); ++ download_loop.Run(); ++} ++ ++TEST_P(BlobURLStoreImplTestP, ResolveAsURLLoaderFactoryWithFragmentUrl) { ++ const blink::StorageKey kWrongStorageKey = blink::StorageKey::Create( ++ kOrigin, kWrongTopLevelSite, blink::mojom::AncestorChainBit::kCrossSite); ++ ++ mojo::PendingRemote blob = ++ CreateBlobFromString(kId, "hello world"); ++ ++ BlobURLStoreImpl url_store1(kWrongStorageKey, kStorageKey.origin(), ++ /*rph_id=*/0, url_registry_.AsWeakPtr()); ++ mojo::Remote url_store2(CreateURLStore()); ++ RegisterURL(url_store2.get(), std::move(blob), kFragmentUrl); ++ ++ mojo::Remote factory; ++ base::RunLoop resolve_loop; ++ url_store1.ResolveAsURLLoaderFactory( ++ kFragmentUrl, factory.BindNewPipeAndPassReceiver(), ++ base::BindLambdaForTesting( ++ [&](const std::optional& ++ unsafe_agent_cluster_id, ++ const std::optional& unsafe_top_level_site) { ++ // TODO(crbug.com/40775506): Fix fragment URL bug. ++ if (BlockCrossPartitionBlobUrlFetchingEnabled() || ++ !StoragePartitioningEnabled()) { ++ EXPECT_FALSE(unsafe_agent_cluster_id.has_value()); ++ EXPECT_FALSE(unsafe_top_level_site.has_value()); ++ } else { ++ EXPECT_EQ(*unsafe_agent_cluster_id, agent_cluster_id_); ++ } ++ resolve_loop.Quit(); ++ })); ++ ++ resolve_loop.Run(); ++ auto request = std::make_unique(); ++ request->url = kFragmentUrl; ++ auto loader = network::SimpleURLLoader::Create(std::move(request), ++ TRAFFIC_ANNOTATION_FOR_TESTS); ++ base::RunLoop download_loop; ++ loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( ++ factory.get(), base::BindLambdaForTesting( ++ [&](std::unique_ptr response_body) { ++ download_loop.Quit(); ++ if (BlockCrossPartitionBlobUrlFetchingEnabled() || ++ !StoragePartitioningEnabled()) { ++ EXPECT_FALSE(response_body); ++ } else { ++ ASSERT_TRUE(response_body); ++ EXPECT_EQ("hello world", *response_body); ++ } ++ })); ++ download_loop.Run(); ++} ++ + TEST_P(BlobURLStoreImplTestP, ResolveForNavigation) { + mojo::PendingRemote blob = + CreateBlobFromString(kId, "hello world"); +@@ -418,11 +535,22 @@ TEST_P(BlobURLStoreImplTestP, ResolveForNavigation) { + INSTANTIATE_TEST_SUITE_P( + BlobURLStoreImplTests, + BlobURLStoreImplTestP, +- ::testing::Values( +- PartitionedBlobUrlTestCase::kPartitioningDisabledWithSupportDisabled, +- PartitionedBlobUrlTestCase::kPartitioningDisabledWithSupportEnabled, +- PartitionedBlobUrlTestCase::kPartitioningEnabledWithSupportDisabled, +- PartitionedBlobUrlTestCase::kPartitioningEnabledWithSupportEnabled)); ++ testing::Values( ++ PartitionedBlobUrlTestCase::kPartitioningDisabled, ++ PartitionedBlobUrlTestCase::kBlockCrossPartitionBlobUrlFetchingDisabled, ++ PartitionedBlobUrlTestCase::kBlockCrossPartitionBlobUrlFetchingEnabled), ++ [](const testing::TestParamInfo& info) { ++ switch (info.param) { ++ case PartitionedBlobUrlTestCase::kPartitioningDisabled: ++ return "PartitioningDisabled"; ++ case PartitionedBlobUrlTestCase:: ++ kBlockCrossPartitionBlobUrlFetchingDisabled: ++ return "BlockCrossPartitionBlobUrlFetchingDisabled"; ++ case PartitionedBlobUrlTestCase:: ++ kBlockCrossPartitionBlobUrlFetchingEnabled: ++ return "BlockCrossPartitionBlobUrlFetchingEnabled"; ++ } ++ }); + + } // namespace + } // namespace storage +diff --git a/storage/browser/blob/features.cc b/storage/browser/blob/features.cc +new file mode 100644 +index 0000000000000..17003b52f595c +--- /dev/null ++++ b/storage/browser/blob/features.cc +@@ -0,0 +1,16 @@ ++// Copyright 2024 The Chromium Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#include "storage/browser/blob/features.h" ++ ++namespace features { ++ ++// Please keep features in alphabetical order. ++BASE_FEATURE(kBlockCrossPartitionBlobUrlFetching, ++ "BlockCrossPartitionBlobUrlFetching", ++ base::FEATURE_DISABLED_BY_DEFAULT); ++ ++// Please keep features in alphabetical order. ++ ++} // namespace features +diff --git a/storage/browser/blob/features.h b/storage/browser/blob/features.h +new file mode 100644 +index 0000000000000..901ba07756b16 +--- /dev/null ++++ b/storage/browser/blob/features.h +@@ -0,0 +1,22 @@ ++// Copyright 2024 The Chromium Authors ++// Use of this source code is governed by a BSD-style license that can be ++// found in the LICENSE file. ++ ++#ifndef STORAGE_BROWSER_BLOB_FEATURES_H_ ++#define STORAGE_BROWSER_BLOB_FEATURES_H_ ++ ++#include "base/component_export.h" ++#include "base/features.h" ++ ++namespace features { ++ ++// Please keep features in alphabetical order. ++// Enables blob URL fetches to fail when cross-partition. ++COMPONENT_EXPORT(STORAGE_BROWSER) ++BASE_DECLARE_FEATURE(kBlockCrossPartitionBlobUrlFetching); ++ ++// Please keep features in alphabetical order. ++ ++} // namespace features ++ ++#endif // STORAGE_BROWSER_BLOB_FEATURES_H_ diff --git a/vanadium_patches/0191-Enable-blocking-cross-partition-blob-url-fetching-by.patch b/vanadium_patches/0191-Enable-blocking-cross-partition-blob-url-fetching-by.patch new file mode 100644 index 00000000..33118164 --- /dev/null +++ b/vanadium_patches/0191-Enable-blocking-cross-partition-blob-url-fetching-by.patch @@ -0,0 +1,22 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: fgei +Date: Thu, 22 Aug 2024 14:05:52 +0000 +Subject: [PATCH] Enable blocking cross partition blob url fetching by default + +--- + storage/browser/blob/features.cc | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/storage/browser/blob/features.cc b/storage/browser/blob/features.cc +index 17003b52f595c..627acffc08bbc 100644 +--- a/storage/browser/blob/features.cc ++++ b/storage/browser/blob/features.cc +@@ -9,7 +9,7 @@ namespace features { + // Please keep features in alphabetical order. + BASE_FEATURE(kBlockCrossPartitionBlobUrlFetching, + "BlockCrossPartitionBlobUrlFetching", +- base::FEATURE_DISABLED_BY_DEFAULT); ++ base::FEATURE_ENABLED_BY_DEFAULT); + + // Please keep features in alphabetical order. + diff --git a/vanadium_patches/0192-Support-restriction-of-dynamic-code.patch b/vanadium_patches/0192-Support-restriction-of-dynamic-code.patch new file mode 100644 index 00000000..b90eb4e1 --- /dev/null +++ b/vanadium_patches/0192-Support-restriction-of-dynamic-code.patch @@ -0,0 +1,150 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: qua3k +Date: Thu, 4 Nov 2021 00:00:00 +0000 +Subject: [PATCH] Support restriction of dynamic code + +This patchset is ported from Hexavalent Browser, authored by qua3k, +intended to restrict dynamic code generation on Android. + +Original description from Hexavalent: + +This commit has three parts, utilizing seccomp-bpf to prevent: + +1. the creation of executable anonymous mappings +2. the creation of writable and executable file mappings +3. making a non-executable mapping executable + +It's inspired by PaX MPROTECT restrictions. +--- + .../syscall_parameters_restrictions.cc | 55 +++++++++++++++++++ + .../syscall_parameters_restrictions.h | 18 ++++++ + 2 files changed, 73 insertions(+) + +diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc +index bb0e13f4d2d9c..318eb4d55f3b2 100644 +--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc ++++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.cc +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -244,6 +245,31 @@ ResultExpr RestrictMmapFlags() { + return If((flags & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS()); + } + ++ResultExpr RestrictMmapFlagsNoWX() { ++ // The flags you see are actually the allowed ones, and the variable is a ++ // "denied" mask because of the negation operator. ++ // Significantly, we don't permit MAP_HUGETLB, or the newer flags such as ++ // MAP_POPULATE. ++ // TODO(davidung), remove MAP_DENYWRITE with updated Tegra libraries. ++ ++ const Arg prot(2); ++ const Arg flags(3); ++ ++ const BoolExpr is_mapping_w_x = (prot & (PROT_WRITE | PROT_EXEC)) != (PROT_WRITE | PROT_EXEC); ++ ++ const BoolExpr is_anon_mapping_nx = ++ AllOf((prot & PROT_EXEC) == 0, ++ (flags & MAP_ANONYMOUS) == MAP_ANONYMOUS); ++ ++ const uint64_t kAllowedMask = MAP_SHARED | MAP_PRIVATE | MAP_STACK | ++ MAP_NORESERVE | MAP_FIXED | MAP_DENYWRITE | ++ MAP_LOCKED; ++ ++ return If(is_anon_mapping_nx, Allow()) ++ .ElseIf(AllOf(is_mapping_w_x, (flags & ~kAllowedMask) == 0), Allow()) ++ .Else(CrashSIGSYS()); ++} ++ + ResultExpr RestrictMprotectFlags() { + // The flags you see are actually the allowed ones, and the variable is a + // "denied" mask because of the negation operator. +@@ -262,6 +288,24 @@ ResultExpr RestrictMprotectFlags() { + return If((prot & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS()); + } + ++ResultExpr RestrictMprotectFlagsNoWX() { ++ // The flags you see are actually the allowed ones, and the variable is a ++ // "denied" mask because of the negation operator. ++ // Significantly, we don't permit making non-executable pages executable, ++ // as well as weird undocumented flags such as PROT_GROWSDOWN. ++#if defined(ARCH_CPU_ARM64) ++ // Allows PROT_MTE and PROT_BTI (as explained higher up) on only Arm ++ // platforms. ++ const uint64_t kArchSpecificFlags = PROT_MTE | PROT_BTI; ++#else ++ const uint64_t kArchSpecificFlags = 0; ++#endif ++ const uint64_t kAllowedMask = ++ PROT_READ | PROT_WRITE | kArchSpecificFlags; ++ const Arg prot(2); ++ return If((prot & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS()); ++} ++ + ResultExpr RestrictFcntlCommands() { + // We also restrict the flags in F_SETFL. We don't want to permit flags with + // a history of trouble such as O_DIRECT. The flags you see are actually the +@@ -304,6 +348,17 @@ ResultExpr RestrictFcntlCommands() { + // clang-format on + } + ++ResultExpr RestrictShmatFlags() { ++ // The flags you see are actually the allowed ones, and the variable is a ++ // "denied" mask because of the negation operator. ++ // Significantly, we don't permit flags that allow for dynamic code ++ // generation such as SHM_EXEC. ++ const uint64_t kAllowedMask = ++ 0 | SHM_RND | SHM_RDONLY | SHM_REMAP; ++ const Arg shmflg(2); ++ return If((shmflg & ~kAllowedMask) == 0, Allow()).Else(CrashSIGSYS()); ++} ++ + #if defined(__i386__) || defined(__mips__) + ResultExpr RestrictSocketcallCommand() { + // Unfortunately, we are unable to restrict the first parameter to +diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h +index 171191ec518b5..4ea27bff6d563 100644 +--- a/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h ++++ b/sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h +@@ -40,11 +40,25 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictIoctl(); + // Crash if any other flag is used. + SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictMmapFlags(); + ++// Restrict mmap(2) arguments to: ++// Allow: MAP_SHARED | MAP_PRIVATE | MAP_ANONYMOUS | ++// MAP_STACK | MAP_NORESERVE | MAP_FIXED | MAP_DENYWRITE. ++// Crash if any other flag is used. ++// Also, in prots, restrict the allowed protections to: ++// PROT_READ | PROT_WRITE ^ PROT_EXEC. ++// PROT_BTI | PROT_MTE is additionally allowed on 64-bit Arm. ++SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictMmapFlagsNoWX(); ++ + // Restrict the prot argument in mprotect(2). + // Only allow: PROT_READ | PROT_WRITE | PROT_EXEC. + // PROT_BTI | PROT_MTE is additionally allowed on 64-bit Arm. + SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictMprotectFlags(); + ++// Restrict the prot argument in mprotect(2). ++// Only allow: PROT_READ | PROT_WRITE. ++// PROT_BTI | PROT_MTE is additionally allowed on 64-bit Arm. ++SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictMprotectFlagsNoWX(); ++ + // Restrict fcntl(2) cmd argument to: + // We allow F_GETFL, F_SETFL, F_GETFD, F_SETFD, F_DUPFD, F_DUPFD_CLOEXEC, + // F_SETLK, F_SETLKW and F_GETLK. +@@ -52,6 +66,10 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictMprotectFlags(); + // O_NONBLOCK | O_SYNC | O_LARGEFILE | O_CLOEXEC | O_NOATIME. + SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictFcntlCommands(); + ++// Restrict the shmflg argument in shmat(2). ++// Only allow: SHM_RND | SHM_RDONLY | SHM_REMAP. ++SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictShmatFlags(); ++ + #if defined(__i386__) || defined(__mips__) + // Restrict socketcall(2) to only allow socketpair(2), send(2), recv(2), + // sendto(2), recvfrom(2), shutdown(2), sendmsg(2) and recvmsg(2). diff --git a/vanadium_patches/0193-Restriction-of-dynamic-code-execution-via-seccomp-bp.patch b/vanadium_patches/0193-Restriction-of-dynamic-code-execution-via-seccomp-bp.patch new file mode 100644 index 00000000..c3798a11 --- /dev/null +++ b/vanadium_patches/0193-Restriction-of-dynamic-code-execution-via-seccomp-bp.patch @@ -0,0 +1,320 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: qua3k +Date: Thu, 4 Nov 2021 00:00:00 +0000 +Subject: [PATCH] Restriction of dynamic code execution via seccomp-bpf + +This patchset is ported from Hexavalent Browser, authored by qua3k, +intended to restrict dynamic code generation on Android. + +Original description from Hexavalent: + +Forbid dynamic code generation on Linux + +The Windows sandbox prevents dynamic code generation via setting +MITIGATION_DYNAMIC_CODE_DISABLE on certain processes; prevent dynamic +code generation in the same processes on Linux via seccomp-bpf. +--- + ...renderer_main_platform_delegate_android.cc | 28 +++++++++-- + .../seccomp-bpf-helpers/baseline_policy.cc | 6 +-- + .../policy/linux/bpf_audio_policy_linux.cc | 3 ++ + .../policy/linux/bpf_renderer_policy_linux.cc | 25 ++++++++-- + .../policy/linux/bpf_renderer_policy_linux.h | 8 ++- + .../policy/linux/bpf_service_policy_linux.cc | 21 ++++++++ + .../policy/linux/bpf_service_policy_linux.h | 5 +- + .../policy/linux/sandbox_seccomp_bpf_linux.cc | 49 +++++++++++++++++-- + 8 files changed, 128 insertions(+), 17 deletions(-) + +diff --git a/content/renderer/renderer_main_platform_delegate_android.cc b/content/renderer/renderer_main_platform_delegate_android.cc +index c7def9142f594..952ad402036cd 100644 +--- a/content/renderer/renderer_main_platform_delegate_android.cc ++++ b/content/renderer/renderer_main_platform_delegate_android.cc +@@ -17,6 +17,10 @@ + #include "sandbox/policy/linux/bpf_renderer_policy_linux.h" + #include "sandbox/policy/mojom/sandbox.mojom.h" + #include "sandbox/policy/sandbox_type.h" ++ ++#include "base/command_line.h" ++#include "base/strings/string_split.h" ++#include "third_party/blink/public/common/switches.h" + #endif + + namespace content { +@@ -52,10 +56,28 @@ bool RendererMainPlatformDelegate::EnableSandbox() { + if (sandbox::policy::SandboxTypeFromCommandLine( + *base::CommandLine::ForCurrentProcess()) == + sandbox::mojom::Sandbox::kRenderer && +- base::FeatureList::IsEnabled( +- sandbox::policy::features::kUseRendererProcessPolicy)) { ++ base::FeatureList::IsEnabled( ++ sandbox::policy::features::kUseRendererProcessPolicy)) { ++ const base::CommandLine& command_line = ++ *base::CommandLine::ForCurrentProcess(); ++ bool dynamic_code_can_be_disabled = false; ++ if (command_line.HasSwitch(blink::switches::kJavaScriptFlags)) { ++ std::string js_flags = ++ command_line.GetSwitchValueASCII(blink::switches::kJavaScriptFlags); ++ std::vector js_flag_list = base::SplitStringPiece( ++ js_flags, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); ++ for (const auto& js_flag : js_flag_list) { ++ if (js_flag == "--jitless") { ++ // If v8 is running jitless then there is no need for the ability to ++ // mark writable pages as executable to be available to the process. ++ dynamic_code_can_be_disabled = true; ++ break; ++ } ++ } ++ } + starter.set_policy( +- std::make_unique(options)); ++ std::make_unique(options, ++ dynamic_code_can_be_disabled)); + } else { + starter.set_policy( + std::make_unique(options)); +diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc +index 7bde501115bdf..0f1e4ae0c7b28 100644 +--- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc ++++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc +@@ -257,19 +257,19 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno, + #if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \ + defined(__aarch64__) + if (sysno == __NR_mmap) +- return RestrictMmapFlags(); ++ return RestrictMmapFlagsNoWX(); + #endif + + #if defined(__i386__) || defined(__arm__) || \ + (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) + if (sysno == __NR_mmap2) +- return RestrictMmapFlags(); ++ return RestrictMmapFlagsNoWX(); + #endif + + if (sysno == __NR_mprotect || sysno == __NR_pkey_mprotect) { + // pkey_mprotect is identical to mprotect except for the additional (last) + // parameter, which can be ignored here. +- return RestrictMprotectFlags(); ++ return RestrictMprotectFlagsNoWX(); + } + + if (sysno == __NR_prctl) +diff --git a/sandbox/policy/linux/bpf_audio_policy_linux.cc b/sandbox/policy/linux/bpf_audio_policy_linux.cc +index e1716b97e8f21..dc25d460460d5 100644 +--- a/sandbox/policy/linux/bpf_audio_policy_linux.cc ++++ b/sandbox/policy/linux/bpf_audio_policy_linux.cc +@@ -121,6 +121,9 @@ ResultExpr AudioProcessPolicy::EvaluateSyscall(int system_call_number) const { + #endif + default: + #if defined(__x86_64__) ++ if (system_call_number == __NR_shmat) ++ return RestrictShmatFlags(); ++ + if (SyscallSets::IsSystemVSemaphores(system_call_number) || + SyscallSets::IsSystemVSharedMemory(system_call_number)) { + return Allow(); +diff --git a/sandbox/policy/linux/bpf_renderer_policy_linux.cc b/sandbox/policy/linux/bpf_renderer_policy_linux.cc +index 0555a85bc6a2a..663793ac605a7 100644 +--- a/sandbox/policy/linux/bpf_renderer_policy_linux.cc ++++ b/sandbox/policy/linux/bpf_renderer_policy_linux.cc +@@ -49,15 +49,34 @@ ResultExpr RestrictIoctl() { + + } // namespace + #if !BUILDFLAG(IS_ANDROID) +-RendererProcessPolicy::RendererProcessPolicy() = default; ++RendererProcessPolicy::RendererProcessPolicy(bool is_jit_disabled) ++ : is_jit_disabled_(is_jit_disabled) {} + #else + RendererProcessPolicy::RendererProcessPolicy( +- const BaselinePolicyAndroid::RuntimeOptions& options) +- : BPFBasePolicy(options) {} ++ const BaselinePolicyAndroid::RuntimeOptions& options, ++ bool is_jit_disabled) ++ : BPFBasePolicy(options), is_jit_disabled_(is_jit_disabled) {} + #endif // !BUILDFLAG(IS_ANDROID) + RendererProcessPolicy::~RendererProcessPolicy() = default; + + ResultExpr RendererProcessPolicy::EvaluateSyscall(int sysno) const { ++ if (!is_jit_disabled_) { ++ switch (sysno) { ++#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \ ++ defined(__aarch64__) ++ case __NR_mmap: ++#endif ++#if defined(__i386__) || defined(__arm__) || \ ++ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) ++ case __NR_mmap2: ++#endif ++ return RestrictMmapFlags(); ++ case __NR_mprotect: ++ case __NR_pkey_mprotect: ++ return RestrictMprotectFlags(); ++ } ++ } ++ + switch (sysno) { + // The baseline policy allows __NR_clock_gettime. Allow + // clock_getres() for V8. crbug.com/329053. +diff --git a/sandbox/policy/linux/bpf_renderer_policy_linux.h b/sandbox/policy/linux/bpf_renderer_policy_linux.h +index 41ed0eaac13c7..630a1c04fd369 100644 +--- a/sandbox/policy/linux/bpf_renderer_policy_linux.h ++++ b/sandbox/policy/linux/bpf_renderer_policy_linux.h +@@ -19,10 +19,11 @@ namespace sandbox::policy { + class SANDBOX_POLICY_EXPORT RendererProcessPolicy : public BPFBasePolicy { + public: + #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +- RendererProcessPolicy(); ++ explicit RendererProcessPolicy(bool is_jit_disabled); + #elif BUILDFLAG(IS_ANDROID) + explicit RendererProcessPolicy( +- const BaselinePolicyAndroid::RuntimeOptions& options); ++ const BaselinePolicyAndroid::RuntimeOptions& options, ++ bool is_jit_disabled); + #endif + + RendererProcessPolicy(const RendererProcessPolicy&) = delete; +@@ -31,6 +32,9 @@ class SANDBOX_POLICY_EXPORT RendererProcessPolicy : public BPFBasePolicy { + ~RendererProcessPolicy() override; + + bpf_dsl::ResultExpr EvaluateSyscall(int system_call_number) const override; ++ ++ private: ++ const bool is_jit_disabled_; // Disable dynamic code execution if jitless + }; + + } // namespace sandbox::policy +diff --git a/sandbox/policy/linux/bpf_service_policy_linux.cc b/sandbox/policy/linux/bpf_service_policy_linux.cc +index 32754e67be3d6..aff36f0119ee2 100644 +--- a/sandbox/policy/linux/bpf_service_policy_linux.cc ++++ b/sandbox/policy/linux/bpf_service_policy_linux.cc +@@ -20,7 +20,28 @@ using sandbox::bpf_dsl::ResultExpr; + namespace sandbox { + namespace policy { + ++ServiceProcessPolicy::ServiceProcessPolicy(bool is_jit_disabled) ++ : is_jit_disabled_(is_jit_disabled) {} ++ + ResultExpr ServiceProcessPolicy::EvaluateSyscall(int sysno) const { ++ ++ if (!is_jit_disabled_) { ++ switch (sysno) { ++#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \ ++ defined(__aarch64__) ++ case __NR_mmap: ++#endif ++#if defined(__i386__) || defined(__arm__) || \ ++ (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) ++ case __NR_mmap2: ++#endif ++ return RestrictMmapFlags(); ++ case __NR_mprotect: ++ case __NR_pkey_mprotect: ++ return RestrictMprotectFlags(); ++ } ++ } ++ + switch (sysno) { + case __NR_ioctl: + return RestrictIoctl(); +diff --git a/sandbox/policy/linux/bpf_service_policy_linux.h b/sandbox/policy/linux/bpf_service_policy_linux.h +index 0f33163d6a87f..48626cb8111fa 100644 +--- a/sandbox/policy/linux/bpf_service_policy_linux.h ++++ b/sandbox/policy/linux/bpf_service_policy_linux.h +@@ -16,13 +16,16 @@ namespace policy { + // Consider UtilityProcessPolicy if this is too restrictive. + class ServiceProcessPolicy : public BPFBasePolicy { + public: +- ServiceProcessPolicy() = default; ++ explicit ServiceProcessPolicy(bool is_jit_disabled); + ~ServiceProcessPolicy() override = default; + + bpf_dsl::ResultExpr EvaluateSyscall(int system_call_number) const override; + + ServiceProcessPolicy(const ServiceProcessPolicy&) = delete; + ServiceProcessPolicy& operator=(const ServiceProcessPolicy&) = delete; ++ ++ private: ++ const bool is_jit_disabled_; // Disable dynamic code generation if jitless + }; + + } // namespace policy +diff --git a/sandbox/policy/linux/sandbox_seccomp_bpf_linux.cc b/sandbox/policy/linux/sandbox_seccomp_bpf_linux.cc +index 4c2bfa444d714..7bdb1d4b1d661 100644 +--- a/sandbox/policy/linux/sandbox_seccomp_bpf_linux.cc ++++ b/sandbox/policy/linux/sandbox_seccomp_bpf_linux.cc +@@ -17,6 +17,8 @@ + #include "base/command_line.h" + #include "base/feature_list.h" + #include "base/notreached.h" ++#include "base/strings/string_split.h" ++#include "gin/gin_features.h" + #include "build/build_config.h" + #include "build/chromeos_buildflags.h" + #include "ppapi/buildflags/buildflags.h" +@@ -54,6 +56,7 @@ + #include "sandbox/policy/linux/bpf_service_policy_linux.h" + #include "sandbox/policy/linux/bpf_speech_recognition_policy_linux.h" + #include "sandbox/policy/linux/bpf_utility_policy_linux.h" ++#include "third_party/blink/public/common/switches.h" + + #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) + #include "sandbox/policy/linux/bpf_screen_ai_policy_linux.h" +@@ -182,8 +185,26 @@ std::unique_ptr SandboxSeccompBPF::PolicyForSandboxType( + switch (sandbox_type) { + case sandbox::mojom::Sandbox::kGpu: + return GetGpuProcessSandbox(options); +- case sandbox::mojom::Sandbox::kRenderer: +- return std::make_unique(); ++ case sandbox::mojom::Sandbox::kRenderer: { ++ const base::CommandLine& command_line = ++ *base::CommandLine::ForCurrentProcess(); ++ bool dynamic_code_can_be_disabled = false; ++ if (command_line.HasSwitch(blink::switches::kJavaScriptFlags)) { ++ std::string js_flags = ++ command_line.GetSwitchValueASCII(blink::switches::kJavaScriptFlags); ++ std::vector js_flag_list = base::SplitStringPiece( ++ js_flags, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); ++ for (const auto& js_flag : js_flag_list) { ++ if (js_flag == "--jitless") { ++ // If v8 is running jitless then there is no need for the ability to ++ // mark writable pages as executable to be available to the process. ++ dynamic_code_can_be_disabled = true; ++ break; ++ } ++ } ++ } ++ return std::make_unique(dynamic_code_can_be_disabled); ++ } + #if BUILDFLAG(ENABLE_PPAPI) + case sandbox::mojom::Sandbox::kPpapi: + return std::make_unique(); +@@ -205,9 +226,27 @@ std::unique_ptr SandboxSeccompBPF::PolicyForSandboxType( + case sandbox::mojom::Sandbox::kAudio: + return std::make_unique(); + case sandbox::mojom::Sandbox::kService: +- return std::make_unique(); +- case sandbox::mojom::Sandbox::kServiceWithJit: +- return std::make_unique(); ++ return std::make_unique(true); ++ case sandbox::mojom::Sandbox::kServiceWithJit: { ++ const base::CommandLine& command_line = ++ *base::CommandLine::ForCurrentProcess(); ++ bool dynamic_code_can_be_disabled = false; ++ if (command_line.HasSwitch(blink::switches::kJavaScriptFlags)) { ++ std::string js_flags = ++ command_line.GetSwitchValueASCII(blink::switches::kJavaScriptFlags); ++ std::vector js_flag_list = base::SplitStringPiece( ++ js_flags, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); ++ for (const auto& js_flag : js_flag_list) { ++ if (js_flag == "--jitless") { ++ // If v8 is running jitless then there is no need for the ability to ++ // mark writable pages as executable to be available to the process. ++ dynamic_code_can_be_disabled = true; ++ break; ++ } ++ } ++ } ++ return std::make_unique(dynamic_code_can_be_disabled); ++ } + case sandbox::mojom::Sandbox::kSpeechRecognition: + return std::make_unique(); + #if BUILDFLAG(ENABLE_SCREEN_AI_SERVICE) From 62515f7c7e081be1bf74d18d8be05e7eb32cc095 Mon Sep 17 00:00:00 2001 From: Rootkit404 <175176948+RKNF404@users.noreply.github.com> Date: Tue, 3 Sep 2024 11:23:34 -0400 Subject: [PATCH 2/4] Fix patching issues --- ...lementation-with-Cross-Partitioned-B.patch | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch b/vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch index 77ce044e..8bf482bd 100644 --- a/vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch +++ b/vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch @@ -340,3 +340,40 @@ index 0000000000000..901ba07756b16 +} // namespace features + +#endif // STORAGE_BROWSER_BLOB_FEATURES_H_ +diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites +index 81d9507f2a31d..511e13024a0fc 100644 +--- a/third_party/blink/web_tests/VirtualTestSuites ++++ b/third_party/blink/web_tests/VirtualTestSuites +@@ -1160,6 +1160,16 @@ + "owners": ["arichiv@chromium.org", "bingler@chromium.org"] + }, + ++ { ++ "prefix": "block-cross-partition-blob-url-fetching", ++ "platforms": ["Linux"], ++ "bases": [ ++ "external/wpt/FileAPI/BlobURL/cross-partition.tentative.https.html"], ++ "args": ["--enable-features=BlockCrossPartitionBlobUrlFetching"], ++ "expires": "Feb 4, 2025", ++ "owners": ["janiceliu@chromium.org"] ++ }, ++ + "isInputPending requires threaded compositing and layerized iframes", + { + "prefix": "threaded-composited-iframes", +diff --git a/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/README.md b/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/README.md +new file mode 100644 +index 0000000000000..7866d21f26af9 +--- /dev/null ++++ b/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/README.md +@@ -0,0 +1 @@ ++This directory is for tests that need the Block Cross Partition Blob URL Fetching feature enabled. +\ No newline at end of file +diff --git a/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/external/wpt/FileAPI/BlobURL/cross-partition.tentative.https-expected.txt b/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/external/wpt/FileAPI/BlobURL/cross-partition.tentative.https-expected.txt +new file mode 100644 +index 0000000000000..d2490dbd54c3e +--- /dev/null ++++ b/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/external/wpt/FileAPI/BlobURL/cross-partition.tentative.https-expected.txt +@@ -0,0 +1,2 @@ ++This is a testharness.js-based test. ++Harness: the test ran to completion. From 623e97701305e5e938ccfb62dcc94bde5e324105 Mon Sep 17 00:00:00 2001 From: Rootkit404 <175176948+RKNF404@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:21:16 -0400 Subject: [PATCH 3/4] Remove patches that cause build issues, will be added back in upstream --- ...lementation-with-Cross-Partitioned-B.patch | 379 ------------------ ...cross-partition-blob-url-fetching-by.patch | 22 - 2 files changed, 401 deletions(-) delete mode 100644 vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch delete mode 100644 vanadium_patches/0191-Enable-blocking-cross-partition-blob-url-fetching-by.patch diff --git a/vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch b/vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch deleted file mode 100644 index 8bf482bd..00000000 --- a/vanadium_patches/0190-Add-Fetching-Implementation-with-Cross-Partitioned-B.patch +++ /dev/null @@ -1,379 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Janice Liu -Date: Wed, 21 Aug 2024 18:39:10 +0000 -Subject: [PATCH] Add Fetching Implementation with Cross-Partitioned Blob URL - -Bug: 357484649 -Change-Id: I074b15fd78114185f1d7bfddc2647e2dd76bbed7 -Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5762280 -Commit-Queue: Janice Liu -Reviewed-by: Ayu Ishii -Auto-Submit: Janice Liu -Reviewed-by: David Baron -Cr-Commit-Position: refs/heads/main@{#1344948} ---- - storage/browser/BUILD.gn | 2 + - storage/browser/blob/blob_url_store_impl.cc | 13 ++ - .../blob/blob_url_store_impl_unittest.cc | 160 ++++++++++++++++-- - storage/browser/blob/features.cc | 16 ++ - storage/browser/blob/features.h | 22 +++ - third_party/blink/web_tests/VirtualTestSuites | 10 ++ - .../README.md | 1 + - ...oss-partition.tentative.https-expected.txt | 3 + - 8 files changed, 211 insertions(+), 16 deletions(-) - create mode 100644 storage/browser/blob/features.cc - create mode 100644 storage/browser/blob/features.h - create mode 100644 third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/README.md - create mode 100644 third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/external/wpt/FileAPI/BlobURL/cross-partition.tentative.https-expected.txt - -diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn -index b52c014f46fcd..fb0c66e45a953 100644 ---- a/storage/browser/BUILD.gn -+++ b/storage/browser/BUILD.gn -@@ -47,6 +47,8 @@ component("browser") { - "blob/blob_url_store_impl.h", - "blob/blob_url_utils.cc", - "blob/blob_url_utils.h", -+ "blob/features.cc", -+ "blob/features.h", - "blob/mojo_blob_reader.cc", - "blob/mojo_blob_reader.h", - "blob/scoped_file.cc", -diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/blob_url_store_impl.cc -index d9a474d6c2439..bdd06f6230350 100644 ---- a/storage/browser/blob/blob_url_store_impl.cc -+++ b/storage/browser/blob/blob_url_store_impl.cc -@@ -14,6 +14,7 @@ - #include "storage/browser/blob/blob_url_loader_factory.h" - #include "storage/browser/blob/blob_url_registry.h" - #include "storage/browser/blob/blob_url_utils.h" -+#include "storage/browser/blob/features.h" - #include "url/url_util.h" - - namespace storage { -@@ -119,9 +120,21 @@ void BlobURLStoreImpl::ResolveAsURLLoaderFactory( - std::move(callback).Run(std::nullopt, std::nullopt); - return; - } -+ if (base::FeatureList::IsEnabled( -+ features::kBlockCrossPartitionBlobUrlFetching) && -+ !registry_->IsUrlMapped(BlobUrlUtils::ClearUrlFragment(url), -+ storage_key_)) { -+ BlobURLLoaderFactory::Create(mojo::NullRemote(), url, std::move(receiver)); -+ std::move(callback).Run(std::nullopt, std::nullopt); -+ return; -+ } - - BlobURLLoaderFactory::Create(registry_->GetBlobFromUrl(url), url, - std::move(receiver)); -+ // When a fragment URL is present, registry_->GetUnsafeAgentClusterID(url) and -+ // registry_->GetUnsafeTopLevelSite(url) will return nullopt because their -+ // implementations don't remove the fragment and only support fragmentless -+ // URLs (crbug.com/40775506). - std::move(callback).Run(registry_->GetUnsafeAgentClusterID(url), - registry_->GetUnsafeTopLevelSite(url)); - } -diff --git a/storage/browser/blob/blob_url_store_impl_unittest.cc b/storage/browser/blob/blob_url_store_impl_unittest.cc -index bd3d6ed6fe3bb..e398d6bae304e 100644 ---- a/storage/browser/blob/blob_url_store_impl_unittest.cc -+++ b/storage/browser/blob/blob_url_store_impl_unittest.cc -@@ -21,6 +21,7 @@ - #include "storage/browser/blob/blob_impl.h" - #include "storage/browser/blob/blob_storage_context.h" - #include "storage/browser/blob/blob_url_registry.h" -+#include "storage/browser/blob/features.h" - #include "testing/gtest/include/gtest/gtest.h" - - using blink::mojom::BlobURLStore; -@@ -30,10 +31,9 @@ namespace storage { - namespace { - - enum class PartitionedBlobUrlTestCase { -- kPartitioningDisabledWithSupportDisabled, -- kPartitioningDisabledWithSupportEnabled, -- kPartitioningEnabledWithSupportDisabled, -- kPartitioningEnabledWithSupportEnabled, -+ kPartitioningDisabled, -+ kBlockCrossPartitionBlobUrlFetchingEnabled, -+ kBlockCrossPartitionBlobUrlFetchingDisabled, - }; - - class BlobURLStoreImplTestP -@@ -51,14 +51,17 @@ class BlobURLStoreImplTestP - &BlobURLStoreImplTestP::OnBadMessage, base::Unretained(this))); - } - -- void TearDown() override { -- mojo::SetDefaultProcessErrorHandler(base::NullCallback()); -- } -- - void InitializeScopedFeatureList() { - std::vector enabled_features{}; - std::vector disabled_features{}; - -+ if (BlockCrossPartitionBlobUrlFetchingEnabled()) { -+ enabled_features.push_back(features::kBlockCrossPartitionBlobUrlFetching); -+ } else { -+ disabled_features.push_back( -+ features::kBlockCrossPartitionBlobUrlFetching); -+ } -+ - if (StoragePartitioningEnabled()) { - enabled_features.push_back(net::features::kThirdPartyStoragePartitioning); - } else { -@@ -69,16 +72,26 @@ class BlobURLStoreImplTestP - scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); - } - -- bool StoragePartitioningEnabled() { -+ bool BlockCrossPartitionBlobUrlFetchingEnabled() { - switch (test_case_) { -- case PartitionedBlobUrlTestCase::kPartitioningEnabledWithSupportDisabled: -- case PartitionedBlobUrlTestCase::kPartitioningEnabledWithSupportEnabled: -+ case PartitionedBlobUrlTestCase:: -+ kBlockCrossPartitionBlobUrlFetchingDisabled: -+ case PartitionedBlobUrlTestCase:: -+ kBlockCrossPartitionBlobUrlFetchingEnabled: - return true; - default: - return false; - } - } - -+ bool StoragePartitioningEnabled() { -+ return test_case_ != PartitionedBlobUrlTestCase::kPartitioningDisabled; -+ } -+ -+ void TearDown() override { -+ mojo::SetDefaultProcessErrorHandler(base::NullCallback()); -+ } -+ - void OnBadMessage(const std::string& error) { - bad_messages_.push_back(error); - } -@@ -377,6 +390,110 @@ TEST_P(BlobURLStoreImplTestP, ResolveAsURLLoaderFactory) { - download_loop.Run(); - } - -+TEST_P(BlobURLStoreImplTestP, -+ ResolveAsURLLoaderFactoryWithSeparateStorageKeys) { -+ const blink::StorageKey kWrongStorageKey = blink::StorageKey::Create( -+ kOrigin, kWrongTopLevelSite, blink::mojom::AncestorChainBit::kCrossSite); -+ -+ mojo::PendingRemote blob = -+ CreateBlobFromString(kId, "hello world"); -+ -+ BlobURLStoreImpl url_store1(kStorageKey, kStorageKey.origin(), /*rph_id=*/0, -+ url_registry_.AsWeakPtr()); -+ BlobURLStoreImpl url_store2(kWrongStorageKey, kStorageKey.origin(), -+ /*rph_id=*/0, url_registry_.AsWeakPtr()); -+ -+ RegisterURL(&url_store1, std::move(blob), kValidUrl); -+ -+ mojo::Remote factory; -+ base::RunLoop resolve_loop; -+ url_store2.ResolveAsURLLoaderFactory( -+ kValidUrl, factory.BindNewPipeAndPassReceiver(), -+ base::BindLambdaForTesting( -+ [&](const std::optional& -+ unsafe_agent_cluster_id, -+ const std::optional& unsafe_top_level_site) { -+ if (BlockCrossPartitionBlobUrlFetchingEnabled()) { -+ EXPECT_FALSE(unsafe_agent_cluster_id.has_value()); -+ EXPECT_FALSE(unsafe_top_level_site.has_value()); -+ } else { -+ EXPECT_EQ(*unsafe_agent_cluster_id, agent_cluster_id_); -+ } -+ resolve_loop.Quit(); -+ })); -+ -+ resolve_loop.Run(); -+ auto request = std::make_unique(); -+ request->url = kValidUrl; -+ auto loader = network::SimpleURLLoader::Create(std::move(request), -+ TRAFFIC_ANNOTATION_FOR_TESTS); -+ base::RunLoop download_loop; -+ loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( -+ factory.get(), base::BindLambdaForTesting( -+ [&](std::unique_ptr response_body) { -+ download_loop.Quit(); -+ if (BlockCrossPartitionBlobUrlFetchingEnabled()) { -+ EXPECT_FALSE(response_body); -+ } else { -+ ASSERT_TRUE(response_body); -+ EXPECT_EQ("hello world", *response_body); -+ } -+ })); -+ download_loop.Run(); -+} -+ -+TEST_P(BlobURLStoreImplTestP, ResolveAsURLLoaderFactoryWithFragmentUrl) { -+ const blink::StorageKey kWrongStorageKey = blink::StorageKey::Create( -+ kOrigin, kWrongTopLevelSite, blink::mojom::AncestorChainBit::kCrossSite); -+ -+ mojo::PendingRemote blob = -+ CreateBlobFromString(kId, "hello world"); -+ -+ BlobURLStoreImpl url_store1(kWrongStorageKey, kStorageKey.origin(), -+ /*rph_id=*/0, url_registry_.AsWeakPtr()); -+ mojo::Remote url_store2(CreateURLStore()); -+ RegisterURL(url_store2.get(), std::move(blob), kFragmentUrl); -+ -+ mojo::Remote factory; -+ base::RunLoop resolve_loop; -+ url_store1.ResolveAsURLLoaderFactory( -+ kFragmentUrl, factory.BindNewPipeAndPassReceiver(), -+ base::BindLambdaForTesting( -+ [&](const std::optional& -+ unsafe_agent_cluster_id, -+ const std::optional& unsafe_top_level_site) { -+ // TODO(crbug.com/40775506): Fix fragment URL bug. -+ if (BlockCrossPartitionBlobUrlFetchingEnabled() || -+ !StoragePartitioningEnabled()) { -+ EXPECT_FALSE(unsafe_agent_cluster_id.has_value()); -+ EXPECT_FALSE(unsafe_top_level_site.has_value()); -+ } else { -+ EXPECT_EQ(*unsafe_agent_cluster_id, agent_cluster_id_); -+ } -+ resolve_loop.Quit(); -+ })); -+ -+ resolve_loop.Run(); -+ auto request = std::make_unique(); -+ request->url = kFragmentUrl; -+ auto loader = network::SimpleURLLoader::Create(std::move(request), -+ TRAFFIC_ANNOTATION_FOR_TESTS); -+ base::RunLoop download_loop; -+ loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( -+ factory.get(), base::BindLambdaForTesting( -+ [&](std::unique_ptr response_body) { -+ download_loop.Quit(); -+ if (BlockCrossPartitionBlobUrlFetchingEnabled() || -+ !StoragePartitioningEnabled()) { -+ EXPECT_FALSE(response_body); -+ } else { -+ ASSERT_TRUE(response_body); -+ EXPECT_EQ("hello world", *response_body); -+ } -+ })); -+ download_loop.Run(); -+} -+ - TEST_P(BlobURLStoreImplTestP, ResolveForNavigation) { - mojo::PendingRemote blob = - CreateBlobFromString(kId, "hello world"); -@@ -418,11 +535,22 @@ TEST_P(BlobURLStoreImplTestP, ResolveForNavigation) { - INSTANTIATE_TEST_SUITE_P( - BlobURLStoreImplTests, - BlobURLStoreImplTestP, -- ::testing::Values( -- PartitionedBlobUrlTestCase::kPartitioningDisabledWithSupportDisabled, -- PartitionedBlobUrlTestCase::kPartitioningDisabledWithSupportEnabled, -- PartitionedBlobUrlTestCase::kPartitioningEnabledWithSupportDisabled, -- PartitionedBlobUrlTestCase::kPartitioningEnabledWithSupportEnabled)); -+ testing::Values( -+ PartitionedBlobUrlTestCase::kPartitioningDisabled, -+ PartitionedBlobUrlTestCase::kBlockCrossPartitionBlobUrlFetchingDisabled, -+ PartitionedBlobUrlTestCase::kBlockCrossPartitionBlobUrlFetchingEnabled), -+ [](const testing::TestParamInfo& info) { -+ switch (info.param) { -+ case PartitionedBlobUrlTestCase::kPartitioningDisabled: -+ return "PartitioningDisabled"; -+ case PartitionedBlobUrlTestCase:: -+ kBlockCrossPartitionBlobUrlFetchingDisabled: -+ return "BlockCrossPartitionBlobUrlFetchingDisabled"; -+ case PartitionedBlobUrlTestCase:: -+ kBlockCrossPartitionBlobUrlFetchingEnabled: -+ return "BlockCrossPartitionBlobUrlFetchingEnabled"; -+ } -+ }); - - } // namespace - } // namespace storage -diff --git a/storage/browser/blob/features.cc b/storage/browser/blob/features.cc -new file mode 100644 -index 0000000000000..17003b52f595c ---- /dev/null -+++ b/storage/browser/blob/features.cc -@@ -0,0 +1,16 @@ -+// Copyright 2024 The Chromium Authors -+// Use of this source code is governed by a BSD-style license that can be -+// found in the LICENSE file. -+ -+#include "storage/browser/blob/features.h" -+ -+namespace features { -+ -+// Please keep features in alphabetical order. -+BASE_FEATURE(kBlockCrossPartitionBlobUrlFetching, -+ "BlockCrossPartitionBlobUrlFetching", -+ base::FEATURE_DISABLED_BY_DEFAULT); -+ -+// Please keep features in alphabetical order. -+ -+} // namespace features -diff --git a/storage/browser/blob/features.h b/storage/browser/blob/features.h -new file mode 100644 -index 0000000000000..901ba07756b16 ---- /dev/null -+++ b/storage/browser/blob/features.h -@@ -0,0 +1,22 @@ -+// Copyright 2024 The Chromium Authors -+// Use of this source code is governed by a BSD-style license that can be -+// found in the LICENSE file. -+ -+#ifndef STORAGE_BROWSER_BLOB_FEATURES_H_ -+#define STORAGE_BROWSER_BLOB_FEATURES_H_ -+ -+#include "base/component_export.h" -+#include "base/features.h" -+ -+namespace features { -+ -+// Please keep features in alphabetical order. -+// Enables blob URL fetches to fail when cross-partition. -+COMPONENT_EXPORT(STORAGE_BROWSER) -+BASE_DECLARE_FEATURE(kBlockCrossPartitionBlobUrlFetching); -+ -+// Please keep features in alphabetical order. -+ -+} // namespace features -+ -+#endif // STORAGE_BROWSER_BLOB_FEATURES_H_ -diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites -index 81d9507f2a31d..511e13024a0fc 100644 ---- a/third_party/blink/web_tests/VirtualTestSuites -+++ b/third_party/blink/web_tests/VirtualTestSuites -@@ -1160,6 +1160,16 @@ - "owners": ["arichiv@chromium.org", "bingler@chromium.org"] - }, - -+ { -+ "prefix": "block-cross-partition-blob-url-fetching", -+ "platforms": ["Linux"], -+ "bases": [ -+ "external/wpt/FileAPI/BlobURL/cross-partition.tentative.https.html"], -+ "args": ["--enable-features=BlockCrossPartitionBlobUrlFetching"], -+ "expires": "Feb 4, 2025", -+ "owners": ["janiceliu@chromium.org"] -+ }, -+ - "isInputPending requires threaded compositing and layerized iframes", - { - "prefix": "threaded-composited-iframes", -diff --git a/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/README.md b/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/README.md -new file mode 100644 -index 0000000000000..7866d21f26af9 ---- /dev/null -+++ b/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/README.md -@@ -0,0 +1 @@ -+This directory is for tests that need the Block Cross Partition Blob URL Fetching feature enabled. -\ No newline at end of file -diff --git a/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/external/wpt/FileAPI/BlobURL/cross-partition.tentative.https-expected.txt b/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/external/wpt/FileAPI/BlobURL/cross-partition.tentative.https-expected.txt -new file mode 100644 -index 0000000000000..d2490dbd54c3e ---- /dev/null -+++ b/third_party/blink/web_tests/virtual/block-cross-partition-blob-url-fetching/external/wpt/FileAPI/BlobURL/cross-partition.tentative.https-expected.txt -@@ -0,0 +1,2 @@ -+This is a testharness.js-based test. -+Harness: the test ran to completion. diff --git a/vanadium_patches/0191-Enable-blocking-cross-partition-blob-url-fetching-by.patch b/vanadium_patches/0191-Enable-blocking-cross-partition-blob-url-fetching-by.patch deleted file mode 100644 index 33118164..00000000 --- a/vanadium_patches/0191-Enable-blocking-cross-partition-blob-url-fetching-by.patch +++ /dev/null @@ -1,22 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: fgei -Date: Thu, 22 Aug 2024 14:05:52 +0000 -Subject: [PATCH] Enable blocking cross partition blob url fetching by default - ---- - storage/browser/blob/features.cc | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/storage/browser/blob/features.cc b/storage/browser/blob/features.cc -index 17003b52f595c..627acffc08bbc 100644 ---- a/storage/browser/blob/features.cc -+++ b/storage/browser/blob/features.cc -@@ -9,7 +9,7 @@ namespace features { - // Please keep features in alphabetical order. - BASE_FEATURE(kBlockCrossPartitionBlobUrlFetching, - "BlockCrossPartitionBlobUrlFetching", -- base::FEATURE_DISABLED_BY_DEFAULT); -+ base::FEATURE_ENABLED_BY_DEFAULT); - - // Please keep features in alphabetical order. - From 1ac183ae74223c2c7311b9595ccbb87d92f4b304 Mon Sep 17 00:00:00 2001 From: Rootkit404 <175176948+RKNF404@users.noreply.github.com> Date: Thu, 5 Sep 2024 19:30:49 -0400 Subject: [PATCH 4/4] chore: Vanadium patch updates --- vanadium_patches/0012-Checkout-PGO-profiles.patch | 2 +- vanadium_patches/0013-disable-checkout_nacl.patch | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vanadium_patches/0012-Checkout-PGO-profiles.patch b/vanadium_patches/0012-Checkout-PGO-profiles.patch index b5d181f5..0856b970 100644 --- a/vanadium_patches/0012-Checkout-PGO-profiles.patch +++ b/vanadium_patches/0012-Checkout-PGO-profiles.patch @@ -8,7 +8,7 @@ Subject: [PATCH] Checkout PGO profiles 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS -index 76ea649d79e24..8ce0c6fd25774 100644 +index f975c66c1d9ed..fd207091cb1b2 100644 --- a/DEPS +++ b/DEPS @@ -149,7 +149,7 @@ vars = { diff --git a/vanadium_patches/0013-disable-checkout_nacl.patch b/vanadium_patches/0013-disable-checkout_nacl.patch index c7351e9d..e0b16344 100644 --- a/vanadium_patches/0013-disable-checkout_nacl.patch +++ b/vanadium_patches/0013-disable-checkout_nacl.patch @@ -8,7 +8,7 @@ Subject: [PATCH] disable checkout_nacl 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DEPS b/DEPS -index 8ce0c6fd25774..10f8c4dea1d90 100644 +index fd207091cb1b2..373091d2151ab 100644 --- a/DEPS +++ b/DEPS @@ -118,7 +118,7 @@ vars = {