--- a/security/sandbox/linux/SandboxBrokerClient.cpp
+++ b/security/sandbox/linux/SandboxBrokerClient.cpp
@@ -15,17 +15,16 @@
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "mozilla/Assertions.h"
#include "mozilla/NullPtr.h"
#include "base/strings/safe_sprintf.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
namespace mozilla {
SandboxBrokerClient::SandboxBrokerClient(int aFd)
: mFileDesc(aFd)
{
}
@@ -170,42 +169,26 @@ SandboxBrokerClient::Open(const char* aP
int
SandboxBrokerClient::Access(const char* aPath, int aMode)
{
Request req = { SANDBOX_FILE_ACCESS, aMode, 0 };
return DoCall(&req, aPath, nullptr, nullptr, false);
}
int
-SandboxBrokerClient::Stat(const char* aPath, struct stat* aStat)
+SandboxBrokerClient::Stat(const char* aPath, statstruct* aStat)
{
- // This is actually stat64 on 32-bit Linux, so adjust the
- // struct to have the right expected size.
-#if defined(__NR_stat64)
- Request req = { SANDBOX_FILE_STAT, 0, sizeof(struct stat64) };
-#elif defined(__NR_stat)
- Request req = { SANDBOX_FILE_STAT, 0, sizeof(struct stat) };
-#else
-#error Missing include.
-#endif
+ Request req = { SANDBOX_FILE_STAT, 0, sizeof(statstruct) };
return DoCall(&req, aPath, nullptr, (void*)aStat, false);
}
int
-SandboxBrokerClient::LStat(const char* aPath, struct stat* aStat)
+SandboxBrokerClient::LStat(const char* aPath, statstruct* aStat)
{
- // This is actually stat64 on 32-bit Linux, so adjust the
- // struct to have the right expected size.
-#if defined(__NR_stat64)
- Request req = { SANDBOX_FILE_STAT, O_NOFOLLOW, sizeof(struct stat64) };
-#elif defined(__NR_stat)
- Request req = { SANDBOX_FILE_STAT, O_NOFOLLOW, sizeof(struct stat) };
-#else
-#error Missing include.
-#endif
+ Request req = { SANDBOX_FILE_STAT, O_NOFOLLOW, sizeof(statstruct) };
return DoCall(&req, aPath, nullptr, (void*)aStat, false);
}
int
SandboxBrokerClient::Chmod(const char* aPath, int aMode)
{
Request req = {SANDBOX_FILE_CHMOD, aMode, 0};
return DoCall(&req, aPath, nullptr, nullptr, false);
--- a/security/sandbox/linux/SandboxBrokerClient.h
+++ b/security/sandbox/linux/SandboxBrokerClient.h
@@ -3,16 +3,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_SandboxBrokerClient_h
#define mozilla_SandboxBrokerClient_h
#include "broker/SandboxBrokerCommon.h"
+#include "broker/SandboxBrokerUtils.h"
#include "mozilla/Attributes.h"
// This is the client for the sandbox broker described in
// broker/SandboxBroker.h; its constructor takes the file descriptor
// returned by SandboxBroker::Create, passed to the child over IPC.
//
// The operations exposed here can be called from any thread and in
@@ -26,18 +27,18 @@ namespace mozilla {
class SandboxBrokerClient final : private SandboxBrokerCommon {
public:
explicit SandboxBrokerClient(int aFd);
~SandboxBrokerClient();
int Open(const char* aPath, int aFlags);
int Access(const char* aPath, int aMode);
- int Stat(const char* aPath, struct stat* aStat);
- int LStat(const char* aPath, struct stat* aStat);
+ int Stat(const char* aPath, statstruct* aStat);
+ int LStat(const char* aPath, statstruct* aStat);
int Chmod(const char* aPath, int aMode);
int Link(const char* aPath, const char* aPath2);
int Mkdir(const char* aPath, int aMode);
int Symlink(const char* aOldPath, const char* aNewPath);
int Rename(const char* aOldPath, const char* aNewPath);
int Unlink(const char* aPath);
int Rmdir(const char* aPath);
int Readlink(const char* aPath, void* aBuf, size_t aBufSize);
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -378,32 +378,32 @@ class ContentSandboxPolicy : public Sand
return BlockedSyscallTrap(aArgs, nullptr);
}
return broker->Access(path, mode);
}
static intptr_t StatTrap(ArgsRef aArgs, void* aux) {
auto broker = static_cast<SandboxBrokerClient*>(aux);
auto path = reinterpret_cast<const char*>(aArgs.args[0]);
- auto buf = reinterpret_cast<struct stat*>(aArgs.args[1]);
+ auto buf = reinterpret_cast<statstruct*>(aArgs.args[1]);
return broker->Stat(path, buf);
}
static intptr_t LStatTrap(ArgsRef aArgs, void* aux) {
auto broker = static_cast<SandboxBrokerClient*>(aux);
auto path = reinterpret_cast<const char*>(aArgs.args[0]);
- auto buf = reinterpret_cast<struct stat*>(aArgs.args[1]);
+ auto buf = reinterpret_cast<statstruct*>(aArgs.args[1]);
return broker->LStat(path, buf);
}
static intptr_t StatAtTrap(ArgsRef aArgs, void* aux) {
auto broker = static_cast<SandboxBrokerClient*>(aux);
auto fd = static_cast<int>(aArgs.args[0]);
auto path = reinterpret_cast<const char*>(aArgs.args[1]);
- auto buf = reinterpret_cast<struct stat*>(aArgs.args[2]);
+ auto buf = reinterpret_cast<statstruct*>(aArgs.args[2]);
auto flags = static_cast<int>(aArgs.args[3]);
if (fd != AT_FDCWD && path[0] != '/') {
SANDBOX_LOG_ERROR("unsupported fd-relative fstatat(%d, \"%s\", %p, %d)",
fd, path, buf, flags);
return BlockedSyscallTrap(aArgs, nullptr);
}
if ((flags & ~AT_SYMLINK_NOFOLLOW) != 0) {
SANDBOX_LOG_ERROR("unsupported flags %d in fstatat(%d, \"%s\", %p, %d)",
--- a/security/sandbox/linux/broker/SandboxBroker.cpp
+++ b/security/sandbox/linux/broker/SandboxBroker.cpp
@@ -2,16 +2,17 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "SandboxBroker.h"
#include "SandboxInfo.h"
#include "SandboxLogging.h"
+#include "SandboxBrokerUtils.h"
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
@@ -360,27 +361,20 @@ AllowOpen(int aReqFlags, int aPerms)
needed |= SandboxBroker::MAY_CREATE;
}
return (aPerms & needed) == needed;
}
static int
DoStat(const char* aPath, void* aBuff, int aFlags)
{
-#if defined(__NR_stat64)
if (aFlags & O_NOFOLLOW) {
- return lstat64(aPath, (struct stat64*)aBuff);
+ return lstatsyscall(aPath, (statstruct*)aBuff);
}
- return stat64(aPath, (struct stat64*)aBuff);
-#else
- if (aFlags & O_NOFOLLOW) {
- return lstat(aPath, (struct stat*)aBuff);
- }
- return stat(aPath, (struct stat*)aBuff);
-#endif
+ return statsyscall(aPath, (statstruct*)aBuff);
}
static int
DoLink(const char* aPath, const char* aPath2,
SandboxBrokerCommon::Operation aOper)
{
if (aOper == SandboxBrokerCommon::Operation::SANDBOX_FILE_LINK) {
return link(aPath, aPath2);
--- a/security/sandbox/linux/broker/SandboxBrokerCommon.h
+++ b/security/sandbox/linux/broker/SandboxBrokerCommon.h
@@ -1,16 +1,16 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
-#ifndef mozilla_SandboxBrokerTypes_h
-#define mozilla_SandboxBrokerTypes_h
+#ifndef mozilla_SandboxBrokerCommon_h
+#define mozilla_SandboxBrokerCommon_h
#include <sys/types.h>
struct iovec;
// This file defines the protocol between the filesystem broker,
// described in SandboxBroker.h, and its client, described in
// ../SandboxBrokerClient.h; and it defines some utility functions
@@ -64,9 +64,9 @@ public:
static ssize_t RecvWithFd(int aFd, const iovec* aIO, size_t aNumIO,
int* aPassedFdPtr);
static ssize_t SendWithFd(int aFd, const iovec* aIO, size_t aNumIO,
int aPassedFd);
};
} // namespace mozilla
-#endif // mozilla_SandboxBrokerTypes_h
+#endif // mozilla_SandboxBrokerCommon_h
--- a/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
+++ b/security/sandbox/linux/broker/SandboxBrokerPolicyFactory.cpp
@@ -8,16 +8,17 @@
#include "SandboxInfo.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Preferences.h"
#include "nsPrintfCString.h"
#include "nsString.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
+#include "SpecialSystemDirectory.h"
#ifdef ANDROID
#include "cutils/properties.h"
#endif
namespace mozilla {
/* static */ bool
@@ -113,17 +114,33 @@ SandboxBrokerPolicyFactory::SandboxBroke
policy->AddPath(rdonly, "/data/local/tmp/profiler.options",
SandboxBroker::Policy::AddAlways); // bug 1029337
mCommonContentPolicy.reset(policy);
#elif defined(MOZ_CONTENT_SANDBOX)
SandboxBroker::Policy* policy = new SandboxBroker::Policy;
policy->AddDir(rdonly, "/");
policy->AddDir(rdwrcr, "/dev/shm");
- policy->AddDir(rdwrcr, "/tmp");
+ // Add write permissions on the temporary directory. This can come
+ // from various environment variables (TMPDIR,TMP,TEMP,...) so
+ // make sure to use the full logic.
+ nsCOMPtr<nsIFile> tmpDir;
+ nsresult rv = GetSpecialSystemDirectory(OS_TemporaryDirectory,
+ getter_AddRefs(tmpDir));
+ if (NS_SUCCEEDED(rv)) {
+ nsAutoCString tmpPath;
+ rv = tmpDir->GetNativePath(tmpPath);
+ if (NS_SUCCEEDED(rv)) {
+ policy->AddDir(rdwrcr, tmpPath.get());
+ }
+ }
+ // If the above fails at any point, fall back to a very good guess.
+ if (NS_FAILED(rv)) {
+ policy->AddDir(rdwrcr, "/tmp");
+ }
mCommonContentPolicy.reset(policy);
#endif
}
#ifdef MOZ_CONTENT_SANDBOX
UniquePtr<SandboxBroker::Policy>
SandboxBrokerPolicyFactory::GetContentPolicy(int aPid)
{
new file mode 100644
--- /dev/null
+++ b/security/sandbox/linux/broker/SandboxBrokerUtils.h
@@ -0,0 +1,30 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+#ifndef mozilla_SandboxBrokerUtils_h
+#define mozilla_SandboxBrokerUtils_h
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "sandbox/linux/system_headers/linux_syscalls.h"
+
+// On 32-bit Linux, stat calls are translated by libc into stat64
+// calls. We'll intercept those and handle them in the stat functions
+// but must be sure to use the right structure layout.
+
+#if defined(__NR_stat64)
+typedef struct stat64 statstruct;
+#define statsyscall stat64
+#define lstatsyscall lstat64
+#elif defined(__NR_stat)
+typedef struct stat statstruct;
+#define statsyscall stat
+#define lstatsyscall lstat
+#else
+#error Missing stat syscall include.
+#endif
+
+#endif // mozilla_SandboxBrokerUtils_h
--- a/security/sandbox/linux/gtest/TestBroker.cpp
+++ b/security/sandbox/linux/gtest/TestBroker.cpp
@@ -2,16 +2,17 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "broker/SandboxBroker.h"
+#include "broker/SandboxBrokerUtils.h"
#include "SandboxBrokerClient.h"
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdlib.h>
#include <sched.h>
#include <semaphore.h>
@@ -49,20 +50,20 @@ class SandboxBrokerTest : public ::testi
protected:
int Open(const char* aPath, int aFlags) {
return mClient->Open(aPath, aFlags);
}
int Access(const char* aPath, int aMode) {
return mClient->Access(aPath, aMode);
}
- int Stat(const char* aPath, struct stat* aStat) {
+ int Stat(const char* aPath, statstruct* aStat) {
return mClient->Stat(aPath, aStat);
}
- int LStat(const char* aPath, struct stat* aStat) {
+ int LStat(const char* aPath, statstruct* aStat) {
return mClient->LStat(aPath, aStat);
}
int Chmod(const char* aPath, int aMode) {
return mClient->Chmod(aPath, aMode);
}
int Link(const char* aPath, const char* bPath) {
return mClient->Link(aPath, bPath);
}
@@ -204,33 +205,33 @@ TEST_F(SandboxBrokerTest, Access)
EXPECT_EQ(0, Access("/proc/self", F_OK));
EXPECT_EQ(-EACCES, Access("/proc/self", R_OK));
EXPECT_EQ(-EACCES, Access("/proc/self/stat", F_OK));
}
TEST_F(SandboxBrokerTest, Stat)
{
- struct stat brokeredStat, realStat;
- ASSERT_EQ(0, stat("/dev/null", &realStat)) << "Shouldn't ever fail!";
+ statstruct realStat, brokeredStat;
+ ASSERT_EQ(0, statsyscall("/dev/null", &realStat)) << "Shouldn't ever fail!";
EXPECT_EQ(0, Stat("/dev/null", &brokeredStat));
EXPECT_EQ(realStat.st_ino, brokeredStat.st_ino);
EXPECT_EQ(realStat.st_rdev, brokeredStat.st_rdev);
EXPECT_EQ(-ENOENT, Stat("/var/empty/qwertyuiop", &brokeredStat));
EXPECT_EQ(-EACCES, Stat("/dev", &brokeredStat));
EXPECT_EQ(0, Stat("/proc/self", &brokeredStat));
EXPECT_TRUE(S_ISDIR(brokeredStat.st_mode));
}
TEST_F(SandboxBrokerTest, LStat)
{
- struct stat brokeredStat, realStat;
- ASSERT_EQ(0, lstat("/dev/null", &realStat));
+ statstruct realStat, brokeredStat;
+ ASSERT_EQ(0, lstatsyscall("/dev/null", &realStat));
EXPECT_EQ(0, LStat("/dev/null", &brokeredStat));
EXPECT_EQ(realStat.st_ino, brokeredStat.st_ino);
EXPECT_EQ(realStat.st_rdev, brokeredStat.st_rdev);
EXPECT_EQ(-ENOENT, LStat("/var/empty/qwertyuiop", &brokeredStat));
EXPECT_EQ(-EACCES, LStat("/dev", &brokeredStat));
EXPECT_EQ(0, LStat("/proc/self", &brokeredStat));
@@ -255,22 +256,22 @@ TEST_F(SandboxBrokerTest, Chmod)
ASSERT_GE(fd, 0) << "Opening /tmp/blublu for writing failed.";
close(fd);
// Set read only. SandboxBroker enforces 0600 mode flags.
ASSERT_EQ(0, Chmod("/tmp/blublu", S_IRUSR));
// SandboxBroker doesn't use real access(), it just checks against
// the policy. So it can't see the change in permisions here.
// This won't work:
// EXPECT_EQ(-EACCES, Access("/tmp/blublu", W_OK));
- struct stat realStat;
- EXPECT_EQ(0, stat("/tmp/blublu", &realStat));
+ statstruct realStat;
+ EXPECT_EQ(0, statsyscall("/tmp/blublu", &realStat));
EXPECT_EQ((mode_t)S_IRUSR, realStat.st_mode & 0777);
ASSERT_EQ(0, Chmod("/tmp/blublu", S_IRUSR | S_IWUSR));
- EXPECT_EQ(0, stat("/tmp/blublu", &realStat));
+ EXPECT_EQ(0, statsyscall("/tmp/blublu", &realStat));
EXPECT_EQ((mode_t)(S_IRUSR | S_IWUSR), realStat.st_mode & 0777);
EXPECT_EQ(0, unlink("/tmp/blublu"));
PrePostTestCleanup();
}
TEST_F(SandboxBrokerTest, Link)
{
@@ -293,18 +294,18 @@ TEST_F(SandboxBrokerTest, Symlink)
{
PrePostTestCleanup();
int fd = Open("/tmp/blublu", O_WRONLY | O_CREAT);
ASSERT_GE(fd, 0) << "Opening /tmp/blublu for writing failed.";
close(fd);
ASSERT_EQ(0, Symlink("/tmp/blublu", "/tmp/blublublu"));
EXPECT_EQ(0, Access("/tmp/blublublu", F_OK));
- struct stat aStat;
- ASSERT_EQ(0, lstat("/tmp/blublublu", &aStat));
+ statstruct aStat;
+ ASSERT_EQ(0, lstatsyscall("/tmp/blublublu", &aStat));
EXPECT_EQ((mode_t)S_IFLNK, aStat.st_mode & S_IFMT);
// Not whitelisted target path
EXPECT_EQ(-EACCES, Symlink("/tmp/blublu", "/tmp/nope"));
EXPECT_EQ(0, unlink("/tmp/blublublu"));
EXPECT_EQ(0, unlink("/tmp/blublu"));
PrePostTestCleanup();
}
@@ -416,23 +417,23 @@ void SandboxBrokerTest::MultiThreadOpenW
}
TEST_F(SandboxBrokerTest, MultiThreadStat) {
RunOnManyThreads<SandboxBrokerTest,
&SandboxBrokerTest::MultiThreadStatWorker>();
}
void SandboxBrokerTest::MultiThreadStatWorker() {
static const int kNumLoops = 7500;
- struct stat nullStat, zeroStat, selfStat;
+ statstruct nullStat, zeroStat, selfStat;
dev_t realNullDev, realZeroDev;
ino_t realSelfInode;
- ASSERT_EQ(0, stat("/dev/null", &nullStat)) << "Shouldn't ever fail!";
- ASSERT_EQ(0, stat("/dev/zero", &zeroStat)) << "Shouldn't ever fail!";
- ASSERT_EQ(0, lstat("/proc/self", &selfStat)) << "Shouldn't ever fail!";
+ ASSERT_EQ(0, statsyscall("/dev/null", &nullStat)) << "Shouldn't ever fail!";
+ ASSERT_EQ(0, statsyscall("/dev/zero", &zeroStat)) << "Shouldn't ever fail!";
+ ASSERT_EQ(0, lstatsyscall("/proc/self", &selfStat)) << "Shouldn't ever fail!";
ASSERT_TRUE(S_ISLNK(selfStat.st_mode)) << "Shouldn't ever fail!";
realNullDev = nullStat.st_rdev;
realZeroDev = zeroStat.st_rdev;
realSelfInode = selfStat.st_ino;
for (int i = 1; i <= kNumLoops; ++i) {
ASSERT_EQ(0, Stat("/dev/null", &nullStat))
<< "Loop " << i << "/" << kNumLoops;
ASSERT_EQ(0, Stat("/dev/zero", &zeroStat))
--- a/toolkit/crashreporter/nsExceptionHandler.cpp
+++ b/toolkit/crashreporter/nsExceptionHandler.cpp
@@ -1179,22 +1179,24 @@ bool MinidumpCallback(
#endif
}
#endif // XP_MACOSX
#endif // XP_UNIX
return returnValue;
}
-#if defined(XP_MACOSX) || defined(__ANDROID__)
+#if defined(XP_MACOSX) || defined(__ANDROID__) || defined(XP_LINUX)
static size_t
EnsureTrailingSlash(XP_CHAR* aBuf, size_t aBufLen)
{
size_t len = XP_STRLEN(aBuf);
- if ((len + 2) < aBufLen && aBuf[len - 1] != XP_PATH_SEPARATOR_CHAR) {
+ if ((len + 1) < aBufLen
+ && len > 0
+ && aBuf[len - 1] != XP_PATH_SEPARATOR_CHAR) {
aBuf[len] = XP_PATH_SEPARATOR_CHAR;
++len;
aBuf[len] = 0;
}
return len;
}
#endif
@@ -1257,21 +1259,24 @@ BuildTempPath(char* aBuf, size_t aBufLen
return EnsureTrailingSlash(aBuf, aBufLen);
}
#elif defined(XP_UNIX)
static size_t
BuildTempPath(char* aBuf, size_t aBufLen)
{
- // we assume it's always /tmp on unix systems
- NS_NAMED_LITERAL_CSTRING(tmpPath, "/tmp/");
+ const char *tempenv = PR_GetEnv("TMPDIR");
+ const char *tmpPath = "/tmp/";
+ if (!tempenv) {
+ tempenv = tmpPath;
+ }
int size = (int)aBufLen;
- Concat(aBuf, tmpPath.get(), &size);
- return tmpPath.Length();
+ Concat(aBuf, tempenv, &size);
+ return EnsureTrailingSlash(aBuf, aBufLen);
}
#else
#error "Implement this for your platform"
#endif
template <typename CharT, size_t N>
static size_t