shadow_shim_helper_rs/
shim_event.rs

1use shadow_shmem::allocator::ShMemBlockSerialized;
2use vasi::VirtualAddressSpaceIndependent;
3
4use crate::syscall_types::{ForeignPtr, SyscallArgs, SyscallReg, UntypedForeignPtr};
5
6#[derive(Copy, Clone, Debug, VirtualAddressSpaceIndependent)]
7#[repr(C)]
8/// Data for [`ShimEventToShim::StartRes`]
9pub struct ShimEventStartRes {
10    /// Pseudorandom data to be used to overwrite the data linux provides
11    /// in its auxiliary vector.
12    // TODO: Consider replacing this with a seed for a shim-side PRNG, particularly
13    // when implementing the getrandom vdso (#3362).
14    pub auxvec_random: [u8; 16],
15}
16
17#[derive(Copy, Clone, Debug, VirtualAddressSpaceIndependent)]
18#[repr(C)]
19/// Data for [`ShimEventToShim::Syscall`] and [`ShimEventToShadow::Syscall`]
20pub struct ShimEventSyscall {
21    pub syscall_args: SyscallArgs,
22}
23
24/// Data for [`ShimEventToShim::SyscallComplete`] and [`ShimEventToShadow::SyscallComplete`]
25#[derive(Copy, Clone, Debug, VirtualAddressSpaceIndependent)]
26#[repr(C)]
27pub struct ShimEventSyscallComplete {
28    pub retval: SyscallReg,
29    /// Whether the syscall is eligible to be restarted. Only applicable
30    /// when retval is -EINTR. See signal(7).
31    pub restartable: bool,
32}
33
34/// Data for [`ShimEventToShim::AddThreadReq`]
35#[derive(Copy, Clone, Debug, VirtualAddressSpaceIndependent)]
36#[repr(C)]
37pub struct ShimEventAddThreadReq {
38    pub ipc_block: ShMemBlockSerialized,
39    /// clone flags.
40    pub flags: libc::c_ulong,
41    /// clone stack. u8 pointer in shim's memory
42    pub child_stack: UntypedForeignPtr,
43    /// clone ptid. pid_t pointer in shim's memory
44    pub ptid: UntypedForeignPtr,
45    /// clone ctid. pid_t pointer in shim's memory
46    pub ctid: UntypedForeignPtr,
47    /// clone tls.
48    pub newtls: libc::c_ulong,
49}
50
51/// Data for [`ShimEventToShadow::AddThreadRes`]
52#[derive(Copy, Clone, Debug, VirtualAddressSpaceIndependent)]
53#[repr(C)]
54pub struct ShimEventAddThreadRes {
55    pub clone_res: i64,
56}
57
58/// Data for [`ShimEventToShadow::StartReq`]
59#[derive(Copy, Clone, Debug, VirtualAddressSpaceIndependent)]
60#[repr(C)]
61pub struct ShimEventStartReq {
62    /// Shim pointer to be initd by Shadow. Required.
63    pub thread_shmem_block_to_init: ForeignPtr<ShMemBlockSerialized>,
64    /// Shim pointer to be initd by Shadow. Optional.
65    pub process_shmem_block_to_init: ForeignPtr<ShMemBlockSerialized>,
66
67    /// Shim pointer to be initd by Shadow. Optional.
68    /// If set, shadow will write a null-terminated path.
69    // TODO: Consider putting in persistent shared memory instead.
70    // This has the drawback though of requiring us to statically allocate
71    // the maximum path size (e.g. linux_api::limits::PATH_MAX == 4k).
72    // Whether and how to do this also depends how we end up implementing
73    // `chdir` https://github.com/shadow/shadow/issues/2960
74    pub initial_working_dir_to_init: ForeignPtr<u8>,
75    pub initial_working_dir_to_init_len: usize,
76}
77
78/// A message between Shadow and the Shim.
79
80#[derive(Copy, Clone, Debug, VirtualAddressSpaceIndependent)]
81// SAFETY: `shimevent2shadow_getId` assumes this representation.
82#[repr(u32)]
83// Clippy suggests boxing large enum variants. We can't do that, since
84// it'd make ShimEvent unsafe for use in shared memory.
85#[allow(clippy::large_enum_variant)]
86pub enum ShimEventToShadow {
87    /// First message from the shim, requesting that it's ready to start
88    /// executing.
89    StartReq(ShimEventStartReq),
90    /// The whole process has died.
91    /// We inject this event to trigger cleanup after we've detected that the
92    /// native process has died.
93    ProcessDeath,
94    /// Request to emulate the given syscall.
95    Syscall(ShimEventSyscall),
96    /// Response to ShimEventToShim::Syscall
97    SyscallComplete(ShimEventSyscallComplete),
98    /// Response to `ShimEventToShim::AddThreadReq`
99    AddThreadRes(ShimEventAddThreadRes),
100}
101
102#[derive(Copy, Clone, Debug, VirtualAddressSpaceIndependent)]
103// SAFETY: `shimevent2shim_getId` assumes this representation.
104#[repr(u32)]
105// Clippy suggests boxing large enum variants. We can't do that, since
106// it'd make ShimEvent unsafe for use in shared memory.
107#[allow(clippy::large_enum_variant)]
108pub enum ShimEventToShim {
109    /// First message from shadow, indicating that it is ready for
110    /// the shim to start executing.
111    StartRes(ShimEventStartRes),
112    /// Request to execute the given syscall natively.
113    Syscall(ShimEventSyscall),
114    /// Request from Shadow to Shim to take the included shared memory block,
115    /// which holds an `IpcData`, and use it to initialize a newly spawned
116    /// thread.
117    AddThreadReq(ShimEventAddThreadReq),
118    /// Response to ShimEventToShadow::Syscall
119    SyscallComplete(ShimEventSyscallComplete),
120    /// Response to ShimEventToShadow::Syscall indicating to execute it
121    /// natively.
122    SyscallDoNative,
123}