Bug 990230 - Fix heap use-after-free in memory reporter. r=n.nethercote

This commit is contained in:
Dave Hylands
2014-04-17 16:57:30 -07:00
parent 40ec2911c2
commit 258fc06a82
2 changed files with 53 additions and 35 deletions

View File

@@ -11,7 +11,7 @@
#include <errno.h> #include <errno.h>
#include "mozilla/Services.h" #include "mozilla/Services.h"
#include "nsIObserverService.h" #include "nsIObserverService.h"
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#if defined(XP_LINUX) || defined(__FreeBSD__) // { #if defined(XP_LINUX) || defined(__FreeBSD__) // {
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
@@ -20,6 +20,8 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
using namespace mozilla;
/* /*
* The following code supports triggering a registered callback upon * The following code supports triggering a registered callback upon
* receiving a specific signal. * receiving a specific signal.
@@ -118,25 +120,26 @@ SignalPipeWatcher::GetSingleton()
return sSingleton; return sSingleton;
} }
/* static */ void void
SignalPipeWatcher::RegisterCallback(const uint8_t aSignal, SignalPipeWatcher::RegisterCallback(uint8_t aSignal,
PipeCallback aCallback) PipeCallback aCallback)
{ {
for (SignalInfoArray::index_type i = 0; MutexAutoLock lock(mSignalInfoLock);
i < SignalPipeWatcher::mSignalInfo.Length(); i++)
for (SignalInfoArray::index_type i = 0; i < mSignalInfo.Length(); i++)
{ {
if (SignalPipeWatcher::mSignalInfo[i].mSignal == aSignal) { if (mSignalInfo[i].mSignal == aSignal) {
LOG("Register Signal(%d) callback failed! (DUPLICATE)", aSignal); LOG("Register Signal(%d) callback failed! (DUPLICATE)", aSignal);
return; return;
} }
} }
SignalInfo aSignalInfo = { aSignal, aCallback }; SignalInfo signalInfo = { aSignal, aCallback };
SignalPipeWatcher::mSignalInfo.AppendElement(aSignalInfo); mSignalInfo.AppendElement(signalInfo);
SignalPipeWatcher::RegisterSignalHandler(aSignalInfo.mSignal); RegisterSignalHandler(signalInfo.mSignal);
} }
/* static */ void void
SignalPipeWatcher::RegisterSignalHandler(const uint8_t aSignal) SignalPipeWatcher::RegisterSignalHandler(uint8_t aSignal)
{ {
struct sigaction action; struct sigaction action;
memset(&action, 0, sizeof(action)); memset(&action, 0, sizeof(action));
@@ -148,10 +151,11 @@ SignalPipeWatcher::RegisterSignalHandler(const uint8_t aSignal)
LOG("SignalPipeWatcher failed to register sig %d.", aSignal); LOG("SignalPipeWatcher failed to register sig %d.", aSignal);
} }
} else { } else {
for (SignalInfoArray::index_type i = 0; i < SignalPipeWatcher::mSignalInfo.Length(); i++) { MutexAutoLock lock(mSignalInfoLock);
if (sigaction(SignalPipeWatcher::mSignalInfo[i].mSignal, &action, nullptr)) { for (SignalInfoArray::index_type i = 0; i < mSignalInfo.Length(); i++) {
if (sigaction(mSignalInfo[i].mSignal, &action, nullptr)) {
LOG("SignalPipeWatcher failed to register signal(%d) " LOG("SignalPipeWatcher failed to register signal(%d) "
"dump signal handler.",SignalPipeWatcher::mSignalInfo[i].mSignal); "dump signal handler.", mSignalInfo[i].mSignal);
} }
} }
} }
@@ -159,8 +163,9 @@ SignalPipeWatcher::RegisterSignalHandler(const uint8_t aSignal)
SignalPipeWatcher::~SignalPipeWatcher() SignalPipeWatcher::~SignalPipeWatcher()
{ {
if (sDumpPipeWriteFd != -1) if (sDumpPipeWriteFd != -1) {
SignalPipeWatcher::StopWatching(); StopWatching();
}
} }
int SignalPipeWatcher::OpenFd() int SignalPipeWatcher::OpenFd()
@@ -182,7 +187,7 @@ int SignalPipeWatcher::OpenFd()
int readFd = pipeFds[0]; int readFd = pipeFds[0];
sDumpPipeWriteFd = pipeFds[1]; sDumpPipeWriteFd = pipeFds[1];
SignalPipeWatcher::RegisterSignalHandler(); RegisterSignalHandler();
return readFd; return readFd;
} }
@@ -215,12 +220,15 @@ void SignalPipeWatcher::OnFileCanReadWithoutBlocking(int aFd)
return; return;
} }
for (SignalInfoArray::index_type i = 0; i < SignalPipeWatcher::mSignalInfo.Length(); i++) { {
if(signum == SignalPipeWatcher::mSignalInfo[i].mSignal) { MutexAutoLock lock(mSignalInfoLock);
SignalPipeWatcher::mSignalInfo[i].mCallback(signum); for (SignalInfoArray::index_type i = 0; i < mSignalInfo.Length(); i++) {
if(signum == mSignalInfo[i].mSignal) {
mSignalInfo[i].mCallback(signum);
return; return;
} }
} }
}
LOG("SignalPipeWatcher got unexpected signum."); LOG("SignalPipeWatcher got unexpected signum.");
} }
@@ -257,25 +265,26 @@ FifoWatcher::MaybeCreate()
} }
// The FifoWatcher is held alive by the observer service. // The FifoWatcher is held alive by the observer service.
if (!FifoWatcher::sSingleton) { if (!sSingleton) {
FifoWatcher::GetSingleton(); GetSingleton();
} }
return true; return true;
} }
void void
FifoWatcher::RegisterCallback(const nsCString& aCommand,FifoCallback aCallback) FifoWatcher::RegisterCallback(const nsCString& aCommand, FifoCallback aCallback)
{ {
for (FifoInfoArray::index_type i = 0; MutexAutoLock lock(mFifoInfoLock);
i < FifoWatcher::mFifoInfo.Length(); i++)
for (FifoInfoArray::index_type i = 0; i < mFifoInfo.Length(); i++)
{ {
if (FifoWatcher::mFifoInfo[i].mCommand.Equals(aCommand)) { if (mFifoInfo[i].mCommand.Equals(aCommand)) {
LOG("Register command(%s) callback failed! (DUPLICATE)", aCommand.get()); LOG("Register command(%s) callback failed! (DUPLICATE)", aCommand.get());
return; return;
} }
} }
FifoInfo aFifoInfo = { aCommand, aCallback }; FifoInfo aFifoInfo = { aCommand, aCallback };
FifoWatcher::mFifoInfo.AppendElement(aFifoInfo); mFifoInfo.AppendElement(aFifoInfo);
} }
FifoWatcher::~FifoWatcher() FifoWatcher::~FifoWatcher()
@@ -392,13 +401,17 @@ void FifoWatcher::OnFileCanReadWithoutBlocking(int aFd)
// it'll actually write "foo\n" to the fifo. // it'll actually write "foo\n" to the fifo.
inputStr.Trim("\b\t\r\n"); inputStr.Trim("\b\t\r\n");
for (FifoInfoArray::index_type i = 0; i < FifoWatcher::mFifoInfo.Length(); i++) { {
const nsCString commandStr = FifoWatcher::mFifoInfo[i].mCommand; MutexAutoLock lock(mFifoInfoLock);
for (FifoInfoArray::index_type i = 0; i < mFifoInfo.Length(); i++) {
const nsCString commandStr = mFifoInfo[i].mCommand;
if(inputStr == commandStr.get()) { if(inputStr == commandStr.get()) {
FifoWatcher::mFifoInfo[i].mCallback(inputStr); mFifoInfo[i].mCallback(inputStr);
return; return;
} }
} }
}
LOG("Got unexpected value from fifo; ignoring it."); LOG("Got unexpected value from fifo; ignoring it.");
} }

