Merged PR 772872: Update FileAccessManifest parsing for Linux and implement missing functionality

- Moves the FAM parsing out of the macos code.
- Implements parsing path translations and breakaway processes.
- Uses new coding style for Linux sandbox (which the rest of our code will eventually use)

Related work items: #2111123
This commit is contained in:
Pasindu Gunasekara 🍣 2024-03-21 22:44:29 +00:00
Родитель d3f3c61fd8
Коммит 84bb9a1850
18 изменённых файлов: 438 добавлений и 46 удалений

3
.vscode/c_cpp_properties.json поставляемый
Просмотреть файл

@ -8,7 +8,8 @@
"${workspaceFolder}/Public/Src/Sandbox/MacOs/Sandbox/Src",
"${workspaceFolder}/Public/Src/Sandbox/MacOs/Sandbox/Src/FileAccessManifest",
"${workspaceFolder}/Public/Src/Sandbox/Windows/DetoursServices",
"${workspaceFolder}/**"
"${workspaceFolder}/**",
"${workspaceFolder}/Public/Src/Sandbox/Common"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",

Просмотреть файл

@ -850,6 +850,7 @@ namespace BuildXL.Processes
}
// CODESYNC: FileAccessManifestParser.cpp :: init
// CODESYNC: Public/Src/Sandbox/Common/FileAccessManifest.cc FileAccessManifest::ParseFileAccessManifest
private static void WriteChildProcessesToBreakAwayFromSandbox(
BinaryWriter writer,
IReadOnlyCollection<BreakawayChildProcess>? breakawayChildProcesses)

Просмотреть файл

