Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/sandbox/mac/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 25 kB image not shown  

Quelle  Sandbox.mm   Sprache: unbekannt

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 http://mozilla.org/MPL/2.0/. */

// The Mac sandbox module is a static library (a Library in moz.build terms)
// that can be linked into any binary (for example plugin-container or XUL).
// It must not have dependencies on any other Mozilla module.  This is why,
// for example, it has its own OS X version detection code, rather than
// linking to nsCocoaFeatures.mm in XUL.

#include "Sandbox.h"

#include <CoreFoundation/CoreFoundation.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysctl.h>
#include <sys/types.h>

#include <iostream>
#include <sstream>
#include <vector>

#include "SandboxPolicyContent.h"
#include "SandboxPolicyGMP.h"
#include "SandboxPolicyRDD.h"
#include "SandboxPolicySocket.h"
#include "SandboxPolicyUtility.h"
#include "mozilla/Assertions.h"

#include "mozilla/GeckoArgs.h"
#include "mozilla/ipc/UtilityProcessSandboxing.h"

// Undocumented sandbox setup routines.
extern "C" int sandbox_init_with_parameters(const char* profile, uint64_t flags,
                                            const char* const parameters[],
                                            char** errorbuf);
extern "C" void sandbox_free_error(char* errorbuf);
extern "C" int sandbox_check(pid_t pid, const char* operation, int type, ...);

// Note about "major", "minor" and "bugfix" in the following code:
//
// The code decomposes an OS X version number into these components, and in
// doing so follows Apple's terminology in Gestalt.h.  But this is very
// misleading, because in other contexts Apple uses the "minor" component of
// an OS X version number to indicate a "major" release (for example the "9"
// in OS X 10.9.5), and the "bugfix" component to indicate a "minor" release
// (for example the "5" in OS X 10.9.5).
class OSXVersion {
 public:
  static void Get(int32_t& aMajor, int32_t& aMinor);

 private:
  static void GetSystemVersion(int32_t& aMajor, int32_t& aMinor,
                               int32_t& aBugFix);
  static bool mCached;
  static int32_t mOSXVersionMajor;
  static int32_t mOSXVersionMinor;
};

bool OSXVersion::mCached = false;
int32_t OSXVersion::mOSXVersionMajor;
int32_t OSXVersion::mOSXVersionMinor;

void OSXVersion::Get(int32_t& aMajor, int32_t& aMinor) {
  if (!mCached) {
    int32_t major, minor, bugfix;
    GetSystemVersion(major, minor, bugfix);
    mOSXVersionMajor = major;
    mOSXVersionMinor = minor;
    mCached = true;
  }
  aMajor = mOSXVersionMajor;
  aMinor = mOSXVersionMinor;
}

void OSXVersion::GetSystemVersion(int32_t& aMajor, int32_t& aMinor,
                                  int32_t& aBugFix) {
  SInt32 major = 0, minor = 0, bugfix = 0;

  CFURLRef url = CFURLCreateWithString(
      kCFAllocatorDefault,
      CFSTR("file:///System/Library/CoreServices/SystemVersion.plist"), NULL);
  CFReadStreamRef stream = CFReadStreamCreateWithFile(kCFAllocatorDefault, url);
  CFReadStreamOpen(stream);
  CFDictionaryRef sysVersionPlist =
      (CFDictionaryRef)CFPropertyListCreateWithStream(
          kCFAllocatorDefault, stream, 0, kCFPropertyListImmutable, NULL, NULL);
  CFReadStreamClose(stream);
  CFRelease(stream);
  CFRelease(url);

  CFStringRef versionString = (CFStringRef)CFDictionaryGetValue(
      sysVersionPlist, CFSTR("ProductVersion"));
  CFArrayRef versions = CFStringCreateArrayBySeparatingStrings(
      kCFAllocatorDefault, versionString, CFSTR("."));
  CFIndex count = CFArrayGetCount(versions);
  if (count > 0) {
    CFStringRef component = (CFStringRef)CFArrayGetValueAtIndex(versions, 0);
    major = CFStringGetIntValue(component);
    if (count > 1) {
      component = (CFStringRef)CFArrayGetValueAtIndex(versions, 1);
      minor = CFStringGetIntValue(component);
      if (count > 2) {
        component = (CFStringRef)CFArrayGetValueAtIndex(versions, 2);
        bugfix = CFStringGetIntValue(component);
      }
    }
  }
  CFRelease(sysVersionPlist);
  CFRelease(versions);

  if (major < 10) {
    // If 'major' isn't what we expect, assume 10.6.
    aMajor = 10;
    aMinor = 6;
    aBugFix = 0;
  } else if ((major == 10) && (minor >= 16)) {
    // Account for SystemVersionCompat.plist being used which is
    // automatically used for builds using older SDK versions and
    // results in 11.0 being reported as 10.16. Assume the compat
    // version will increase in step with the correct version.
    aMajor = 11;
    aMinor = minor - 16;
    aBugFix = bugfix;
  } else {
    aMajor = major;
    aMinor = minor;
    aBugFix = bugfix;
  }
}

