-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathlib.rs
More file actions
237 lines (219 loc) · 8.75 KB
/
lib.rs
File metadata and controls
237 lines (219 loc) · 8.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
#![allow(dead_code)]
use anyhow::Result;
use wasmtime_lind_dylink::DynamicLoader;
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use sysdefs::constants::lind_platform_const::{UNUSED_ARG, UNUSED_ID};
use threei::threei::{
copy_data_between_cages, copy_handler_table_to_cage, make_syscall, register_handler,
};
use threei::threei_const;
use typemap::path_conversion::get_cstr;
use wasmtime::Caller;
use wasmtime_lind_multi_process::{get_memory_base, LindHost};
// These syscalls (`clone`, `exec`, `exit`, `fork`) require special handling
// inside Lind Wasmtime before delegating to RawPOSIX. For example, they may
// involve operations like setting up stack memory that must be performed
// at the Wasmtime layer. Therefore, in the unified syscall entry point of
// Wasmtime, these calls are routed to their dedicated logic, while other
// syscalls are passed directly to 3i’s `make_syscall`.
//
// `UNUSED_ID` / `UNUSED_ARG` / `UNUSED_NAME` is a placeholder argument
// for functions that require a fixed number of parameters but do not utilize
// all of them.
use wasmtime_lind_utils::lind_syscall_numbers::{CLONE_SYSCALL, EXEC_SYSCALL, EXIT_SYSCALL};
// function to expose the handler to wasm module
// linker: wasmtime's linker to link the imported function to the actual function definition
pub fn add_to_linker<
T: LindHost<T, U> + Clone + Send + 'static + std::marker::Sync,
U: Clone + Send + 'static + std::marker::Sync,
>(
linker: &mut wasmtime::Linker<T>,
dynamic_loader: DynamicLoader<T>,
) -> anyhow::Result<()>
{
// attach make_syscall to wasmtime
linker.func_wrap(
"lind",
"make-syscall",
move |mut caller: Caller<'_, T>,
call_number: u32,
call_name: u64,
self_cageid: u64,
target_cageid: u64,
arg1: u64,
arg1cageid: u64,
arg2: u64,
arg2cageid: u64,
arg3: u64,
arg3cageid: u64,
arg4: u64,
arg4cageid: u64,
arg5: u64,
arg5cageid: u64,
arg6: u64,
arg6cageid: u64|
-> i32 {
// TODO:
// 1. add a signal check here as Linux also has a signal check when transition from kernel to userspace
// However, Asyncify management in this function should be carefully rethinking if adding signal check here
// With Asyncify enabled, an unwind/rewind resumes Wasmtime execution by re-entering
// the original call site. This means the same hostcall/trampoline path can be
// executed multiple times while representing a *single* logical operation.
//
// `clone` is particularly sensitive here: during a logical `clone`, the lind
// trampoline can be re-entered multiple times (e.g., 3 times) after unwind/rewind.
// If we forward the syscall to RawPOSIX on every re-entry, we will perform the
// operation multiple times.
//
// In lind-boot we forward syscalls directly to RawPOSIX, so we replicate the state
// check here to early-return when we are on a rewind replay path.
if call_number as i32 == CLONE_SYSCALL {
if let Some(rewind_res) = wasmtime_lind_multi_process::catch_rewind(&mut caller) {
return rewind_res;
}
}
// Some thread-related operations must be executed against a specific thread's
// VMContext (e.g., pthread_create/exit). Because syscalls may be interposed/routed
// through 3i functionality and the effective thread instance cannot be reliably derived
// from self/target cage IDs or per-argument cage IDs, we explicitly attach the *current*
// source thread id (tid) for selected syscalls. (Note: `self_cageid == target_cageid` means
// the syscall executes from cage)
//
// Concretely, for CLONE/EXEC we override arg2 with the current tid so that, when the call back
// to wasmtime, it can resolve the correct thread instance deterministically, independent of
// interposition or cross-cage routing.
let final_arg2 = if self_cageid == target_cageid
&& matches!(call_number as i32, CLONE_SYSCALL | EXIT_SYSCALL)
{
wasmtime_lind_multi_process::current_tid(&mut caller) as u64
} else {
arg2
};
make_syscall(
self_cageid,
call_number as u64,
call_name,
target_cageid,
arg1,
arg1cageid,
final_arg2,
arg2cageid,
arg3,
arg3cageid,
arg4,
arg4cageid,
arg5,
arg5cageid,
arg6,
arg6cageid,
)
},
)?;
// attach copy_handler_table_to_cage to wasmtime
linker.func_wrap(
"lind",
"copy_handler_table_to_cage",
move |thiscage: u64, targetcage: u64| -> i32 {
copy_handler_table_to_cage(
UNUSED_ARG, thiscage, targetcage, UNUSED_ID, UNUSED_ARG, UNUSED_ID, UNUSED_ARG,
UNUSED_ID, UNUSED_ARG, UNUSED_ID, UNUSED_ARG, UNUSED_ID, UNUSED_ARG, UNUSED_ID,
) as i32
},
)?;
// export lind-get-memory-base for libc to query base address
linker.func_wrap(
"lind",
"lind-get-memory-base",
move |mut caller: Caller<'_, T>| -> u64 {
// Return the base address of memory[0] for the calling instance
let base = get_memory_base(&mut caller);
base
},
)?;
// export lind-get-cage-id for libc to query the current cage id
linker.func_wrap(
"lind",
"lind-get-cage-id",
move |mut caller: Caller<'_, T>| -> u64 {
let cageid = wasmtime_lind_multi_process::current_cageid(&mut caller) as u64;
cageid
},
)?;
// attach lind-debug-panic to wasmtime
linker.func_wrap("lind", "debug-panic", move |str: u64| -> () {
let _panic_str = unsafe { std::ffi::CStr::from_ptr(str as *const i8).to_str().unwrap() };
sysdefs::logging::lind_debug_panic(format!("FROM GUEST: {}", _panic_str).as_str());
})?;
// attach setjmp to wasmtime
linker.func_wrap(
"lind",
"lind-setjmp",
move |mut caller: Caller<'_, T>, jmp_buf: i32| -> i32 {
wasmtime_lind_multi_process::setjmp_call(&mut caller, jmp_buf as u32)
},
)?;
// attach longjmp to wasmtime
linker.func_wrap(
"lind",
"lind-longjmp",
move |mut caller: Caller<'_, T>, jmp_buf: i32, retval: i32| -> i32 {
wasmtime_lind_multi_process::longjmp_call(&mut caller, jmp_buf as u32, retval)
},
)?;
// epoch callback function
linker.func_wrap(
"lind",
"epoch_callback",
move |mut caller: Caller<'_, T>| {
wasmtime_lind_multi_process::signal::signal_handler(&mut caller);
},
)?;
let cloned_dynamic_loader = dynamic_loader.clone();
linker.func_wrap(
"lind",
"dlopen",
move |mut caller: wasmtime::Caller<'_, T>, file: i32, mode: i32| -> i32 {
wasmtime_lind_dylink::dlopen_call(&mut caller, file, mode, cloned_dynamic_loader.clone())
},
)?;
// attach copy_handler_table_to_cage to wasmtime
linker.func_wrap(
"lind",
"dlsym",
move |mut caller: wasmtime::Caller<'_, T>, handle: i32, name: i32| -> i32 {
wasmtime_lind_dylink::dlsym_call(&mut caller, handle, name)
},
)?;
// export lind-get-memory-base for libc to query base address
linker.func_wrap(
"lind",
"dlclose",
move |mut caller: wasmtime::Caller<'_, T>, handle: i32| -> i32 {
wasmtime_lind_dylink::dlclose_call(&mut caller, handle)
},
)?;
#[cfg(feature = "lind_debug")]
{
linker.func_wrap(
"debug",
"lind_debug_num",
move |_caller: Caller<'_, T>, num: u32| -> u32 {
eprintln!("[LIND DEBUG NUM]: {}", num);
num // Return the value to the WASM stack
},
)?;
linker.func_wrap(
"debug",
"lind_debug_str",
move |mut caller: Caller<'_, T>, ptr: i32| -> i32 {
let mem_base = get_memory_base(&mut caller);
if let Ok(msg) = get_cstr(mem_base + (ptr as u32) as u64) {
eprintln!("[LIND DEBUG STR]: {}", msg);
}
ptr // Return the pointer to the WASM stack
},
)?;
}
Ok(())
}