@ -0,0 +1,233 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#include "FileAccessManifest.h"
#include "DataTypes.h"
namespace buildxl {
namespace common {
FileAccessManifest::FileAccessManifest(char *payload, size_t payload_size) {
payload_ = std::unique_ptr<char []>(payload);
payload_size_ = payload_size;
ParseFileAccessManifest();
}
FileAccessManifest::~FileAccessManifest() { }
bool FileAccessManifest::ParseFileAccessManifest() {
if (payload_size_ == 0) {
return true;
}
size_t offset = 0;
// CODESYNC: Public/Src/Engine/Processes/FileAccessManifest.cs
// The parsing order must match the order in FileAccessManifest.GetPayloadBytes
// Certain parts of the manifest are not used in Unix, so we don't parse them (this will change in the future when the Windows sandbox also uses this code)
// NOTE: Each of the Parse* functions in this file will advance the offset by the size of the parsed value.
// 1. Debug Flag
auto debugFlag = reinterpret_cast<PCManifestDebugFlag>(&(payload_.get()[offset]));
if (!debugFlag->CheckValidityAndHandleInvalid()) {
assert(false && "Invalid debug flag");
return false;
}
offset += debugFlag->GetSize();
// 2. Injection Timeout
auto injection_timeout_minutes = reinterpret_cast<PCManifestInjectionTimeout>(&(payload_.get()[offset]));
if (!injection_timeout_minutes->CheckValidityAndHandleInvalid()) {
assert(false && "Invalid injection timeout");
return false;
}
injection_timeout_minutes_ = static_cast<unsigned long>(injection_timeout_minutes->Flags);
offset += injection_timeout_minutes->GetSize();
// 3. Breakaway Child Processes
auto child_processes_to_break_away_from_job = ParseAndAdvancePointer<PManifestChildProcessesToBreakAwayFromJob>(offset);
for (uint32_t i = 0; i < child_processes_to_break_away_from_job->Count; i++) {
std::basic_string<PathChar> process_name;
ParseUtf16CharArrayToString(offset, process_name);
if (!process_name.empty()) {
std::basic_string<PathChar> required_args;
ParseUtf16CharArrayToString(offset, required_args);
auto ignore_case = ParseByte(offset) == 1U;
breakaway_child_processes_.push_back(BreakawayChildProcess(process_name, required_args, ignore_case));
}
}
// 4. Translation Path Strings
auto translate_paths_strings = ParseAndAdvancePointer<PManifestTranslatePathsStrings>(offset);
for (uint32_t i = 0; i < translate_paths_strings->Count; i++) {
std::basic_string<PathChar> from;
std::basic_string<PathChar> to;
ParseUtf16CharArrayToString(offset, from);
ParseUtf16CharArrayToString(offset, to);
if (!to.empty()) {
translate_paths_.push_back(TranslatePathTuple(from, to));
}
}
// 5. Error Dump Location
ParseAndAdvancePointer<PManifestInternalDetoursErrorNotificationFileString>(offset);
// The path is not part of the PManifestInternalDetoursErrorNotificationFileString struct, extract it manually
// On Linux this does not point to a real path, however to align with the Windows format for the file access manifest this is re-used
auto error_dump_loc_len = ParseUtf16CharArrayToString(offset, error_dump_location_);
// 6. Flags
auto flags = ParseAndAdvancePointer<PCManifestFlags>(offset);
flags_ = static_cast<FileAccessManifestFlag>(flags->Flags);
// 7. Extra Flags
auto extra_flags = ParseAndAdvancePointer<PCManifestExtraFlags>(offset);
extra_flags_ = static_cast<FileAccessManifestExtraFlag>(extra_flags->ExtraFlags);
// 8. PipId
auto pip_id = ParseAndAdvancePointer<PCManifestPipId>(offset);
pip_id_ = static_cast<uint64_t>(pip_id->PipId);
// 9. Report
report_ = ParseAndAdvancePointer<PCManifestReport>(offset);
// 10. Dll
dll_ = ParseAndAdvancePointer<PCManifestDllBlock>(offset);
// 11. Substitute Process Shim Block
auto shim_info = ParseAndAdvancePointer<PCManifestSubstituteProcessExecutionShim>(offset);
auto shim_path_len = SkipChar16Array(offset);
if (shim_path_len > 0) {
SkipChar16Array(offset); // SubstituteProcessExecutionPluginDll32Path
SkipChar16Array(offset); // SubstituteProcessExecutionPluginDll64Path
auto num_process_matches = ParseUint32(offset);
for (uint32_t i = 0; i < num_process_matches; i++) {
SkipChar16Array(offset); // ProcessName
SkipChar16Array(offset); // ArgumentMatch
}
}
// 12. Manifest Tree
manifest_tree_ = Parse<PCManifestRecord>(offset);
manifest_tree_->AssertValid();
// Verify the parsed manifest
// TODO [pgunasekara]: Change this to run only on Linux when Windows uses this code
std::string error;
assert(CheckValidUnixManifestTreeRoot(manifest_tree_, error) == true && error.c_str());
return true;
}
// Manifest Validation
bool FileAccessManifest::CheckValidUnixManifestTreeRoot(PCManifestRecord node, std::string& error) {
// empty manifest is ok
if (node->BucketCount == 0) {
return true;
}
// otherwise, there must be exactly one root node corresponding to the unix root sentinel '/'
// (see UnixPathRootSentinel from HierarchicalNameTable.cs)
if (node->BucketCount != 1) {
error = "Root manifest node is expected to have exactly one child (corresponding to the unix root sentinel: '/')";
return false;
}
unsigned int expectedHash = HashPath(kUnixRootSentinal, 0);
if (node->GetChildRecord(0)->Hash != expectedHash) {
error = "Wrong hash code for the unix root sentinel node";
return false;
}
return true;
}
std::basic_string<PathChar> FileAccessManifest::ManifestTreeToString(PCManifestRecord node, const int indent, const int index) {
if (node == nullptr) {
node = manifest_tree_;
}
PathChar indent_str[indent+1];
indent_str[indent] = L'\0';
for (int i = 0; i < indent; i++) indent_str[i] = L' ';
std::basic_string<PathChar> output("| ");
output.append(indent_str);
output.append(" [");
output.append(std::to_string(index));
output.append("] '");
output.append(node->GetPartialPath());
output.append("' (cone policy = ");
output.append(std::to_string(node->GetConePolicy() & FileAccessPolicy_ReportAccess));
output.append(", node policy = ");
output.append(std::to_string(node->GetNodePolicy() & FileAccessPolicy_ReportAccess));
output.append(")\n");
for (int i = 0; i < node->BucketCount; i++)
{
PCManifestRecord child = node->GetChildRecord(i);
if (child == nullptr) continue;
output.append(ManifestTreeToString(child, indent + 2, i));
}
return output;
}
// Parsing Functions
template <class T> T FileAccessManifest::Parse(size_t& offset) {
return reinterpret_cast<T>(&(payload_.get()[offset]));
}
template <class T> T FileAccessManifest::ParseAndAdvancePointer(size_t& offset) {
T result = Parse<T>(offset);
result->CheckValid();
offset += result->GetSize();
return result;
}
inline uint32_t FileAccessManifest::ParseUint32(size_t& offset) {
uint32_t i = *(uint32_t*)(&(payload_.get()[offset]));
offset += sizeof(uint32_t);
return i;
}
size_t FileAccessManifest::SkipChar16Array(size_t& offset) {
uint32_t length = ParseUint32(offset);
// Strings in the BuildXL FAM are encoded in unicode rather than utf-8, so here we explicitly skip 2 bytes per character even on Linux.
offset += sizeof(char16_t) * length;
return length;
}
size_t FileAccessManifest::ParseUtf16CharArrayToString(size_t& offset, std::basic_string<PathChar>& output) {
uint32_t length = ParseUint32(offset);
if (length == 0) {
output = "";
return 0;
}
output = std::basic_string<PathChar>();
output.reserve(length);
for (int i = 0; i < length; i++) {
// This is a narrowing cast from char16 to char8.
// On Unix this is safe, but potentially unsafe on Windows.
// TODO [pgunasekara]: Update this to avoid casting when running on Windows.
output.push_back(static_cast<char>(payload_[offset + (i * sizeof(char16_t))]));
}
offset += sizeof(char16_t) * length;
return length;
}
inline BYTE FileAccessManifest::ParseByte(size_t& offset) {
BYTE b = (BYTE)payload_[offset];
offset += sizeof(BYTE);
return b;
}
} // namespace common
} // namespace buildxl

