Skip to main content

shadow_rs/host/syscall/handler/
shadow.rs

1use std::ffi::CString;
2
3use linux_api::errno::Errno;
4use shadow_shim_helper_rs::syscall_types::ForeignPtr;
5
6use crate::core::worker::Worker;
7use crate::host::syscall::handler::{SyscallContext, SyscallHandler};
8use crate::host::syscall::type_formatting::{SyscallBufferArg, SyscallSockAddrArg};
9use crate::host::syscall::types::ForeignArrayPtr;
10use crate::utility::case_insensitive_eq;
11
12impl SyscallHandler {
13    log_syscall!(shadow_yield, /* rv */ std::ffi::c_int);
14    pub fn shadow_yield(_ctx: &mut SyscallContext) -> Result<(), Errno> {
15        Ok(())
16    }
17
18    log_syscall!(
19        shadow_hostname_to_addr_ipv4,
20        /* rv */ std::ffi::c_int,
21        /* name_ptr */ SyscallBufferArg</* name_len */ 1>,
22        /* name_len */ u64,
23        /* addr_ptr */ SyscallSockAddrArg</* addr_len */ 3>,
24        /* addr_len */ u64,
25    );
26    pub fn shadow_hostname_to_addr_ipv4(
27        ctx: &mut SyscallContext,
28        name_ptr: ForeignPtr<std::ffi::c_char>,
29        name_len: u64,
30        addr_ptr: ForeignPtr<()>,
31        addr_len: u64,
32    ) -> Result<(), Errno> {
33        log::trace!("Handling custom syscall shadow_hostname_to_addr_ipv4");
34
35        let name_len: usize = name_len.try_into().unwrap();
36        let addr_len: usize = addr_len.try_into().unwrap();
37
38        if addr_len < std::mem::size_of::<u32>() {
39            log::trace!("Invalid addr_len {addr_len}, returning EINVAL");
40            return Err(Errno::EINVAL);
41        }
42
43        let name_ptr = name_ptr.cast::<u8>();
44        let name_ptr = ForeignArrayPtr::new(name_ptr, name_len);
45        let addr_ptr = addr_ptr.cast::<u32>();
46
47        let mut mem = ctx.objs.process.memory_borrow_mut();
48
49        let name = mem.read_vec(name_ptr)?;
50        let Ok(name) = CString::new(name) else {
51            // name contained an internal (or trailing) nul byte.
52            // treat as not-found.
53
54            // Following existing comment to "return EFAULT like gethostname".
55            return Err(Errno::EFAULT);
56        };
57
58        let addr = if case_insensitive_eq(name.as_bytes(), &b"localhost"[..]) {
59            log::trace!("Returning loopback address for localhost");
60            std::net::Ipv4Addr::LOCALHOST
61        } else if case_insensitive_eq(name.as_bytes(), ctx.objs.host.info().name.as_bytes()) {
62            log::trace!("Using default address for my own hostname {name:?}");
63            ctx.objs.host.default_ip()
64        } else if let Some(addr) = Worker::resolve_name_to_ip(&name) {
65            addr
66        } else {
67            log::trace!("Unable to find address for name {name:?}");
68            // return EFAULT like gethostname
69            return Err(Errno::EFAULT);
70        };
71
72        log::trace!("Found address {addr} for name {name:?}");
73
74        let addr = u32::from(addr);
75        mem.write(addr_ptr, &addr.to_be())?;
76
77        Ok(())
78    }
79}