From 7082834baf05e9813ae84775decccaa79d68e3d9 Mon Sep 17 00:00:00 2001 From: Alphan Chen Date: Wed, 21 May 2014 13:49:36 +0800 Subject: [PATCH] Bug 996996 - Move fopen into non-sanboxed process. r=mrbkap --- dom/base/Navigator.cpp | 45 +++++++++++++-------------------- dom/ipc/ContentChild.cpp | 17 +++++++++++++ dom/ipc/ContentChild.h | 3 +++ dom/ipc/ContentParent.cpp | 19 ++++++++++++++ dom/ipc/ContentParent.h | 2 +- dom/ipc/PContent.ipdl | 4 +++ hal/Hal.cpp | 5 ++++ hal/Hal.h | 8 ++++++ hal/fallback/FallbackMemory.cpp | 6 +++++ hal/linux/LinuxMemory.cpp | 32 +++++++++++++++++++++++ 10 files changed, 113 insertions(+), 28 deletions(-) diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 8451e21e90f..cdad021ccdb 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -98,6 +98,11 @@ #include "WorkerPrivate.h" #include "WorkerRunnable.h" +#if defined(XP_LINUX) +#include "mozilla/Hal.h" +#endif +#include "mozilla/dom/ContentChild.h" + namespace mozilla { namespace dom { @@ -1483,41 +1488,27 @@ Navigator::GetFeature(const nsAString& aName) #if defined(XP_LINUX) if (aName.EqualsLiteral("hardware.memory")) { - static int memLevel = 1; - if (memLevel == 1) { - FILE* f = fopen("/proc/meminfo", "r"); - if (!f) { - p->MaybeReject(NS_LITERAL_STRING("CannotOpenMeminfo")); - return p.forget(); - } - - int memTotal; - int n = fscanf(f, "MemTotal: %d kB\n", &memTotal); - fclose(f); - - if (memTotal == 0 || n != 1) { + // with seccomp enabled, fopen() should be in a non-sandboxed process + if (XRE_GetProcessType() == GeckoProcessType_Default) { + uint32_t memLevel = mozilla::hal::GetTotalSystemMemoryLevel(); + if (memLevel == 0) { p->MaybeReject(NS_LITERAL_STRING("Abnormal")); return p.forget(); } - // From KB to MB - memTotal /= 1024; - - // round the value up to the next power of two - while (memLevel <= memTotal) { - memLevel *= 2; - } + p->MaybeResolve((int)memLevel); + } else { + mozilla::dom::ContentChild* cc = + mozilla::dom::ContentChild::GetSingleton(); + nsRefPtr ipcRef(p); + cc->SendGetSystemMemory(reinterpret_cast(ipcRef.forget().take())); } - p->MaybeResolve(memLevel); + return p.forget(); } // hardware.memory - else #endif - { - // resolve with because the feature name is not supported - p->MaybeResolve(JS::UndefinedHandleValue); - } + // resolve with because the feature name is not supported + p->MaybeResolve(JS::UndefinedHandleValue); return p.forget(); - } diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index d9defc47567..ccd2ba4847e 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -23,6 +23,7 @@ #include "mozilla/dom/ExternalHelperAppChild.h" #include "mozilla/dom/PCrashReporterChild.h" #include "mozilla/dom/DOMStorageIPC.h" +#include "mozilla/dom/Promise.h" #include "mozilla/hal_sandbox/PHalChild.h" #include "mozilla/ipc/BackgroundChild.h" #include "mozilla/ipc/FileDescriptorUtils.h" @@ -1437,6 +1438,22 @@ ContentChild::AddRemoteAlertObserver(const nsString& aData, return NS_OK; } + +bool +ContentChild::RecvSystemMemoryAvailable(const uint64_t& aGetterId, + const uint32_t& aMemoryAvailable) +{ + nsRefPtr p = dont_AddRef(reinterpret_cast(aGetterId)); + + if (!aMemoryAvailable) { + p->MaybeReject(NS_LITERAL_STRING("Abnormal")); + return true; + } + + p->MaybeResolve((int)aMemoryAvailable); + return true; +} + bool ContentChild::RecvPreferenceUpdate(const PrefSetting& aPref) { diff --git a/dom/ipc/ContentChild.h b/dom/ipc/ContentChild.h index 12b3f533dd7..556cbb18177 100644 --- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -218,6 +218,9 @@ public: // auto remove when alertfinished is received. nsresult AddRemoteAlertObserver(const nsString& aData, nsIObserver* aObserver); + virtual bool RecvSystemMemoryAvailable(const uint64_t& aGetterId, + const uint32_t& aMemoryAvailable) MOZ_OVERRIDE; + virtual bool RecvPreferenceUpdate(const PrefSetting& aPref) MOZ_OVERRIDE; virtual bool RecvNotifyAlertsObserver(const nsCString& aType, diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 9d480d1058e..77409ad8db7 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -119,6 +119,10 @@ #include "nsSystemInfo.h" #endif +#if defined(XP_LINUX) +#include "mozilla/Hal.h" +#endif + #ifdef ANDROID # include "gfxAndroidPlatform.h" #endif @@ -3056,6 +3060,21 @@ ContentParent::RecvGetRandomValues(const uint32_t& length, return true; } +bool +ContentParent::RecvGetSystemMemory(const uint64_t& aGetterId) +{ + uint32_t memoryTotal = 0; + +#if defined(XP_LINUX) + memoryTotal = mozilla::hal::GetTotalSystemMemoryLevel(); +#endif + + unused << SendSystemMemoryAvailable(aGetterId, memoryTotal); + + return true; +} + + bool ContentParent::RecvLoadURIExternal(const URIParams& uri) { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index f5d600b9dac..cc0a8bae25b 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -523,7 +523,7 @@ private: virtual bool RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel, const bool& aHidden) MOZ_OVERRIDE; - + virtual bool RecvGetSystemMemory(const uint64_t& getterId) MOZ_OVERRIDE; virtual bool RecvBroadcastVolume(const nsString& aVolumeName) MOZ_OVERRIDE; virtual bool RecvSpeakerManagerGetSpeakerStatus(bool* aValue) MOZ_OVERRIDE; diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index a330d76372b..c588a0483db 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -357,6 +357,8 @@ child: async NotifyVisited(URIParams uri); + async SystemMemoryAvailable(uint64_t getterId, uint32_t memoryAvailable); + PreferenceUpdate(PrefSetting pref); NotifyAlertsObserver(nsCString topic, nsString data); @@ -436,6 +438,8 @@ parent: sync GetRandomValues(uint32_t length) returns (uint8_t[] randomValues); + async GetSystemMemory(uint64_t getterId); + PHal(); PIndexedDB(); diff --git a/hal/Hal.cpp b/hal/Hal.cpp index 58834564add..17c602d6b2b 100644 --- a/hal/Hal.cpp +++ b/hal/Hal.cpp @@ -1232,6 +1232,11 @@ GetTotalSystemMemory() return hal_impl::GetTotalSystemMemory(); } +uint32_t +GetTotalSystemMemoryLevel() +{ + return hal_impl::GetTotalSystemMemoryLevel(); +} } // namespace hal } // namespace mozilla diff --git a/hal/Hal.h b/hal/Hal.h index 0d35a7e2e48..a01f4fe3cc2 100644 --- a/hal/Hal.h +++ b/hal/Hal.h @@ -616,6 +616,14 @@ void StopDiskSpaceWatcher(); */ uint32_t GetTotalSystemMemory(); +/** + * Get the level of total system memory on device in MiB. + * (round the value up to the next power of two) + * + * Returns 0 if we are unable to determine this information from /proc/meminfo. + */ +uint32_t GetTotalSystemMemoryLevel(); + } // namespace MOZ_HAL_NAMESPACE } // namespace mozilla diff --git a/hal/fallback/FallbackMemory.cpp b/hal/fallback/FallbackMemory.cpp index 2750eebd82f..d3715c8f4cb 100644 --- a/hal/fallback/FallbackMemory.cpp +++ b/hal/fallback/FallbackMemory.cpp @@ -16,5 +16,11 @@ GetTotalSystemMemory() return 0; } +uint32_t +GetTotalSystemMemoryLevel() +{ + return 0; +} + } // namespace hal_impl } // namespace mozilla diff --git a/hal/linux/LinuxMemory.cpp b/hal/linux/LinuxMemory.cpp index 14ed63146a1..e814a3edbb5 100644 --- a/hal/linux/LinuxMemory.cpp +++ b/hal/linux/LinuxMemory.cpp @@ -35,5 +35,37 @@ GetTotalSystemMemory() return sTotalMemory * 1024; } +uint32_t +GetTotalSystemMemoryLevel() +{ + static uint32_t sTotalMemoryLevel = 1; + uint32_t sTotalMemory; + static bool sTotalMemoryObtained = false; + + if (!sTotalMemoryObtained) { + sTotalMemoryObtained = true; + + FILE* fd = fopen("/proc/meminfo", "r"); + if (!fd) { + return 0; + } + + int rv = fscanf(fd, "MemTotal: %i kB", &sTotalMemory); + + if (fclose(fd) || rv != 1) { + return 0; + } + + // From KB to MiB + sTotalMemory /= 1024; + + while (sTotalMemoryLevel <= sTotalMemory) { + sTotalMemoryLevel *= 2; + } + } + + return sTotalMemoryLevel; +} + } // namespace hal_impl } // namespace mozilla