summaryrefslogtreecommitdiffstats
path: root/sandbox/linux/seccomp/stat.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/linux/seccomp/stat.cc')
-rw-r--r--sandbox/linux/seccomp/stat.cc110
1 files changed, 110 insertions, 0 deletions
diff --git a/sandbox/linux/seccomp/stat.cc b/sandbox/linux/seccomp/stat.cc
new file mode 100644
index 0000000..8634fdf
--- /dev/null
+++ b/sandbox/linux/seccomp/stat.cc
@@ -0,0 +1,110 @@
+#include "debug.h"
+#include "sandbox_impl.h"
+
+namespace playground {
+
+int Sandbox::sandbox_stat(const char *path, void *buf) {
+ Debug::syscall(__NR_stat, "Executing handler");
+ size_t len = strlen(path);
+ struct Request {
+ int sysnum;
+ long long cookie;
+ Stat stat_req;
+ char pathname[0];
+ } __attribute__((packed)) *request;
+ char data[sizeof(struct Request) + len];
+ request = reinterpret_cast<struct Request*>(data);
+ request->sysnum = __NR_stat;
+ request->cookie = cookie();
+ request->stat_req.sysnum = __NR_stat;
+ request->stat_req.path_length = len;
+ request->stat_req.buf = buf;
+ memcpy(request->pathname, path, len);
+
+ long rc;
+ SysCalls sys;
+ if (write(sys, processFdPub(), request, sizeof(data)) != (int)sizeof(data) ||
+ read(sys, threadFdPub(), &rc, sizeof(rc)) != sizeof(rc)) {
+ die("Failed to forward stat() request [sandbox]");
+ }
+ return static_cast<int>(rc);
+}
+
+#if defined(__NR_stat64)
+int Sandbox::sandbox_stat64(const char *path, void *buf) {
+ Debug::syscall(__NR_stat64, "Executing handler");
+ size_t len = strlen(path);
+ struct Request {
+ int sysnum;
+ long long cookie;
+ Stat stat_req;
+ char pathname[0];
+ } __attribute__((packed)) *request;
+ char data[sizeof(struct Request) + len];
+ request = reinterpret_cast<struct Request*>(data);
+ request->sysnum = __NR_stat64;
+ request->cookie = cookie();
+ request->stat_req.sysnum = __NR_stat64;
+ request->stat_req.path_length = len;
+ request->stat_req.buf = buf;
+ memcpy(request->pathname, path, len);
+
+ long rc;
+ SysCalls sys;
+ if (write(sys, processFdPub(), request, sizeof(data)) != (int)sizeof(data) ||
+ read(sys, threadFdPub(), &rc, sizeof(rc)) != sizeof(rc)) {
+ die("Failed to forward stat64() request [sandbox]");
+ }
+ return static_cast<int>(rc);
+}
+#endif
+
+bool Sandbox::process_stat(int parentProc, int sandboxFd, int threadFdPub,
+ int threadFd, SecureMem::Args* mem) {
+ // Read request
+ SysCalls sys;
+ Stat stat_req;
+ if (read(sys, sandboxFd, &stat_req, sizeof(stat_req)) != sizeof(stat_req)) {
+ read_parm_failed:
+ die("Failed to read parameters for stat() [process]");
+ }
+ int rc = -ENAMETOOLONG;
+ if (stat_req.path_length >= (int)sizeof(mem->pathname)) {
+ char buf[32];
+ while (stat_req.path_length > 0) {
+ size_t len = stat_req.path_length > sizeof(buf) ?
+ sizeof(buf) : stat_req.path_length;
+ ssize_t i = read(sys, sandboxFd, buf, len);
+ if (i <= 0) {
+ goto read_parm_failed;
+ }
+ stat_req.path_length -= i;
+ }
+ if (write(sys, threadFd, &rc, sizeof(rc)) != sizeof(rc)) {
+ die("Failed to return data from stat() [process]");
+ }
+ return false;
+ }
+ SecureMem::lockSystemCall(parentProc, mem);
+ if (read(sys, sandboxFd, mem->pathname, stat_req.path_length) !=
+ (ssize_t)stat_req.path_length) {
+ goto read_parm_failed;
+ }
+ mem->pathname[stat_req.path_length] = '\000';
+
+ // TODO(markus): Implement sandboxing policy
+ Debug::message(("Allowing access to \"" + std::string(mem->pathname) +
+ "\"").c_str());
+
+ // Tell trusted thread to stat the file.
+ SecureMem::sendSystemCall(threadFdPub, true, parentProc, mem,
+ #if defined(__i386__)
+ stat_req.sysnum == __NR_stat64 ? __NR_stat64 :
+ #endif
+ __NR_stat,
+ mem->pathname - (char*)mem + (char*)mem->self,
+ stat_req.buf);
+ return true;
+}
+
+} // namespace