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}