/* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "berberis/kernel_api/runtime_bridge.h" #include #include #include "berberis/base/bit_util.h" #include "berberis/base/config.h" #include "berberis/base/tracing.h" #include "berberis/guest_os_primitives/guest_signal.h" #include "berberis/guest_os_primitives/guest_thread.h" #include "berberis/guest_os_primitives/guest_thread_manager.h" #include "berberis/kernel_api/sys_mman_emulation.h" #include "sigevent_emulation.h" namespace berberis { long RunGuestSyscall___NR_rt_sigaction(long sig_num_arg, long act_arg, long old_act_arg, long sigset_size_arg) { TRACE("'rt_sigaction' called for signal %ld", sig_num_arg); int sig_num = static_cast(sig_num_arg); const Guest_sigaction* act = bit_cast(act_arg); Guest_sigaction* old_act = bit_cast(old_act_arg); size_t sigset_size = bit_cast(sigset_size_arg); if (sigset_size != sizeof(Guest_sigset_t)) { errno = EINVAL; return -1; } int error; if (SetGuestSignalHandler(sig_num, act, old_act, &error)) { return 0; } errno = error; return -1; } long RunGuestSyscall___NR_sigaltstack(long stack, long old_stack) { int error; if (GetCurrentGuestThread()->SigAltStack( bit_cast(stack), bit_cast(old_stack), &error)) { return 0; } errno = error; return -1; } long RunGuestSyscall___NR_timer_create(long arg_1, long arg_2, long arg_3) { struct sigevent host_sigevent; return syscall(__NR_timer_create, arg_1, ConvertGuestSigeventToHost(bit_cast(arg_2), &host_sigevent), arg_3); } long RunGuestSyscall___NR_exit(long code) { ExitCurrentThread(code); return 0; } long RunGuestSyscall___NR_clone(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) { // NOTE: clone syscall argument ordering is architecture dependent. This implementation assumes // CLONE_BACKWARDS is enabled (tls before child_tid), which is true for both x86 and RISC-V. return CloneGuestThread(GetCurrentGuestThread(), arg_1, arg_2, arg_3, arg_4, arg_5); } long RunGuestSyscall___NR_mmap(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5, long arg_6) { return bit_cast(MmapForGuest(bit_cast(arg_1), // addr bit_cast(arg_2), // length static_cast(arg_3), // prot static_cast(arg_4), // flags static_cast(arg_5), // fd static_cast(arg_6))); // offset } long RunGuestSyscall___NR_mmap2(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5, long arg_6) { return bit_cast( MmapForGuest(bit_cast(arg_1), // addr bit_cast(arg_2), // length static_cast(arg_3), // prot static_cast(arg_4), // flags static_cast(arg_5), // fd static_cast(arg_6) * config::kGuestPageSize)); // pgoffset to offset } long RunGuestSyscall___NR_munmap(long arg_1, long arg_2) { return static_cast(MunmapForGuest(bit_cast(arg_1), // addr bit_cast(arg_2))); // length } long RunGuestSyscall___NR_mprotect(long arg_1, long arg_2, long arg_3) { return static_cast(MprotectForGuest(bit_cast(arg_1), // addr bit_cast(arg_2), // length static_cast(arg_3))); // prot } long RunGuestSyscall___NR_mremap(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) { return bit_cast(MremapForGuest(bit_cast(arg_1), // old_addr bit_cast(arg_2), // old_size bit_cast(arg_3), // new_size static_cast(arg_4), // flags bit_cast(arg_5))); // new_addr } } // namespace berberis