1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "sandboxed_api/sandbox2/util/syscall_trap.h"
16
17 #include <ucontext.h>
18
19 #include <array>
20 #include <cerrno>
21 #include <csignal>
22 #include <cstdint>
23
24 #include "absl/log/check.h"
25 #include "sandboxed_api/config.h"
26
27 namespace sandbox2 {
28 namespace {
29
30 #if defined(SAPI_X86_64)
31 constexpr int kRegResult = REG_RAX;
32 constexpr int kRegSyscall = REG_RAX;
33 // ANDROID: On musl these are distinct enum types. Coerce to int.
34 constexpr std::array<int, 6> kRegArgs = {REG_RDI, REG_RSI, REG_RDX,
35 REG_R10, REG_R8, REG_R9};
36 #elif defined(SAPI_PPC64_LE)
37 constexpr int kRegResult = 3;
38 constexpr int kRegSyscall = 0;
39 constexpr std::array kRegArgs = {3, 4, 5, 6, 7, 8};
40 #elif defined(SAPI_ARM64)
41 constexpr int kRegResult = 0;
42 constexpr int kRegSyscall = 8;
43 constexpr std::array kRegArgs = {0, 1, 2, 3, 4, 5};
44 #elif defined(SAPI_ARM)
45 constexpr int kRegResult = 0;
46 constexpr int kRegSyscall = 8;
47 constexpr std::array kRegArgs = {0, 1, 2, 3, 4, 5};
48 #endif
49
50 #ifndef SYS_SECCOMP
51 constexpr int SYS_SECCOMP = 1;
52 #endif
53
54 SyscallTrap* g_instance = nullptr;
55
56 } // namespace
57
SignalHandler(int nr,siginfo_t * info,void * context)58 void SyscallTrap::SignalHandler(int nr, siginfo_t* info, void* context) {
59 return g_instance->SignalHandlerImpl(nr, info, context);
60 }
61
InvokeOldAct(int nr,siginfo_t * info,void * context)62 void SyscallTrap::InvokeOldAct(int nr, siginfo_t* info, void* context) {
63 if (oldact_.sa_flags & SA_SIGINFO) {
64 if (oldact_.sa_sigaction) {
65 oldact_.sa_sigaction(nr, info, context);
66 }
67 } else if (oldact_.sa_handler == SIG_IGN) {
68 return;
69 } else if (oldact_.sa_handler == SIG_DFL) {
70 sigaction(SIGSYS, &oldact_, nullptr);
71 raise(SIGSYS);
72 } else if (oldact_.sa_handler) {
73 oldact_.sa_handler(nr);
74 }
75 }
76
SignalHandlerImpl(int nr,siginfo_t * info,void * context)77 void SyscallTrap::SignalHandlerImpl(int nr, siginfo_t* info, void* context) {
78 int old_errno = errno;
79 if (nr != SIGSYS) {
80 InvokeOldAct(nr, info, context);
81 errno = old_errno;
82 return;
83 }
84 if (info->si_code != SYS_SECCOMP) {
85 InvokeOldAct(nr, info, context);
86 errno = old_errno;
87 return;
88 }
89 auto* uctx = static_cast<ucontext_t*>(context);
90 if (!uctx) {
91 errno = old_errno;
92 return;
93 }
94
95 #if defined(SAPI_X86_64)
96 auto* registers = uctx->uc_mcontext.gregs;
97 #elif defined(SAPI_PPC64_LE)
98 auto* registers = uctx->uc_mcontext.gp_regs;
99 #elif defined(SAPI_ARM64)
100 auto* registers = uctx->uc_mcontext.regs;
101 #elif defined(SAPI_ARM)
102 auto* registers = &uctx->uc_mcontext.arm_r0;
103 #endif
104 int syscall_nr = static_cast<int>(registers[kRegSyscall]);
105 Args args = {static_cast<uintptr_t>(registers[kRegArgs[0]]),
106 static_cast<uintptr_t>(registers[kRegArgs[1]]),
107 static_cast<uintptr_t>(registers[kRegArgs[2]]),
108 static_cast<uintptr_t>(registers[kRegArgs[3]]),
109 static_cast<uintptr_t>(registers[kRegArgs[4]]),
110 static_cast<uintptr_t>(registers[kRegArgs[5]])};
111 uintptr_t rv;
112 if (!handler_(syscall_nr, args, &rv)) {
113 InvokeOldAct(nr, info, context);
114 errno = old_errno;
115 return;
116 }
117 registers[kRegResult] = rv;
118 }
119
Install(bool (* handler)(int nr,Args args,uintptr_t * result))120 bool SyscallTrap::Install(bool (*handler)(int nr, Args args,
121 uintptr_t* result)) {
122 if (g_instance) {
123 return false;
124 }
125 g_instance = new SyscallTrap(handler);
126 sigset_t mask;
127 sigemptyset(&mask);
128 sigaddset(&mask, SIGSYS);
129
130 struct sigaction act = {};
131 act.sa_sigaction = &SignalHandler;
132 act.sa_flags = SA_SIGINFO;
133
134 CHECK_EQ(sigaction(SIGSYS, &act, &g_instance->oldact_), 0);
135 CHECK_EQ(sigprocmask(SIG_UNBLOCK, &mask, nullptr), 0);
136 return true;
137 }
138
139 } // namespace sandbox2
140