зеркало из https://github.com/microsoft/BuildXL.git
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:
Родитель
d3f3c61fd8
Коммит
84bb9a1850
|
@ -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
|
Загрузка…
Ссылка в новой задаче