tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ProcessIsolationTest.cpp (9789B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "gtest/gtest.h"
      8 #include "mozilla/BasePrincipal.h"
      9 #include "mozilla/ExpandedPrincipal.h"
     10 #include "mozilla/ExtensionPolicyService.h"
     11 #include "mozilla/NullPrincipal.h"
     12 #include "mozilla/StaticPrefs_browser.h"
     13 #include "mozilla/SystemPrincipal.h"
     14 #include "mozilla/dom/ProcessIsolation.h"
     15 #include "mozilla/dom/WorkerPrivate.h"
     16 #include "mozilla/gtest/MozAssertions.h"
     17 #include "mozilla/gtest/MozHelpers.h"
     18 
     19 using namespace mozilla;
     20 using namespace mozilla::dom;
     21 
     22 static nsCOMPtr<nsIPrincipal> MakeTestPrincipal(const char* aURI) {
     23  nsCOMPtr<nsIURI> uri;
     24  MOZ_ALWAYS_SUCCEEDS(NS_NewURI(getter_AddRefs(uri), aURI));
     25  return BasePrincipal::CreateContentPrincipal(uri, {});
     26 }
     27 
     28 namespace {
     29 struct RemoteTypes {
     30  nsCString mIsolated;
     31  nsCString mUnisolated;
     32 };
     33 
     34 struct WorkerExpectation {
     35  nsCOMPtr<nsIPrincipal> mPrincipal;
     36  WorkerKind mWorkerKind = WorkerKindShared;
     37  Result<RemoteTypes, nsresult> mExpected = Err(NS_ERROR_FAILURE);
     38  nsCString mCurrentRemoteType = "fakeRemoteType"_ns;
     39 
     40  void Check(bool aUseRemoteSubframes) {
     41    nsAutoCString origin;
     42    ASSERT_NS_SUCCEEDED(mPrincipal->GetOrigin(origin));
     43 
     44    nsPrintfCString describe(
     45        "origin: %s, workerKind: %s, currentRemoteType: %s, "
     46        "useRemoteSubframes: %d",
     47        origin.get(), mWorkerKind == WorkerKindShared ? "shared" : "service",
     48        mCurrentRemoteType.get(), aUseRemoteSubframes);
     49 
     50    auto result = IsolationOptionsForWorker(
     51        mPrincipal, mWorkerKind, mCurrentRemoteType, aUseRemoteSubframes);
     52    ASSERT_EQ(result.isOk(), mExpected.isOk())
     53        << "Unexpected status (expected " << (mExpected.isOk() ? "ok" : "err")
     54        << ") for " << describe;
     55    if (mExpected.isOk()) {
     56      const nsCString& expected = aUseRemoteSubframes
     57                                      ? mExpected.inspect().mIsolated
     58                                      : mExpected.inspect().mUnisolated;
     59      ASSERT_EQ(result.inspect().mRemoteType, expected)
     60          << "Unexpected remote type (expected " << expected << ") for "
     61          << describe;
     62    }
     63  }
     64 };
     65 }  // namespace
     66 
     67 static nsCString WebIsolatedRemoteType(nsIPrincipal* aPrincipal) {
     68  nsAutoCString origin;
     69  MOZ_ALWAYS_SUCCEEDS(aPrincipal->GetSiteOrigin(origin));
     70  return FISSION_WEB_REMOTE_TYPE + "="_ns + origin;
     71 }
     72 
     73 static nsCString CoopCoepRemoteType(nsIPrincipal* aPrincipal) {
     74  nsAutoCString origin;
     75  MOZ_ALWAYS_SUCCEEDS(aPrincipal->GetSiteOrigin(origin));
     76  return WITH_COOP_COEP_REMOTE_TYPE + "="_ns + origin;
     77 }
     78 
     79 static nsCString ServiceWorkerIsolatedRemoteType(nsIPrincipal* aPrincipal) {
     80  nsAutoCString origin;
     81  MOZ_ALWAYS_SUCCEEDS(aPrincipal->GetSiteOrigin(origin));
     82  return SERVICEWORKER_REMOTE_TYPE + "="_ns + origin;
     83 }
     84 
     85 TEST(ProcessIsolationTest, WorkerOptions)
     86 {
     87  // Forcibly enable the privileged mozilla content process for the duration of
     88  // the test.
     89  MOZ_ALWAYS_SUCCEEDS(Preferences::SetCString(
     90      "browser.tabs.remote.separatedMozillaDomains", "addons.mozilla.org"));
     91  MOZ_ALWAYS_SUCCEEDS(Preferences::SetBool(
     92      "browser.tabs.remote.separatePrivilegedMozillaWebContentProcess", true));
     93  auto cleanup = MakeScopeExit([&] {
     94    MOZ_ALWAYS_SUCCEEDS(
     95        Preferences::ClearUser("browser.tabs.remote.separatedMozillaDomains"));
     96    MOZ_ALWAYS_SUCCEEDS(Preferences::ClearUser(
     97        "browser.tabs.remote.separatePrivilegedMozillaWebContentProcess"));
     98  });
     99 
    100  nsCOMPtr<nsIPrincipal> systemPrincipal = SystemPrincipal::Get();
    101  nsCOMPtr<nsIPrincipal> nullPrincipal =
    102      NullPrincipal::CreateWithoutOriginAttributes();
    103  nsCOMPtr<nsIPrincipal> secureComPrincipal =
    104      MakeTestPrincipal("https://example.com");
    105  nsCOMPtr<nsIPrincipal> secureOrgPrincipal =
    106      MakeTestPrincipal("https://example.org");
    107  nsCOMPtr<nsIPrincipal> insecureOrgPrincipal =
    108      MakeTestPrincipal("http://example.org");
    109  nsCOMPtr<nsIPrincipal> filePrincipal =
    110      MakeTestPrincipal("file:///path/to/dir");
    111  nsCOMPtr<nsIPrincipal> extensionPrincipal =
    112      MakeTestPrincipal("moz-extension://fake-uuid");
    113  nsCOMPtr<nsIPrincipal> privilegedMozillaPrincipal =
    114      MakeTestPrincipal("https://addons.mozilla.org");
    115  nsCOMPtr<nsIPrincipal> expandedPrincipal = ExpandedPrincipal::Create(
    116      nsTArray{secureComPrincipal, extensionPrincipal}, {});
    117  nsCOMPtr<nsIPrincipal> nullSecureComPrecursorPrincipal =
    118      NullPrincipal::CreateWithInheritedAttributes(secureComPrincipal);
    119 
    120  nsCString extensionRemoteType =
    121      ExtensionPolicyService::GetSingleton().UseRemoteExtensions()
    122          ? EXTENSION_REMOTE_TYPE
    123          : NOT_REMOTE_TYPE;
    124  nsCString fileRemoteType =
    125      StaticPrefs::browser_tabs_remote_separateFileUriProcess()
    126          ? FILE_REMOTE_TYPE
    127          : WEB_REMOTE_TYPE;
    128 
    129  WorkerExpectation expectations[] = {
    130      // Neither service not shared workers can have expanded principals
    131      {.mPrincipal = expandedPrincipal,
    132       .mWorkerKind = WorkerKindService,
    133       .mExpected = Err(NS_ERROR_UNEXPECTED)},
    134      {.mPrincipal = expandedPrincipal,
    135       .mWorkerKind = WorkerKindShared,
    136       .mExpected = Err(NS_ERROR_UNEXPECTED)},
    137 
    138      // Service workers cannot have system or null principals
    139      {.mPrincipal = systemPrincipal,
    140       .mWorkerKind = WorkerKindService,
    141       .mExpected = Err(NS_ERROR_UNEXPECTED)},
    142      {.mPrincipal = nullPrincipal,
    143       .mWorkerKind = WorkerKindService,
    144       .mExpected = Err(NS_ERROR_UNEXPECTED)},
    145      {.mPrincipal = nullSecureComPrecursorPrincipal,
    146       .mWorkerKind = WorkerKindService,
    147       .mExpected = Err(NS_ERROR_UNEXPECTED)},
    148 
    149      // Service workers with various content principals
    150      {.mPrincipal = secureComPrincipal,
    151       .mWorkerKind = WorkerKindService,
    152       .mExpected =
    153           RemoteTypes{ServiceWorkerIsolatedRemoteType(secureComPrincipal),
    154                       WEB_REMOTE_TYPE}},
    155      {.mPrincipal = secureOrgPrincipal,
    156       .mWorkerKind = WorkerKindService,
    157       .mExpected =
    158           RemoteTypes{ServiceWorkerIsolatedRemoteType(secureOrgPrincipal),
    159                       WEB_REMOTE_TYPE}},
    160      {.mPrincipal = extensionPrincipal,
    161       .mWorkerKind = WorkerKindService,
    162       .mExpected = RemoteTypes{extensionRemoteType, extensionRemoteType}},
    163      {.mPrincipal = privilegedMozillaPrincipal,
    164       .mWorkerKind = WorkerKindService,
    165       .mExpected = RemoteTypes{PRIVILEGEDMOZILLA_REMOTE_TYPE,
    166                                PRIVILEGEDMOZILLA_REMOTE_TYPE}},
    167 
    168      // Shared Worker loaded from within a webCOOP+COEP remote type process,
    169      // should load elsewhere.
    170      {.mPrincipal = secureComPrincipal,
    171       .mWorkerKind = WorkerKindShared,
    172       .mExpected = RemoteTypes{WebIsolatedRemoteType(secureComPrincipal),
    173                                WEB_REMOTE_TYPE},
    174       .mCurrentRemoteType = CoopCoepRemoteType(secureComPrincipal)},
    175 
    176      // Even precursorless null principal should load elsewhere.
    177      {.mPrincipal = nullPrincipal,
    178       .mWorkerKind = WorkerKindShared,
    179       .mExpected = RemoteTypes{WEB_REMOTE_TYPE, WEB_REMOTE_TYPE},
    180       .mCurrentRemoteType = CoopCoepRemoteType(secureComPrincipal)},
    181 
    182      // System principal shared workers can only load in the parent process or
    183      // the privilegedabout remote type.
    184      {.mPrincipal = systemPrincipal,
    185       .mWorkerKind = WorkerKindShared,
    186       .mExpected = RemoteTypes{NOT_REMOTE_TYPE, NOT_REMOTE_TYPE},
    187       .mCurrentRemoteType = NOT_REMOTE_TYPE},
    188      {.mPrincipal = systemPrincipal,
    189       .mWorkerKind = WorkerKindShared,
    190       .mExpected = RemoteTypes{PRIVILEGEDABOUT_REMOTE_TYPE,
    191                                PRIVILEGEDABOUT_REMOTE_TYPE},
    192       .mCurrentRemoteType = PRIVILEGEDABOUT_REMOTE_TYPE},
    193      {.mPrincipal = systemPrincipal,
    194       .mWorkerKind = WorkerKindShared,
    195       .mExpected = Err(NS_ERROR_UNEXPECTED)},
    196      {.mPrincipal = systemPrincipal,
    197       .mWorkerKind = WorkerKindShared,
    198       .mExpected = Err(NS_ERROR_UNEXPECTED)},
    199 
    200      // Content principals should load in the appropriate remote types,
    201      // ignoring the current remote type.
    202      {.mPrincipal = secureComPrincipal,
    203       .mWorkerKind = WorkerKindShared,
    204       .mExpected = RemoteTypes{WebIsolatedRemoteType(secureComPrincipal),
    205                                WEB_REMOTE_TYPE}},
    206      {.mPrincipal = secureOrgPrincipal,
    207       .mWorkerKind = WorkerKindShared,
    208       .mExpected = RemoteTypes{WebIsolatedRemoteType(secureOrgPrincipal),
    209                                WEB_REMOTE_TYPE}},
    210      {.mPrincipal = insecureOrgPrincipal,
    211       .mWorkerKind = WorkerKindShared,
    212       .mExpected = RemoteTypes{WebIsolatedRemoteType(insecureOrgPrincipal),
    213                                WEB_REMOTE_TYPE}},
    214      {.mPrincipal = filePrincipal,
    215       .mWorkerKind = WorkerKindShared,
    216       .mExpected = RemoteTypes{fileRemoteType, fileRemoteType}},
    217      {.mPrincipal = extensionPrincipal,
    218       .mWorkerKind = WorkerKindShared,
    219       .mExpected = RemoteTypes{extensionRemoteType, extensionRemoteType}},
    220      {.mPrincipal = privilegedMozillaPrincipal,
    221       .mWorkerKind = WorkerKindShared,
    222       .mExpected = RemoteTypes{PRIVILEGEDMOZILLA_REMOTE_TYPE,
    223                                PRIVILEGEDMOZILLA_REMOTE_TYPE}},
    224      {.mPrincipal = nullSecureComPrecursorPrincipal,
    225       .mWorkerKind = WorkerKindShared,
    226       .mExpected = RemoteTypes{WebIsolatedRemoteType(secureComPrincipal),
    227                                WEB_REMOTE_TYPE}},
    228  };
    229 
    230  for (auto& expectation : expectations) {
    231    expectation.Check(true);
    232    expectation.Check(false);
    233  }
    234 }