Bug 1409900 - Handle sandboxed statfs() by replacing it with open+fstatfs. r?gcp draft
authorJed Davis <jld@mozilla.com>
Fri, 27 Oct 2017 19:32:37 -0600
changeset 688060 877ce6f1fa91c454cd2306e3a8a882d3617e9215
parent 688059 f19339207df8aefb66b334de7eb4686fad820504
child 737788 62708ddfa95c622e246bb8517a34b47368970e93
push id86658
push userbmo:jld@mozilla.com
push dateSat, 28 Oct 2017 03:11:29 +0000
reviewersgcp
bugs1409900
milestone58.0a1
Bug 1409900 - Handle sandboxed statfs() by replacing it with open+fstatfs. r?gcp MozReview-Commit-ID: 4Q0XMWcxaAc
security/sandbox/linux/SandboxFilter.cpp
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -534,16 +534,50 @@ private:
 
   static intptr_t SocketpairDatagramTrap(ArgsRef aArgs, void* aux) {
     auto fds = reinterpret_cast<int*>(aArgs.args[3]);
     // Return sequential packet sockets instead of the expected
     // datagram sockets; see bug 1355274 for details.
     return ConvertError(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
   }
 
+  static intptr_t StatFsTrap(ArgsRef aArgs, void* aux) {
+    // Warning: the kernel interface is not the C interface.  The
+    // structs are different (<asm/statfs.h> vs. <sys/statfs.h>), and
+    // the statfs64 version takes an additional size parameter.
+    auto path = reinterpret_cast<const char*>(aArgs.args[0]);
+    int fd = open(path, O_RDONLY | O_LARGEFILE);
+    if (fd < 0) {
+      return -errno;
+    }
+
+    intptr_t rv;
+    switch (aArgs.nr) {
+    case __NR_statfs: {
+      auto buf = reinterpret_cast<void*>(aArgs.args[1]);
+      rv = DoSyscall(__NR_fstatfs, fd, buf);
+      break;
+    }
+#ifdef __NR_statfs64
+    case __NR_statfs64: {
+      auto sz = static_cast<size_t>(aArgs.args[1]);
+      auto buf = reinterpret_cast<void*>(aArgs.args[2]);
+      rv = DoSyscall(__NR_fstatfs64, fd, sz, buf);
+      break;
+    }
+#endif
+    default:
+      MOZ_ASSERT(false);
+      rv = -ENOSYS;
+    }
+
+    close(fd);
+    return rv;
+  }
+
 public:
   explicit ContentSandboxPolicy(SandboxBrokerClient* aBroker,
                                 const std::vector<int>& aSyscallWhitelist)
     : mBroker(aBroker),
       mSyscallWhitelist(aSyscallWhitelist) {}
   ~ContentSandboxPolicy() override = default;
   Maybe<ResultExpr> EvaluateSocketCall(int aCall) const override {
     switch(aCall) {
@@ -686,20 +720,22 @@ public:
       }
     }
 
     switch (sysno) {
 #ifdef DESKTOP
     case __NR_getppid:
       return Trap(GetPPidTrap, nullptr);
 
+    CASES_FOR_statfs:
+      return Trap(StatFsTrap, nullptr);
+
       // Filesystem syscalls that need more work to determine who's
       // using them, if they need to be, and what we intend to about it.
     case __NR_getcwd:
-    CASES_FOR_statfs:
     CASES_FOR_fstatfs:
     CASES_FOR_fchown:
     case __NR_fchmod:
     case __NR_flock:
       return Allow();
 
       // Bug 1354731: proprietary GL drivers try to mknod() their devices
     case __NR_mknod: {