bug 1066326. Pre-load (load before starting sandbox) DLLs that are specified in the plugin info file and that are in a pre-approved whitelist. r=jesup, r=cpearce, r=bobowen

This commit is contained in:
Tim Abraldes 2014-10-09 08:45:22 -07:00
parent fe07bea80b
commit 0215cbf09a
2 changed files with 110 additions and 7 deletions

View File

@ -16,6 +16,10 @@
#include "gmp-video-encode.h" #include "gmp-video-encode.h"
#include "GMPPlatform.h" #include "GMPPlatform.h"
#include "mozilla/dom/CrashReporterChild.h" #include "mozilla/dom/CrashReporterChild.h"
#ifdef XP_WIN
#include <fstream>
#include "nsCRT.h"
#endif
using mozilla::dom::CrashReporterChild; using mozilla::dom::CrashReporterChild;
@ -51,28 +55,29 @@ GMPChild::~GMPChild()
} }
static bool static bool
GetPluginFile(const std::string& aPluginPath, GetFileBase(const std::string& aPluginPath,
#if defined(XP_MACOSX) #if defined(XP_MACOSX)
nsCOMPtr<nsIFile>& aLibDirectory, nsCOMPtr<nsIFile>& aLibDirectory,
#endif #endif
nsCOMPtr<nsIFile>& aLibFile) nsCOMPtr<nsIFile>& aFileBase,
nsAutoString& aBaseName)
{ {
nsDependentCString pluginPath(aPluginPath.c_str()); nsDependentCString pluginPath(aPluginPath.c_str());
nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(pluginPath), nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(pluginPath),
true, getter_AddRefs(aLibFile)); true, getter_AddRefs(aFileBase));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return false; return false;
} }
#if defined(XP_MACOSX) #if defined(XP_MACOSX)
if (NS_FAILED(aLibFile->Clone(getter_AddRefs(aLibDirectory)))) { if (NS_FAILED(aFileBase->Clone(getter_AddRefs(aLibDirectory)))) {
return false; return false;
} }
#endif #endif
nsCOMPtr<nsIFile> parent; nsCOMPtr<nsIFile> parent;
rv = aLibFile->GetParent(getter_AddRefs(parent)); rv = aFileBase->GetParent(getter_AddRefs(parent));
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return false; return false;
} }
@ -83,7 +88,25 @@ GetPluginFile(const std::string& aPluginPath,
return false; return false;
} }
nsAutoString baseName(Substring(parentLeafName, 4, parentLeafName.Length() - 1)); aBaseName = Substring(parentLeafName,
4,
parentLeafName.Length() - 1);
return true;
}
static bool
GetPluginFile(const std::string& aPluginPath,
#if defined(XP_MACOSX)
nsCOMPtr<nsIFile>& aLibDirectory,
#endif
nsCOMPtr<nsIFile>& aLibFile)
{
nsAutoString baseName;
#ifdef XP_MACOSX
GetFileBase(aPluginPath, aLibDirectory, aLibFile, baseName);
#else
GetFileBase(aPluginPath, aLibFile, baseName);
#endif
#if defined(XP_MACOSX) #if defined(XP_MACOSX)
nsAutoString binaryName = NS_LITERAL_STRING("lib") + baseName + NS_LITERAL_STRING(".dylib"); nsAutoString binaryName = NS_LITERAL_STRING("lib") + baseName + NS_LITERAL_STRING(".dylib");
@ -98,6 +121,19 @@ GetPluginFile(const std::string& aPluginPath,
return true; return true;
} }
#ifdef XP_WIN
static bool
GetInfoFile(const std::string& aPluginPath,
nsCOMPtr<nsIFile>& aInfoFile)
{
nsAutoString baseName;
GetFileBase(aPluginPath, aInfoFile, baseName);
nsAutoString infoFileName = baseName + NS_LITERAL_STRING(".info");
aInfoFile->AppendRelativePath(infoFileName);
return true;
}
#endif
#if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX) #if defined(XP_MACOSX) && defined(MOZ_GMP_SANDBOX)
static bool static bool
GetPluginPaths(const std::string& aPluginPath, GetPluginPaths(const std::string& aPluginPath,
@ -237,6 +273,10 @@ GMPChild::Init(const std::string& aPluginPath,
return true; return true;
#endif #endif
#ifdef XP_WIN
PreLoadLibraries(aPluginPath);
#endif
#if defined(MOZ_SANDBOX) && defined(XP_WIN) #if defined(MOZ_SANDBOX) && defined(XP_WIN)
mozilla::SandboxTarget::Instance()->StartSandbox(); mozilla::SandboxTarget::Instance()->StartSandbox();
#endif #endif
@ -244,6 +284,66 @@ GMPChild::Init(const std::string& aPluginPath,
return LoadPluginLibrary(aPluginPath); return LoadPluginLibrary(aPluginPath);
} }
#ifdef XP_WIN
// Pre-load DLLs that need to be used by the EME plugin but that can't be
// loaded after the sandbox has started
bool
GMPChild::PreLoadLibraries(const std::string& aPluginPath)
{
// This must be in sorted order and lowercase!
static const char* whitelist[] =
{
"d3d9.dll", // Create an `IDirect3D9` to get adapter information
"dxva2.dll", // Get monitor information
"msauddecmft.dll", // H.264 decoder
"msmpeg2adec.dll", // AAC decoder (on Windows 7)
"msmpeg2vdec.dll", // AAC decoder (on Windows 8)
};
static const int whitelistLen = sizeof(whitelist) / sizeof(whitelist[0]);
nsCOMPtr<nsIFile> infoFile;
GetInfoFile(aPluginPath, infoFile);
nsString path;
infoFile->GetPath(path);
std::ifstream stream;
stream.open(path.get());
if (!stream.good()) {
NS_WARNING("Failure opening info file for required DLLs");
return false;
}
do {
std::string line;
getline(stream, line);
if (stream.fail()) {
NS_WARNING("Failure reading info file for required DLLs");
return false;
}
std::transform(line.begin(), line.end(), line.begin(), tolower);
static const char* prefix = "libraries:";
static const int prefixLen = strlen(prefix);
if (0 == line.compare(0, prefixLen, prefix)) {
char* lineCopy = strdup(line.c_str() + prefixLen);
char* start = lineCopy;
while (char* tok = nsCRT::strtok(start, ", ", &start)) {
for (int i = 0; i < whitelistLen; i++) {
if (0 == strcmp(whitelist[i], tok)) {
LoadLibraryA(tok);
break;
}
}
}
free(lineCopy);
break;
}
} while (!stream.eof());
return true;
}
#endif
bool bool
GMPChild::LoadPluginLibrary(const std::string& aPluginPath) GMPChild::LoadPluginLibrary(const std::string& aPluginPath)
{ {

View File

@ -34,6 +34,9 @@ public:
MessageLoop* aIOLoop, MessageLoop* aIOLoop,
IPC::Channel* aChannel); IPC::Channel* aChannel);
bool LoadPluginLibrary(const std::string& aPluginPath); bool LoadPluginLibrary(const std::string& aPluginPath);
#ifdef XP_WIN
bool PreLoadLibraries(const std::string& aPluginPath);
#endif
MessageLoop* GMPMessageLoop(); MessageLoop* GMPMessageLoop();
// Main thread only. // Main thread only.