• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 <fcntl.h>  // AT_FDCWD, AT_SYMLINK_NOFOLLOW
18 #include <linux/unistd.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 
22 #include <cerrno>
23 
24 #include "berberis/base/macros.h"
25 #include "berberis/base/scoped_errno.h"
26 #include "berberis/base/struct_check.h"
27 #include "berberis/kernel_api/main_executable_real_path_emulation.h"
28 #include "berberis/kernel_api/syscall_emulation_common.h"
29 #include "berberis/kernel_api/tracing.h"
30 
31 #include "epoll_emulation.h"
32 #include "guest_types.h"
33 #include "runtime_bridge.h"
34 
35 namespace berberis {
36 
37 namespace {
38 
ConvertHostStatToGuest(const struct stat & host_stat,Guest_stat * guest_stat)39 void ConvertHostStatToGuest(const struct stat& host_stat, Guest_stat* guest_stat) {
40   guest_stat->st_dev = host_stat.st_dev;
41   guest_stat->st_ino = host_stat.st_ino;
42   guest_stat->st_mode = host_stat.st_mode;
43   guest_stat->st_nlink = host_stat.st_nlink;
44   guest_stat->st_uid = host_stat.st_uid;
45   guest_stat->st_gid = host_stat.st_gid;
46   guest_stat->st_rdev = host_stat.st_rdev;
47   guest_stat->st_size = host_stat.st_size;
48   guest_stat->st_blksize = host_stat.st_blksize;
49   guest_stat->st_blocks = host_stat.st_blocks;
50   guest_stat->st_blocks = host_stat.st_blocks;
51   guest_stat->st_atim = host_stat.st_atim;
52   guest_stat->st_mtim = host_stat.st_mtim;
53   guest_stat->st_ctim = host_stat.st_ctim;
54 }
55 
FstatatForGuest(int dirfd,const char * path,struct stat * buf,int flags)56 int FstatatForGuest(int dirfd, const char* path, struct stat* buf, int flags) {
57   const char* real_path = nullptr;
58   if ((flags & AT_SYMLINK_NOFOLLOW) == 0) {
59     real_path = TryReadLinkToMainExecutableRealPath(path);
60   }
61   return syscall(__NR_newfstatat, dirfd, real_path ? real_path : path, buf, flags);
62 }
63 
RunGuestSyscall___NR_execveat(long arg_1,long arg_2,long arg_3,long arg_4,long arg_5)64 long RunGuestSyscall___NR_execveat(long arg_1, long arg_2, long arg_3, long arg_4, long arg_5) {
65   UNUSED(arg_1, arg_2, arg_3, arg_4, arg_5);
66   KAPI_TRACE("unimplemented syscall __NR_execveat");
67   errno = ENOSYS;
68   return -1;
69 }
70 
RunGuestSyscall___NR_fadvise64(long arg_1,long arg_2,long arg_3,long arg_4)71 long RunGuestSyscall___NR_fadvise64(long arg_1, long arg_2, long arg_3, long arg_4) {
72   // on 64-bit architectures, sys_fadvise64 and sys_fadvise64_64 are equal.
73   return syscall(__NR_fadvise64, arg_1, arg_2, arg_3, arg_4);
74 }
75 
RunGuestSyscall___NR_fstat(long arg_1,long arg_2)76 long RunGuestSyscall___NR_fstat(long arg_1, long arg_2) {
77   struct stat host_stat;
78   long result = syscall(__NR_fstat, arg_1, &host_stat);
79   if (result != -1) {
80     ConvertHostStatToGuest(host_stat, bit_cast<Guest_stat*>(arg_2));
81   }
82   return result;
83 }
84 
RunGuestSyscall___NR_ioctl(long arg_1,long arg_2,long arg_3)85 long RunGuestSyscall___NR_ioctl(long arg_1, long arg_2, long arg_3) {
86   // TODO(b/128614662): translate!
87   KAPI_TRACE("unimplemented ioctl 0x%lx, running host syscall as is", arg_2);
88   return syscall(__NR_ioctl, arg_1, arg_2, arg_3);
89 }
90 
RunGuestSyscall___NR_newfstatat(long arg_1,long arg_2,long arg_3,long arg_4)91 long RunGuestSyscall___NR_newfstatat(long arg_1, long arg_2, long arg_3, long arg_4) {
92   struct stat host_stat;
93   int result = FstatatForGuest(static_cast<int>(arg_1),       // dirfd
94                                bit_cast<const char*>(arg_2),  // path
95                                &host_stat,
96                                static_cast<int>(arg_4));  // flags
97   if (result != -1) {
98     ConvertHostStatToGuest(host_stat, bit_cast<Guest_stat*>(arg_3));
99   }
100   return result;
101 }
102 
103 // RunGuestSyscallImpl.
104 #include "gen_syscall_emulation_riscv64_to_x86_64-inl.h"
105 
106 }  // namespace
107 
RunGuestSyscall(long syscall_nr,long arg0,long arg1,long arg2,long arg3,long arg4,long arg5)108 long RunGuestSyscall(long syscall_nr,
109                      long arg0,
110                      long arg1,
111                      long arg2,
112                      long arg3,
113                      long arg4,
114                      long arg5) {
115   ScopedErrno scoped_errno;
116 
117   // RISCV Linux takes arguments in a0-a5 and syscall number in a7.
118   long result = RunGuestSyscallImpl(syscall_nr, arg0, arg1, arg2, arg3, arg4, arg5);
119   // The result is returned in a0.
120   if (result == -1) {
121     return -errno;
122   } else {
123     return result;
124   }
125 }
126 
127 }  // namespace berberis
128