Bug 1383888 - Restrict sandboxed readlinkat() the same as readlink(). r?gcp draft
authorJed Davis <jld@mozilla.com>
Thu, 27 Jul 2017 17:22:23 -0600
changeset 653392 248ad4eb8cf21d29a78a39f4cccd21ae2c4719b1
parent 653365 03d7b6dd65b93afaa6981269f69e9f7cd34224bc
child 728337 b3ceab47b0ed48f13a70cb25d74ade39a65e2082
push id76325
push userbmo:jld@mozilla.com
push dateFri, 25 Aug 2017 23:36:06 +0000
reviewersgcp
bugs1383888
milestone57.0a1
Bug 1383888 - Restrict sandboxed readlinkat() the same as readlink(). r?gcp MozReview-Commit-ID: 3VLXp7AJePQ
security/sandbox/linux/SandboxFilter.cpp
--- a/security/sandbox/linux/SandboxFilter.cpp
+++ b/security/sandbox/linux/SandboxFilter.cpp
@@ -489,16 +489,30 @@ private:
   static intptr_t ReadlinkTrap(ArgsRef aArgs, void* aux) {
     auto broker = static_cast<SandboxBrokerClient*>(aux);
     auto path = reinterpret_cast<const char*>(aArgs.args[0]);
     auto buf = reinterpret_cast<char*>(aArgs.args[1]);
     auto size = static_cast<size_t>(aArgs.args[2]);
     return broker->Readlink(path, buf, size);
   }
 
+  static intptr_t ReadlinkAtTrap(ArgsRef aArgs, void* aux) {
+    auto broker = static_cast<SandboxBrokerClient*>(aux);
+    auto fd = static_cast<int>(aArgs.args[0]);
+    auto path = reinterpret_cast<const char*>(aArgs.args[1]);
+    auto buf = reinterpret_cast<char*>(aArgs.args[2]);
+    auto size = static_cast<size_t>(aArgs.args[3]);
+    if (fd != AT_FDCWD && path[0] != '/') {
+      SANDBOX_LOG_ERROR("unsupported fd-relative readlinkat(%d, %s, %p, %u)",
+                        fd, path, buf, size);
+      return BlockedSyscallTrap(aArgs, nullptr);
+    }
+    return broker->Readlink(path, buf, size);
+  }
+
   static intptr_t GetPPidTrap(ArgsRef aArgs, void* aux) {
     // In a pid namespace, getppid() will return 0. We will return 0 instead
     // of the real parent pid to see what breaks when we introduce the
     // pid namespace (Bug 1151624).
     return 0;
   }
 
   static intptr_t SocketpairDatagramTrap(ArgsRef aArgs, void* aux) {
@@ -624,16 +638,18 @@ public:
       case __NR_rename:
         return Trap(RenameTrap, mBroker);
       case __NR_rmdir:
         return Trap(RmdirTrap, mBroker);
       case __NR_unlink:
         return Trap(UnlinkTrap, mBroker);
       case __NR_readlink:
         return Trap(ReadlinkTrap, mBroker);
+      case __NR_readlinkat:
+        return Trap(ReadlinkAtTrap, mBroker);
       }
     } else {
       // No broker; allow the syscalls directly.  )-:
       switch(sysno) {
       case __NR_open:
       case __NR_openat:
       case __NR_access:
       case __NR_faccessat:
@@ -643,16 +659,17 @@ public:
       case __NR_chmod:
       case __NR_link:
       case __NR_mkdir:
       case __NR_symlink:
       case __NR_rename:
       case __NR_rmdir:
       case __NR_unlink:
       case __NR_readlink:
+      case __NR_readlinkat:
         return Allow();
       }
     }
 
     switch (sysno) {
 #ifdef DESKTOP
     case __NR_getppid:
       return Trap(GetPPidTrap, nullptr);
@@ -676,25 +693,16 @@ public:
     }
 
       // For ORBit called by GConf (on some systems) to get proxy
       // settings.  Can remove when bug 1325242 happens in some form.
     case __NR_utime:
       return Error(EPERM);
 #endif
 
-    case __NR_readlinkat:
-#ifdef DESKTOP
-      // Bug 1290896
-      return Allow();
-#else
-      // Workaround for bug 964455:
-      return Error(EINVAL);
-#endif
-
     CASES_FOR_select:
     case __NR_pselect6:
       return Allow();
 
     CASES_FOR_getdents:
     CASES_FOR_ftruncate:
     case __NR_writev:
     case __NR_pread64: