Skip to main content

shadow_rs/host/syscall/handler/
shadow.rs

1use linux_api::errno::Errno;
2use shadow_shim_helper_rs::syscall_types::ForeignPtr;
3
4use crate::core::worker::Worker;
5use crate::host::syscall::handler::{SyscallContext, SyscallHandler};
6use crate::host::syscall::type_formatting::{SyscallSockAddrArg, SyscallStringArg};
7use crate::host::syscall::types::ForeignArrayPtr;
8use crate::utility::case_insensitive_eq;
9
10impl SyscallHandler {
11    log_syscall!(shadow_yield, /* rv */ std::ffi::c_int);
12    pub fn shadow_yield(_ctx: &mut SyscallContext) -> Result<(), Errno> {
13        Ok(())
14    }
15
16    log_syscall!(shadow_init_memory_manager, /* rv */ std::ffi::c_int);
17    pub fn shadow_init_memory_manager(ctx: &mut SyscallContext) -> Result<(), Errno> {
18        if !ctx.objs.host.params.use_mem_mapper {
19            log::trace!("Not initializing memory mapper");
20            return Ok(());
21        }
22
23        log::trace!("Initializing memory mapper");
24
25        let mut memory_manager = ctx.objs.process.memory_borrow_mut();
26        if !memory_manager.has_mapper() {
27            memory_manager.init_mapper(ctx.objs)
28        }
29
30        Ok(())
31    }
32
33    log_syscall!(
34        shadow_hostname_to_addr_ipv4,
35        /* rv */ std::ffi::c_int,
36        /* name_ptr */ SyscallStringArg,
37        /* name_len */ u64,
38        /* addr_ptr */ SyscallSockAddrArg<3>,
39        /* addr_len */ u64,
40    );
41    pub fn shadow_hostname_to_addr_ipv4(
42        ctx: &mut SyscallContext,
43        name_ptr: ForeignPtr<std::ffi::c_char>,
44        name_len: u64,
45        addr_ptr: ForeignPtr<()>,
46        addr_len: u64,
47    ) -> Result<(), Errno> {
48        log::trace!("Handling custom syscall shadow_hostname_to_addr_ipv4");
49
50        let name_len: usize = name_len.try_into().unwrap();
51        let addr_len: usize = addr_len.try_into().unwrap();
52
53        if addr_len < std::mem::size_of::<u32>() {
54            log::trace!("Invalid addr_len {addr_len}, returning EINVAL");
55            return Err(Errno::EINVAL);
56        }
57
58        // TODO: Don't add 1 byte to length (if the application gave us a length of X bytes, don't
59        // read more than X bytes). This might not be valid memory. I'm guessing we do this now to
60        // avoid needing to allocate a new `CString` with a NUL byte when calling into the C DNS
61        // code. But in the future when the DNS code is in rust, we won't need NUL-terminated
62        // strings.
63
64        let name_ptr = name_ptr.cast::<u8>();
65        // add one byte to the length and hope that it contains a NUL
66        let name_ptr = ForeignArrayPtr::new(name_ptr, name_len + 1);
67        let addr_ptr = addr_ptr.cast::<u32>();
68
69        let mut mem = ctx.objs.process.memory_borrow_mut();
70
71        let lookup_name_ref = mem.memory_ref_prefix(name_ptr)?;
72        let lookup_name = lookup_name_ref.get_cstr()?;
73        let lookup_name_bytes = lookup_name.to_bytes();
74
75        if case_insensitive_eq(lookup_name_bytes, &b"localhost"[..]) {
76            let addr = u32::from(std::net::Ipv4Addr::LOCALHOST);
77            mem.write(addr_ptr, &addr.to_be())?;
78            log::trace!("Returning loopback address for localhost");
79            return Ok(());
80        }
81
82        // TODO: why do we truncate at `NI_MAXHOST`?
83        let max_len = libc::NI_MAXHOST.try_into().unwrap();
84        let host_name = ctx.objs.host.info().name.as_bytes();
85        let host_name = &host_name[..std::cmp::min(host_name.len(), max_len)];
86        let lookup_name_bytes =
87            &lookup_name_bytes[..std::cmp::min(lookup_name_bytes.len(), max_len)];
88
89        let addr = if case_insensitive_eq(lookup_name_bytes, host_name) {
90            log::trace!("Using default address for my own hostname {lookup_name:?}");
91            Some(ctx.objs.host.default_ip())
92        } else {
93            log::trace!("Looking up name {lookup_name:?}");
94            Worker::resolve_name_to_ip(lookup_name)
95        };
96
97        let Some(addr) = addr else {
98            log::trace!("Unable to find address for name {lookup_name:?}");
99            // return EFAULT like gethostname
100            return Err(Errno::EFAULT);
101        };
102
103        log::trace!("Found address {addr} for name {lookup_name:?}");
104
105        let addr = u32::from(addr);
106        mem.write(addr_ptr, &addr.to_be())?;
107
108        Ok(())
109    }
110}