Просмотреть файл

@ -0,0 +1,138 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#ifndef BUILDXL_SANDBOX_COMMON_FILE_ACCESS_MANIFEST_H
#define BUILDXL_SANDBOX_COMMON_FILE_ACCESS_MANIFEST_H
#include <vector>
#include <string>
#include "DataTypes.h"
#include "StringOperations.h"
namespace buildxl {
namespace common {
// TODO [pgunasekara]: Remove the matching definition in Public/Src/Sandbox/Windows/DetoursServices/DetoursServices.h
/**
* Breakaway child process information.
*/
typedef struct BreakawayChildProcess {
private:
std::basic_string<PathChar> executable;
std::basic_string<PathChar> required_args;
bool ignore_case;
public:
BreakawayChildProcess(std::basic_string<PathChar> executable, std::basic_string<PathChar> required_args, bool ignore_case) {
this->executable = executable;
this->required_args = required_args;
this->ignore_case = ignore_case;
}
BreakawayChildProcess(const BreakawayChildProcess &other)
: BreakawayChildProcess(other.executable, other.required_args, other.ignore_case)
{}
std::basic_string<PathChar> const & GetExecutable() {
return executable;
}
std::basic_string<PathChar> const & GetRequiredArgs() {
return required_args;
}
bool GetIgnoreCase() {
return ignore_case;
}
} BreakawayChildProcess;
// TODO: Remove the matching definition in Public/Src/Sandbox/Windows/DetoursServices/DetoursServices.h
/**
* Tuple of paths to translate.
*/
typedef struct TranslatePathTuple {
private:
std::basic_string<PathChar> from_path;
std::basic_string<PathChar> to_path;
public:
TranslatePathTuple(std::basic_string<PathChar> from, std::basic_string<PathChar> to) {
from_path = from;
to_path = to;
}
std::basic_string<PathChar> const & GetToPath() {
return to_path;
}
std::basic_string<PathChar> const & GetFromPath() {
return from_path;
}
} TranslatePathTuple;
/**
* Parses the file access manifest payload and stores the information in a FileAccessManifest object.
*/
class FileAccessManifest {
private:
// CODESYNC: Public/Src/Utilities/Utilities.Core/HierarchicalNameTable.cs
const PathChar* kUnixRootSentinal = "";
std::unique_ptr<BYTE []> payload_;
size_t payload_size_;
unsigned long injection_timeout_minutes_;
std::vector<BreakawayChildProcess> breakaway_child_processes_;
std::vector<TranslatePathTuple> translate_paths_;
std::basic_string<PathChar> error_dump_location_;
FileAccessManifestFlag flags_;
FileAccessManifestExtraFlag extra_flags_;
uint64_t pip_id_;
PCManifestReport report_;
PCManifestDllBlock dll_;
PCManifestSubstituteProcessExecutionShim shim_info_;
std::basic_string<PathChar> shim_path_;
PCManifestRecord manifest_tree_;
/**
* Parses the serialized manifest payload from the provided payload.
*/
bool ParseFileAccessManifest();
template <class T> T Parse(size_t& offset);
template <class T> T ParseAndAdvancePointer(size_t& offset);
uint32_t ParseUint32(size_t& offset);
size_t SkipChar16Array(size_t& offset);
size_t ParseUtf16CharArrayToString(size_t& offset, std::basic_string<PathChar>& output);
BYTE ParseByte(size_t& offset);
bool CheckValidUnixManifestTreeRoot(PCManifestRecord node, std::string& error);
public:
/**
* Construct a file access manifest object.
* This constructor will create a copy of the payload.
* @param payload The serialized manifest payload.
* @param payload_size The size of the payload.
*/
FileAccessManifest(char *payload, size_t payload_size);
~FileAccessManifest();
inline FileAccessManifestFlag GetFlags() const { return flags_; }
inline FileAccessManifestExtraFlag GetExtraFlags() const { return extra_flags_; }
inline const char* GetInternalErrorDumpLocation() const { return error_dump_location_.c_str(); }
inline uint64_t GetPipId() const { return pip_id_; }
inline PCManifestReport GetReport() const { return report_; }
inline PCManifestDllBlock GetDll() const { return dll_; }
inline PCManifestSubstituteProcessExecutionShim GetShimInfo() const { return shim_info_; }
inline PCManifestRecord GetManifestTreeRoot() const { return manifest_tree_; }
inline PCManifestRecord GetUnixManifestTreeRoot() const { return manifest_tree_->BucketCount > 0 ? manifest_tree_->GetChildRecord(0) : manifest_tree_; }
// TODO [pgunasekara]: accept a length argument as reference instead of a pointer.
inline const char *GetReportsPath(int *length) const { *length = report_->Size; return report_->Report.ReportPath; }
inline bool AllowChildProcessesToBreakAway() const { return breakaway_child_processes_.size() > 0; }
// Debugging Helpers
std::basic_string<PathChar> ManifestTreeToString(PCManifestRecord node = nullptr, const int indent = 0, const int index = 0);
};
} // namespace common
} // namespace buildxl
#endif // BUILDXL_SANDBOX_COMMON_FILE_ACCESS_MANIFEST_H

