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 "guest_loader_impl.h"
18 
19 #include <sys/auxv.h>
20 #include <cstdint>
21 
22 #include "berberis/base/bit_util.h"  // AlignDown
23 #include "berberis/calling_conventions/calling_conventions_riscv64.h"
24 #include "berberis/guest_state/guest_addr.h"
25 #include "berberis/kernel_api/exec_emulation.h"  // DemangleGuestEnvp
26 
27 namespace berberis {
28 
29 // TODO(b/279068747): Ensure these paths are correct.
30 // Paths required by guest_loader_impl.h.
31 const char* kAppProcessPath = "/system/bin/riscv64/app_process64";
32 const char* kPtInterpPath = "/system/bin/riscv64/linker64";
33 const char* kVdsoPath = "/system/lib64/riscv64/libnative_bridge_vdso.so";
34 const char* kProxyPrefix = "libberberis_proxy_";
35 
InitKernelArgs(GuestAddr guest_sp,size_t argc,const char * argv[],char * envp[],GuestAddr linker_base_addr,GuestAddr main_executable_entry_point,GuestAddr phdr,size_t phdr_count,GuestAddr ehdr_vdso,const uint8_t (* random_bytes)[16])36 GuestAddr InitKernelArgs(GuestAddr guest_sp,
37                          size_t argc,
38                          const char* argv[],
39                          char* envp[],
40                          GuestAddr linker_base_addr,
41                          GuestAddr main_executable_entry_point,
42                          GuestAddr phdr,
43                          size_t phdr_count,
44                          GuestAddr ehdr_vdso,
45                          const uint8_t (*random_bytes)[16]) {
46   // TODO(b/119329323): Provide meaningful values for disabled arguments.
47   const uint64_t auxv[] = {
48       // AT_HWCAP,        kRiscv64ValueHwcap,
49       // AT_HWCAP2,       kRiscv64ValueHwcap2,
50       AT_RANDOM,       ToGuestAddr(random_bytes),
51       AT_SECURE,       false,
52       AT_BASE,         linker_base_addr,
53       AT_PHDR,         phdr,
54       AT_PHNUM,        phdr_count,
55       AT_ENTRY,        main_executable_entry_point,
56       AT_PAGESZ,       static_cast<uint64_t>(sysconf(_SC_PAGESIZE)),
57       AT_CLKTCK,       static_cast<uint64_t>(sysconf(_SC_CLK_TCK)),
58       AT_SYSINFO_EHDR, ehdr_vdso,
59       AT_UID,          getuid(),
60       AT_EUID,         geteuid(),
61       AT_GID,          getgid(),
62       AT_EGID,         getegid(),
63       AT_NULL,
64   };
65 
66   size_t envp_count = 0;  // number of environment variables + nullptr
67   while (envp[envp_count++] != nullptr) {
68   }
69 
70   guest_sp -= sizeof(uint64_t) +               // argc
71               sizeof(uint64_t) * (argc + 1) +  // argv + nullptr
72               sizeof(uint64_t) * envp_count +  // envp + nullptr
73               sizeof(auxv);                    // auxv
74   guest_sp = AlignDown(guest_sp, riscv64::CallingConventions::kStackAlignmentBeforeCall);
75 
76   uint64_t* curr = ToHostAddr<uint64_t>(guest_sp);
77 
78   // argc
79   *curr++ = argc;
80 
81   // argv
82   for (size_t i = 0; i < argc; ++i) {
83     *curr++ = reinterpret_cast<uint64_t>(argv[i]);
84   }
85   *curr++ = kNullGuestAddr;
86 
87   // envp
88   curr = reinterpret_cast<uint64_t*>(DemangleGuestEnvp(reinterpret_cast<char**>(curr), envp));
89 
90   // auxv
91   memcpy(curr, auxv, sizeof(auxv));
92 
93   return guest_sp;
94 }
95 
96 }  // namespace berberis
97