Bug 1840515 - Step 1: Use -greomni/-appomni for content processes. r=nika,mhowell

Currently, each content process re-derives the path(s) of the omnijar
file(s).  We used to pass it down as a command-line argument, but
those args were also accepted by the parent process and there were
issues with that (CVE-2020-6799) such that they were completely removed
(bug 1531475).  However, content processes can generally trust their
arguments; note that they currently accept `-appDir`.

We were already using `-gredir` for this on Android (it has a unified
omnijar, so there's no `-appdir` in that case); this patch subsumes the
content-process case of that, but not the parent process (which consumes
basically a fake argv constructed in Java code).

Note that only the parent process and content processes use the
omnijars; every other process type uses either minimal XPCOM, which
doesn't include them, or no XPCOM at all (e.g., GMP before bug 1845946).

The end goal of this patch series is to use those flags with the fork
server (so that it can preload the files without needing any XPCOM), but
this patch changes only the case of content processes.

Differential Revision: https://phabricator.services.mozilla.com/D182510
This commit is contained in:
Jed Davis 2023-08-09 21:35:49 +00:00
Родитель c9012150fb
Коммит 2ad421aaf8
6 изменённых файлов: 74 добавлений и 16 удалений

Просмотреть файл

@ -20,6 +20,7 @@
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/ProcessUtils.h"
#include "mozilla/GeckoArgs.h"
#include "mozilla/Omnijar.h"
#include "nsCategoryManagerUtils.h"
using mozilla::ipc::IOThreadChild;
@ -150,6 +151,9 @@ bool ContentProcess::Init(int aArgc, char* aArgv[]) {
return false;
}
// Handle the -greomni/-appomni flags
Omnijar::ChildProcessInit(aArgc, aArgv);
rv = NS_InitXPCOM(nullptr, xpcomAppDir, &mDirProvider);
if (NS_FAILED(rv)) {
return false;

Просмотреть файл

@ -1255,18 +1255,21 @@ Result<Ok, LaunchError> PosixProcessLauncher::DoSetup() {
mChildArgv.insert(mChildArgv.end(), mExtraOpts.begin(), mExtraOpts.end());
if (mProcessType != GeckoProcessType_GMPlugin) {
# if defined(MOZ_WIDGET_ANDROID)
if (Omnijar::IsInitialized()) {
// Make sure that child processes can find the omnijar
// See XRE_InitCommandLine in nsAppRunner.cpp
nsAutoCString path;
nsCOMPtr<nsIFile> file = Omnijar::GetPath(Omnijar::GRE);
if (file && NS_SUCCEEDED(file->GetNativePath(path))) {
geckoargs::sGREOmni.Put(path.get(), mChildArgv);
}
if (mProcessType == GeckoProcessType_Content && Omnijar::IsInitialized()) {
// Make sure that child processes can find the omnijar, if they
// use full XPCOM. See Omnijar::ChildProcessInit and its callers.
nsAutoCString path;
nsCOMPtr<nsIFile> greFile = Omnijar::GetPath(Omnijar::GRE);
if (greFile && NS_SUCCEEDED(greFile->GetNativePath(path))) {
geckoargs::sGREOmni.Put(path.get(), mChildArgv);
}
# endif
nsCOMPtr<nsIFile> appFile = Omnijar::GetPath(Omnijar::APP);
if (appFile && NS_SUCCEEDED(appFile->GetNativePath(path))) {
geckoargs::sAppOmni.Put(path.get(), mChildArgv);
}
}
if (mProcessType != GeckoProcessType_GMPlugin) {
// Add the application directory path (-appdir path)
# ifdef XP_MACOSX
AddAppDirToCommandLine(mChildArgv, mAppDir, mProfileDir);

Просмотреть файл

@ -5971,12 +5971,16 @@ nsresult XRE_InitCommandLine(int aArgc, char* aArgv[]) {
#endif
#if defined(MOZ_WIDGET_ANDROID)
nsCOMPtr<nsIFile> greOmni =
gAppData ? gAppData->xreDirectory : GreOmniPath(aArgc, aArgv);
if (!greOmni) {
return NS_ERROR_FAILURE;
// gAppData is non-null iff this is the parent process. Otherwise,
// the `-greomni`/`-appomni` flags are cross-platform and handled in
// ContentProcess::Init.
if (gAppData) {
nsCOMPtr<nsIFile> greOmni = gAppData->xreDirectory;
if (!greOmni) {
return NS_ERROR_FAILURE;
}
mozilla::Omnijar::Init(greOmni, greOmni);
}
mozilla::Omnijar::Init(greOmni, greOmni);
#endif
return rv;

Просмотреть файл

@ -8,6 +8,7 @@
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#include "mozilla/GeckoArgs.h"
#include "nsIFile.h"
#include "nsZipArchive.h"
#include "nsNetUtil.h"
@ -195,4 +196,36 @@ nsresult Omnijar::GetURIString(Type aType, nsACString& aResult) {
return NS_OK;
}
void Omnijar::ChildProcessInit(int& aArgc, char** aArgv) {
nsCOMPtr<nsIFile> greOmni, appOmni;
if (auto greOmniStr = geckoargs::sGREOmni.Get(aArgc, aArgv)) {
if (NS_WARN_IF(NS_FAILED(
XRE_GetFileFromPath(*greOmniStr, getter_AddRefs(greOmni))))) {
greOmni = nullptr;
}
}
if (auto appOmniStr = geckoargs::sAppOmni.Get(aArgc, aArgv)) {
if (NS_WARN_IF(NS_FAILED(
XRE_GetFileFromPath(*appOmniStr, getter_AddRefs(appOmni))))) {
appOmni = nullptr;
}
}
// If we're unified, then only the -greomni flag is present
// (reflecting the state of sPath in the parent process) but that
// path should be used for both (not nullptr, which will try to
// invoke the directory service, which probably isn't up yet.)
if (!appOmni) {
appOmni = greOmni;
}
if (greOmni) {
Init(greOmni, appOmni);
} else {
// We should never have an appOmni without a greOmni.
MOZ_ASSERT(!appOmni);
}
}
} /* namespace mozilla */

Просмотреть файл

@ -87,6 +87,15 @@ class Omnijar {
*/
static void Init(nsIFile* aGrePath = nullptr, nsIFile* aAppPath = nullptr);
/**
* Initializes the Omnijar API for a child process, given its argument
* list, if the `-greomni` flag and optionally also the `-appomni` flag
* is present. (`-appomni` is absent in the case of a unified jar.) If
* neither flag is present, the Omnijar API is not initialized. The
* flags, if present, will be removed from the argument list.
*/
static void ChildProcessInit(int& aArgc, char** aArgv);
/**
* Cleans up the Omnijar API
*/

Просмотреть файл

@ -354,6 +354,11 @@ NS_InitXPCOM(nsIServiceManager** aResult, nsIFile* aBinDirectory,
nsDirectoryService::gService->Set(NS_XPCOM_LIBRARY_FILE, xpcomLib);
if (!mozilla::Omnijar::IsInitialized()) {
// If you added a new process type that uses NS_InitXPCOM, and you're
// *sure* you don't want NS_InitMinimalXPCOM: in addition to everything
// else you'll probably have to do, please add it to the case in
// GeckoChildProcessHost.cpp which sets the greomni/appomni flags.
MOZ_ASSERT(XRE_IsParentProcess() || XRE_IsContentProcess());
mozilla::Omnijar::Init();
}