зеркало из https://github.com/microsoft/BuildXL.git
Merged PR 546149: [linux-sandbox] Eagerly load syscall symbols of importance
- eagerly call `dlsym` to resolve all sycall symbols upfront (instead of lazily once we are already handling a syscall) - call the original syscall implementation before reporting accesses (helps avoid potential deadlocks when there are multiple libraries intercepting syscalls) - capture the value of `errno` right after calling the original implementation, and restore it right before returning Related work items: #1706182
This commit is contained in:
Родитель
efdcf576a2
Коммит
ec26ac404a
|
@ -57,10 +57,7 @@ namespace Tests.Linux {
|
|||
// Engine
|
||||
createDef(importFrom("BuildXL.Core.UnitTests").Cache.dll, true),
|
||||
createDef(importFrom("BuildXL.Core.UnitTests").Cache.Plugin.Core.dll, true),
|
||||
createDef(importFrom("BuildXL.Core.UnitTests").Processes.test_BuildXL_Processes_dll, true,
|
||||
/* deploySeparately */ false,
|
||||
// TODO: re-anable process tests once the issue with AzDev Ubuntu VM is resolved
|
||||
/* testClasses */ [ "Bogus.Test.Class" ]),
|
||||
createDef(importFrom("BuildXL.Core.UnitTests").Processes.test_BuildXL_Processes_dll, true),
|
||||
|
||||
// createDef(importFrom("BuildXL.Core.UnitTests").Engine.dll, true,
|
||||
// /* deploySeparately */ false,
|
||||
|
|
|
@ -73,17 +73,15 @@ namespace BuildXL.Processes
|
|||
internal string ReportsFifoPath { get; }
|
||||
internal string FamPath { get; }
|
||||
|
||||
private readonly LoggingContext m_loggingContext;
|
||||
private readonly Sandbox.ManagedFailureCallback m_failureCallback;
|
||||
private readonly Dictionary<string, PathCacheRecord> m_pathCache; // TODO: use AbsolutePath instead of string
|
||||
private readonly HashSet<int> m_activeProcesses;
|
||||
private readonly Lazy<SafeFileHandle> m_lazyWriteHandle;
|
||||
private readonly Thread m_workerThread;
|
||||
|
||||
internal Info(Sandbox.ManagedFailureCallback failureCallback, LoggingContext loggingContext, SandboxedProcessUnix process, string reportsFifoPath, string famPath)
|
||||
internal Info(Sandbox.ManagedFailureCallback failureCallback, SandboxedProcessUnix process, string reportsFifoPath, string famPath)
|
||||
{
|
||||
m_failureCallback = failureCallback;
|
||||
m_loggingContext = loggingContext;
|
||||
Process = process;
|
||||
ReportsFifoPath = reportsFifoPath;
|
||||
FamPath = famPath;
|
||||
|
@ -96,7 +94,11 @@ namespace BuildXL.Processes
|
|||
|
||||
// create a write handle (used to keep the fifo open, i.e.,
|
||||
// the 'read' syscall won't receive EOF until we close this writer
|
||||
m_lazyWriteHandle = new Lazy<SafeFileHandle>(() => IO.Open(ReportsFifoPath, IO.OpenFlags.O_WRONLY, 0));
|
||||
m_lazyWriteHandle = new Lazy<SafeFileHandle>(() =>
|
||||
{
|
||||
LogDebug($"Opening FIFO '{ReportsFifoPath}' for writing");
|
||||
return IO.Open(ReportsFifoPath, IO.OpenFlags.O_WRONLY, 0);
|
||||
});
|
||||
|
||||
// start a background thread for reading from the FIFO
|
||||
m_workerThread = new Thread(StartReceivingAccessReports);
|
||||
|
@ -118,6 +120,7 @@ namespace BuildXL.Processes
|
|||
/// </summary>
|
||||
internal void RequestStop()
|
||||
{
|
||||
LogDebug($"Closing the write handle for FIFO '{ReportsFifoPath}'");
|
||||
// this will cause read() on the other end of the FIFO to return EOF once all native writers are done writing
|
||||
m_lazyWriteHandle.Value.Dispose();
|
||||
}
|
||||
|
@ -125,7 +128,8 @@ namespace BuildXL.Processes
|
|||
/// <summary>Adds <paramref name="pid" /> to the set of active processes</summary>
|
||||
internal void AddPid(int pid)
|
||||
{
|
||||
m_activeProcesses.Add(pid);
|
||||
bool added = m_activeProcesses.Add(pid);
|
||||
LogDebug($"AddPid({pid}) :: added: {added}; size: {m_activeProcesses.Count()}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -134,7 +138,8 @@ namespace BuildXL.Processes
|
|||
/// </summary>
|
||||
internal void RemovePid(int pid)
|
||||
{
|
||||
m_activeProcesses.Remove(pid);
|
||||
bool removed = m_activeProcesses.Remove(pid);
|
||||
LogDebug($"RemovePid({pid}) :: removed: {removed}; size: {m_activeProcesses.Count()}");
|
||||
if (m_activeProcesses.Count == 0)
|
||||
{
|
||||
RequestStop();
|
||||
|
@ -158,19 +163,13 @@ namespace BuildXL.Processes
|
|||
|
||||
internal void LogError(string message)
|
||||
{
|
||||
if (m_loggingContext != null)
|
||||
{
|
||||
Logger.Log.PipProcessStartFailed(m_loggingContext, Process.PipSemiStableHash, Process.PipDescription, Marshal.GetLastWin32Error(), message);
|
||||
m_failureCallback?.Invoke(1, message);
|
||||
}
|
||||
Process.LogDebug("[ERROR]: " + message);
|
||||
m_failureCallback?.Invoke(1, message);
|
||||
}
|
||||
|
||||
internal void LogDebug(string message)
|
||||
{
|
||||
if (m_loggingContext != null)
|
||||
{
|
||||
Tracing.Logger.Log.LogDetoursDebugMessage(m_loggingContext, Process.PipSemiStableHash, message);
|
||||
}
|
||||
Process.LogDebug(message);
|
||||
}
|
||||
|
||||
/// <nodoc />
|
||||
|
@ -189,7 +188,8 @@ namespace BuildXL.Processes
|
|||
// Format:
|
||||
// "%s|%d|%d|%d|%d|%d|%d|%s\n", __progname, getpid(), access, status, explicitLogging, err, opcode, reportPath
|
||||
string message = Encoding.GetString(bytes).TrimEnd('\n');
|
||||
|
||||
LogDebug($"Processing message: {message}");
|
||||
|
||||
// parse message and create AccessReport
|
||||
string[] parts = message.Split(new[] { '|' });
|
||||
Contract.Assert(parts.Length == 8);
|
||||
|
@ -266,6 +266,7 @@ namespace BuildXL.Processes
|
|||
var fifoName = ReportsFifoPath;
|
||||
|
||||
// opening FIFO for reading (blocks until there is at least one writer connected)
|
||||
LogDebug($"Opening FIFO '{fifoName}' for reading");
|
||||
using var readHandle = IO.Open(fifoName, IO.OpenFlags.O_RDONLY, 0);
|
||||
if (readHandle.IsInvalid)
|
||||
{
|
||||
|
@ -312,8 +313,7 @@ namespace BuildXL.Processes
|
|||
break;
|
||||
}
|
||||
|
||||
// Update last received timestamp
|
||||
long now = DateTime.UtcNow.Ticks;
|
||||
LogDebug($"Received a {numRead}-byte message");
|
||||
|
||||
// Add message to processing queue
|
||||
actionBlock.Post(messageBytes);
|
||||
|
@ -424,6 +424,8 @@ namespace BuildXL.Processes
|
|||
File.WriteAllBytes(famPath, manifestBytes.ToArray());
|
||||
}
|
||||
|
||||
process.LogDebug($"Saved FAM to '{famPath}'");
|
||||
|
||||
// create a FIFO (named pipe)
|
||||
if (IO.MkFifo(fifoPath, IO.FilePermissions.S_IRWXU) != 0)
|
||||
{
|
||||
|
@ -431,8 +433,10 @@ namespace BuildXL.Processes
|
|||
return false;
|
||||
}
|
||||
|
||||
process.LogDebug($"Created FIFO at '{fifoPath}'");
|
||||
|
||||
// create and save info for this pip
|
||||
var info = new Info(m_failureCallback, loggingContext, process, fifoPath, famPath);
|
||||
var info = new Info(m_failureCallback, process, fifoPath, famPath);
|
||||
if (!m_pipProcesses.TryAdd(process.PipId, info))
|
||||
{
|
||||
throw new BuildXLException($"Process with PidId {process.PipId} already exists");
|
||||
|
|
|
@ -592,6 +592,17 @@ namespace BuildXL.Processes
|
|||
m_sumOfReportQueueTimesUs += (stats.DequeueTime - stats.EnqueueTime) / 1000;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Logs a detailed message if <see cref="FileAccessManifest.ReportFileAccesses"/> is set.
|
||||
/// </summary>
|
||||
internal void LogDebug(string message)
|
||||
{
|
||||
if (ShouldReportFileAccesses)
|
||||
{
|
||||
LogProcessState(message);
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleAccessReport(AccessReport report)
|
||||
{
|
||||
if (ShouldReportFileAccesses)
|
||||
|
|
|
@ -28,18 +28,19 @@ BxlObserver* BxlObserver::GetInstance()
|
|||
|
||||
BxlObserver::BxlObserver()
|
||||
{
|
||||
GEN_REAL(FILE*, fopen, const char *, const char *);
|
||||
GEN_REAL(size_t, fread, void*, size_t, size_t, FILE*);
|
||||
GEN_REAL(int, fclose, FILE*);
|
||||
GEN_REAL(ssize_t, readlink, const char *, char *, size_t);
|
||||
|
||||
real_readlink("/proc/self/exe", progFullPath_, PATH_MAX);
|
||||
InitFam();
|
||||
InitLogFile();
|
||||
}
|
||||
|
||||
void BxlObserver::InitFam()
|
||||
{
|
||||
// read FAM env var
|
||||
const char *famPath = getenv(BxlEnvFamPath);
|
||||
if (!(famPath && *famPath))
|
||||
{
|
||||
_fatal("Env var '%s' not set", BxlEnvFamPath);
|
||||
fprintf(stderr, "[%s] ERROR: Env var '%s' not set\n", __func__, BxlEnvFamPath);
|
||||
return;
|
||||
}
|
||||
|
||||
// read FAM
|
||||
|
@ -74,12 +75,22 @@ BxlObserver::BxlObserver()
|
|||
sandbox_->SetAccessReportCallback(HandleAccessReport);
|
||||
}
|
||||
|
||||
void BxlObserver::InitLogFile()
|
||||
{
|
||||
const char *logPath = getenv(BxlEnvLogPath);
|
||||
if (logPath && *logPath)
|
||||
{
|
||||
strlcpy(logFile_, logPath, PATH_MAX);
|
||||
logFile_[PATH_MAX-1] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
logFile_[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
bool BxlObserver::Send(const char *buf, size_t bufsiz)
|
||||
{
|
||||
GEN_REAL(int, open, const char *, int);
|
||||
GEN_REAL(ssize_t, write, int, const void*, size_t);
|
||||
GEN_REAL(int, close, int);
|
||||
|
||||
if (!real_open)
|
||||
{
|
||||
_fatal("syscall 'open' not found; errno: %d", errno);
|
||||
|
@ -92,7 +103,7 @@ bool BxlObserver::Send(const char *buf, size_t bufsiz)
|
|||
}
|
||||
|
||||
const char *reportsPath = GetReportsPath();
|
||||
int logFd = real_open(reportsPath, O_WRONLY | O_APPEND);
|
||||
int logFd = real_open(reportsPath, O_WRONLY | O_APPEND, 0);
|
||||
if (logFd == -1)
|
||||
{
|
||||
_fatal("Could not open file '%s'; errno: %d", reportsPath, errno);
|
||||
|
@ -110,8 +121,6 @@ bool BxlObserver::Send(const char *buf, size_t bufsiz)
|
|||
|
||||
bool BxlObserver::SendReport(AccessReport &report)
|
||||
{
|
||||
GEN_REAL(char*, realpath, const char*, char*);
|
||||
|
||||
// there is no central sendbox process here (i.e., there is an instance of this
|
||||
// guy in every child process), so counting process tree size is not feasible
|
||||
if (report.operation == FileOperation::kOpProcessTreeCompleted)
|
||||
|
@ -119,19 +128,12 @@ bool BxlObserver::SendReport(AccessReport &report)
|
|||
return true;
|
||||
}
|
||||
|
||||
char realpathBuf[PATH_MAX];
|
||||
char *realpathPtr = real_realpath(report.path, realpathBuf);
|
||||
|
||||
int err = realpathPtr == NULL ? 2 : 0;
|
||||
const char *reportPath = realpathPtr == NULL ? report.path : realpathPtr;
|
||||
RequestedAccess realAccess = realpathPtr == NULL ? RequestedAccess::Probe : (RequestedAccess)report.requestedAccess;
|
||||
|
||||
const int PrefixLength = sizeof(uint);
|
||||
char buffer[PIPE_BUF] = {0};
|
||||
int maxMessageLength = PIPE_BUF - PrefixLength;
|
||||
int numWritten = snprintf(
|
||||
&buffer[PrefixLength], maxMessageLength, "%s|%d|%d|%d|%d|%d|%d|%s\n",
|
||||
__progname, getpid(), (int)realAccess, report.status, report.reportExplicitly, err, report.operation, reportPath);
|
||||
__progname, getpid(), report.requestedAccess, report.status, report.reportExplicitly, report.error, report.operation, report.path);
|
||||
if (numWritten == maxMessageLength)
|
||||
{
|
||||
// TODO: once 'send' is capable of sending more than PIPE_BUF at once, allocate a bigger buffer and send that
|
||||
|
@ -141,3 +143,128 @@ bool BxlObserver::SendReport(AccessReport &report)
|
|||
*(uint*)(buffer) = numWritten;
|
||||
return Send(buffer, numWritten + PrefixLength);
|
||||
}
|
||||
|
||||
bool BxlObserver::report_access(const char *syscallName, es_event_type_t eventType, std::string reportPath, std::string secondPath)
|
||||
{
|
||||
// TODO: don't stat all the time
|
||||
struct stat s;
|
||||
mode_t mode = real___lxstat(1, reportPath.c_str(), &s) == 0
|
||||
? s.st_mode
|
||||
: 0;
|
||||
|
||||
std::string execPath = eventType == ES_EVENT_TYPE_NOTIFY_EXEC
|
||||
? reportPath
|
||||
: std::string(progFullPath_);
|
||||
|
||||
IOEvent event(getpid(), 0, getppid(), eventType, reportPath, secondPath, execPath, mode, false);
|
||||
return report_access(syscallName, event);
|
||||
}
|
||||
|
||||
bool BxlObserver::report_access(const char *syscallName, IOEvent &event)
|
||||
{
|
||||
es_event_type_t eventType = event.GetEventType();
|
||||
|
||||
LogDebug("(( %10s:%2d )) %s", syscallName, event.GetEventType(), event.GetEventPath());
|
||||
|
||||
if (IsValid())
|
||||
{
|
||||
IOHandler handler(sandbox_);
|
||||
handler.SetProcess(process_);
|
||||
handler.HandleEvent(event); // TODO: this should return AccessCheckResult, which should be returned from here
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool BxlObserver::report_access(const char *syscallName, es_event_type_t eventType, const char *pathname)
|
||||
{
|
||||
return report_access(syscallName, eventType, normalize_path(pathname), "");
|
||||
}
|
||||
|
||||
bool BxlObserver::report_access_fd(const char *syscallName, es_event_type_t eventType, int fd)
|
||||
{
|
||||
char fullpath[PATH_MAX] = {0};
|
||||
fd_to_path(fd, fullpath, PATH_MAX);
|
||||
|
||||
return report_access(syscallName, eventType, fullpath);
|
||||
}
|
||||
|
||||
bool BxlObserver::report_access_at(const char *syscallName, es_event_type_t eventType, int dirfd, const char *pathname)
|
||||
{
|
||||
char fullpath[PATH_MAX] = {0};
|
||||
ssize_t len = 0;
|
||||
|
||||
if (dirfd == AT_FDCWD)
|
||||
{
|
||||
getcwd(fullpath, PATH_MAX);
|
||||
len = strlen(fullpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = fd_to_path(dirfd, fullpath, PATH_MAX);
|
||||
}
|
||||
|
||||
if (len <= 0)
|
||||
{
|
||||
_fatal("Could not get path for fd %d; errno: %d", dirfd, errno);
|
||||
}
|
||||
|
||||
snprintf(&fullpath[len], PATH_MAX - len, "/%s", pathname);
|
||||
return report_access(syscallName, eventType, fullpath);
|
||||
}
|
||||
|
||||
static enum RequestedAccess oflag_to_access(int oflag)
|
||||
{
|
||||
return oflag & (O_WRONLY | O_RDWR) ? RequestedAccess::Write : RequestedAccess::Read;
|
||||
}
|
||||
|
||||
ssize_t BxlObserver::fd_to_path(int fd, char *buf, size_t bufsiz)
|
||||
{
|
||||
char procPath[100] = {0};
|
||||
sprintf(procPath, "/proc/self/fd/%d", fd);
|
||||
return real_readlink(procPath, buf, bufsiz);
|
||||
}
|
||||
|
||||
std::string BxlObserver::normalize_path_at(int dirfd, const char *pathname)
|
||||
{
|
||||
char fullpath[PATH_MAX] = {0};
|
||||
char finalPath[PATH_MAX] = {0};
|
||||
ssize_t len = 0;
|
||||
|
||||
// no pathname given --> read path for dirfd
|
||||
if (pathname == NULL)
|
||||
{
|
||||
fd_to_path(dirfd, fullpath, PATH_MAX);
|
||||
return fullpath;
|
||||
}
|
||||
// if relative path --> resolve it against dirfd
|
||||
else if (*pathname != '/' && *pathname != '~')
|
||||
{
|
||||
if (dirfd == AT_FDCWD)
|
||||
{
|
||||
getcwd(fullpath, PATH_MAX);
|
||||
len = strlen(fullpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = fd_to_path(dirfd, fullpath, PATH_MAX);
|
||||
}
|
||||
|
||||
if (len <= 0)
|
||||
{
|
||||
_fatal("Could not get path for fd %d; errno: %d", dirfd, errno);
|
||||
}
|
||||
|
||||
snprintf(&fullpath[len], PATH_MAX - len, "/%s", pathname);
|
||||
char *result = real_realpath(fullpath, finalPath);
|
||||
return result != NULL ? result : fullpath;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *result = real_realpath(pathname, finalPath);
|
||||
return result != NULL ? result : pathname;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,14 +14,43 @@
|
|||
|
||||
#define ARRAYSIZE(arr) (sizeof(arr)/sizeof(arr[0]))
|
||||
|
||||
#define GEN_REAL(ret, name, ...) \
|
||||
#define GEN_FN_DEF(ret, name, ...) \
|
||||
typedef ret (*fn_real_##name)(__VA_ARGS__); \
|
||||
static fn_real_##name real_##name = NULL; \
|
||||
if (!real_##name) { real_##name = (fn_real_##name)dlsym(RTLD_NEXT, #name); assert(real_##name); }
|
||||
const fn_real_##name real_##name = (fn_real_##name)dlsym(RTLD_NEXT, #name);
|
||||
|
||||
#define INTERPOSE(ret, name, ...) \
|
||||
ret name(__VA_ARGS__)
|
||||
|
||||
#define _fatal(fmt, ...) do { fprintf(stderr, "(%s) " fmt "\n", __func__, __VA_ARGS__); _exit(1); } while (0)
|
||||
#define fatal(msg) _fatal("%s", msg)
|
||||
|
||||
/**
|
||||
* Wraps the result of a syscall together with the current 'errno'.
|
||||
*
|
||||
* When the destructor is called, 'errno' is reset back to the value
|
||||
* that was captured in the constructor.
|
||||
*/
|
||||
template <typename T>
|
||||
class result_t final
|
||||
{
|
||||
private:
|
||||
int my_errno_;
|
||||
T result_;
|
||||
|
||||
public:
|
||||
result_t(T result) : result_(result), my_errno_(errno) {}
|
||||
~result_t() { errno = my_errno_; }
|
||||
operator T() { return result_; }
|
||||
};
|
||||
|
||||
/**
|
||||
* Singleton class responsible for reporting accesses.
|
||||
*
|
||||
* Accesses are observed by intercepting syscalls.
|
||||
*
|
||||
* Accesses are reported to a file (can be a regular file or a FIFO)
|
||||
* at the location specified by the FileAccessManifest.
|
||||
*/
|
||||
class BxlObserver final
|
||||
{
|
||||
private:
|
||||
|
@ -31,23 +60,87 @@ private:
|
|||
BxlObserver& operator = (const BxlObserver&) = delete;
|
||||
|
||||
char progFullPath_[PATH_MAX];
|
||||
|
||||
char logFile_[PATH_MAX];
|
||||
std::shared_ptr<SandboxedPip> pip_;
|
||||
std::shared_ptr<SandboxedProcess> process_;
|
||||
Sandbox *sandbox_;
|
||||
|
||||
static BxlObserver *sInstance;
|
||||
|
||||
void InitFam();
|
||||
void InitLogFile();
|
||||
bool Send(const char *buf, size_t bufsiz);
|
||||
|
||||
bool IsValid() { return sandbox_ != NULL; }
|
||||
|
||||
static BxlObserver *sInstance;
|
||||
|
||||
#define LogDebug(fmt, ...) if (logFile_ && *logFile_) do { \
|
||||
FILE* _lf = real_fopen(logFile_, "a"); \
|
||||
if (_lf) fprintf(_lf, "[%s:%d] " fmt "\n", __progname, getpid(), __VA_ARGS__); \
|
||||
if (_lf) real_fclose(_lf); \
|
||||
} while(0);
|
||||
|
||||
public:
|
||||
static BxlObserver* GetInstance();
|
||||
|
||||
bool SendReport(AccessReport &report);
|
||||
|
||||
inline std::shared_ptr<SandboxedPip> GetPip() { return pip_; }
|
||||
inline std::shared_ptr<SandboxedProcess> GetProcess() { return process_; }
|
||||
inline Sandbox* GetSandbox() { return sandbox_; }
|
||||
inline const char* GetProgramPath() { return progFullPath_; }
|
||||
inline const char* GetReportsPath() { int len; return pip_->GetReportsPath(&len); }
|
||||
const char* GetProgramPath() { return progFullPath_; }
|
||||
const char* GetReportsPath() { int len; return IsValid() ? pip_->GetReportsPath(&len) : NULL; }
|
||||
|
||||
static BxlObserver* GetInstance();
|
||||
bool report_access(const char *syscallName, IOEvent &event);
|
||||
bool report_access(const char *syscallName, es_event_type_t eventType, const char *pathname);
|
||||
bool report_access(const char *syscallName, es_event_type_t eventType, std::string reportPath, std::string secondPath);
|
||||
|
||||
bool report_access_fd(const char *syscallName, es_event_type_t eventType, int fd);
|
||||
bool report_access_at(const char *syscallName, es_event_type_t eventType, int dirfd, const char *pathname);
|
||||
|
||||
ssize_t fd_to_path(int fd, char *buf, size_t bufsiz);
|
||||
std::string normalize_path_at(int dirfd, const char *pathname);
|
||||
|
||||
std::string normalize_path(const char *pathname)
|
||||
{
|
||||
return normalize_path_at(AT_FDCWD, pathname);
|
||||
}
|
||||
|
||||
std::string normalize_fd(int fd)
|
||||
{
|
||||
return normalize_path_at(fd, NULL);
|
||||
}
|
||||
|
||||
GEN_FN_DEF(pid_t, fork, void)
|
||||
GEN_FN_DEF(int, fexecve, int, char *const[], char *const[])
|
||||
GEN_FN_DEF(int, execv, const char *, char *const[])
|
||||
GEN_FN_DEF(int, execve, const char *, char *const[], char *const[])
|
||||
GEN_FN_DEF(int, execvp, const char *, char *const[])
|
||||
GEN_FN_DEF(int, execvpe, const char *, char *const[], char *const[])
|
||||
GEN_FN_DEF(int, __fxstat, int, int, struct stat*);
|
||||
GEN_FN_DEF(int, statfs, const char *, struct statfs *)
|
||||
GEN_FN_DEF(int, __xstat, int, const char *, struct stat *)
|
||||
GEN_FN_DEF(int, __lxstat, int, const char *, struct stat *)
|
||||
GEN_FN_DEF(int, __xstat64, int, const char*, struct stat64*)
|
||||
GEN_FN_DEF(int, __lxstat64, int, const char*, struct stat64*)
|
||||
GEN_FN_DEF(int, __fxstat64, int, int, struct stat64*)
|
||||
GEN_FN_DEF(FILE*, fopen, const char *, const char *)
|
||||
GEN_FN_DEF(size_t, fread, void*, size_t, size_t, FILE*)
|
||||
GEN_FN_DEF(int, fclose, FILE*)
|
||||
GEN_FN_DEF(int, access, const char *, int)
|
||||
GEN_FN_DEF(int, faccessat, int, const char *, int, int)
|
||||
GEN_FN_DEF(int, creat, const char *, mode_t)
|
||||
GEN_FN_DEF(int, open, const char *, int, mode_t)
|
||||
GEN_FN_DEF(int, openat, int, const char *, int, mode_t)
|
||||
GEN_FN_DEF(int, close, int)
|
||||
GEN_FN_DEF(ssize_t, write, int, const void*, size_t)
|
||||
GEN_FN_DEF(int, remove, const char *)
|
||||
GEN_FN_DEF(int, rename, const char *, const char *)
|
||||
GEN_FN_DEF(int, link, const char *, const char *)
|
||||
GEN_FN_DEF(int, linkat, int, const char *, int, const char *, int)
|
||||
GEN_FN_DEF(int, unlink, const char *)
|
||||
GEN_FN_DEF(int, symlink, const char *, const char *)
|
||||
GEN_FN_DEF(int, symlinkat, const char *, int, const char *)
|
||||
GEN_FN_DEF(ssize_t, readlink, const char *, char *, size_t)
|
||||
GEN_FN_DEF(ssize_t, readlinkat, int, const char *, char *, size_t)
|
||||
GEN_FN_DEF(char*, realpath, const char*, char*)
|
||||
GEN_FN_DEF(DIR*, opendir, const char*)
|
||||
GEN_FN_DEF(int, utimensat, int, const char*, const struct timespec[2], int)
|
||||
GEN_FN_DEF(int, futimens, int, const struct timespec[2])
|
||||
};
|
||||
|
|
|
@ -21,378 +21,249 @@
|
|||
#include <sys/xattr.h>
|
||||
|
||||
#include "bxl_observer.hpp"
|
||||
#include "IOHandler.hpp"
|
||||
#include "EventProcessor.hpp"
|
||||
|
||||
static ssize_t fd_to_path(int fd, char *buf, size_t bufsiz)
|
||||
static BxlObserver *g_bxl = BxlObserver::GetInstance();
|
||||
|
||||
INTERPOSE(pid_t, fork, void)
|
||||
{
|
||||
GEN_REAL(ssize_t, readlink, const char *, char *, size_t);
|
||||
|
||||
char procPath[100] = {0};
|
||||
sprintf(procPath, "/proc/self/fd/%d", fd);
|
||||
return real_readlink(procPath, buf, bufsiz);
|
||||
}
|
||||
|
||||
static std::string normalize_path_at(int dirfd, const char *pathname)
|
||||
{
|
||||
// TODO: remove since it's being done in Send
|
||||
GEN_REAL(char*, realpath, const char*, char*);
|
||||
|
||||
char fullpath[PATH_MAX] = {0};
|
||||
char finalPath[PATH_MAX] = {0};
|
||||
ssize_t len = 0;
|
||||
|
||||
// no pathname given --> read path for dirfd
|
||||
if (pathname == NULL)
|
||||
{
|
||||
fd_to_path(dirfd, fullpath, PATH_MAX);
|
||||
return fullpath;
|
||||
}
|
||||
// if relative path --> resolve it against dirfd
|
||||
else if (*pathname != '/' && *pathname != '~')
|
||||
{
|
||||
if (dirfd == AT_FDCWD)
|
||||
{
|
||||
getcwd(fullpath, PATH_MAX);
|
||||
len = strlen(fullpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = fd_to_path(dirfd, fullpath, PATH_MAX);
|
||||
}
|
||||
|
||||
if (len <= 0)
|
||||
{
|
||||
_fatal("Could not get path for fd %d; errno: %d", dirfd, errno);
|
||||
}
|
||||
|
||||
snprintf(&fullpath[len], PATH_MAX - len, "/%s", pathname);
|
||||
char *result = real_realpath(fullpath, finalPath);
|
||||
return result != NULL ? result : fullpath;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *result = real_realpath(pathname, finalPath);
|
||||
return result != NULL ? result : pathname;
|
||||
}
|
||||
}
|
||||
|
||||
static std::string normalize_path(const char *pathname)
|
||||
{
|
||||
return normalize_path_at(AT_FDCWD, pathname);
|
||||
}
|
||||
|
||||
static std::string normalize_fd(int fd)
|
||||
{
|
||||
return normalize_path_at(fd, NULL);
|
||||
}
|
||||
|
||||
static bool report_access(const char *syscallName, IOEvent &event);
|
||||
|
||||
static bool report_access(const char *syscallName, es_event_type_t eventType, std::string reportPath, std::string secondPath)
|
||||
{
|
||||
GEN_REAL(int, __lxstat, int, const char *, struct stat *);
|
||||
GEN_REAL(ssize_t, readlink, const char *, char *, size_t);
|
||||
|
||||
// TODO: don't stat all the time
|
||||
struct stat s;
|
||||
mode_t mode = real___lxstat(1, reportPath.c_str(), &s) == 0
|
||||
? s.st_mode
|
||||
: 0;
|
||||
|
||||
std::string execPath = eventType == ES_EVENT_TYPE_NOTIFY_EXEC
|
||||
? reportPath
|
||||
: std::string(BxlObserver::GetInstance()->GetProgramPath());
|
||||
|
||||
IOEvent event(getpid(), 0, getppid(), eventType, reportPath, secondPath, execPath, mode, false);
|
||||
return report_access(syscallName, event);
|
||||
}
|
||||
|
||||
static bool report_access(const char *syscallName, IOEvent &event)
|
||||
{
|
||||
es_event_type_t eventType = event.GetEventType();
|
||||
|
||||
BxlObserver *bxl_observer = BxlObserver::GetInstance();
|
||||
IOHandler handler(bxl_observer->GetSandbox());
|
||||
handler.SetProcess(bxl_observer->GetProcess());
|
||||
|
||||
// TODO: this should return AccessCheckResult, which should be returned from here
|
||||
handler.HandleEvent(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool report_access(const char *syscallName, es_event_type_t eventType, const char *pathname, const char *otherPath = NULL)
|
||||
{
|
||||
std::string reportPath = normalize_path(pathname);
|
||||
std::string secondPath = otherPath != NULL
|
||||
? normalize_path(otherPath)
|
||||
: "";
|
||||
return report_access(syscallName, eventType, reportPath, secondPath);
|
||||
}
|
||||
|
||||
static bool report_access_fd(const char *syscallName, es_event_type_t eventType, int fd)
|
||||
{
|
||||
char fullpath[PATH_MAX] = {0};
|
||||
fd_to_path(fd, fullpath, PATH_MAX);
|
||||
|
||||
return report_access(syscallName, eventType, fullpath);
|
||||
}
|
||||
|
||||
static bool report_access_at(const char *syscallName, es_event_type_t eventType, int dirfd, const char *pathname)
|
||||
{
|
||||
char fullpath[PATH_MAX] = {0};
|
||||
ssize_t len = 0;
|
||||
|
||||
if (dirfd == AT_FDCWD)
|
||||
{
|
||||
getcwd(fullpath, PATH_MAX);
|
||||
len = strlen(fullpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
len = fd_to_path(dirfd, fullpath, PATH_MAX);
|
||||
}
|
||||
|
||||
if (len <= 0)
|
||||
{
|
||||
_fatal("Could not get path for fd %d; errno: %d", dirfd, errno);
|
||||
}
|
||||
|
||||
snprintf(&fullpath[len], PATH_MAX - len, "/%s", pathname);
|
||||
return report_access(syscallName, eventType, fullpath);
|
||||
}
|
||||
|
||||
static enum RequestedAccess oflag_to_access(int oflag)
|
||||
{
|
||||
return oflag & (O_WRONLY | O_RDWR) ? RequestedAccess::Write : RequestedAccess::Read;
|
||||
}
|
||||
|
||||
pid_t fork(void)
|
||||
{
|
||||
GEN_REAL(pid_t, fork);
|
||||
GEN_REAL(ssize_t, readlink, const char *, char *, size_t);
|
||||
|
||||
pid_t childPid = real_fork();
|
||||
result_t<pid_t> childPid = g_bxl->real_fork();
|
||||
|
||||
// report fork only when we are in the parent process
|
||||
if (childPid > 0)
|
||||
{
|
||||
std::string exePath(BxlObserver::GetInstance()->GetProgramPath());
|
||||
std::string exePath(g_bxl->GetProgramPath());
|
||||
IOEvent event(getpid(), childPid, getppid(), ES_EVENT_TYPE_NOTIFY_FORK, exePath, std::string(""), exePath, 0, false);
|
||||
report_access(__func__, event);
|
||||
g_bxl->report_access(__func__, event);
|
||||
}
|
||||
|
||||
return childPid;
|
||||
}
|
||||
|
||||
int fexecve(int fd, char *const argv[], char *const envp[]) {
|
||||
GEN_REAL(int, fexecve, int, char *const[], char *const[])
|
||||
report_access_fd(__func__, ES_EVENT_TYPE_NOTIFY_EXEC, fd);
|
||||
return real_fexecve(fd, argv, envp);
|
||||
}
|
||||
|
||||
int execv(const char *file, char *const argv[]) {
|
||||
GEN_REAL(int, execv, const char *, char *const[])
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_EXEC, file);
|
||||
return real_execv(file, argv);
|
||||
}
|
||||
|
||||
int execve(const char *file, char *const argv[], char *const envp[]) {
|
||||
GEN_REAL(int, execve, const char *, char *const[], char *const[])
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_EXEC, file);
|
||||
return real_execve(file, argv, envp);
|
||||
}
|
||||
|
||||
int execvp(const char *file, char *const argv[]) {
|
||||
GEN_REAL(int, execvp, const char *, char *const[])
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_EXEC, std::string(file), std::string(""));
|
||||
return real_execvp(file, argv);
|
||||
}
|
||||
|
||||
int execvpe(const char *file, char *const argv[], char *const envp[]) {
|
||||
GEN_REAL(int, execvpe, const char *, char *const[], char *const[])
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_EXEC, std::string(file), std::string(""));
|
||||
return real_execvpe(file, argv, envp);
|
||||
}
|
||||
|
||||
int __fxstat(int __ver, int fd, struct stat *__stat_buf) {
|
||||
GEN_REAL(int, __fxstat, int, int, struct stat*);
|
||||
report_access_fd(__func__, ES_EVENT_TYPE_NOTIFY_STAT, fd);
|
||||
return real___fxstat(__ver, fd, __stat_buf);
|
||||
}
|
||||
|
||||
int statfs(const char *pathname, struct statfs *buf) {
|
||||
GEN_REAL(int, statfs, const char *, struct statfs *);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_STAT, pathname);
|
||||
return real_statfs(pathname, buf);
|
||||
}
|
||||
|
||||
int __xstat(int __ver, const char *pathname, struct stat *buf) {
|
||||
GEN_REAL(int, __xstat, int, const char *, struct stat *);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_STAT, pathname);
|
||||
return real___xstat(__ver, pathname, buf);
|
||||
}
|
||||
|
||||
int __xstat64(int __ver, const char *pathname, struct stat64 *buf)
|
||||
INTERPOSE(int, fexecve, int fd, char *const argv[], char *const envp[])
|
||||
{
|
||||
GEN_REAL(int, __xstat64, int, const char*, struct stat64*);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_STAT, pathname);
|
||||
return real___xstat64(__ver, pathname, buf);
|
||||
g_bxl->report_access_fd(__func__, ES_EVENT_TYPE_NOTIFY_EXEC, fd);
|
||||
return g_bxl->real_fexecve(fd, argv, envp);
|
||||
}
|
||||
|
||||
int __lxstat64(int __ver, const char *pathname, struct stat64 *buf)
|
||||
INTERPOSE(int, execv, const char *file, char *const argv[])
|
||||
{
|
||||
GEN_REAL(int, __lxstat64, int, const char*, struct stat64*);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_STAT, pathname);
|
||||
return real___lxstat64(__ver, pathname, buf);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_EXEC, file);
|
||||
return g_bxl->real_execv(file, argv);
|
||||
}
|
||||
|
||||
int __fxstat64(int __ver, int fd, struct stat64 *buf)
|
||||
INTERPOSE(int, execve, const char *file, char *const argv[], char *const envp[])
|
||||
{
|
||||
GEN_REAL(int, __fxstat64, int, int, struct stat64*);
|
||||
report_access_fd(__func__, ES_EVENT_TYPE_NOTIFY_STAT, fd);
|
||||
return real___fxstat64(__ver, fd, buf);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_EXEC, file);
|
||||
return g_bxl->real_execve(file, argv, envp);
|
||||
}
|
||||
|
||||
int __lxstat(int __ver, const char *pathname, struct stat *buf) {
|
||||
GEN_REAL(int, __lxstat, int, const char *, struct stat *);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_STAT, pathname);
|
||||
return real___lxstat(__ver, pathname, buf);
|
||||
INTERPOSE(int, execvp, const char *file, char *const argv[])
|
||||
{
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_EXEC, std::string(file), std::string(""));
|
||||
return g_bxl->real_execvp(file, argv);
|
||||
}
|
||||
|
||||
FILE* fopen(const char *pathname, const char *mode) {
|
||||
GEN_REAL(FILE*, fopen, const char *, const char *);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_OPEN, pathname);
|
||||
return real_fopen(pathname, mode);
|
||||
INTERPOSE(int, execvpe, const char *file, char *const argv[], char *const envp[])
|
||||
{
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_EXEC, std::string(file), std::string(""));
|
||||
return g_bxl->real_execvpe(file, argv, envp);
|
||||
}
|
||||
|
||||
int access(const char *pathname, int mode) {
|
||||
GEN_REAL(int, access, const char *, int);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_ACCESS, pathname);
|
||||
return real_access(pathname, mode);
|
||||
INTERPOSE(int, __fxstat, int __ver, int fd, struct stat *__stat_buf)
|
||||
{
|
||||
result_t<int> result = g_bxl->real___fxstat(__ver, fd, __stat_buf);
|
||||
g_bxl->report_access_fd(__func__, ES_EVENT_TYPE_NOTIFY_STAT, fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
int faccessat(int dirfd, const char *pathname, int mode, int flags) {
|
||||
GEN_REAL(int, faccessat, int, const char *, int, int);
|
||||
report_access_at(__func__, ES_EVENT_TYPE_NOTIFY_ACCESS, dirfd, pathname);
|
||||
return real_faccessat(dirfd, pathname, mode, flags);
|
||||
INTERPOSE(int, statfs, const char *pathname, struct statfs *buf)
|
||||
{
|
||||
result_t<int> result = g_bxl->real_statfs(pathname, buf);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_STAT, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
int open(const char *path, int oflag, ...) {
|
||||
GEN_REAL(int, open, const char *, int, mode_t);
|
||||
INTERPOSE(int, __xstat, int __ver, const char *pathname, struct stat *buf)
|
||||
{
|
||||
result_t<int> result = g_bxl->real___xstat(__ver, pathname, buf);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_STAT, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, __xstat64, int __ver, const char *pathname, struct stat64 *buf)
|
||||
{
|
||||
result_t<int> result(g_bxl->real___xstat64(__ver, pathname, buf));
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_STAT, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, __lxstat64, int __ver, const char *pathname, struct stat64 *buf)
|
||||
{
|
||||
result_t<int> result(g_bxl->real___lxstat64(__ver, pathname, buf));
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_STAT, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, __fxstat64, int __ver, int fd, struct stat64 *buf)
|
||||
{
|
||||
result_t<int> result(g_bxl->real___fxstat64(__ver, fd, buf));
|
||||
g_bxl->report_access_fd(__func__, ES_EVENT_TYPE_NOTIFY_STAT, fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, __lxstat, int __ver, const char *pathname, struct stat *buf)
|
||||
{
|
||||
result_t<int> result = g_bxl->real___lxstat(__ver, pathname, buf);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_STAT, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(FILE*, fopen, const char *pathname, const char *mode)
|
||||
{
|
||||
result_t<FILE*> result = g_bxl->real_fopen(pathname, mode);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_OPEN, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, access, const char *pathname, int mode)
|
||||
{
|
||||
result_t<int> result = g_bxl->real_access(pathname, mode);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_ACCESS, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, faccessat, int dirfd, const char *pathname, int mode, int flags)
|
||||
{
|
||||
result_t<int> result = g_bxl->real_faccessat(dirfd, pathname, mode, flags);
|
||||
g_bxl->report_access_at(__func__, ES_EVENT_TYPE_NOTIFY_ACCESS, dirfd, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, open, const char *path, int oflag, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, oflag);
|
||||
mode_t mode = va_arg(args, mode_t);
|
||||
va_end(args);
|
||||
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_OPEN, path);
|
||||
return real_open(path, oflag, mode);
|
||||
result_t<int> result = g_bxl->real_open(path, oflag, mode);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_OPEN, path);
|
||||
return result;
|
||||
}
|
||||
|
||||
int creat(const char *pathname, mode_t mode) {
|
||||
GEN_REAL(int, creat, const char *, mode_t);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_CREATE, pathname);
|
||||
return real_creat(pathname, mode);
|
||||
INTERPOSE(int, creat, const char *pathname, mode_t mode)
|
||||
{
|
||||
result_t<int> result = g_bxl->real_creat(pathname, mode);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_CREATE, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
int openat(int dirfd, const char *pathname, int flags, ...) {
|
||||
GEN_REAL(int, openat, int, const char *, int, mode_t);
|
||||
|
||||
INTERPOSE(int, openat, int dirfd, const char *pathname, int flags, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, flags);
|
||||
mode_t mode = va_arg(args, mode_t);
|
||||
va_end(args);
|
||||
|
||||
report_access_at(__func__, ES_EVENT_TYPE_NOTIFY_OPEN, dirfd, pathname);
|
||||
return real_openat(dirfd, pathname, flags, mode);
|
||||
result_t<int> result = g_bxl->real_openat(dirfd, pathname, flags, mode);
|
||||
g_bxl->report_access_at(__func__, ES_EVENT_TYPE_NOTIFY_OPEN, dirfd, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
ssize_t write(int fd, const void *buf, size_t bufsiz)
|
||||
INTERPOSE(ssize_t, write, int fd, const void *buf, size_t bufsiz)
|
||||
{
|
||||
GEN_REAL(ssize_t, write, int, const void*, size_t);
|
||||
report_access_fd(__func__, ES_EVENT_TYPE_NOTIFY_WRITE, fd);
|
||||
return real_write(fd, buf, bufsiz);
|
||||
result_t<ssize_t> result = g_bxl->real_write(fd, buf, bufsiz);
|
||||
g_bxl->report_access_fd(__func__, ES_EVENT_TYPE_NOTIFY_WRITE, fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
int remove(const char *pathname) {
|
||||
GEN_REAL(int, remove, const char *);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_UNLINK, pathname);
|
||||
return real_remove(pathname);
|
||||
}
|
||||
|
||||
int rename(const char *old, const char *n) {
|
||||
GEN_REAL(int, rename, const char *, const char *);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_RENAME, old, n);
|
||||
return real_rename(old, n);
|
||||
}
|
||||
|
||||
int link(const char *path1, const char *path2) {
|
||||
GEN_REAL(int, link, const char *, const char *);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_LINK, path1, path2);
|
||||
return real_link(path1, path2);
|
||||
}
|
||||
|
||||
int linkat(int fd1, const char *name1, int fd2, const char *name2, int flag) {
|
||||
GEN_REAL(int, linkat, int, const char *, int, const char *, int);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_LINK, normalize_path_at(fd1, name1), normalize_path_at(fd2, name2));
|
||||
return real_linkat(fd1, name1, fd2, name2, flag);
|
||||
}
|
||||
|
||||
int unlink(const char *path) {
|
||||
GEN_REAL(int, unlink, const char *);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_UNLINK, path);
|
||||
return real_unlink(path);
|
||||
}
|
||||
|
||||
int symlink(const char *path1, const char *path2) {
|
||||
GEN_REAL(int, symlink, const char *, const char *);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_CREATE, path2);
|
||||
return real_symlink(path1, path2);
|
||||
}
|
||||
|
||||
int symlinkat(const char *name1, int fd, const char *name2) {
|
||||
GEN_REAL(int, symlinkat, const char *, int, const char *);
|
||||
report_access_at(__func__, ES_EVENT_TYPE_NOTIFY_CREATE, fd, name2);
|
||||
return real_symlinkat(name1, fd, name2);
|
||||
}
|
||||
|
||||
ssize_t readlink(const char *path, char *buf, size_t bufsize) {
|
||||
GEN_REAL(ssize_t, readlink, const char *, char *, size_t);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_READLINK, path);
|
||||
return real_readlink(path, buf, bufsize);
|
||||
}
|
||||
|
||||
ssize_t readlinkat(int fd, const char *path, char *buf, size_t bufsize) {
|
||||
GEN_REAL(ssize_t, readlinkat, int, const char *, char *, size_t);
|
||||
report_access_at(__func__, ES_EVENT_TYPE_NOTIFY_READLINK, fd, path);
|
||||
return real_readlinkat(fd, path, buf, bufsize);
|
||||
}
|
||||
|
||||
DIR* opendir(const char *name) {
|
||||
GEN_REAL(DIR*, opendir, const char*);
|
||||
report_access(__func__, ES_EVENT_TYPE_NOTIFY_READDIR, name);
|
||||
return real_opendir(name);
|
||||
}
|
||||
|
||||
int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags)
|
||||
INTERPOSE(int, remove, const char *pathname)
|
||||
{
|
||||
GEN_REAL(int, utimensat, int, const char*, const struct timespec[2], int);
|
||||
report_access_at(__func__, ES_EVENT_TYPE_NOTIFY_SETTIME, dirfd, pathname);
|
||||
return real_utimensat(dirfd, pathname, times, flags);
|
||||
result_t<int> result = g_bxl->real_remove(pathname);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_UNLINK, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
int futimens(int fd, const struct timespec times[2])
|
||||
INTERPOSE(int, rename, const char *old, const char *n)
|
||||
{
|
||||
GEN_REAL(int, futimens, int, const struct timespec[2]);
|
||||
report_access_fd(__func__, ES_EVENT_TYPE_NOTIFY_SETTIME, fd);
|
||||
return real_futimens(fd, times);
|
||||
result_t<int> result = g_bxl->real_rename(old, n);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_RENAME, old, n);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void report_exit()
|
||||
INTERPOSE(int, link, const char *path1, const char *path2)
|
||||
{
|
||||
report_access("atexit", ES_EVENT_TYPE_NOTIFY_EXIT, std::string(""), std::string(""));
|
||||
result_t<int> result = g_bxl->real_link(path1, path2);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_LINK, path1, path2);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, linkat, int fd1, const char *name1, int fd2, const char *name2, int flag)
|
||||
{
|
||||
result_t<int> result = g_bxl->real_linkat(fd1, name1, fd2, name2, flag);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_LINK, g_bxl->normalize_path_at(fd1, name1), g_bxl->normalize_path_at(fd2, name2));
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, unlink, const char *path)
|
||||
{
|
||||
result_t<int> result = g_bxl->real_unlink(path);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_UNLINK, path);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, symlink, const char *path1, const char *path2)
|
||||
{
|
||||
result_t<int> result = g_bxl->real_symlink(path1, path2);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_CREATE, path2);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, symlinkat, const char *name1, int fd, const char *name2)
|
||||
{
|
||||
result_t<int> result = g_bxl->real_symlinkat(name1, fd, name2);
|
||||
g_bxl->report_access_at(__func__, ES_EVENT_TYPE_NOTIFY_CREATE, fd, name2);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(ssize_t, readlink, const char *path, char *buf, size_t bufsize)
|
||||
{
|
||||
result_t<int> result = g_bxl->real_readlink(path, buf, bufsize);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_READLINK, path);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(ssize_t, readlinkat, int fd, const char *path, char *buf, size_t bufsize)
|
||||
{
|
||||
result_t<ssize_t> result = g_bxl->real_readlinkat(fd, path, buf, bufsize);
|
||||
g_bxl->report_access_at(__func__, ES_EVENT_TYPE_NOTIFY_READLINK, fd, path);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(DIR*, opendir, const char *name)
|
||||
{
|
||||
result_t<DIR*> result = g_bxl->real_opendir(name);
|
||||
g_bxl->report_access(__func__, ES_EVENT_TYPE_NOTIFY_READDIR, name);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, utimensat, int dirfd, const char *pathname, const struct timespec times[2], int flags)
|
||||
{
|
||||
result_t<int> result = g_bxl->real_utimensat(dirfd, pathname, times, flags);
|
||||
g_bxl->report_access_at(__func__, ES_EVENT_TYPE_NOTIFY_SETTIME, dirfd, pathname);
|
||||
return result;
|
||||
}
|
||||
|
||||
INTERPOSE(int, futimens, int fd, const struct timespec times[2])
|
||||
{
|
||||
result_t<int> result = g_bxl->real_futimens(fd, times);
|
||||
g_bxl->report_access_fd(__func__, ES_EVENT_TYPE_NOTIFY_SETTIME, fd);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void report_exit()
|
||||
{
|
||||
g_bxl->report_access("atexit", ES_EVENT_TYPE_NOTIFY_EXIT, std::string(""), std::string(""));
|
||||
}
|
||||
|
||||
void __attribute__ ((constructor)) _bxl_linux_sandbox_init(void)
|
||||
|
@ -407,35 +278,4 @@ int main(int argc, char **argv)
|
|||
{
|
||||
BxlObserver *inst = BxlObserver::GetInstance();
|
||||
printf("Path: %s\n", inst->GetReportsPath());
|
||||
|
||||
GEN_REAL(int, fexecve, int, char *const[], char *const[])
|
||||
GEN_REAL(int, execv, const char *, char *const[])
|
||||
GEN_REAL(int, execve, const char *, char *const[], char *const[])
|
||||
GEN_REAL(int, execvp, const char *, char *const[])
|
||||
GEN_REAL(int, execvpe, const char *, char *const[], char *const[])
|
||||
GEN_REAL(int, __fxstat, int, int, struct stat*);
|
||||
GEN_REAL(int, statfs, const char *, struct statfs *);
|
||||
GEN_REAL(int, __xstat, int, const char *, struct stat *);
|
||||
GEN_REAL(int, __lxstat, int, const char *, struct stat *);
|
||||
GEN_REAL(int, __xstat64, int, const char*, struct stat64*);
|
||||
GEN_REAL(int, __lxstat64, int, const char*, struct stat64*);
|
||||
GEN_REAL(int, __fxstat64, int, const char*, struct stat64*);
|
||||
GEN_REAL(FILE*, fopen, const char *, const char *);
|
||||
GEN_REAL(int, access, const char *, int);
|
||||
GEN_REAL(int, faccessat, int, const char *, int, int);
|
||||
GEN_REAL(int, open, const char *, int, mode_t);
|
||||
GEN_REAL(int, creat, const char *, mode_t);
|
||||
GEN_REAL(int, openat, int, const char *, int, mode_t);
|
||||
GEN_REAL(ssize_t, write, int, const void*, size_t);
|
||||
GEN_REAL(int, remove, const char *);
|
||||
GEN_REAL(int, rename, const char *, const char *);
|
||||
GEN_REAL(int, link, const char *, const char *);
|
||||
GEN_REAL(int, linkat, int, const char *, int, const char *, int);
|
||||
GEN_REAL(int, unlink, const char *);
|
||||
GEN_REAL(int, symlink, const char *, const char *);
|
||||
GEN_REAL(int, symlinkat, const char *, int, const char *);
|
||||
GEN_REAL(ssize_t, readlink, const char *, char *, size_t);
|
||||
GEN_REAL(ssize_t, readlinkat, int, const char *, char *, size_t);
|
||||
GEN_REAL(DIR*, opendir, const char*);
|
||||
GEN_REAL(int, utimensat, int, const char*, const struct timespec[2], int);
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
#!/bin/bash
|
||||
|
||||
readonly __dir=$(cd `dirname ${BASH_SOURCE[0]}` && pwd)
|
||||
|
||||
set -e
|
||||
set -u
|
||||
|
||||
function onExit {
|
||||
popd > /dev/null 2>&1
|
||||
}
|
||||
|
||||
readonly version="$1"
|
||||
readonly pkgName="runtime.linux-x64.BuildXL.${version}"
|
||||
|
||||
pushd "${__dir}" > /dev/null 2>&1
|
||||
trap onExit EXIT
|
||||
|
||||
cd "${__dir}"
|
||||
make debug release
|
||||
|
||||
cd bin
|
||||
|
||||
rm -rf "${pkgName}"
|
||||
mkdir -p "${pkgName}/ref/netstandard"
|
||||
touch "${pkgName}/ref/netstandard/_._"
|
||||
|
||||
mkdir -p "${pkgName}/runtimes/linux-x64/native"
|
||||
cp -r debug release "${pkgName}/runtimes/linux-x64/native"
|
||||
|
||||
cat > "${pkgName}/runtime.linux-x64.buildxl.nuspec" <<EOF
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2013/01/nuspec.xsd">
|
||||
<metadata minClientVersion="2.12">
|
||||
<id>runtime.linux-x64.BuildXL</id>
|
||||
<version>${version}</version>
|
||||
<title>runtime.linux-x64.BuildXL</title>
|
||||
<authors>Microsoft</authors>
|
||||
<owners>microsoft,buildxl,bxl</owners>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<description>The BuildXL runtime libraries for Linux.</description>
|
||||
<copyright>© Microsoft Corporation. All rights reserved.</copyright>
|
||||
<serviceable>true</serviceable>
|
||||
</metadata>
|
||||
</package>
|
||||
EOF
|
||||
|
||||
cd "${pkgName}"
|
||||
zip -v ../${pkgName}.nupkg *
|
|
@ -4326,7 +4326,7 @@
|
|||
"Type": "NuGet",
|
||||
"NuGet": {
|
||||
"Name": "runtime.linux-x64.BuildXL",
|
||||
"Version": "0.0.3"
|
||||
"Version": "0.0.4"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -333,7 +333,7 @@ config({
|
|||
// Runtime dependencies for Linux
|
||||
{
|
||||
id: "runtime.linux-x64.BuildXL",
|
||||
version: "0.0.3",
|
||||
version: "0.0.4",
|
||||
osSkip: importFile(f`config.microsoftInternal.dsc`).isMicrosoftInternal
|
||||
? []
|
||||
: [ "win", "macOS", "linux" ]
|
||||
|
|
Загрузка…
Ссылка в новой задаче