Просмотреть файл

@ -14,13 +14,13 @@ namespace Sandbox {
...glob(d`../MacOs/Interop/Sandbox/Data`, "*.cpp"),
...glob(d`../MacOs/Interop/Sandbox/Handlers`, "*.cpp"),
f`../MacOs/Interop/Sandbox/Sandbox.cpp`,
f`../MacOs/Sandbox/Src/FileAccessManifest/FileAccessManifestParser.cpp`,
f`../MacOs/Sandbox/Src/Kauth/Checkers.cpp`,
f`../MacOs/Sandbox/Src/Kauth/OpNames.cpp`,
f`../Windows/DetoursServices/PolicyResult_common.cpp`,
f`../Windows/DetoursServices/PolicySearch.cpp`,
f`../Windows/DetoursServices/StringOperations.cpp`,
f`../Windows/DetoursServices/FilesCheckedForAccess.cpp`
f`../Windows/DetoursServices/FilesCheckedForAccess.cpp`,
f`../Common/FileAccessManifest.cpp`
];
const utilsSrc = [ f`utils.c` ];
const bxlEnvSrc = [ f`bxl-env.c` ];
@ -35,7 +35,8 @@ namespace Sandbox {
d`../MacOs/Sandbox/Src`,
d`../MacOs/Sandbox/Src/FileAccessManifest`,
d`../MacOs/Sandbox/Src/Kauth`,
d`../Windows/DetoursServices`
d`../Windows/DetoursServices`,
d`../Common`
];
const headers = incDirs.mapMany(d => ["*.h", "*.hpp"].mapMany(q => glob(d, q)));

