shadow_rs/host/syscall/handler/
close_range.rs1use linux_api::close_range::CloseRangeFlags;
2use linux_api::errno::Errno;
3use linux_api::fcntl::DescriptorFlags;
4
5use crate::host::descriptor::descriptor_table;
6use crate::host::syscall::handler::{SyscallContext, SyscallHandler};
7use crate::utility::callback_queue::CallbackQueue;
8
9impl SyscallHandler {
10    log_syscall!(
11        close_range,
12        std::ffi::c_int,
13        std::ffi::c_uint,
14        std::ffi::c_uint,
15        CloseRangeFlags,
16    );
17    pub fn close_range(
18        ctx: &mut SyscallContext,
19        first: std::ffi::c_uint,
20        last: std::ffi::c_uint,
21        flags: std::ffi::c_uint,
22    ) -> Result<(), Errno> {
23        if first > last {
26            return Err(Errno::EINVAL);
27        }
28
29        if first > descriptor_table::FD_MAX {
31            return Ok(());
32        }
33
34        let last = std::cmp::min(last, descriptor_table::FD_MAX);
36
37        let first = first.try_into().unwrap();
39        let last = last.try_into().unwrap();
40
41        let range = first..=last;
42
43        let Some(flags) = CloseRangeFlags::from_bits(flags) else {
44            log::debug!("Invalid close_range flags: {flags}");
45            return Err(Errno::EINVAL);
46        };
47
48        if flags.contains(CloseRangeFlags::CLOSE_RANGE_UNSHARE) {
49            log::debug!("The CLOSE_RANGE_UNSHARE flag is not implemented");
50            return Err(Errno::EINVAL);
51        }
52
53        let mut desc_table = ctx.objs.thread.descriptor_table_borrow_mut(ctx.objs.host);
54
55        if flags.contains(CloseRangeFlags::CLOSE_RANGE_CLOEXEC) {
56            for (fd, desc) in desc_table.iter_mut() {
62                if range.contains(fd) {
63                    desc.set_flags(desc.flags() | DescriptorFlags::FD_CLOEXEC);
64                }
65            }
66        } else {
67            let descriptors = desc_table.remove_range(range);
69
70            CallbackQueue::queue_and_run_with_legacy(|cb_queue| {
72                for desc in descriptors {
73                    let _ = desc.close(ctx.objs.host, cb_queue);
76                }
77            });
78        }
79
80        Ok(())
81    }
82}