shadow_rs/host/syscall/handler/
resource.rs

1use linux_api::errno::Errno;
2use shadow_shim_helper_rs::syscall_types::ForeignPtr;
3
4use crate::host::process::ProcessId;
5use crate::host::syscall::handler::{SyscallContext, SyscallHandler};
6use crate::host::syscall::types::SyscallError;
7
8impl SyscallHandler {
9    fn prlimit64_impl(
10        ctx: &mut SyscallContext,
11        pid: linux_api::posix_types::kernel_pid_t,
12        resource: std::ffi::c_uint,
13        new_rlim: Option<&linux_api::resource::rlimit64>,
14        old_rlim: Option<&mut linux_api::resource::rlimit64>,
15    ) -> Result<(), SyscallError> {
16        let Ok(resource) = linux_api::resource::Resource::try_from(resource) else {
17            return Err(Errno::EINVAL.into());
18        };
19
20        if pid == 0 {
21            // process is calling prlimit on itself
22            ctx.objs.process.prlimit64(resource, new_rlim, old_rlim)?;
23        } else {
24            // calling on another process
25            let Ok(id) = ProcessId::try_from(pid) else {
26                return Err(Errno::ESRCH.into());
27            };
28            let Some(process) = ctx.objs.host.process_borrow(id) else {
29                return Err(Errno::ESRCH.into());
30            };
31            process
32                .borrow(ctx.objs.host.root())
33                .prlimit64(resource, new_rlim, old_rlim)?;
34        }
35        Ok(())
36    }
37
38    log_syscall!(
39        prlimit64,
40        /* rv */ std::ffi::c_int,
41        /* pid */ linux_api::posix_types::kernel_pid_t,
42        /* resource */ linux_api::resource::Resource,
43        /* new_rlim */ *const linux_api::resource::rlimit64,
44        /* old_rlim */ *const linux_api::resource::rlimit64,
45    );
46    pub fn prlimit64(
47        ctx: &mut SyscallContext,
48        pid: linux_api::posix_types::kernel_pid_t,
49        resource: std::ffi::c_uint,
50        new_rlim_ptr: ForeignPtr<linux_api::resource::rlimit64>,
51        old_rlim_ptr: ForeignPtr<linux_api::resource::rlimit64>,
52    ) -> Result<(), SyscallError> {
53        let new_rlim = if new_rlim_ptr.is_null() {
54            None
55        } else {
56            Some(&ctx.objs.process.memory_borrow().read(new_rlim_ptr)?)
57        };
58
59        let mut old_rlim = if old_rlim_ptr.is_null() {
60            None
61        } else {
62            Some(&mut linux_api::resource::rlimit64 {
63                rlim_cur: 0,
64                rlim_max: 0,
65            })
66        };
67
68        SyscallHandler::prlimit64_impl(ctx, pid, resource, new_rlim, old_rlim.as_deref_mut())?;
69
70        if !old_rlim_ptr.is_null() {
71            ctx.objs
72                .process
73                .memory_borrow_mut()
74                .write(old_rlim_ptr, old_rlim.unwrap())?;
75        }
76
77        Ok(())
78    }
79
80    log_syscall!(
81        getrlimit,
82        /* rv */ std::ffi::c_int,
83        /* resource */ linux_api::resource::Resource,
84        /* rlimit */ *const linux_api::resource::rlimit,
85    );
86    pub fn getrlimit(
87        ctx: &mut SyscallContext,
88        resource: std::ffi::c_uint,
89        rlimit_ptr: ForeignPtr<linux_api::resource::rlimit>,
90    ) -> Result<(), SyscallError> {
91        let mut rlim_val64 = linux_api::resource::rlimit64 {
92            rlim_cur: 0,
93            rlim_max: 0,
94        };
95        SyscallHandler::prlimit64_impl(ctx, 0, resource, None, Some(&mut rlim_val64))?;
96        let rlim_val = linux_api::resource::rlimit {
97            rlim_cur: rlim_val64.rlim_cur,
98            rlim_max: rlim_val64.rlim_max,
99        };
100        ctx.objs
101            .process
102            .memory_borrow_mut()
103            .write(rlimit_ptr, &rlim_val)?;
104        Ok(())
105    }
106
107    log_syscall!(
108        setrlimit,
109        /* rv */ std::ffi::c_int,
110        /* resource */ linux_api::resource::Resource,
111        /* rlimit */ *const linux_api::resource::rlimit,
112    );
113    pub fn setrlimit(
114        ctx: &mut SyscallContext,
115        resource: std::ffi::c_uint,
116        rlimit: ForeignPtr<linux_api::resource::rlimit>,
117    ) -> Result<(), SyscallError> {
118        let rlim_val = ctx.objs.process.memory_borrow().read(rlimit)?;
119        let rlim_val = linux_api::resource::rlimit64 {
120            rlim_cur: rlim_val.rlim_cur,
121            rlim_max: rlim_val.rlim_max,
122        };
123        SyscallHandler::prlimit64_impl(ctx, 0, resource, Some(&rlim_val), None)?;
124        Ok(())
125    }
126}