Просмотреть файл

@ -133,13 +133,12 @@ void BxlObserver::InitFam(pid_t pid)
long famLength = ftell(famFile);
rewind(famFile);
char *famPayload = (char *)malloc(famLength);
auto famPayload = new char [famLength];
real_fread(famPayload, famLength, 1, famFile);
real_fclose(famFile);
// create SandboxedPip (which parses FAM and throws on error)
pip_ = shared_ptr<SandboxedPip>(new SandboxedPip(pid, famPayload, famLength));
free(famPayload);
// create sandbox
sandbox_ = new Sandbox(0, Configuration::DetoursLinuxSandboxType);

Просмотреть файл

@ -148,7 +148,7 @@ static const char GLIBC_23[] = "GLIBC_2.3";
RenderSyscall(#name, result, std::forward<TArgs>(args)...).c_str(), \
return_value.get_errno()); \
return return_value; \
} \
} \
template<typename ...TArgs> ret check_fwd_and_report_##name( \
AccessReportGroup& report, \
AccessCheckResult &check, \

Просмотреть файл

@ -0,0 +1,2 @@
# Coding Style
The Linux Sandbox code follows the [Google C++ Coding Style](https://google.github.io/styleguide/cppguide.html).

Просмотреть файл

@ -60,6 +60,8 @@
3CD0BB4222F2E84A008C0AC9 /* IOHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3C44208022F1F5B1000E1003 /* IOHandler.cpp */; };
3CD0BB4322F2E84A008C0AC9 /* IOHandler.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3C44208422F1F5B1000E1003 /* IOHandler.hpp */; };
3CE4B4752450724B00ACC220 /* ESConstants.hpp in Headers */ = {isa = PBXBuildFile; fileRef = 3CE4B4742450724B00ACC220 /* ESConstants.hpp */; };
4E78D3A62BA4D24E00EAF7B0 /* FileAccessManifest.h in Headers */ = {isa = PBXBuildFile; fileRef = 4E78D3A52BA4D24E00EAF7B0 /* FileAccessManifest.h */; };
4E78D3A82BA4D25A00EAF7B0 /* FileAccessManifest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4E78D3A72BA4D25900EAF7B0 /* FileAccessManifest.cpp */; };
F588040520D03EB7006CF533 /* PolicyResult.h in Headers */ = {isa = PBXBuildFile; fileRef = F588040320D03EB7006CF533 /* PolicyResult.h */; };
F588040720D042FB006CF533 /* PolicyResult_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F588040620D042FB006CF533 /* PolicyResult_common.cpp */; };
F58E9207220B5B3D0083C57E /* utf8proc.c in Sources */ = {isa = PBXBuildFile; fileRef = F58E9204220B5B3C0083C57E /* utf8proc.c */; };
@ -148,6 +150,8 @@
3CF3733F20C1897400D14240 /* KextSandbox.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = KextSandbox.hpp; sourceTree = "<group>"; };
3CF74D9522F1C1A50018A1AF /* SandboxedProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SandboxedProcess.cpp; sourceTree = "<group>"; };
3CF74D9622F1C1A50018A1AF /* SandboxedProcess.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = SandboxedProcess.hpp; sourceTree = "<group>"; };
4E78D3A52BA4D24E00EAF7B0 /* FileAccessManifest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileAccessManifest.h; path = ../../Common/FileAccessManifest.h; sourceTree = "<group>"; };
4E78D3A72BA4D25900EAF7B0 /* FileAccessManifest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileAccessManifest.cpp; path = ../../Common/FileAccessManifest.cpp; sourceTree = "<group>"; };
F588040320D03EB7006CF533 /* PolicyResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PolicyResult.h; path = ../../Windows/DetoursServices/PolicyResult.h; sourceTree = "<group>"; };
F588040620D042FB006CF533 /* PolicyResult_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PolicyResult_common.cpp; path = ../../Windows/DetoursServices/PolicyResult_common.cpp; sourceTree = "<group>"; };
F58E9204220B5B3C0083C57E /* utf8proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = utf8proc.c; sourceTree = "<group>"; };
@ -371,6 +375,8 @@
F5CF3B0720C1E35C00DC1B2E /* BuildXLSandbox */ = {
isa = PBXGroup;
children = (
4E78D3A72BA4D25900EAF7B0 /* FileAccessManifest.cpp */,
4E78D3A52BA4D24E00EAF7B0 /* FileAccessManifest.h */,
F5CF3B0C20C1E3DC00DC1B2E /* BuildXLSandboxShared.hpp */,
3C4C636622F386AE0014D9AA /* Checkers.cpp */,
3C4C636422F386AE0014D9AA /* Checkers.hpp */,
@ -408,6 +414,7 @@
3C7237A623FD4483001B15CC /* Trie.hpp in Headers */,
3C3B60C922F1E2B400130AB3 /* Common.hpp in Headers */,
3C1D7C9320C03E830069CF65 /* Dependencies.h in Headers */,
4E78D3A62BA4D24E00EAF7B0 /* FileAccessManifest.h in Headers */,
3C7237A923FE9475001B15CC /* BuildXLException.hpp in Headers */,
3C3B60C322F1DEB200130AB3 /* KextSandbox.hpp in Headers */,
F588040520D03EB7006CF533 /* PolicyResult.h in Headers */,
@ -559,6 +566,7 @@
F5CF3B1720C1E40C00DC1B2E /* StringOperations.cpp in Sources */,
3C1D7C8D20C0262B0069CF65 /* cpu.c in Sources */,
3C80E70921347B9700ECBD6E /* io.c in Sources */,
4E78D3A82BA4D25A00EAF7B0 /* FileAccessManifest.cpp in Sources */,
3C1FD6D520D3F766007A0C1A /* process.c in Sources */,
3C3B60CA22F1E2BC00130AB3 /* Common.cpp in Sources */,
F5CF3B1620C1E40C00DC1B2E /* PolicySearch.cpp in Sources */,

Просмотреть файл

@ -29,7 +29,11 @@ extern "C"
return KEXT_SendPipStarted(processId, pipId, famBytes, famBytesLength, *context);
}
case GenericSandbox:
return Sandbox_SendPipStarted(processId, pipId, famBytes, famBytesLength);
{
char *famBytesCopy = new char[famBytesLength];
memcpy(famBytesCopy, famBytes, famBytesLength);
return Sandbox_SendPipStarted(processId, pipId, famBytesCopy, famBytesLength);
}
}
return false;

