Bug 1477790: Add ability for firefox.exe to use launcher process by default when the build is configured to do so; r=mhowell

Since we don't want to inadvertently expose some way for malware to disable the
launcher via command-line/environment, I opted to query Windows for the PID of
the process that launched us, and then compare its executable path against ours.

Strictly speaking, the PROCESS_BASIC_INFORMATION::InheritedFromUniqueProcessId
field is not necessarily the parent pid, but it will match any process that was
created via the normal CreateProcess machinery.
This commit is contained in:
Aaron Klotz 2018-07-16 16:41:55 -06:00
Родитель 33fc6f7c47
Коммит 5d912c2b75
3 изменённых файлов: 75 добавлений и 5 удалений

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

@ -25,8 +25,7 @@
{ MOZ_LITERAL_UNICODE_STRING(L##name), __VA_ARGS__ },
#define DLL_BLOCKLIST_STRING_TYPE UNICODE_STRING
// Restrict the blocklist definitions to Nightly-only for now
#if defined(NIGHTLY_BUILD)
#if defined(MOZ_LAUNCHER_PROCESS) || defined(NIGHTLY_BUILD)
#include "mozilla/WindowsDllBlocklistDefs.h"
#else
#include "mozilla/WindowsDllBlocklistCommon.h"

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

@ -104,16 +104,60 @@ ProcessCmdLine(int& aArgc, wchar_t* aArgv[])
return result;
}
#if defined(MOZ_LAUNCHER_PROCESS)
static mozilla::Maybe<bool>
IsSameBinaryAsParentProcess()
{
mozilla::Maybe<DWORD> parentPid = mozilla::nt::GetParentProcessId();
if (!parentPid) {
return mozilla::Nothing();
}
nsAutoHandle parentProcess(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
FALSE, parentPid.value()));
if (!parentProcess.get()) {
return mozilla::Nothing();
}
WCHAR parentExe[MAX_PATH + 1] = {};
DWORD parentExeLen = mozilla::ArrayLength(parentExe);
if (!::QueryFullProcessImageNameW(parentProcess.get(), 0, parentExe,
&parentExeLen)) {
return mozilla::Nothing();
}
WCHAR ourExe[MAX_PATH + 1] = {};
DWORD ourExeOk = ::GetModuleFileNameW(nullptr, ourExe,
mozilla::ArrayLength(ourExe));
if (!ourExeOk || ourExeOk == mozilla::ArrayLength(ourExe)) {
return mozilla::Nothing();
}
bool isSame = parentExeLen == ourExeOk &&
!_wcsnicmp(ourExe, parentExe, ourExeOk);
return mozilla::Some(isSame);
}
#endif // defined(MOZ_LAUNCHER_PROCESS)
namespace mozilla {
// Eventually we want to be able to set a build config flag such that, when set,
// this function will always return true.
bool
RunAsLauncherProcess(int& argc, wchar_t** argv)
{
#if defined(MOZ_LAUNCHER_PROCESS)
Maybe<bool> isChildOfFirefox = IsSameBinaryAsParentProcess();
if (!isChildOfFirefox) {
return true;
}
return !isChildOfFirefox.value();
#else
return CheckArg(argc, argv, L"launcher",
static_cast<const wchar_t**>(nullptr),
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg);
CheckArgFlag::CheckOSInt | CheckArgFlag::RemoveArg) == ARG_FOUND;
#endif // defined(MOZ_LAUNCHER_PROCESS)
}
int

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

@ -18,6 +18,7 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
extern "C" {
@ -554,6 +555,32 @@ RtlGetProcessHeap()
return peb->Reserved4[1];
}
inline Maybe<DWORD>
GetParentProcessId()
{
struct PROCESS_BASIC_INFORMATION
{
NTSTATUS ExitStatus;
PPEB PebBaseAddress;
ULONG_PTR AffinityMask;
KPRIORITY BasePriority;
ULONG_PTR UniqueProcessId;
ULONG_PTR InheritedFromUniqueProcessId;
};
ULONG returnLength;
PROCESS_BASIC_INFORMATION pbi = {};
NTSTATUS status = ::NtQueryInformationProcess(::GetCurrentProcess(),
ProcessBasicInformation,
&pbi, sizeof(pbi),
&returnLength);
if (!NT_SUCCESS(status)) {
return Nothing();
}
return Some(static_cast<DWORD>(pbi.InheritedFromUniqueProcessId & 0xFFFFFFFF));
}
} // namespace nt
} // namespace mozilla