mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 1284897 - Add mechanism to libsandbox_s to track names of files that have been given special sandbox access permissions (PermissionsService). r=bobowen, r=glandium
Hook this into the browser via the XREAppData. This patch does not include the changes to Chromium source code.
This commit is contained in:
parent
cb9c91b2bb
commit
e9bcaf4cbe
@ -217,6 +217,8 @@ static int do_main(int argc, char* argv[], char* envp[])
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
sandbox::BrokerServices* brokerServices =
|
||||
sandboxing::GetInitializedBrokerServices();
|
||||
sandboxing::PermissionsService* permissionsService =
|
||||
sandboxing::GetPermissionsService();
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
if (!brokerServices) {
|
||||
Output("Couldn't initialize the broker services.\n");
|
||||
@ -224,6 +226,7 @@ static int do_main(int argc, char* argv[], char* envp[])
|
||||
}
|
||||
#endif
|
||||
config.sandboxBrokerServices = brokerServices;
|
||||
config.sandboxPermissionsService = permissionsService;
|
||||
#endif
|
||||
|
||||
#ifdef LIBFUZZER
|
||||
|
@ -0,0 +1,136 @@
|
||||
/* -*- 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/. */
|
||||
|
||||
/* SandboxPermissions.cpp - Special permissions granted to sandboxed processes */
|
||||
|
||||
#include "permissionsService.h"
|
||||
#include <algorithm>
|
||||
#include <winternl.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace sandboxing {
|
||||
|
||||
static const std::wstring ZONE_IDENTIFIER_STR(L":ZONE.IDENTIFIER");
|
||||
static const std::wstring ZONE_ID_DATA_STR(L":ZONE.IDENTIFIER:$DATA");
|
||||
|
||||
bool
|
||||
StringEndsWith(const std::wstring& str, const std::wstring& strEnding)
|
||||
{
|
||||
if (strEnding.size() > str.size()) {
|
||||
return false;
|
||||
}
|
||||
return std::equal(strEnding.rbegin(), strEnding.rend(), str.rbegin());
|
||||
}
|
||||
|
||||
// Converts NT device internal filenames to normal user-space by stripping
|
||||
// the prefixes and suffixes from the file name.
|
||||
std::wstring
|
||||
GetPlainFileName(const wchar_t* aNTFileName)
|
||||
{
|
||||
while (*aNTFileName == L'\\' || *aNTFileName == L'.' ||
|
||||
*aNTFileName == L'?' || *aNTFileName == L':' ) {
|
||||
++aNTFileName;
|
||||
}
|
||||
std::wstring nameCopy(aNTFileName);
|
||||
std::transform(nameCopy.begin(), nameCopy.end(), nameCopy.begin(), towupper);
|
||||
if (StringEndsWith(nameCopy, ZONE_ID_DATA_STR)) {
|
||||
nameCopy = nameCopy.substr(0, nameCopy.size() - ZONE_ID_DATA_STR.size());
|
||||
} else if (StringEndsWith(nameCopy, ZONE_IDENTIFIER_STR)) {
|
||||
nameCopy = nameCopy.substr(0, nameCopy.size() - ZONE_IDENTIFIER_STR.size());
|
||||
}
|
||||
return nameCopy;
|
||||
}
|
||||
|
||||
/* static */ PermissionsService*
|
||||
PermissionsService::GetInstance()
|
||||
{
|
||||
static PermissionsService sPermissionsService;
|
||||
return &sPermissionsService;
|
||||
}
|
||||
|
||||
PermissionsService::PermissionsService() :
|
||||
mFileAccessViolationFunc(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
PermissionsService::GrantFileAccess(uint32_t aProcessId,
|
||||
const wchar_t* aFilename,
|
||||
bool aPermitWrite)
|
||||
{
|
||||
FilePermissionMap& permissions = mProcessFilePermissions[aProcessId];
|
||||
std::wstring filename = GetPlainFileName(aFilename);
|
||||
permissions[filename] |= aPermitWrite;
|
||||
}
|
||||
|
||||
void
|
||||
PermissionsService::SetFileAccessViolationFunc(FileAccessViolationFunc aFavFunc)
|
||||
{
|
||||
mFileAccessViolationFunc = aFavFunc;
|
||||
}
|
||||
|
||||
void
|
||||
PermissionsService::ReportBlockedFile(bool aNeedsWrite)
|
||||
{
|
||||
if (mFileAccessViolationFunc) {
|
||||
mFileAccessViolationFunc(aNeedsWrite);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
PermissionsService::UserGrantedFileAccess(uint32_t aProcessId,
|
||||
const wchar_t* aFilename,
|
||||
uint32_t aAccess,
|
||||
uint32_t aDisposition)
|
||||
{
|
||||
// There are 3 types of permissions:
|
||||
// * Those available w/ read-only permission
|
||||
// * Those available w/ read-only AND read-write permission
|
||||
// * Those always forbidden.
|
||||
const uint32_t FORBIDDEN_FLAGS =
|
||||
FILE_EXECUTE | FILE_LIST_DIRECTORY | FILE_TRAVERSE | STANDARD_RIGHTS_EXECUTE;
|
||||
const uint32_t NEEDS_WRITE_FLAGS =
|
||||
FILE_WRITE_DATA | FILE_WRITE_ATTRIBUTES | FILE_WRITE_EA | FILE_APPEND_DATA |
|
||||
DELETE | STANDARD_RIGHTS_WRITE;
|
||||
bool needsWrite =
|
||||
(aAccess & NEEDS_WRITE_FLAGS) || (aDisposition != FILE_OPEN);
|
||||
|
||||
if (aAccess & FORBIDDEN_FLAGS) {
|
||||
ReportBlockedFile(needsWrite);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto permissions = mProcessFilePermissions.find(aProcessId);
|
||||
if (permissions == mProcessFilePermissions.end()) {
|
||||
ReportBlockedFile(needsWrite);
|
||||
return false; // process has no special file access at all
|
||||
}
|
||||
|
||||
std::wstring filename = GetPlainFileName(aFilename);
|
||||
auto itPermission = permissions->second.find(filename);
|
||||
if (itPermission == permissions->second.end()) {
|
||||
ReportBlockedFile(needsWrite);
|
||||
return false; // process has no access to this file
|
||||
}
|
||||
|
||||
// We have read permission. Check for write permission if requested.
|
||||
if (!needsWrite || itPermission->second) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We needed write access but didn't have it.
|
||||
ReportBlockedFile(needsWrite);
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
PermissionsService::RemovePermissionsForProcess(uint32_t aProcessId)
|
||||
{
|
||||
mProcessFilePermissions.erase(aProcessId);
|
||||
}
|
||||
|
||||
} // namespace sandboxing
|
||||
} // namespace mozilla
|
@ -0,0 +1,78 @@
|
||||
/* -*- 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_sandboxing_permissionsService_h
|
||||
#define mozilla_sandboxing_permissionsService_h
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace mozilla {
|
||||
namespace sandboxing {
|
||||
|
||||
/*
|
||||
* Represents additional permissions granted to sandboxed processes.
|
||||
* The members are virtual so that the object can be created in any
|
||||
* library that links with libsandbox_s and then shared with and used
|
||||
* by libXUL, which does not link with libsandbox_s.
|
||||
*/
|
||||
class PermissionsService
|
||||
{
|
||||
public:
|
||||
static PermissionsService* GetInstance();
|
||||
|
||||
/*
|
||||
* Allow future access to aFilename by the plugin process.
|
||||
*/
|
||||
virtual void GrantFileAccess(uint32_t aProcessId, const wchar_t* aFilename,
|
||||
bool aPermitWrite);
|
||||
|
||||
/*
|
||||
* Type of callback function that the sandbox uses to report file
|
||||
* accesses that were denied.
|
||||
* Parameter is a boolean indicating the access request was read-only
|
||||
* (false) or read-write (true)
|
||||
*/
|
||||
typedef void (*FileAccessViolationFunc)(bool);
|
||||
|
||||
/*
|
||||
* Sets the callback function that is called whenever a file access is
|
||||
* denied by the sandbox.
|
||||
*/
|
||||
virtual void SetFileAccessViolationFunc(FileAccessViolationFunc aFavFunc);
|
||||
|
||||
/*
|
||||
* Returns true if the user has granted the sandboxed plugin process the
|
||||
* requested permission to open the file.
|
||||
* Calls aFavFunc with file info if the file access was blocked.
|
||||
*/
|
||||
virtual bool UserGrantedFileAccess(uint32_t aProcessId, const wchar_t* aFilename,
|
||||
uint32_t aAccess, uint32_t aDisposition);
|
||||
|
||||
/*
|
||||
* Clears all special file access for the given plugin process.
|
||||
*/
|
||||
virtual void RemovePermissionsForProcess(uint32_t aProcessId);
|
||||
|
||||
private:
|
||||
PermissionsService();
|
||||
void ReportBlockedFile(bool aNeedsWrite);
|
||||
|
||||
// Maps from filenames to a boolean indicating read-only permission (false) or
|
||||
// read-write permission (true).
|
||||
typedef std::unordered_map<std::wstring, bool> FilePermissionMap;
|
||||
|
||||
// Maps from process ID to map of user-granted file permissions for
|
||||
// that process.
|
||||
typedef std::unordered_map<uint32_t, FilePermissionMap> ProcessFilePermissionMap;
|
||||
|
||||
ProcessFilePermissionMap mProcessFilePermissions;
|
||||
FileAccessViolationFunc mFileAccessViolationFunc;
|
||||
};
|
||||
|
||||
} // namespace sandboxing
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_sandboxing_permissionsService_h
|
@ -19,6 +19,7 @@ elif CONFIG['OS_ARCH'] == 'WINNT':
|
||||
|
||||
DIRS += [
|
||||
'win/src/sandboxbroker',
|
||||
'win/src/sandboxpermissions',
|
||||
'win/src/sandboxtarget',
|
||||
]
|
||||
|
||||
@ -29,6 +30,7 @@ elif CONFIG['OS_ARCH'] == 'WINNT':
|
||||
EXPORTS.mozilla.sandboxing += [
|
||||
'chromium-shim/sandbox/win/loggingCallbacks.h',
|
||||
'chromium-shim/sandbox/win/loggingTypes.h',
|
||||
'chromium-shim/sandbox/win/permissionsService.h',
|
||||
'chromium-shim/sandbox/win/sandboxLogging.h',
|
||||
'win/SandboxInitialization.h',
|
||||
]
|
||||
@ -36,6 +38,7 @@ elif CONFIG['OS_ARCH'] == 'WINNT':
|
||||
SOURCES += [
|
||||
'chromium-shim/base/files/file_path.cpp',
|
||||
'chromium-shim/base/logging.cpp',
|
||||
'chromium-shim/sandbox/win/permissionsService.cpp',
|
||||
'chromium-shim/sandbox/win/sandboxLogging.cpp',
|
||||
'chromium/base/at_exit.cc',
|
||||
'chromium/base/base_switches.cc',
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "SandboxInitialization.h"
|
||||
|
||||
#include "sandbox/win/src/sandbox_factory.h"
|
||||
#include "mozilla/sandboxing/permissionsService.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace sandboxing {
|
||||
@ -77,5 +78,10 @@ GetInitializedBrokerServices()
|
||||
return sInitializedBrokerServices;
|
||||
}
|
||||
|
||||
PermissionsService* GetPermissionsService()
|
||||
{
|
||||
return PermissionsService::GetInstance();
|
||||
}
|
||||
|
||||
} // sandboxing
|
||||
} // mozilla
|
||||
|
@ -21,6 +21,8 @@ namespace mozilla {
|
||||
// sandbox for our namespace painful.
|
||||
namespace sandboxing {
|
||||
|
||||
class PermissionsService;
|
||||
|
||||
/**
|
||||
* Initializes (if required) and returns the Chromium sandbox TargetServices.
|
||||
*
|
||||
@ -41,6 +43,8 @@ void LowerSandbox();
|
||||
*/
|
||||
sandbox::BrokerServices* GetInitializedBrokerServices();
|
||||
|
||||
PermissionsService* GetPermissionsService();
|
||||
|
||||
} // sandboxing
|
||||
} // mozilla
|
||||
|
||||
|
22
security/sandbox/win/src/sandboxpermissions/moz.build
Normal file
22
security/sandbox/win/src/sandboxpermissions/moz.build
Normal file
@ -0,0 +1,22 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
SOURCES += [
|
||||
'sandboxPermissions.cpp',
|
||||
]
|
||||
|
||||
EXPORTS += [
|
||||
'sandboxPermissions.h',
|
||||
]
|
||||
|
||||
for var in ('UNICODE', '_UNICODE'):
|
||||
DEFINES[var] = True
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/security/sandbox/win',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
@ -0,0 +1,39 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=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 "sandboxPermissions.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/sandboxing/permissionsService.h"
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
||||
sandboxing::PermissionsService* SandboxPermissions::sPermissionsService = nullptr;
|
||||
|
||||
void
|
||||
SandboxPermissions::Initialize(sandboxing::PermissionsService* aPermissionsService,
|
||||
FileAccessViolationFunc aFileAccessViolationFunc)
|
||||
{
|
||||
sPermissionsService = aPermissionsService;
|
||||
sPermissionsService->SetFileAccessViolationFunc(aFileAccessViolationFunc);
|
||||
}
|
||||
|
||||
void
|
||||
SandboxPermissions::GrantFileAccess(uint32_t aProcessId, const wchar_t* aFilename,
|
||||
bool aPermitWrite)
|
||||
{
|
||||
MOZ_ASSERT(sPermissionsService, "Must initialize sandbox PermissionsService");
|
||||
sPermissionsService->GrantFileAccess(aProcessId, aFilename, aPermitWrite);
|
||||
}
|
||||
|
||||
void
|
||||
SandboxPermissions::RemovePermissionsForProcess(uint32_t aProcessId)
|
||||
{
|
||||
MOZ_ASSERT(sPermissionsService, "Must initialize sandbox PermissionsService");
|
||||
sPermissionsService->RemovePermissionsForProcess(aProcessId);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
@ -0,0 +1,57 @@
|
||||
/* -*- 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_sandboxing_sandboxPermissions_h
|
||||
#define mozilla_sandboxing_sandboxPermissions_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
namespace sandboxing {
|
||||
class PermissionsService;
|
||||
}
|
||||
|
||||
/*
|
||||
* This object wraps a PermissionsService object. This object is available
|
||||
* in libXUL but PermissionsService is not.
|
||||
*/
|
||||
class SandboxPermissions
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Type of callback function that the sandbox uses to report file
|
||||
* accesses that were denied.
|
||||
* Parameter is a boolean indicating the access request was read-only
|
||||
* (false) or read-write (true)
|
||||
*/
|
||||
typedef void (*FileAccessViolationFunc)(bool);
|
||||
|
||||
/*
|
||||
* Prepare this object by providing it with the internal permissions service.
|
||||
*/
|
||||
static void Initialize(sandboxing::PermissionsService* aPermissionsService,
|
||||
FileAccessViolationFunc aFileAccessViolationFunc);
|
||||
|
||||
/*
|
||||
* Allow future access to aFilename by the process with the given ID.
|
||||
*/
|
||||
void GrantFileAccess(uint32_t aProcessId, const wchar_t* aFilename,
|
||||
bool aPermitWrite);
|
||||
|
||||
/*
|
||||
* Clears all special file access for the given process.
|
||||
*/
|
||||
void RemovePermissionsForProcess(uint32_t aProcessId);
|
||||
|
||||
private:
|
||||
static sandboxing::PermissionsService* sPermissionsService;
|
||||
};
|
||||
|
||||
} // mozilla
|
||||
|
||||
#endif // mozilla_sandboxing_sandboxPermissions_h
|
@ -31,11 +31,18 @@ class BrokerServices;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
namespace sandboxing {
|
||||
class PermissionsService;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct BootstrapConfig
|
||||
{
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
/* Chromium sandbox BrokerServices. */
|
||||
sandbox::BrokerServices* sandboxBrokerServices;
|
||||
sandboxing::PermissionsService* sandboxPermissionsService;
|
||||
#endif
|
||||
/* Pointer to static XRE AppData from application.ini.h */
|
||||
const StaticXREAppData* appData;
|
||||
|
@ -214,6 +214,7 @@
|
||||
#include "mozilla/SandboxInfo.h"
|
||||
#elif defined(XP_WIN)
|
||||
#include "SandboxBroker.h"
|
||||
#include "SandboxPermissions.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -3318,6 +3319,10 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
||||
NS_WARNING("Failed to initialize broker services, sandboxed processes will "
|
||||
"fail to start.");
|
||||
}
|
||||
if (mAppData->sandboxPermissionsService) {
|
||||
SandboxPermissions::Initialize(mAppData->sandboxPermissionsService,
|
||||
nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
@ -4606,6 +4611,7 @@ XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig)
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
mAppData->sandboxBrokerServices = aConfig.sandboxBrokerServices;
|
||||
mAppData->sandboxPermissionsService = aConfig.sandboxPermissionsService;
|
||||
#endif
|
||||
|
||||
mozilla::IOInterposerInit ioInterposerGuard;
|
||||
|
@ -17,6 +17,11 @@
|
||||
namespace sandbox {
|
||||
class BrokerServices;
|
||||
}
|
||||
namespace mozilla {
|
||||
namespace sandboxing {
|
||||
class PermissionsService;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
@ -194,6 +199,7 @@ public:
|
||||
* Chromium sandbox BrokerServices.
|
||||
*/
|
||||
sandbox::BrokerServices* sandboxBrokerServices = nullptr;
|
||||
mozilla::sandboxing::PermissionsService* sandboxPermissionsService;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -49,6 +49,7 @@ XREAppData::operator=(const XREAppData& aOther)
|
||||
UAName = aOther.UAName;
|
||||
#if defined(XP_WIN) && defined(MOZ_SANDBOX)
|
||||
sandboxBrokerServices = aOther.sandboxBrokerServices;
|
||||
sandboxPermissionsService = aOther.sandboxPermissionsService;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user