tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SandboxFilterUtil.cpp (5343B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "SandboxFilterUtil.h"
      8 
      9 #ifndef ANDROID
     10 #  include <linux/ipc.h>
     11 #endif
     12 #include <linux/net.h>
     13 #include <sys/socket.h>
     14 #include <sys/syscall.h>
     15 #include <unistd.h>
     16 
     17 #include "mozilla/UniquePtr.h"
     18 #include "sandbox/linux/bpf_dsl/bpf_dsl.h"
     19 
     20 // Older kernel headers (mostly Android, but also some older desktop
     21 // distributions) are missing some or all of these:
     22 #ifndef SYS_ACCEPT4
     23 #  define SYS_ACCEPT4 18
     24 #endif
     25 #ifndef SYS_RECVMMSG
     26 #  define SYS_RECVMMSG 19
     27 #endif
     28 #ifndef SYS_SENDMMSG
     29 #  define SYS_SENDMMSG 20
     30 #endif
     31 
     32 using namespace sandbox::bpf_dsl;
     33 #define CASES SANDBOX_BPF_DSL_CASES
     34 
     35 namespace mozilla {
     36 
     37 sandbox::bpf_dsl::ResultExpr SandboxPolicyBase::EvaluateSyscall(
     38    int aSysno) const {
     39  switch (aSysno) {
     40 #ifdef __NR_socketcall
     41    case __NR_socketcall: {
     42      Arg<int> call(0);
     43      UniquePtr<Caser<int>> acc(new Caser<int>(Switch(call)));
     44      for (int i = SYS_SOCKET; i <= SYS_SENDMMSG; ++i) {
     45        auto thisCase = EvaluateSocketCall(i, false);
     46        // Optimize out cases that are equal to the default.
     47        if (thisCase) {
     48          acc.reset(new Caser<int>(acc->Case(i, *thisCase)));
     49        }
     50      }
     51      return acc->Default(InvalidSyscall());
     52    }
     53 #  ifndef ANDROID
     54    case __NR_ipc: {
     55      Arg<int> callAndVersion(0);
     56      auto call = callAndVersion & 0xFFFF;
     57      UniquePtr<Caser<int>> acc(new Caser<int>(Switch(call)));
     58      for (int i = SEMOP; i <= DIPC; ++i) {
     59        auto thisCase = EvaluateIpcCall(i, 1);
     60        // Optimize out cases that are equal to the default.
     61        if (thisCase) {
     62          acc.reset(new Caser<int>(acc->Case(i, *thisCase)));
     63        }
     64      }
     65      return acc->Default(InvalidSyscall());
     66    }
     67 #  endif  // ANDROID
     68 #endif    // __NR_socketcall
     69          // clang-format off
     70 #define DISPATCH_SOCKETCALL(sysnum, socketnum) \
     71  case sysnum:                                 \
     72    return EvaluateSocketCall(socketnum, true).valueOr(InvalidSyscall())
     73      DISPATCH_SOCKETCALL(__NR_socket,      SYS_SOCKET);
     74      DISPATCH_SOCKETCALL(__NR_bind,        SYS_BIND);
     75      DISPATCH_SOCKETCALL(__NR_connect,     SYS_CONNECT);
     76      DISPATCH_SOCKETCALL(__NR_listen,      SYS_LISTEN);
     77 #ifdef __NR_accept
     78      DISPATCH_SOCKETCALL(__NR_accept,      SYS_ACCEPT);
     79 #endif
     80      DISPATCH_SOCKETCALL(__NR_getsockname, SYS_GETSOCKNAME);
     81      DISPATCH_SOCKETCALL(__NR_getpeername, SYS_GETPEERNAME);
     82      DISPATCH_SOCKETCALL(__NR_socketpair,  SYS_SOCKETPAIR);
     83 #ifdef __NR_send
     84      DISPATCH_SOCKETCALL(__NR_send,        SYS_SEND);
     85      DISPATCH_SOCKETCALL(__NR_recv,        SYS_RECV);
     86 #endif  // __NR_send
     87      DISPATCH_SOCKETCALL(__NR_sendto,      SYS_SENDTO);
     88      DISPATCH_SOCKETCALL(__NR_recvfrom,    SYS_RECVFROM);
     89      DISPATCH_SOCKETCALL(__NR_shutdown,    SYS_SHUTDOWN);
     90      DISPATCH_SOCKETCALL(__NR_setsockopt,  SYS_SETSOCKOPT);
     91      DISPATCH_SOCKETCALL(__NR_getsockopt,  SYS_GETSOCKOPT);
     92      DISPATCH_SOCKETCALL(__NR_sendmsg,     SYS_SENDMSG);
     93      DISPATCH_SOCKETCALL(__NR_recvmsg,     SYS_RECVMSG);
     94      DISPATCH_SOCKETCALL(__NR_accept4,     SYS_ACCEPT4);
     95      DISPATCH_SOCKETCALL(__NR_recvmmsg,    SYS_RECVMMSG);
     96      DISPATCH_SOCKETCALL(__NR_sendmmsg,    SYS_SENDMMSG);
     97 #  ifdef __NR_recvmmsg_time64
     98      // recvmmsg_time64 is available only as a syscall, not a legacy
     99      // socketcall.  The types are the same as the non-Y2K38-ready
    100      // recvmmsg except for the struct timespec, which the filter
    101      // shouldn't need to inspect, so they're treated the same here.
    102      DISPATCH_SOCKETCALL(__NR_recvmmsg_time64, SYS_RECVMMSG);
    103 #  endif
    104 #undef DISPATCH_SOCKETCALL
    105 #ifndef __NR_socketcall
    106 #ifndef ANDROID
    107 #define DISPATCH_SYSVCALL(sysnum, ipcnum) \
    108  case sysnum:                            \
    109    return EvaluateIpcCall(ipcnum, 0).valueOr(InvalidSyscall())
    110      DISPATCH_SYSVCALL(__NR_semop,       SEMOP);
    111      DISPATCH_SYSVCALL(__NR_semget,      SEMGET);
    112      DISPATCH_SYSVCALL(__NR_semctl,      SEMCTL);
    113      DISPATCH_SYSVCALL(__NR_semtimedop,  SEMTIMEDOP);
    114      DISPATCH_SYSVCALL(__NR_msgsnd,      MSGSND);
    115      DISPATCH_SYSVCALL(__NR_msgrcv,      MSGRCV);
    116      DISPATCH_SYSVCALL(__NR_msgget,      MSGGET);
    117      DISPATCH_SYSVCALL(__NR_msgctl,      MSGCTL);
    118      DISPATCH_SYSVCALL(__NR_shmat,       SHMAT);
    119      DISPATCH_SYSVCALL(__NR_shmdt,       SHMDT);
    120      DISPATCH_SYSVCALL(__NR_shmget,      SHMGET);
    121      DISPATCH_SYSVCALL(__NR_shmctl,      SHMCTL);
    122 #undef DISPATCH_SYSVCALL
    123 #endif  // ANDROID
    124 #endif  // __NR_socketcall
    125          // clang-format on
    126    default:
    127      return InvalidSyscall();
    128  }
    129 }
    130 
    131 /* static */ bool SandboxPolicyBase::HasSeparateSocketCalls() {
    132 #ifdef __NR_socketcall
    133  // If we have both syscalls, dynamically detect (and cache).
    134  static const bool kCache = [] {
    135    int fd = syscall(__NR_socket, AF_LOCAL, SOCK_STREAM, 0);
    136    if (fd < 0) {
    137      MOZ_DIAGNOSTIC_ASSERT(errno == ENOSYS);
    138      return false;
    139    }
    140    close(fd);
    141    return true;
    142  }();
    143  return kCache;
    144 #else  // no socketcall; must be separate syscalls
    145  return true;
    146 #endif
    147 }
    148 
    149 }  // namespace mozilla