bool GetRealPath(std::string& aOutputPath, const char* aInputPath) {
  char* resolvedPath = realpath(aInputPath, nullptr);
  if (resolvedPath == nullptr) {
    return false;
  }

  aOutputPath = resolvedPath;
  free(resolvedPath);

  return !aOutputPath.empty();
}

/*
 * Returns true if the process is running under Rosetta translation. Returns
 * false if running natively or if an error was encountered. To be called
 * before enabling the sandbox therefore not requiring the sysctl be allowed
 * by the sandbox policy. We use the `sysctl.proc_translated` sysctl which is
 * documented by Apple to be used for this purpose.
 */
bool ProcessIsRosettaTranslated() {
  int ret = 0;
  size_t size = sizeof(ret);
  if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) {
    if (errno != ENOENT) {
      fprintf(stderr, "Failed to check for translation environment\n");
    }
    return false;
  }
  return (ret == 1);
}

void MacSandboxInfo::AppendAsParams(std::vector<std::string>& aParams) const {
  this->AppendStartupParam(aParams);
  this->AppendLoggingParam(aParams);
  this->AppendAppPathParam(aParams);

  switch (this->type) {
    case MacSandboxType_Content:
      this->AppendLevelParam(aParams);
      this->AppendAudioParam(aParams);
      this->AppendWindowServerParam(aParams);
      this->AppendReadPathParams(aParams);
#ifdef DEBUG
      this->AppendDebugWriteDirParam(aParams);
#endif
      break;
    case MacSandboxType_RDD:
    case MacSandboxType_Socket:
    case MacSandboxType_Utility:
      break;
    case MacSandboxType_GMP:
      this->AppendPluginPathParam(aParams);
      this->AppendWindowServerParam(aParams);
      this->AppendReadPathParams(aParams);
      break;
    default:
      // Before supporting a new process type, add a case statement
      // here to append any neccesary process-type-specific params.
      MOZ_RELEASE_ASSERT(false);
      break;
  }
}

void MacSandboxInfo::AppendStartupParam(
    std::vector<std::string>& aParams) const {
  aParams.push_back("-sbStartup");
}

void MacSandboxInfo::AppendLoggingParam(
    std::vector<std::string>& aParams) const {
  if (this->shouldLog) {
    aParams.push_back("-sbLogging");
  }
}

void MacSandboxInfo::AppendAppPathParam(
    std::vector<std::string>& aParams) const {
  aParams.push_back("-sbAppPath");
  aParams.push_back(this->appPath);
}

void MacSandboxInfo::AppendPluginPathParam(
    std::vector<std::string>& aParams) const {
  aParams.push_back("-sbPluginPath");
  aParams.push_back(this->pluginPath);
}

/* static */
void MacSandboxInfo::AppendFileAccessParam(std::vector<std::string>& aParams,
                                           bool aHasFilePrivileges) {
  if (aHasFilePrivileges) {
    aParams.push_back("-sbAllowFileAccess");
  }
}

void MacSandboxInfo::AppendLevelParam(std::vector<std::string>& aParams) const {
  std::ostringstream os;
  os << this->level;
  std::string levelString = os.str();
  aParams.push_back("-sbLevel");
  aParams.push_back(levelString);
}

void MacSandboxInfo::AppendAudioParam(std::vector<std::string>& aParams) const {
  if (this->hasAudio) {
    aParams.push_back("-sbAllowAudio");
  }
}

void MacSandboxInfo::AppendWindowServerParam(
    std::vector<std::string>& aParams) const {
  if (this->hasWindowServer) {
    aParams.push_back("-sbAllowWindowServer");
  }
}

