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
EvaluateSyscall(int aSysno) const37 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);
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 #ifdef __NR_socket
74 DISPATCH_SOCKETCALL(__NR_socket, SYS_SOCKET);
75 DISPATCH_SOCKETCALL(__NR_bind, SYS_BIND);
76 DISPATCH_SOCKETCALL(__NR_connect, SYS_CONNECT);
77 DISPATCH_SOCKETCALL(__NR_listen, SYS_LISTEN);
78 #ifdef __NR_accept
79 DISPATCH_SOCKETCALL(__NR_accept, SYS_ACCEPT);
80 #endif
81 DISPATCH_SOCKETCALL(__NR_getsockname, SYS_GETSOCKNAME);
82 DISPATCH_SOCKETCALL(__NR_getpeername, SYS_GETPEERNAME);
83 DISPATCH_SOCKETCALL(__NR_socketpair, SYS_SOCKETPAIR);
84 #ifdef __NR_send
85 DISPATCH_SOCKETCALL(__NR_send, SYS_SEND);
86 DISPATCH_SOCKETCALL(__NR_recv, SYS_RECV);
87 #endif // __NR_send
88 DISPATCH_SOCKETCALL(__NR_sendto, SYS_SENDTO);
89 DISPATCH_SOCKETCALL(__NR_recvfrom, SYS_RECVFROM);
90 DISPATCH_SOCKETCALL(__NR_shutdown, SYS_SHUTDOWN);
91 DISPATCH_SOCKETCALL(__NR_setsockopt, SYS_SETSOCKOPT);
92 DISPATCH_SOCKETCALL(__NR_getsockopt, SYS_GETSOCKOPT);
93 DISPATCH_SOCKETCALL(__NR_sendmsg, SYS_SENDMSG);
94 DISPATCH_SOCKETCALL(__NR_recvmsg, SYS_RECVMSG);
95 DISPATCH_SOCKETCALL(__NR_accept4, SYS_ACCEPT4);
96 DISPATCH_SOCKETCALL(__NR_recvmmsg, SYS_RECVMMSG);
97 DISPATCH_SOCKETCALL(__NR_sendmmsg, SYS_SENDMMSG);
98 #endif // __NR_socket
99 #undef DISPATCH_SOCKETCALL
100 #ifndef __NR_socketcall
101 #ifndef ANDROID
102 #define DISPATCH_SYSVCALL(sysnum, ipcnum) \
103 case sysnum: \
104 return EvaluateIpcCall(ipcnum).valueOr(InvalidSyscall())
105 DISPATCH_SYSVCALL(__NR_semop, SEMOP);
106 DISPATCH_SYSVCALL(__NR_semget, SEMGET);
107 DISPATCH_SYSVCALL(__NR_semctl, SEMCTL);
108 DISPATCH_SYSVCALL(__NR_semtimedop, SEMTIMEDOP);
109 DISPATCH_SYSVCALL(__NR_msgsnd, MSGSND);
110 DISPATCH_SYSVCALL(__NR_msgrcv, MSGRCV);
111 DISPATCH_SYSVCALL(__NR_msgget, MSGGET);
112 DISPATCH_SYSVCALL(__NR_msgctl, MSGCTL);
113 DISPATCH_SYSVCALL(__NR_shmat, SHMAT);
114 DISPATCH_SYSVCALL(__NR_shmdt, SHMDT);
115 DISPATCH_SYSVCALL(__NR_shmget, SHMGET);
116 DISPATCH_SYSVCALL(__NR_shmctl, SHMCTL);
117 #undef DISPATCH_SYSVCALL
118 #endif // ANDROID
119 #endif // __NR_socketcall
120 // clang-format on
121 default:
122 return InvalidSyscall();
123 }
124 }
125
HasSeparateSocketCalls()126 /* static */ bool SandboxPolicyBase::HasSeparateSocketCalls() {
127 #ifdef __NR_socket
128 // If there's no socketcall, then obviously there are separate syscalls.
129 # ifdef __NR_socketcall
130 // This could be memoized, but currently it's called at most once
131 // per process.
132 int fd = syscall(__NR_socket, AF_LOCAL, SOCK_STREAM, 0);
133 if (fd < 0) {
134 MOZ_DIAGNOSTIC_ASSERT(errno == ENOSYS);
135 return false;
136 }
137 close(fd);
138 # endif // __NR_socketcall
139 return true;
140 #else // ifndef __NR_socket
141 return false;
142 #endif // __NR_socket
143 }
144
145 } // namespace mozilla
146