1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef BERBERIS_KERNEL_API_SYSCALL_EMULATION_COMMON_H_
18 #define BERBERIS_KERNEL_API_SYSCALL_EMULATION_COMMON_H_
19
20 #include <sys/stat.h>
21 #include <sys/syscall.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24
25 #include <cerrno>
26
27 #include "berberis/base/bit_util.h"
28 #include "berberis/base/macros.h"
29 #include "berberis/guest_state/guest_addr.h"
30 #include "berberis/kernel_api/exec_emulation.h"
31 #include "berberis/kernel_api/fcntl_emulation.h"
32 #include "berberis/kernel_api/open_emulation.h"
33 #include "berberis/kernel_api/sys_prctl_emulation.h"
34 #include "berberis/kernel_api/sys_ptrace_emulation.h"
35 #include "berberis/kernel_api/tracing.h"
36 #include "berberis/kernel_api/unistd_emulation.h"
37
38 namespace berberis {
39
40 void ConvertHostStatToGuestArch(const struct stat& host_stat, GuestAddr guest_stat);
41
RunGuestSyscall___NR_clone3(long arg_1,long arg_2)42 inline long RunGuestSyscall___NR_clone3(long arg_1, long arg_2) {
43 UNUSED(arg_1, arg_2);
44 KAPI_TRACE("unimplemented syscall __NR_clone3");
45 errno = ENOSYS;
46 return -1;
47 }
48
RunGuestSyscall___NR_close(long arg_1)49 inline long RunGuestSyscall___NR_close(long arg_1) {
50 CloseEmulatedProcSelfMapsFileDescriptor(arg_1);
51 return syscall(__NR_close, arg_1);
52 }
53
RunGuestSyscall___NR_execve(long arg_1,long arg_2,long arg_3)54 inline long RunGuestSyscall___NR_execve(long arg_1, long arg_2, long arg_3) {
55 return static_cast<long>(ExecveForGuest(bit_cast<const char*>(arg_1), // filename
56 bit_cast<char* const*>(arg_2), // argv
57 bit_cast<char* const*>(arg_3))); // envp
58 }
59
RunGuestSyscall___NR_faccessat(long arg_1,long arg_2,long arg_3)60 inline long RunGuestSyscall___NR_faccessat(long arg_1, long arg_2, long arg_3) {
61 // TODO(b/128614662): translate!
62 KAPI_TRACE("unimplemented syscall __NR_faccessat, running host syscall as is");
63 return syscall(__NR_faccessat, arg_1, arg_2, arg_3);
64 }
65
RunGuestSyscall___NR_fstat(long arg_1,long arg_2)66 inline long RunGuestSyscall___NR_fstat(long arg_1, long arg_2) {
67 // We are including this structure from library headers (sys/stat.h) and assume
68 // that it matches kernel's layout.
69 // TODO(b/232598137): Add a check for this. It seems like this is an issue for 32-bit
70 // guest syscall, since compiled with bionic this declares `struct stat64` while
71 // the syscall will expect `struct stat`
72 struct stat host_stat;
73 long result;
74 if (IsFileDescriptorEmulatedProcSelfMaps(arg_1)) {
75 KAPI_TRACE("Emulating fstat for /proc/self/maps");
76 result = syscall(__NR_stat, "/proc/self/maps", &host_stat);
77 } else {
78 result = syscall(__NR_fstat, arg_1, &host_stat);
79 }
80 if (result != -1) {
81 ConvertHostStatToGuestArch(host_stat, bit_cast<GuestAddr>(arg_2));
82 }
83 return result;
84 }
85
RunGuestSyscall___NR_fstatfs(long arg_1,long arg_2)86 inline long RunGuestSyscall___NR_fstatfs(long arg_1, long arg_2) {
87 if (IsFileDescriptorEmulatedProcSelfMaps(arg_1)) {
88 KAPI_TRACE("Emulating fstatfs for /proc/self/maps");
89 // arg_2 (struct statfs*) has kernel expected layout, which is different from
90 // what libc may expect. E.g. this happens for 32-bit bionic where the library call
91 // expects struct statfs64. Thus ensure we invoke syscall, not library call.
92 return syscall(__NR_statfs, "/proc/self/maps", arg_2);
93 }
94 return syscall(__NR_fstatfs, arg_1, arg_2);
95 }
96
RunGuestSyscall___NR_fcntl(long arg_1,long arg_2,long arg_3)97 inline long RunGuestSyscall___NR_fcntl(long arg_1, long arg_2, long arg_3) {
98 return GuestFcntl(arg_1, arg_2, arg_3);
99 }
100
RunGuestSyscall___NR_openat(long arg_1,long arg_2,long arg_3,long arg_4)101 inline long RunGuestSyscall___NR_openat(long arg_1, long arg_2, long arg_3, long arg_4) {
102 return static_cast<long>(OpenatForGuest(static_cast<int>(arg_1), // dirfd
103 bit_cast<const char*>(arg_2), // path
104 static_cast<int>(arg_3), // flags
105 static_cast<mode_t>(arg_4))); // mode
106 }
107
RunGuestSyscall___NR_prctl(long arg_1,long arg_2,long arg_3,long arg_4,long arg_5)108 inline long RunGuestSyscall___NR_prctl(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) {
109 return PrctlForGuest(arg_1, arg_2, arg_3, arg_4, arg_5);
110 }
111
RunGuestSyscall___NR_ptrace(long arg_1,long arg_2,long arg_3,long arg_4)112 inline long RunGuestSyscall___NR_ptrace(long arg_1, long arg_2, long arg_3, long arg_4) {
113 return static_cast<long>(PtraceForGuest(static_cast<int>(arg_1), // request
114 static_cast<pid_t>(arg_2), // pid
115 bit_cast<void*>(arg_3), // addr
116 bit_cast<void*>(arg_4))); // data
117 }
118
RunGuestSyscall___NR_readlinkat(long arg_1,long arg_2,long arg_3,long arg_4)119 inline long RunGuestSyscall___NR_readlinkat(long arg_1, long arg_2, long arg_3, long arg_4) {
120 return static_cast<long>(ReadLinkAtForGuest(static_cast<int>(arg_1), // dirfd
121 bit_cast<const char*>(arg_2), // path
122 bit_cast<char*>(arg_3), // buf
123 bit_cast<size_t>(arg_4))); // buf_size
124 }
125
RunGuestSyscall___NR_rt_sigreturn(long)126 inline long RunGuestSyscall___NR_rt_sigreturn(long) {
127 KAPI_TRACE("unsupported syscall __NR_rt_sigaction");
128 errno = ENOSYS;
129 return -1;
130 }
131
RunGuestSyscall___NR_statx(long arg_1,long arg_2,long arg_3,long arg_4,long arg_5)132 inline long RunGuestSyscall___NR_statx(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) {
133 #if defined(__NR_statx)
134 // TODO(b/128614662): add struct statx layout checkers.
135 return syscall(__NR_statx, arg_1, arg_2, arg_3, arg_4, arg_5);
136 #else
137 UNUSED(arg_1, arg_2, arg_3, arg_4, arg_5);
138 errno = ENOSYS;
139 return -1;
140 #endif
141 }
142
RunUnknownGuestSyscall(long guest_nr,long arg_1,long arg_2,long arg_3,long arg_4,long arg_5,long arg_6)143 long RunUnknownGuestSyscall(long guest_nr,
144 long arg_1,
145 long arg_2,
146 long arg_3,
147 long arg_4,
148 long arg_5,
149 long arg_6) {
150 UNUSED(arg_1, arg_2, arg_3, arg_4, arg_5, arg_6);
151 KAPI_TRACE("unknown syscall %ld", guest_nr);
152 errno = ENOSYS;
153 return -1;
154 }
155
156 } // namespace berberis
157
158 #endif // BERBERIS_KERNEL_API_SYSCALL_EMULATION_COMMON_H_
159