View File

@@ -11,6 +11,7 @@
#include "base/message_loop.h" #include "base/message_loop.h"
#include "nsXULAppAPI.h" #include "nsXULAppAPI.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "mozilla/Mutex.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "nsTArray.h" #include "nsTArray.h"
@@ -126,8 +127,10 @@ private:
FifoWatcher(nsCString aPath) FifoWatcher(nsCString aPath)
: mDirPath(aPath) : mDirPath(aPath)
, mFifoInfoLock("FifoWatcher.mFifoInfoLock")
{} {}
mozilla::Mutex mFifoInfoLock; // protects mFifoInfo
FifoInfoArray mFifoInfo; FifoInfoArray mFifoInfo;
}; };
@@ -143,9 +146,9 @@ class SignalPipeWatcher : public FdWatcher
public: public:
static SignalPipeWatcher* GetSingleton(); static SignalPipeWatcher* GetSingleton();
void RegisterCallback(const uint8_t aSignal, PipeCallback aCallback); void RegisterCallback(uint8_t aSignal, PipeCallback aCallback);
void RegisterSignalHandler(const uint8_t aSignal = 0); void RegisterSignalHandler(uint8_t aSignal = 0);
virtual ~SignalPipeWatcher(); virtual ~SignalPipeWatcher();
@@ -159,10 +162,12 @@ private:
static StaticRefPtr<SignalPipeWatcher> sSingleton; static StaticRefPtr<SignalPipeWatcher> sSingleton;
SignalPipeWatcher() SignalPipeWatcher()
: mSignalInfoLock("SignalPipeWatcher.mSignalInfoLock")
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
} }
mozilla::Mutex mSignalInfoLock; // protects mSignalInfo
SignalInfoArray mSignalInfo; SignalInfoArray mSignalInfo;
}; };