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