зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1506198 - Remove content temp dir r=gcp
Differential Revision: https://phabricator.services.mozilla.com/D220369
This commit is contained in:
Родитель
61f5cb3849
Коммит
8ffb617205
|
@ -1548,13 +1548,6 @@ pref("browser.bookmarks.editDialog.maxRecentFolders", 7);
|
|||
pref("security.sandbox.content.level", 1);
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
// ID (a UUID when set by gecko) that is used to form the name of a
|
||||
// sandbox-writable temporary directory to be used by content processes
|
||||
// when a temporary writable file is required.
|
||||
pref("security.sandbox.content.tempDirSuffix", "");
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
pref("browser.taskbar.previews.enable", false);
|
||||
pref("browser.taskbar.previews.max", 20);
|
||||
|
|
|
@ -1191,6 +1191,7 @@ void ChromeUtils::DefineESModuleGetters(
|
|||
/* static */
|
||||
void ChromeUtils::GetLibcConstants(const GlobalObject&,
|
||||
LibcConstants& aConsts) {
|
||||
aConsts.mEPERM.Construct(EPERM);
|
||||
aConsts.mEINTR.Construct(EINTR);
|
||||
aConsts.mEACCES.Construct(EACCES);
|
||||
aConsts.mEAGAIN.Construct(EAGAIN);
|
||||
|
|
|
@ -1123,6 +1123,7 @@ enum JSRFPTarget {
|
|||
|
||||
#ifdef XP_UNIX
|
||||
dictionary LibcConstants {
|
||||
long EPERM;
|
||||
long EINTR;
|
||||
long EACCES;
|
||||
long EAGAIN;
|
||||
|
|
|
@ -159,21 +159,24 @@ class BaseProcessLauncher {
|
|||
std::vector<std::string>&& aExtraOpts)
|
||||
: mProcessType(aHost->mProcessType),
|
||||
mLaunchOptions(std::move(aHost->mLaunchOptions)),
|
||||
mExtraOpts(std::move(aExtraOpts)),
|
||||
mExtraOpts(std::move(aExtraOpts))
|
||||
#ifdef XP_WIN
|
||||
mGroupId(aHost->mGroupId),
|
||||
,
|
||||
mGroupId(aHost->mGroupId)
|
||||
#endif
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
,
|
||||
mAllowedFilesRead(aHost->mAllowedFilesRead),
|
||||
mSandboxLevel(aHost->mSandboxLevel),
|
||||
mSandbox(aHost->mSandbox),
|
||||
mIsFileContent(aHost->mIsFileContent),
|
||||
mEnableSandboxLogging(aHost->mEnableSandboxLogging),
|
||||
mEnableSandboxLogging(aHost->mEnableSandboxLogging)
|
||||
#endif
|
||||
#if defined(XP_MACOSX) && defined(MOZ_SANDBOX)
|
||||
mDisableOSActivityMode(aHost->mDisableOSActivityMode),
|
||||
,
|
||||
mDisableOSActivityMode(aHost->mDisableOSActivityMode)
|
||||
#endif
|
||||
mTmpDirName(aHost->mTmpDirName) {
|
||||
{
|
||||
SprintfLiteral(mPidString, "%" PRIPID, base::GetCurrentProcId());
|
||||
aHost->mInitialChannelId.ToProvidedString(mInitialChannelIdString);
|
||||
SprintfLiteral(mChildIDString, "%d", aHost->mChildID);
|
||||
|
@ -246,7 +249,6 @@ class BaseProcessLauncher {
|
|||
// environment variable OS_ACTIVITY_MODE set to "disabled".
|
||||
bool mDisableOSActivityMode;
|
||||
#endif
|
||||
nsCString mTmpDirName;
|
||||
LaunchResults mResults = LaunchResults();
|
||||
TimeStamp mStartTimeStamp = TimeStamp::Now();
|
||||
char mPidString[32];
|
||||
|
@ -415,17 +417,7 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
|
|||
}
|
||||
sGeckoChildProcessHosts->insertBack(this);
|
||||
#if defined(MOZ_SANDBOX) && defined(XP_LINUX)
|
||||
if (aProcessType == GeckoProcessType_Content) {
|
||||
# if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
// The content process needs the content temp dir:
|
||||
nsCOMPtr<nsIFile> contentTempDir;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
|
||||
getter_AddRefs(contentTempDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
contentTempDir->GetNativePath(mTmpDirName);
|
||||
}
|
||||
# endif
|
||||
} else if (aProcessType == GeckoProcessType_RDD) {
|
||||
if (aProcessType == GeckoProcessType_RDD) {
|
||||
// The RDD process makes limited use of EGL. If Mesa's shader
|
||||
// cache is enabled and the directory isn't explicitly set, then
|
||||
// it will try to getpwuid() the user which can cause problems
|
||||
|
@ -1190,18 +1182,6 @@ Result<Ok, LaunchError> LinuxProcessLauncher::DoSetup() {
|
|||
mLaunchOptions->env_map["NO_AT_BRIDGE"] = "1";
|
||||
}
|
||||
|
||||
# ifdef MOZ_SANDBOX
|
||||
if (!mTmpDirName.IsEmpty()) {
|
||||
// Point a bunch of things that might want to write from content to our
|
||||
// shiny new content-process specific tmpdir
|
||||
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("TMPDIR")] =
|
||||
ENVIRONMENT_STRING(mTmpDirName.get());
|
||||
// Partial fix for bug 1380051 (not persistent - should be)
|
||||
mLaunchOptions->env_map[ENVIRONMENT_LITERAL("MESA_GLSL_CACHE_DIR")] =
|
||||
ENVIRONMENT_STRING(mTmpDirName.get());
|
||||
}
|
||||
# endif // MOZ_SANDBOX
|
||||
|
||||
return Ok();
|
||||
}
|
||||
#endif // MOZ_WIDGET_GTK
|
||||
|
|
|
@ -312,8 +312,6 @@ class GeckoChildProcessHost : public SupportsWeakPtr,
|
|||
// Removes the instance from sGeckoChildProcessHosts
|
||||
void RemoveFromProcessList();
|
||||
|
||||
// Linux-Only. Set this up before we're called from a different thread.
|
||||
nsCString mTmpDirName;
|
||||
// Mac and Windows. Set this up before we're called from a different thread.
|
||||
nsCOMPtr<nsIFile> mProfileDir;
|
||||
|
||||
|
|
|
@ -71,17 +71,6 @@ SandboxBroker::SandboxBroker(UniquePtr<const Policy> aPolicy, int aChildPid,
|
|||
mFileDesc = -1;
|
||||
aClientFd = -1;
|
||||
}
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
nsCOMPtr<nsIFile> tmpDir;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
|
||||
getter_AddRefs(tmpDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = tmpDir->GetNativePath(mContentTempPath);
|
||||
if (NS_FAILED(rv)) {
|
||||
mContentTempPath.Truncate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
UniquePtr<SandboxBroker> SandboxBroker::Create(
|
||||
|
@ -572,36 +561,6 @@ size_t SandboxBroker::ConvertRelativePath(char* aPath, size_t aBufSize,
|
|||
return aPathLen;
|
||||
}
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
size_t SandboxBroker::RemapTempDirs(char* aPath, size_t aBufSize,
|
||||
size_t aPathLen) {
|
||||
nsAutoCString path(aPath);
|
||||
|
||||
size_t prefixLen = 0;
|
||||
if (!mTempPath.IsEmpty() && StringBeginsWith(path, mTempPath)) {
|
||||
prefixLen = mTempPath.Length();
|
||||
} else if (StringBeginsWith(path, tempDirPrefix)) {
|
||||
prefixLen = tempDirPrefix.Length();
|
||||
}
|
||||
|
||||
if (prefixLen) {
|
||||
const nsDependentCSubstring cutPath =
|
||||
Substring(path, prefixLen, path.Length() - prefixLen);
|
||||
|
||||
// Only now try to get the content process temp dir
|
||||
if (!mContentTempPath.IsEmpty()) {
|
||||
nsAutoCString tmpPath;
|
||||
tmpPath.Assign(mContentTempPath);
|
||||
tmpPath.Append(cutPath);
|
||||
base::strlcpy(aPath, tmpPath.get(), aBufSize);
|
||||
return strlen(aPath);
|
||||
}
|
||||
}
|
||||
|
||||
return aPathLen;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCString SandboxBroker::ReverseSymlinks(const nsACString& aPath) {
|
||||
// Revert any symlinks we previously resolved.
|
||||
int32_t cutLength = aPath.Length();
|
||||
|
@ -679,38 +638,6 @@ void SandboxBroker::ThreadMain(void) {
|
|||
// before the main thread loop starts
|
||||
bool permissive = SandboxInfo::Get().Test(SandboxInfo::kPermissive);
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
// Find the current temporary directory
|
||||
nsCOMPtr<nsIFile> tmpDir;
|
||||
nsresult rv =
|
||||
GetSpecialSystemDirectory(OS_TemporaryDirectory, getter_AddRefs(tmpDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
rv = tmpDir->GetNativePath(mTempPath);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// Make sure there's no terminating /
|
||||
if (mTempPath.Last() == '/') {
|
||||
mTempPath.Truncate(mTempPath.Length() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If we can't find it, we aren't bothered much: we will
|
||||
// always try /tmp anyway in the substitution code
|
||||
if (NS_FAILED(rv) || mTempPath.IsEmpty()) {
|
||||
if (SandboxInfo::Get().Test(SandboxInfo::kVerbose)) {
|
||||
SANDBOX_LOG("Tempdir: /tmp");
|
||||
}
|
||||
} else {
|
||||
if (SandboxInfo::Get().Test(SandboxInfo::kVerbose)) {
|
||||
SANDBOX_LOG("Tempdir: %s", mTempPath.get());
|
||||
}
|
||||
// If it's /tmp, clear it here so we don't compare against
|
||||
// it twice. Just let the fallback code do the work.
|
||||
if (mTempPath.Equals(tempDirPrefix)) {
|
||||
mTempPath.Truncate();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
while (true) {
|
||||
struct iovec ios[2];
|
||||
// We will receive the path strings in 1 buffer and split them back up.
|
||||
|
@ -802,14 +729,6 @@ void SandboxBroker::ThreadMain(void) {
|
|||
pathLen = ConvertRelativePath(pathBuf, sizeof(pathBuf), pathLen);
|
||||
perms = mPolicy->Lookup(nsDependentCString(pathBuf, pathLen));
|
||||
|
||||
// We don't have permissions on the requested dir.
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
if (!perms) {
|
||||
// Was it a tempdir that we can remap?
|
||||
pathLen = RemapTempDirs(pathBuf, sizeof(pathBuf), pathLen);
|
||||
perms = mPolicy->Lookup(nsDependentCString(pathBuf, pathLen));
|
||||
}
|
||||
#endif
|
||||
if (!perms) {
|
||||
// Did we arrive from a symlink in a path that is not writable?
|
||||
// Then try to figure out the original path and see if that is
|
||||
|
|
|
@ -144,10 +144,6 @@ class SandboxBroker final : private SandboxBrokerCommon,
|
|||
int mFileDesc;
|
||||
const int mChildPid;
|
||||
const UniquePtr<const Policy> mPolicy;
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
nsCString mTempPath;
|
||||
nsCString mContentTempPath;
|
||||
#endif
|
||||
|
||||
typedef nsTHashMap<nsCStringHashKey, nsCString> PathMap;
|
||||
PathMap mSymlinkMap;
|
||||
|
@ -161,10 +157,6 @@ class SandboxBroker final : private SandboxBrokerCommon,
|
|||
// Remap relative paths to absolute paths.
|
||||
size_t ConvertRelativePath(char* aPath, size_t aBufSize, size_t aPathLen);
|
||||
size_t RealPath(char* aPath, size_t aBufSize, size_t aPathLen);
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
// Remap references to /tmp and friends to the content process tempdir
|
||||
size_t RemapTempDirs(char* aPath, size_t aBufSize, size_t aPathLen);
|
||||
#endif
|
||||
nsCString ReverseSymlinks(const nsACString& aPath);
|
||||
// Retrieves permissions for the path the original symlink sits in.
|
||||
int SymlinkPermissions(const char* aPath, const size_t aPathLen);
|
||||
|
|
|
@ -680,20 +680,6 @@ void SandboxBrokerPolicyFactory::InitContentPolicy() {
|
|||
AddDynamicPathList(policy, "security.sandbox.content.read_path_whitelist",
|
||||
rdonly);
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
// Add write permissions on the content process specific temporary dir.
|
||||
nsCOMPtr<nsIFile> tmpDir;
|
||||
rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
|
||||
getter_AddRefs(tmpDir));
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsAutoCString tmpPath;
|
||||
rv = tmpDir->GetNativePath(tmpPath);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
policy->AddDir(rdwrcr, tmpPath.get());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// userContent.css and the extensions dir sit in the profile, which is
|
||||
// normally blocked.
|
||||
nsCOMPtr<nsIFile> profileDir;
|
||||
|
|
|
@ -3,55 +3,84 @@
|
|||
/* import-globals-from browser_content_sandbox_utils.js */
|
||||
"use strict";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
/* getLibcConstants is only present on *nix */
|
||||
ChromeUtils.defineLazyGetter(lazy, "LIBC", () =>
|
||||
ChromeUtils.getLibcConstants()
|
||||
);
|
||||
|
||||
// Test if the content process can create in $HOME, this should fail
|
||||
async function createFileInHome() {
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let homeFile = fileInHomeDir();
|
||||
let path = homeFile.path;
|
||||
let fileCreated = await SpecialPowers.spawn(browser, [path], createFile);
|
||||
ok(!fileCreated.ok, "creating a file in home dir is not permitted");
|
||||
ok(!fileCreated.ok, "creating a file in home dir failed");
|
||||
is(
|
||||
fileCreated.code,
|
||||
Cr.NS_ERROR_FILE_ACCESS_DENIED,
|
||||
"creating a file in home dir failed with access denied"
|
||||
);
|
||||
if (fileCreated.ok) {
|
||||
// content process successfully created the file, now remove it
|
||||
homeFile.remove(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Test if the content process can create a temp file, this is disallowed on
|
||||
// macOS and Windows but allowed everywhere else. Also test that the content
|
||||
// process cannot create symlinks on macOS or delete files.
|
||||
// Test if the content process can create a temp file, this is forbidden on all
|
||||
// platforms. Also test that the content process cannot create symlinks on
|
||||
// macOS/Linux or delete files.
|
||||
async function createTempFile() {
|
||||
// On Windows we allow access to the temp dir for DEBUG builds, because of
|
||||
// logging that uses that dir.
|
||||
let isOptWin = isWin() && !SpecialPowers.isDebugBuild;
|
||||
let isDbgWin = isWin() && SpecialPowers.isDebugBuild;
|
||||
|
||||
let browser = gBrowser.selectedBrowser;
|
||||
let path = fileInTempDir().path;
|
||||
let fileCreated = await SpecialPowers.spawn(browser, [path], createFile);
|
||||
if (isMac() || isOptWin) {
|
||||
ok(!fileCreated.ok, "creating a file in temp is not permitted");
|
||||
if (isDbgWin) {
|
||||
ok(fileCreated.ok, "creating a file in temp suceeded");
|
||||
} else {
|
||||
ok(!!fileCreated.ok, "creating a file in temp is permitted");
|
||||
}
|
||||
// now delete the file
|
||||
let fileDeleted = await SpecialPowers.spawn(browser, [path], deleteFile);
|
||||
if (isMac() || isOptWin) {
|
||||
// On macOS we do not allow file deletion - it is not needed by the content
|
||||
// process itself, and macOS uses a different permission to control access
|
||||
// so revoking it is easy.
|
||||
ok(!fileDeleted.ok, "deleting a file in temp is not permitted");
|
||||
} else {
|
||||
ok(!!fileDeleted.ok, "deleting a file in temp is permitted");
|
||||
ok(!fileCreated.ok, "creating a file in temp failed");
|
||||
is(
|
||||
fileCreated.code,
|
||||
Cr.NS_ERROR_FILE_ACCESS_DENIED,
|
||||
"creating a file in temp failed with access denied"
|
||||
);
|
||||
}
|
||||
|
||||
// Test that symlink creation is not allowed on macOS.
|
||||
if (isMac()) {
|
||||
// now delete the file
|
||||
let fileDeleted = await SpecialPowers.spawn(browser, [path], deleteFile);
|
||||
if (isDbgWin) {
|
||||
ok(fileDeleted.ok, "deleting a file in temp succeeded");
|
||||
} else {
|
||||
ok(!fileDeleted.ok, "deleting a file in temp failed");
|
||||
const expectedError = isLinux()
|
||||
? Cr.NS_ERROR_FILE_ACCESS_DENIED
|
||||
: Cr.NS_ERROR_FILE_NOT_FOUND;
|
||||
is(
|
||||
fileDeleted.code,
|
||||
expectedError,
|
||||
"deleting a file in temp failed with access denied"
|
||||
);
|
||||
}
|
||||
|
||||
// Test that symlink creation is not allowed on macOS/Linux.
|
||||
if (isMac() || isLinux()) {
|
||||
let path = fileInTempDir().path;
|
||||
let symlinkCreated = await SpecialPowers.spawn(
|
||||
browser,
|
||||
[path],
|
||||
createSymlink
|
||||
);
|
||||
ok(!symlinkCreated.ok, "created a symlink in temp is not permitted");
|
||||
ok(!symlinkCreated.ok, "created a symlink in temp failed");
|
||||
const expectedError = isLinux() ? lazy.LIBC.EACCES : lazy.LIBC.EPERM;
|
||||
is(
|
||||
symlinkCreated.code,
|
||||
expectedError,
|
||||
"created a symlink in temp failed with access denied"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -301,8 +301,8 @@ add_task(async function () {
|
|||
// use open syscall
|
||||
if (isLinux() || isMac()) {
|
||||
// open a file for writing in the content temp dir, this should fail on
|
||||
// macOS and work on Linux. The open handler in the content process closes
|
||||
// the file for us
|
||||
// macOS and Linux. The open handler in the content process closes the file
|
||||
// for us
|
||||
let path = fileInTempDir().path;
|
||||
let flags = lazy.LIBC.O_CREAT | lazy.LIBC.O_WRONLY;
|
||||
let fd = await SpecialPowers.spawn(
|
||||
|
@ -310,19 +310,11 @@ add_task(async function () {
|
|||
[{ lib, path, flags }],
|
||||
callOpen
|
||||
);
|
||||
if (isMac()) {
|
||||
Assert.strictEqual(
|
||||
fd,
|
||||
-1,
|
||||
"opening a file for writing in content temp is not permitted"
|
||||
);
|
||||
} else {
|
||||
Assert.greaterOrEqual(
|
||||
fd,
|
||||
0,
|
||||
"opening a file for writing in content temp is permitted"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// use fork syscall
|
||||
|
|
|
@ -48,6 +48,8 @@ function sanityChecks() {
|
|||
// with .ok boolean to indicate true if the file was successfully created,
|
||||
// otherwise false. Include imports so this can be safely serialized and run
|
||||
// remotely by ContentTask.spawn.
|
||||
//
|
||||
// Report the exception's error code in .code as well.
|
||||
function createFile(path) {
|
||||
const { FileUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FileUtils.sys.mjs"
|
||||
|
@ -76,7 +78,7 @@ function createFile(path) {
|
|||
ostream.close();
|
||||
fstream.close();
|
||||
} catch (e) {
|
||||
return { ok: false };
|
||||
return { ok: false, code: e.result };
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
|
@ -86,14 +88,19 @@ function createFile(path) {
|
|||
// object with .ok boolean to indicate true if the symlink was successfully
|
||||
// created, otherwise false. Include imports so this can be safely serialized
|
||||
// and run remotely by ContentTask.spawn.
|
||||
//
|
||||
// Report the exception's error code in .code as well.
|
||||
// Report errno in .code if syscall returns -1.
|
||||
function createSymlink(path) {
|
||||
const { ctypes } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/ctypes.sys.mjs"
|
||||
);
|
||||
|
||||
try {
|
||||
// Trying to open "libc.so" on linux will fail with invalid elf header error
|
||||
// because it would be a linker script. Using libc.so.6 avoids that.
|
||||
const libc = ctypes.open(
|
||||
Services.appinfo.OS === "Darwin" ? "libSystem.B.dylib" : "libc.so"
|
||||
Services.appinfo.OS === "Darwin" ? "libSystem.B.dylib" : "libc.so.6"
|
||||
);
|
||||
|
||||
const symlink = libc.declare(
|
||||
|
@ -104,11 +111,14 @@ function createSymlink(path) {
|
|||
ctypes.char.ptr //linkpath
|
||||
);
|
||||
|
||||
if (symlink("/etc", path)) {
|
||||
return { ok: false };
|
||||
ctypes.errno = 0;
|
||||
const rv = symlink("/etc", path);
|
||||
const _errno = ctypes.errno;
|
||||
if (rv < 0) {
|
||||
return { ok: false, code: _errno };
|
||||
}
|
||||
} catch (e) {
|
||||
return { ok: false };
|
||||
return { ok: false, code: e.result };
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
|
@ -118,6 +128,8 @@ function createSymlink(path) {
|
|||
// with .ok boolean to indicate true if the file was successfully deleted,
|
||||
// otherwise false. Include imports so this can be safely serialized and run
|
||||
// remotely by ContentTask.spawn.
|
||||
//
|
||||
// Report the exception's error code in .code as well.
|
||||
function deleteFile(path) {
|
||||
const { FileUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FileUtils.sys.mjs"
|
||||
|
@ -127,7 +139,7 @@ function deleteFile(path) {
|
|||
const file = new FileUtils.File(path);
|
||||
file.remove(false);
|
||||
} catch (e) {
|
||||
return { ok: false };
|
||||
return { ok: false, code: e.result };
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
|
@ -137,6 +149,8 @@ function deleteFile(path) {
|
|||
// iteration over the directory finishes or encounters an error. The promise
|
||||
// resolves with an object where .ok indicates success or failure and
|
||||
// .numEntries is the number of directory entries found.
|
||||
//
|
||||
// Report the exception's error code in .code as well.
|
||||
function readDir(path) {
|
||||
const { FileUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FileUtils.sys.mjs"
|
||||
|
@ -153,7 +167,7 @@ function readDir(path) {
|
|||
numEntries++;
|
||||
}
|
||||
} catch (e) {
|
||||
return { ok: false, numEntries };
|
||||
return { ok: false, numEntries, code: e.result };
|
||||
}
|
||||
|
||||
return { ok: true, numEntries };
|
||||
|
@ -162,6 +176,8 @@ function readDir(path) {
|
|||
// Reads the file at |path| and returns a promise that resolves when
|
||||
// reading is completed. Returned object has boolean .ok to indicate
|
||||
// success or failure.
|
||||
//
|
||||
// Report the exception's error code in .code as well.
|
||||
function readFile(path) {
|
||||
const { FileUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FileUtils.sys.mjs"
|
||||
|
@ -183,7 +199,7 @@ function readFile(path) {
|
|||
const available = istream.available();
|
||||
void istream.readBytes(available);
|
||||
} catch (e) {
|
||||
return { ok: false };
|
||||
return { ok: false, code: e.result };
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
|
@ -192,6 +208,8 @@ function readFile(path) {
|
|||
// Does a stat of |path| and returns a promise that resolves if the
|
||||
// stat is successful. Returned object has boolean .ok to indicate
|
||||
// success or failure.
|
||||
//
|
||||
// Report the exception's error code in .code as well.
|
||||
function statPath(path) {
|
||||
const { FileUtils } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/FileUtils.sys.mjs"
|
||||
|
@ -201,7 +219,7 @@ function statPath(path) {
|
|||
const file = new FileUtils.File(path);
|
||||
void file.lastModifiedTime;
|
||||
} catch (e) {
|
||||
return { ok: false };
|
||||
return { ok: false, code: e.result };
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
|
|
|
@ -3497,9 +3497,6 @@ option(
|
|||
set_config("MOZ_SANDBOX", True, when="--enable-sandbox")
|
||||
set_define("MOZ_SANDBOX", True, when="--enable-sandbox")
|
||||
|
||||
with only_when(depends(target.kernel)(lambda k: k not in ("Darwin", "WINNT"))):
|
||||
set_define("MOZ_CONTENT_TEMP_DIR", True, when="--enable-sandbox")
|
||||
|
||||
# Searching of system directories for extensions.
|
||||
# ==============================================================
|
||||
# Note: this switch is meant to be used for test builds whose behavior should
|
||||
|
|
|
@ -80,12 +80,6 @@
|
|||
# include "UIKitDirProvider.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
# include "mozilla/SandboxSettings.h"
|
||||
# include "nsID.h"
|
||||
# include "mozilla/Unused.h"
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
# define APP_REGISTRY_NAME "Application Registry"
|
||||
#elif defined(XP_WIN)
|
||||
|
@ -96,16 +90,6 @@
|
|||
|
||||
#define PREF_OVERRIDE_DIRNAME "preferences"
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
static already_AddRefed<nsIFile> GetProcessSandboxTempDir(
|
||||
GeckoProcessType type);
|
||||
static nsresult DeleteDirIfExists(nsIFile* dir);
|
||||
static bool IsContentSandboxDisabled();
|
||||
static const char* GetProcessTempBaseDirKey();
|
||||
static already_AddRefed<nsIFile> CreateProcessSandboxTempDir(
|
||||
GeckoProcessType procType);
|
||||
#endif
|
||||
|
||||
nsXREDirProvider* gDirServiceProvider = nullptr;
|
||||
nsIFile* gDataDirHomeLocal = nullptr;
|
||||
nsIFile* gDataDirHome = nullptr;
|
||||
|
@ -447,17 +431,7 @@ nsXREDirProvider::GetFile(const char* aProperty, bool* aPersistent,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
bool unused;
|
||||
rv = dirsvc->GetFile("XCurProcD", &unused, getter_AddRefs(file));
|
||||
}
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
else if (!strcmp(aProperty, NS_APP_CONTENT_PROCESS_TEMP_DIR)) {
|
||||
if (!mContentTempDir) {
|
||||
rv = LoadContentProcessTempDir();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
rv = mContentTempDir->Clone(getter_AddRefs(file));
|
||||
}
|
||||
#endif // defined(MOZ_CONTENT_TEMP_DIR)
|
||||
else if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
|
||||
} else if (!strcmp(aProperty, NS_APP_USER_CHROME_DIR)) {
|
||||
// It isn't clear why this uses GetProfileStartupDir instead of
|
||||
// GetProfileDir. It could theoretically matter in a non-main
|
||||
// process where some other directory provider has defined
|
||||
|
@ -519,166 +493,6 @@ static void LoadDirIntoArray(nsIFile* dir, const char* const* aAppendList,
|
|||
}
|
||||
}
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
|
||||
static const char* GetProcessTempBaseDirKey() { return NS_OS_TEMP_DIR; }
|
||||
|
||||
//
|
||||
// Sets mContentTempDir so that it refers to the appropriate temp dir.
|
||||
// If the sandbox is enabled, NS_APP_CONTENT_PROCESS_TEMP_DIR, otherwise
|
||||
// NS_OS_TEMP_DIR is used.
|
||||
//
|
||||
nsresult nsXREDirProvider::LoadContentProcessTempDir() {
|
||||
// The parent is responsible for creating the sandbox temp dir.
|
||||
if (XRE_IsParentProcess()) {
|
||||
mContentProcessSandboxTempDir =
|
||||
CreateProcessSandboxTempDir(GeckoProcessType_Content);
|
||||
mContentTempDir = mContentProcessSandboxTempDir;
|
||||
} else {
|
||||
mContentTempDir = !IsContentSandboxDisabled()
|
||||
? GetProcessSandboxTempDir(GeckoProcessType_Content)
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
if (!mContentTempDir) {
|
||||
nsresult rv =
|
||||
NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mContentTempDir));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool IsContentSandboxDisabled() {
|
||||
return !mozilla::BrowserTabsRemoteAutostart() ||
|
||||
(!mozilla::IsContentSandboxEnabled());
|
||||
}
|
||||
|
||||
//
|
||||
// If a process sandbox temp dir is to be used, returns an nsIFile
|
||||
// for the directory. Returns null if an error occurs.
|
||||
//
|
||||
static already_AddRefed<nsIFile> GetProcessSandboxTempDir(
|
||||
GeckoProcessType type) {
|
||||
nsCOMPtr<nsIFile> localFile;
|
||||
|
||||
nsresult rv = NS_GetSpecialDirectory(GetProcessTempBaseDirKey(),
|
||||
getter_AddRefs(localFile));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(type == GeckoProcessType_Content);
|
||||
|
||||
const char* prefKey = "security.sandbox.content.tempDirSuffix";
|
||||
nsAutoString tempDirSuffix;
|
||||
rv = mozilla::Preferences::GetString(prefKey, tempDirSuffix);
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || tempDirSuffix.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rv = localFile->Append(u"Temp-"_ns + tempDirSuffix);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return localFile.forget();
|
||||
}
|
||||
|
||||
//
|
||||
// Create a temporary directory for use from sandboxed processes.
|
||||
// Only called in the parent. The path is derived from a UUID stored in a
|
||||
// pref which is available to content processes. Returns null
|
||||
// if the content sandbox is disabled or if an error occurs.
|
||||
//
|
||||
static already_AddRefed<nsIFile> CreateProcessSandboxTempDir(
|
||||
GeckoProcessType procType) {
|
||||
if ((procType == GeckoProcessType_Content) && IsContentSandboxDisabled()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(procType == GeckoProcessType_Content);
|
||||
|
||||
// Get (and create if blank) temp directory suffix pref.
|
||||
const char* pref = "security.sandbox.content.tempDirSuffix";
|
||||
|
||||
nsresult rv;
|
||||
nsAutoString tempDirSuffix;
|
||||
mozilla::Preferences::GetString(pref, tempDirSuffix);
|
||||
|
||||
if (tempDirSuffix.IsEmpty()) {
|
||||
nsID uuid;
|
||||
rv = nsID::GenerateUUIDInPlace(uuid);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char uuidChars[NSID_LENGTH];
|
||||
uuid.ToProvidedString(uuidChars);
|
||||
tempDirSuffix.AssignASCII(uuidChars, NSID_LENGTH);
|
||||
# ifdef XP_UNIX
|
||||
// Braces in a path are somewhat annoying to deal with
|
||||
// and pretty alien on Unix
|
||||
tempDirSuffix.StripChars(u"{}");
|
||||
# endif
|
||||
|
||||
// Save the pref
|
||||
rv = mozilla::Preferences::SetString(pref, tempDirSuffix);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
// If we fail to save the pref we don't want to create the temp dir,
|
||||
// because we won't be able to clean it up later.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrefService> prefsvc = mozilla::Preferences::GetService();
|
||||
if (!prefsvc || NS_FAILED((rv = prefsvc->SavePrefFile(nullptr)))) {
|
||||
// Again, if we fail to save the pref file we might not be able to clean
|
||||
// up the temp directory, so don't create one. Note that in the case
|
||||
// the preference values allows an off main thread save, the successful
|
||||
// return from the call doesn't mean we actually saved the file. See
|
||||
// bug 1364496 for details.
|
||||
NS_WARNING("Failed to save pref file, cannot create temp dir.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIFile> sandboxTempDir = GetProcessSandboxTempDir(procType);
|
||||
if (!sandboxTempDir) {
|
||||
NS_WARNING("Failed to determine sandbox temp dir path.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Remove the directory. It may exist due to a previous crash.
|
||||
if (NS_FAILED(DeleteDirIfExists(sandboxTempDir))) {
|
||||
NS_WARNING("Failed to reset sandbox temp dir.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create the directory
|
||||
rv = sandboxTempDir->Create(nsIFile::DIRECTORY_TYPE, 0700);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Failed to create sandbox temp dir.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return sandboxTempDir.forget();
|
||||
}
|
||||
|
||||
static nsresult DeleteDirIfExists(nsIFile* dir) {
|
||||
if (dir) {
|
||||
// Don't return an error if the directory doesn't exist.
|
||||
nsresult rv = dir->Remove(/* aRecursive */ true);
|
||||
if (NS_FAILED(rv) && rv != NS_ERROR_FILE_NOT_FOUND) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#endif // defined(MOZ_CONTENT_TEMP_DIR)
|
||||
|
||||
static const char* const kAppendPrefDir[] = {"defaults", "preferences",
|
||||
nullptr};
|
||||
#ifdef MOZ_BACKGROUNDTASKS
|
||||
|
@ -855,15 +669,6 @@ nsXREDirProvider::DoStartup() {
|
|||
mozilla::Telemetry::Accumulate(mozilla::Telemetry::SAFE_MODE_USAGE, mode);
|
||||
|
||||
obsSvc->NotifyObservers(nullptr, "profile-initial-state", nullptr);
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
// Makes sure the content temp dir has been loaded if it hasn't been
|
||||
// already. In the parent this ensures it has been created before we attempt
|
||||
// to start any content processes.
|
||||
if (!mContentTempDir) {
|
||||
mozilla::Unused << NS_WARN_IF(NS_FAILED(LoadContentProcessTempDir()));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -895,12 +700,6 @@ void nsXREDirProvider::DoShutdown() {
|
|||
|
||||
gDataDirProfileLocal = nullptr;
|
||||
gDataDirProfile = nullptr;
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
if (XRE_IsParentProcess()) {
|
||||
mozilla::Unused << DeleteDirIfExists(mContentProcessSandboxTempDir);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
|
|
|
@ -132,11 +132,6 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2,
|
|||
static nsresult SetUserDataProfileDirectory(nsCOMPtr<nsIFile>& aFile,
|
||||
bool aLocal);
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
// Load the temp directory for sandboxed content processes
|
||||
nsresult LoadContentProcessTempDir();
|
||||
#endif
|
||||
|
||||
void Append(nsIFile* aDirectory);
|
||||
|
||||
// On OSX, mGREDir points to .app/Contents/Resources
|
||||
|
@ -149,10 +144,6 @@ class nsXREDirProvider final : public nsIDirectoryServiceProvider2,
|
|||
nsCOMPtr<nsIFile> mProfileLocalDir;
|
||||
bool mAppStarted = false;
|
||||
bool mPrefsInitialized = false;
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
nsCOMPtr<nsIFile> mContentTempDir;
|
||||
nsCOMPtr<nsIFile> mContentProcessSandboxTempDir;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -74,29 +74,4 @@
|
|||
|
||||
#define NS_APP_PERMISSION_PARENT_DIR "permissionDBPDir"
|
||||
|
||||
#if defined(MOZ_CONTENT_TEMP_DIR)
|
||||
//
|
||||
// NS_APP_CONTENT_PROCESS_TEMP_DIR refers to a directory that is read and
|
||||
// write accessible from a sandboxed content process. The key may be used in
|
||||
// either process, but the directory is intended to be used for short-lived
|
||||
// files that need to be saved to the filesystem by the content process and
|
||||
// don't need to survive browser restarts. The directory is reset on startup.
|
||||
//
|
||||
// When MOZ_CONTENT_TEMP_DIR is defined and sandboxing is enabled (versus
|
||||
// manually disabled via prefs), the content process replaces NS_OS_TEMP_DIR
|
||||
// with NS_APP_CONTENT_PROCESS_TEMP_DIR so that legacy code in content
|
||||
// attempting to write to NS_OS_TEMP_DIR will write to
|
||||
// NS_APP_CONTENT_PROCESS_TEMP_DIR instead. When MOZ_SANDBOX is
|
||||
// defined but sandboxing is disabled, NS_APP_CONTENT_PROCESS_TEMP_DIR
|
||||
// falls back to NS_OS_TEMP_DIR in both content and chrome processes.
|
||||
//
|
||||
// New code should avoid writing to the filesystem from the content process
|
||||
// and should instead proxy through the parent process whenever possible.
|
||||
//
|
||||
// At present, all sandboxed content processes use the same directory for
|
||||
// NS_APP_CONTENT_PROCESS_TEMP_DIR, but that should not be relied upon.
|
||||
//
|
||||
# define NS_APP_CONTENT_PROCESS_TEMP_DIR "ContentTmpD"
|
||||
#endif // defined(MOZ_SANDBOX)
|
||||
|
||||
#endif // nsAppDirectoryServiceDefs_h___
|
||||
|
|
Загрузка…
Ссылка в новой задаче