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