void MacSandboxInfo::AppendReadPathParams(
    std::vector<std::string>& aParams) const {
  if (!this->testingReadPath1.empty()) {
    aParams.push_back("-sbTestingReadPath");
    aParams.push_back(this->testingReadPath1.c_str());
  }
  if (!this->testingReadPath2.empty()) {
    aParams.push_back("-sbTestingReadPath");
    aParams.push_back(this->testingReadPath2.c_str());
  }
  if (!this->testingReadPath3.empty()) {
    aParams.push_back("-sbTestingReadPath");
    aParams.push_back(this->testingReadPath3.c_str());
  }
  if (!this->testingReadPath4.empty()) {
    aParams.push_back("-sbTestingReadPath");
    aParams.push_back(this->testingReadPath4.c_str());
  }
}

#ifdef DEBUG
void MacSandboxInfo::AppendDebugWriteDirParam(
    std::vector<std::string>& aParams) const {
  if (!this->debugWriteDir.empty()) {
    aParams.push_back("-sbDebugWriteDir");
    aParams.push_back(this->debugWriteDir.c_str());
  }
}
#endif

namespace mozilla {

bool StartMacSandbox(MacSandboxInfo const& aInfo, std::string& aErrorMessage) {
  std::vector<const char*> params;
  std::string profile;

  // Use a combined version number to simplify version check logic
  // in sandbox policies. For example, 10.14 becomes "1014".
  int32_t major = 0, minor = 0;
  OSXVersion::Get(major, minor);
  MOZ_ASSERT(minor >= 0 && minor < 100);
  std::string combinedVersion = std::to_string((major * 100) + minor);

  params.push_back("IS_ROSETTA_TRANSLATED");
  params.push_back(ProcessIsRosettaTranslated() ? "TRUE" : "FALSE");

  // Used for the content process to access to parts of the cache dir.
  std::string userCacheDir;

  if (aInfo.type == MacSandboxType_Utility) {
    profile = const_cast<char*>(SandboxPolicyUtility);

    switch (aInfo.utilityKind) {
      case ipc::SandboxingKind::GENERIC_UTILITY:
        // Nothing to do here specifically
        break;

#ifdef MOZ_APPLEMEDIA
      case ipc::SandboxingKind::UTILITY_AUDIO_DECODING_APPLE_MEDIA: {
        profile.append(SandboxPolicyUtilityAudioDecoderAppleMediaAddend);
        params.push_back("MAC_OS_VERSION");
        params.push_back(combinedVersion.c_str());
      } break;
#endif

      default:
        MOZ_ASSERT(false, "Invalid SandboxingKind");
        break;
    }
    params.push_back("SHOULD_LOG");
    params.push_back(aInfo.shouldLog ? "TRUE" : "FALSE");
    params.push_back("APP_PATH");
    params.push_back(aInfo.appPath.c_str());
    if (!aInfo.crashServerPort.empty()) {
      params.push_back("CRASH_PORT");
      params.push_back(aInfo.crashServerPort.c_str());
    }
  } else if (aInfo.type == MacSandboxType_RDD) {
    profile = const_cast<char*>(SandboxPolicyRDD);
    params.push_back("SHOULD_LOG");
    params.push_back(aInfo.shouldLog ? "TRUE" : "FALSE");
    params.push_back("MAC_OS_VERSION");
    params.push_back(combinedVersion.c_str());
    params.push_back("APP_PATH");
    params.push_back(aInfo.appPath.c_str());
    params.push_back("HOME_PATH");
    params.push_back(getenv("HOME"));
    if (!aInfo.crashServerPort.empty()) {
      params.push_back("CRASH_PORT");
      params.push_back(aInfo.crashServerPort.c_str());
    }
  } else if (aInfo.type == MacSandboxType_Socket) {
    profile = const_cast<char*>(SandboxPolicySocket);
    params.push_back("SHOULD_LOG");
    params.push_back(aInfo.shouldLog ? "TRUE" : "FALSE");
    params.push_back("APP_PATH");
    params.push_back(aInfo.appPath.c_str());
    if (!aInfo.crashServerPort.empty()) {
      params.push_back("CRASH_PORT");
      params.push_back(aInfo.crashServerPort.c_str());
    }
    params.push_back("HOME_PATH");
    params.push_back(getenv("HOME"));
  } else if (aInfo.type == MacSandboxType_GMP) {
    profile = const_cast<char*>(SandboxPolicyGMP);
    params.push_back("SHOULD_LOG");
    params.push_back(aInfo.shouldLog ? "TRUE" : "FALSE");
    params.push_back("APP_PATH");
    params.push_back(aInfo.appPath.c_str());
    params.push_back("PLUGIN_PATH");
    params.push_back(aInfo.pluginPath.c_str());
    if (!aInfo.pluginBinaryPath.empty()) {
      params.push_back("PLUGIN_BINARY_PATH");
      params.push_back(aInfo.pluginBinaryPath.c_str());
    }
    params.push_back("HAS_WINDOW_SERVER");
    params.push_back(aInfo.hasWindowServer ? "TRUE" : "FALSE");
    if (!aInfo.crashServerPort.empty()) {
      params.push_back("CRASH_PORT");
      params.push_back(aInfo.crashServerPort.c_str());
    }
    if (!aInfo.testingReadPath1.empty()) {
      params.push_back("TESTING_READ_PATH1");
      params.push_back(aInfo.testingReadPath1.c_str());
    }
    if (!aInfo.testingReadPath2.empty()) {
      params.push_back("TESTING_READ_PATH2");
      params.push_back(aInfo.testingReadPath2.c_str());
    }
  } else if (aInfo.type == MacSandboxType_Content) {
    MOZ_ASSERT(aInfo.level >= 1);
    if (aInfo.level >= 1) {
      profile = SandboxPolicyContent;
      params.push_back("SHOULD_LOG");
      params.push_back(aInfo.shouldLog ? "TRUE" : "FALSE");
      params.push_back("SANDBOX_LEVEL_1");
      params.push_back(aInfo.level == 1 ? "TRUE" : "FALSE");
      params.push_back("SANDBOX_LEVEL_2");
      params.push_back(aInfo.level == 2 ? "TRUE" : "FALSE");
      params.push_back("SANDBOX_LEVEL_3");
      params.push_back(aInfo.level == 3 ? "TRUE" : "FALSE");
      params.push_back("MAC_OS_VERSION");
      params.push_back(combinedVersion.c_str());
      params.push_back("APP_PATH");
      params.push_back(aInfo.appPath.c_str());
      params.push_back("PROFILE_DIR");
      params.push_back(aInfo.profileDir.c_str());
      params.push_back("HOME_PATH");
      params.push_back(getenv("HOME"));
      params.push_back("HAS_SANDBOXED_PROFILE");
      params.push_back(aInfo.hasSandboxedProfile ? "TRUE" : "FALSE");
      params.push_back("HAS_WINDOW_SERVER");
      params.push_back(aInfo.hasWindowServer ? "TRUE" : "FALSE");
      if (!aInfo.crashServerPort.empty()) {
        params.push_back("CRASH_PORT");
        params.push_back(aInfo.crashServerPort.c_str());
      }

      params.push_back("DARWIN_USER_CACHE_DIR");
      char confStrBuf[PATH_MAX];
      if (!confstr(_CS_DARWIN_USER_CACHE_DIR, confStrBuf, sizeof(confStrBuf))) {
        return false;
      }
      if (!GetRealPath(userCacheDir, confStrBuf)) {
        return false;
      }
      params.push_back(userCacheDir.c_str());

      if (!aInfo.testingReadPath1.empty()) {
        params.push_back("TESTING_READ_PATH1");
        params.push_back(aInfo.testingReadPath1.c_str());
      }
      if (!aInfo.testingReadPath2.empty()) {
        params.push_back("TESTING_READ_PATH2");
        params.push_back(aInfo.testingReadPath2.c_str());
      }
      if (!aInfo.testingReadPath3.empty()) {
        params.push_back("TESTING_READ_PATH3");
        params.push_back(aInfo.testingReadPath3.c_str());
      }
      if (!aInfo.testingReadPath4.empty()) {
        params.push_back("TESTING_READ_PATH4");
        params.push_back(aInfo.testingReadPath4.c_str());
      }
#ifdef DEBUG
      if (!aInfo.debugWriteDir.empty()) {
        params.push_back("DEBUG_WRITE_DIR");
        params.push_back(aInfo.debugWriteDir.c_str());
      }
#endif  // DEBUG

      if (aInfo.hasFilePrivileges) {
        profile.append(SandboxPolicyContentFileAddend);
      }
      if (aInfo.hasAudio) {
        profile.append(SandboxPolicyContentAudioAddend);
      }
    } else {
      fprintf(stderr,
              "Content sandbox disabled due to sandbox level setting\n");
      return false;
    }
  } else {
    char* msg = NULL;
    asprintf(&msg, "Unexpected sandbox type %u", aInfo.type);
    if (msg) {
      aErrorMessage.assign(msg);
      free(msg);
    }
    return false;
  }

  if (profile.empty()) {
    fprintf(stderr, "Out of memory in StartMacSandbox()!\n");
    return false;
  }

// In order to avoid relying on any other Mozilla modules (as described at the
// top of this file), we use our own #define instead of the existing MOZ_LOG
// infrastructure. This can be used by developers to debug the macOS sandbox
// policy.
#define MAC_SANDBOX_PRINT_POLICY 0
#if MAC_SANDBOX_PRINT_POLICY
  printf("Sandbox params for PID %d:\n", getpid());
  for (size_t i = 0; i < params.size() / 2; i++) {
    printf("  %s = %s\n", params[i * 2], params[(i * 2) + 1]);
  }
  printf("Sandbox profile:\n%s\n", profile.c_str());
#endif

  // The parameters array is null terminated.
  params.push_back(nullptr);

  char* errorbuf = NULL;
  int rv = sandbox_init_with_parameters(profile.c_str(), 0, params.data(),
                                        &errorbuf);
  if (rv) {
    if (errorbuf) {
      char* msg = NULL;
      asprintf(&msg, "sandbox_init() failed with error \"%s\"", errorbuf);
      if (msg) {
        aErrorMessage.assign(msg);
        free(msg);
      }
      fprintf(stderr, "profile: %s\n", profile.c_str());
      sandbox_free_error(errorbuf);
    }
  }
  if (rv) {
    return false;
  }

  return true;
}

/*
 * Fill |aInfo| with content sandbox params parsed from the provided
 * command line arguments. Return false if any sandbox parameters needed
 * for early startup of the sandbox are not present in the arguments.
 */
bool GetContentSandboxParamsFromArgs(int aArgc, char** aArgv,
                                     MacSandboxInfo& aInfo) {
  // Ensure we find these paramaters in the command
  // line arguments. Return false if any are missing.
  bool foundSandboxLevel = false;
  bool foundValidSandboxLevel = false;
  bool foundAppPath = false;

  // Read access directories used in testing
  int nTestingReadPaths = 0;
  std::string testingReadPaths[MAX_CONTENT_TESTING_READ_PATHS] = {};

  // Collect sandbox params from CLI arguments
  for (int i = 0; i < aArgc; i++) {
    if ((strcmp(aArgv[i], "-sbLevel") == 0) && (i + 1 < aArgc)) {
      std::stringstream ss(aArgv[i + 1]);
      int level = 0;
      ss >> level;
      foundSandboxLevel = true;
      aInfo.level = level;
      foundValidSandboxLevel = level > 0 && level <= 3 ? true : false;
      if (!foundValidSandboxLevel) {
        break;
      }
      i++;
      continue;
    }

    if (strcmp(aArgv[i], "-sbLogging") == 0) {
      aInfo.shouldLog = true;
      continue;
    }

    if (strcmp(aArgv[i], "-sbAllowFileAccess") == 0) {
      aInfo.hasFilePrivileges = true;
      continue;
    }

    if (strcmp(aArgv[i], "-sbAllowAudio") == 0) {
      aInfo.hasAudio = true;
      continue;
    }

    if (strcmp(aArgv[i], "-sbAllowWindowServer") == 0) {
      aInfo.hasWindowServer = true;
      continue;
    }

    if ((strcmp(aArgv[i], "-sbAppPath") == 0) && (i + 1 < aArgc)) {
      foundAppPath = true;
      aInfo.appPath.assign(aArgv[i + 1]);
      i++;
      continue;
    }

    if ((strcmp(aArgv[i], "-sbTestingReadPath") == 0) && (i + 1 < aArgc)) {
      if (nTestingReadPaths >= MAX_CONTENT_TESTING_READ_PATHS) {
        MOZ_CRASH("Too many content process -sbTestingReadPath arguments");
      }
      testingReadPaths[nTestingReadPaths] = aArgv[i + 1];
      nTestingReadPaths++;
      i++;
      continue;
    }

    if ((strcmp(aArgv[i], "-profile") == 0) && (i + 1 < aArgc)) {
      aInfo.hasSandboxedProfile = true;
      aInfo.profileDir.assign(aArgv[i + 1]);
      i++;
      continue;
    }

#ifdef DEBUG
    if ((strcmp(aArgv[i], "-sbDebugWriteDir") == 0) && (i + 1 < aArgc)) {
      aInfo.debugWriteDir.assign(aArgv[i + 1]);
      i++;
      continue;
    }
#endif  // DEBUG

    // Handle crash server positional argument
    if (strstr(aArgv[i], "gecko-crash-server-pipe") != NULL) {
      aInfo.crashServerPort.assign(aArgv[i]);
      continue;
    }
  }

  if (!foundSandboxLevel) {
    fprintf(stderr, "Content sandbox disabled due to "
                    "missing sandbox CLI level parameter.\n");
    return false;
  }

  if (!foundValidSandboxLevel) {
    fprintf(stderr,
            "Content sandbox disabled due to invalid"
            "sandbox level (%d)\n",
            aInfo.level);
    return false;
  }

  if (!foundAppPath) {
    fprintf(stderr, "Content sandbox disabled due to "
                    "missing sandbox CLI app path parameter.\n");
    return false;
  }

  aInfo.testingReadPath1 = testingReadPaths[0];
  aInfo.testingReadPath2 = testingReadPaths[1];
  aInfo.testingReadPath3 = testingReadPaths[2];
  aInfo.testingReadPath4 = testingReadPaths[3];

  return true;
}

bool GetUtilitySandboxParamsFromArgs(int aArgc, char** aArgv,
                                     MacSandboxInfo& aInfo,
                                     bool aSandboxingKindRequired = true) {
  // Ensure we find these paramaters in the command
  // line arguments. Return false if any are missing.
  bool foundAppPath = false;

  // Collect sandbox params from CLI arguments
  for (int i = 0; i < aArgc; i++) {
    if (strcmp(aArgv[i], "-sbLogging") == 0) {
      aInfo.shouldLog = true;
      continue;
    }

    if ((strcmp(aArgv[i], "-sbAppPath") == 0) && (i + 1 < aArgc)) {
      foundAppPath = true;
      aInfo.appPath.assign(aArgv[i + 1]);
      i++;
      continue;
    }

    // Handle crash server positional argument
    if (strstr(aArgv[i], "gecko-crash-server-pipe") != NULL) {
      aInfo.crashServerPort.assign(aArgv[i]);
      continue;
    }
  }

  if (aSandboxingKindRequired) {
    Maybe<uint64_t> sandboxingKind =
        geckoargs::sSandboxingKind.Get(aArgc, aArgv, CheckArgFlag::None);
    if (sandboxingKind.isNothing()) {
      fprintf(stderr, "Utility sandbox requires a sandboxingKind");
      return false;
    }
    aInfo.utilityKind = (ipc::SandboxingKind)*sandboxingKind;
  }

  if (!foundAppPath) {
    fprintf(stderr, "Utility sandbox disabled due to "
                    "missing sandbox CLI app path parameter.\n");
    return false;
  }

  return true;
}

bool GetSocketSandboxParamsFromArgs(int aArgc, char** aArgv,
                                    MacSandboxInfo& aInfo) {
  return GetUtilitySandboxParamsFromArgs(aArgc, aArgv, aInfo, false);
}

bool GetPluginSandboxParamsFromArgs(int aArgc, char** aArgv,
                                    MacSandboxInfo& aInfo) {
  // Ensure we find these paramaters in the command
  // line arguments. Return false if any are missing.
  bool foundAppPath = false;
  bool foundPluginPath = false;

  // Read access directories used in testing
  int nTestingReadPaths = 0;
  std::string testingReadPaths[MAX_GMP_TESTING_READ_PATHS] = {};

  // Collect sandbox params from CLI arguments
  for (int i = 0; i < aArgc; i++) {
    if (strcmp(aArgv[i], "-sbLogging") == 0) {
      aInfo.shouldLog = true;
      continue;
    }

    if ((strcmp(aArgv[i], "-sbAppPath") == 0) && (i + 1 < aArgc)) {
      foundAppPath = true;
      aInfo.appPath.assign(aArgv[i + 1]);
      i++;
      continue;
    }

    if ((strcmp(aArgv[i], "-sbPluginPath") == 0) && (i + 1 < aArgc)) {
      foundPluginPath = true;
      aInfo.pluginPath.assign(aArgv[i + 1]);
      i++;
      continue;
    }

    if (strcmp(aArgv[i], "-sbAllowWindowServer") == 0) {
      aInfo.hasWindowServer = true;
      continue;
    }

    if ((strcmp(aArgv[i], "-sbTestingReadPath") == 0) && (i + 1 < aArgc)) {
      if (nTestingReadPaths >= MAX_GMP_TESTING_READ_PATHS) {
        MOZ_CRASH("Too many GMP process -sbTestingReadPath arguments");
      }
      testingReadPaths[nTestingReadPaths] = aArgv[i + 1];
      nTestingReadPaths++;
      i++;
      continue;
    }

    // Handle crash server positional argument
    if (strstr(aArgv[i], "gecko-crash-server-pipe") != NULL) {
      aInfo.crashServerPort.assign(aArgv[i]);
      continue;
    }
  }

  if (!foundPluginPath) {
    fprintf(stderr, "GMP sandbox disabled due to "
                    "missing sandbox CLI plugin path parameter.\n");
    return false;
  }

  if (!foundAppPath) {
    fprintf(stderr, "GMP sandbox disabled due to "
                    "missing sandbox CLI app path parameter.\n");
    return false;
  }

  aInfo.testingReadPath1 = testingReadPaths[0];
  aInfo.testingReadPath2 = testingReadPaths[1];

  return true;
}

bool GetRDDSandboxParamsFromArgs(int aArgc, char** aArgv,
                                 MacSandboxInfo& aInfo) {
  return GetUtilitySandboxParamsFromArgs(aArgc, aArgv, aInfo, false);
}

/*
 * Returns true if no errors were encountered or if early sandbox startup is
 * not enabled for this process. Returns false if an error was encountered.
 */
bool StartMacSandboxIfEnabled(const MacSandboxType aSandboxType, int aArgc,
                              char** aArgv, std::string& aErrorMessage) {
  bool earlyStartupEnabled = false;

  // Check for the -sbStartup CLI parameter which
  // indicates we should start the sandbox now.
  for (int i = 0; i < aArgc; i++) {
    if (strcmp(aArgv[i], "-sbStartup") == 0) {
      earlyStartupEnabled = true;
      break;
    }
  }

  // The sandbox will be started later when/if parent
  // sends the sandbox startup message. Return true
  // indicating no errors occurred.
  if (!earlyStartupEnabled) {
    return true;
  }

  MacSandboxInfo info;
  info.type = aSandboxType;

  // For now, early start is only implemented
  // for content and utility sandbox types.
  switch (aSandboxType) {
    case MacSandboxType_Content:
      if (!GetContentSandboxParamsFromArgs(aArgc, aArgv, info)) {
        return false;
      }
      break;
    case MacSandboxType_GMP:
      if (!GetPluginSandboxParamsFromArgs(aArgc, aArgv, info)) {
        return false;
      }
      break;
    case MacSandboxType_RDD:
      if (!GetRDDSandboxParamsFromArgs(aArgc, aArgv, info)) {
        return false;
      }
      break;
    case MacSandboxType_Socket:
      if (!GetSocketSandboxParamsFromArgs(aArgc, aArgv, info)) {
        return false;
      }
      break;
    case MacSandboxType_Utility:
      if (!GetUtilitySandboxParamsFromArgs(aArgc, aArgv, info)) {
        return false;
      }
      break;
    default:
      MOZ_RELEASE_ASSERT(false);
      break;
  }

  return StartMacSandbox(info, aErrorMessage);
}

bool IsMacSandboxStarted() { return sandbox_check(getpid(), NULL, 0) == 1; }

#ifdef DEBUG
// sandbox_check returns 1 if the specified process is sandboxed
void AssertMacSandboxEnabled() {
  MOZ_ASSERT(sandbox_check(getpid(), NULL, 0) == 1);
}
#endif /* DEBUG */

}  // namespace mozilla

[ Dauer der Verarbeitung: 0.3 Sekunden  (vorverarbeitet)  ]