Просмотреть файл

@ -6,24 +6,12 @@
#pragma mark SandboxedPip Implementation
SandboxedPip::SandboxedPip(pid_t pid, const char *payload, size_t length)
SandboxedPip::SandboxedPip(pid_t pid, char *payload, size_t length)
{
log_debug("Initializing with pid (%d) from: %{public}s", pid, __FUNCTION__);
payload_ = (char *) malloc(length);
if (payload == NULL)
{
throw BuildXLException("Could not allocate memory for FAM payload storage!");
}
memcpy(payload_, payload, length);
fam_.init((BYTE*)payload_, length);
if (fam_.HasErrors())
{
std::string error= "FileAccessManifest parsing exception, error: ";
throw BuildXLException(error.append(fam_.Error()));
}
// If an error occurs with FAM parsing, then an assertion will be thrown
fam_ = std::make_unique<buildxl::common::FileAccessManifest>(payload, length);
processId_ = pid;
processTreeCount_ = 1;

Просмотреть файл

@ -5,7 +5,8 @@
#define SandboxedPip_hpp
#include "BuildXLSandboxShared.hpp"
#include "FileAccessManifestParser.hpp"
#include "FileAccessManifest.h"
#include "FileAccessHelpers.h"
/*!
* Represents the root of the process tree being tracked.
@ -30,7 +31,7 @@ private:
char *payload_;
/*! File access manifest (contains pointers into the 'payload_' byte array */
FileAccessManifestParseResult fam_;
std::unique_ptr<buildxl::common::FileAccessManifest> fam_;
/*! Number of processses in this pip's process tree */
std::atomic<int> processTreeCount_;
@ -38,39 +39,40 @@ private:
public:
SandboxedPip() = delete;
SandboxedPip(pid_t pid, const char *payload, size_t length);
SandboxedPip(pid_t pid, char *payload, size_t length);
~SandboxedPip();
/*! Process id of the root process of this pip. */
inline const pid_t GetProcessId() const { return processId_; }
/*! A unique identifier of this pip. */
inline const pipid_t GetPipId() const { return fam_.GetPipId()->PipId; }
inline const pipid_t GetPipId() const { return fam_->GetPipId(); }
/*! File access manifest record for this pip (to be used for checking file accesses) */
inline const PCManifestRecord GetManifestRecord() const { return fam_.GetUnixRootNode(); }
inline const PCManifestRecord GetManifestRecord() const { return fam_->GetUnixManifestTreeRoot(); }
/*! File access manifest flags */
inline const FileAccessManifestFlag GetFamFlags() const { return fam_.GetFamFlags(); }
inline const FileAccessManifestFlag GetFamFlags() const { return fam_->GetFlags(); }
/*! File access manifest extra flags */
inline const FileAccessManifestExtraFlag GetFamExtraFlags() const { return fam_.GetFamExtraFlags(); }
inline const FileAccessManifestExtraFlag GetFamExtraFlags() const { return fam_->GetExtraFlags(); }
/*!
* Returns the full path of the root process of this pip.
* The lenght of the path is stored in the 'length' argument because the path is not necessarily 0-terminated.
*/
inline const char* GetProcessPath(int *length) const { return fam_.GetProcessPath(length); }
inline const char* GetReportsPath(int *length) const { return fam_.GetReportsPath(length); }
inline const char* GetProcessPath(int *length) const { return fam_->GetReportsPath(length); }
inline const char* GetReportsPath(int *length) const { return fam_->GetReportsPath(length); }
/*! Number of currently active processes in this pip's process tree */
inline const int GetTreeSize() const { return processTreeCount_; }
/*! When this returns true, child processes should not be tracked. */
bool AllowChildProcessesToBreakAway() const { return fam_.AllowChildProcessesToBreakAway(); }
bool AllowChildProcessesToBreakAway() const { return fam_->AllowChildProcessesToBreakAway(); }
inline const char* GetInternalDetoursErrorNotificationFile() const { return fam_.GetInternalDetoursErrorNotificationFile(); }
inline const char* GetInternalDetoursErrorNotificationFile() const { return fam_->GetInternalErrorDumpLocation(); }
inline const std::string GetManifestTreeString() { return fam_->ManifestTreeToString(); }
#pragma mark Process Tree Tracking

Просмотреть файл

@ -54,7 +54,7 @@ extern "C"
#pragma mark Generic sandbox stubs
bool Sandbox_SendPipStarted(const pid_t pid, pipid_t pipId, const char *const famBytes, int famBytesLength)
bool Sandbox_SendPipStarted(const pid_t pid, pipid_t pipId, char *famBytes, int famBytesLength)
{
log_debug("Pip with PipId = %#llX, PID = %d launching", pipId, pid);

Просмотреть файл

@ -40,7 +40,7 @@ extern "C"
void __cdecl ObserverFileAccessReports(SandboxConnectionInfo *info, AccessReportCallback callback, long accessReportSize);
};
bool Sandbox_SendPipStarted(const pid_t pid, pipid_t pipId, const char *const famBytes, int famBytesLength);
bool Sandbox_SendPipStarted(const pid_t pid, pipid_t pipId, char *famBytes, int famBytesLength);
bool Sandbox_SendPipProcessTerminated(pipid_t pipId, pid_t pid);
class Sandbox final

Просмотреть файл

@ -199,25 +199,33 @@ bool FileAccessManifestParseResult::init(const BYTE *payload, size_t payloadSize
}
// Debugging helper
void FileAccessManifestParseResult::PrintManifestTree(PCManifestRecord node,
std::string FileAccessManifestParseResult::PrintManifestTree(PCManifestRecord node,
const int indent,
const int index)
{
if (node == nullptr) node = root_;
PathChar indentStr[indent+1];
indentStr[indent] = L'\0';
for (int i = 0; i < indent; i++) indentStr[i] = L' ';
printf("| %s [%d] '%s' (cone policy = %#x, node policy = %#x)\n",
indentStr,
index,
node->GetPartialPath(),
node->GetConePolicy() & FileAccessPolicy_ReportAccess,
node->GetNodePolicy() & FileAccessPolicy_ReportAccess);
std::string output("| ");
output.append(indentStr);
output.append(" [");
output.append(std::to_string(index));
output.append("] '");
output.append(node->GetPartialPath());
output.append("' (cone policy = ");
output.append(std::to_string(node->GetConePolicy() & FileAccessPolicy_ReportAccess));
output.append(", node policy = ");
output.append(std::to_string(node->GetNodePolicy() & FileAccessPolicy_ReportAccess));
output.append(")\n");
for (int i = 0; i < node->BucketCount; i++)
{
PCManifestRecord child = node->GetChildRecord(i);
if (child == nullptr) continue;
PrintManifestTree(child, indent + 2, i);
output.append(PrintManifestTree(child, indent + 2, i));
}
return output;
}

Просмотреть файл

@ -63,7 +63,7 @@ public:
inline const char* GetInternalDetoursErrorNotificationFile() const { return internalDetoursErrorNotificationFile_; }
// Debugging helper
static void PrintManifestTree(PCManifestRecord node, const int indent = 0, const int index = 0);
std::string PrintManifestTree(PCManifestRecord node = nullptr, const int indent = 0, const int index = 0);
};
#endif /* FileAccessManifestParser_hpp */

Просмотреть файл

@ -51,8 +51,10 @@ public:
#if _WIN32
CanonicalizedPathType Path() const { return m_canonicalizedPath; }
size_t PathLength() const { return m_canonicalizedPath.Length(); }
#else
PCPathChar Path() const { return m_canonicalizedPath.c_str(); }
PCPathChar Path() const { return m_canonicalizedPath.c_str(); }
size_t PathLength() const { return m_canonicalizedPath.length(); }
#endif // _WIN32
#if _WIN32

Просмотреть файл

@ -1,6 +1,9 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
#ifndef PUBLIC_SRC_SANDBOX_WINDOWS_DETOURSSERVICES_STDAFX_UNIX_COMMON_H
#define PUBLIC_SRC_SANDBOX_WINDOWS_DETOURSSERVICES_STDAFX_UNIX_COMMON_H
#include <stddef.h>
#include <stdint.h>
@ -223,3 +226,5 @@ inline ENUMTYPE &operator ^= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((_
#define WriteWarningOrErrorF(format, ...)
#define MaybeBreakOnAccessDenied()
#endif // PUBLIC_SRC_SANDBOX_WINDOWS_DETOURSSERVICES_STDAFX_UNIX_COMMON_H