xref: /aosp_15_r20/external/sandboxed-api/sandboxed_api/sandbox2/util/syscall_trap.cc (revision ec63e07ab9515d95e79c211197c445ef84cefa6a)
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