1 /*
2 * Copyright (C) 2023 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 #include "berberis/kernel_api/runtime_bridge.h"
18
19 #include <cerrno>
20 #include <cstdlib>
21
22 #include "berberis/base/bit_util.h"
23 #include "berberis/base/config.h"
24 #include "berberis/base/tracing.h"
25 #include "berberis/guest_os_primitives/guest_signal.h"
26 #include "berberis/guest_os_primitives/guest_thread.h"
27 #include "berberis/guest_os_primitives/guest_thread_manager.h"
28 #include "berberis/kernel_api/sys_mman_emulation.h"
29
30 #include "sigevent_emulation.h"
31
32 namespace berberis {
33
RunGuestSyscall___NR_rt_sigaction(long sig_num_arg,long act_arg,long old_act_arg,long sigset_size_arg)34 long RunGuestSyscall___NR_rt_sigaction(long sig_num_arg,
35 long act_arg,
36 long old_act_arg,
37 long sigset_size_arg) {
38 TRACE("'rt_sigaction' called for signal %ld", sig_num_arg);
39 int sig_num = static_cast<int>(sig_num_arg);
40 const Guest_sigaction* act = bit_cast<const Guest_sigaction*>(act_arg);
41 Guest_sigaction* old_act = bit_cast<Guest_sigaction*>(old_act_arg);
42 size_t sigset_size = bit_cast<size_t>(sigset_size_arg);
43
44 if (sigset_size != sizeof(Guest_sigset_t)) {
45 errno = EINVAL;
46 return -1;
47 }
48
49 int error;
50 if (SetGuestSignalHandler(sig_num, act, old_act, &error)) {
51 return 0;
52 }
53 errno = error;
54 return -1;
55 }
56
RunGuestSyscall___NR_sigaltstack(long stack,long old_stack)57 long RunGuestSyscall___NR_sigaltstack(long stack, long old_stack) {
58 int error;
59 if (GetCurrentGuestThread()->SigAltStack(
60 bit_cast<const stack_t*>(stack), bit_cast<stack_t*>(old_stack), &error)) {
61 return 0;
62 }
63 errno = error;
64 return -1;
65 }
66
RunGuestSyscall___NR_timer_create(long arg_1,long arg_2,long arg_3)67 long RunGuestSyscall___NR_timer_create(long arg_1, long arg_2, long arg_3) {
68 struct sigevent host_sigevent;
69 return syscall(__NR_timer_create,
70 arg_1,
71 ConvertGuestSigeventToHost(bit_cast<struct sigevent*>(arg_2), &host_sigevent),
72 arg_3);
73 }
74
RunGuestSyscall___NR_exit(long code)75 long RunGuestSyscall___NR_exit(long code) {
76 ExitCurrentThread(code);
77 return 0;
78 }
79
RunGuestSyscall___NR_clone(long arg_1,long arg_2,long arg_3,long arg_4,long arg_5)80 long RunGuestSyscall___NR_clone(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) {
81 // NOTE: clone syscall argument ordering is architecture dependent. This implementation assumes
82 // CLONE_BACKWARDS is enabled (tls before child_tid), which is true for both x86 and RISC-V.
83 return CloneGuestThread(GetCurrentGuestThread(), arg_1, arg_2, arg_3, arg_4, arg_5);
84 }
85
RunGuestSyscall___NR_mmap(long arg_1,long arg_2,long arg_3,long arg_4,long arg_5,long arg_6)86 long RunGuestSyscall___NR_mmap(long arg_1,
87 long arg_2,
88 long arg_3,
89 long arg_4,
90 long arg_5,
91 long arg_6) {
92 return bit_cast<long>(MmapForGuest(bit_cast<void*>(arg_1), // addr
93 bit_cast<size_t>(arg_2), // length
94 static_cast<int>(arg_3), // prot
95 static_cast<int>(arg_4), // flags
96 static_cast<int>(arg_5), // fd
97 static_cast<off64_t>(arg_6))); // offset
98 }
99
RunGuestSyscall___NR_mmap2(long arg_1,long arg_2,long arg_3,long arg_4,long arg_5,long arg_6)100 long RunGuestSyscall___NR_mmap2(long arg_1,
101 long arg_2,
102 long arg_3,
103 long arg_4,
104 long arg_5,
105 long arg_6) {
106 return bit_cast<long>(
107 MmapForGuest(bit_cast<void*>(arg_1), // addr
108 bit_cast<size_t>(arg_2), // length
109 static_cast<int>(arg_3), // prot
110 static_cast<int>(arg_4), // flags
111 static_cast<int>(arg_5), // fd
112 static_cast<off64_t>(arg_6) * config::kGuestPageSize)); // pgoffset to offset
113 }
114
RunGuestSyscall___NR_munmap(long arg_1,long arg_2)115 long RunGuestSyscall___NR_munmap(long arg_1, long arg_2) {
116 return static_cast<long>(MunmapForGuest(bit_cast<void*>(arg_1), // addr
117 bit_cast<size_t>(arg_2))); // length
118 }
119
RunGuestSyscall___NR_mprotect(long arg_1,long arg_2,long arg_3)120 long RunGuestSyscall___NR_mprotect(long arg_1, long arg_2, long arg_3) {
121 return static_cast<long>(MprotectForGuest(bit_cast<void*>(arg_1), // addr
122 bit_cast<size_t>(arg_2), // length
123 static_cast<int>(arg_3))); // prot
124 }
125
RunGuestSyscall___NR_mremap(long arg_1,long arg_2,long arg_3,long arg_4,long arg_5)126 long RunGuestSyscall___NR_mremap(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) {
127 return bit_cast<long>(MremapForGuest(bit_cast<void*>(arg_1), // old_addr
128 bit_cast<size_t>(arg_2), // old_size
129 bit_cast<size_t>(arg_3), // new_size
130 static_cast<int>(arg_4), // flags
131 bit_cast<void*>(arg_5))); // new_addr
132 }
133
134 } // namespace berberis
135