starnix_modules_iouring/
syscalls.rs1use crate::io_uring::{IORING_MAX_ENTRIES, IoUringFileObject};
6use starnix_core::mm::{IOVecPtr, MemoryAccessorExt};
7use starnix_core::security;
8use starnix_core::task::CurrentTask;
9use starnix_core::vfs::{FdFlags, FdNumber};
10use starnix_logging::track_stub;
11
12use starnix_syscalls::{SUCCESS, SyscallResult};
13use starnix_uapi::auth::CAP_SYS_ADMIN;
14use starnix_uapi::errors::Errno;
15use starnix_uapi::signals::SigSet;
16use starnix_uapi::user_address::{UserAddress, UserRef};
17use starnix_uapi::user_value::UserValue;
18use starnix_uapi::{
19 errno, error, io_uring_params,
20 io_uring_register_op_IORING_REGISTER_BUFFERS as IORING_REGISTER_BUFFERS,
21 io_uring_register_op_IORING_REGISTER_IOWQ_MAX_WORKERS as IORING_REGISTER_IOWQ_MAX_WORKERS,
22 io_uring_register_op_IORING_REGISTER_PBUF_RING as IORING_REGISTER_PBUF_RING,
23 io_uring_register_op_IORING_REGISTER_PBUF_STATUS as IORING_REGISTER_PBUF_STATUS,
24 io_uring_register_op_IORING_REGISTER_PERSONALITY as IORING_REGISTER_PERSONALITY,
25 io_uring_register_op_IORING_REGISTER_RING_FDS as IORING_REGISTER_RING_FDS,
26 io_uring_register_op_IORING_UNREGISTER_BUFFERS as IORING_UNREGISTER_BUFFERS,
27 io_uring_register_op_IORING_UNREGISTER_PBUF_RING as IORING_UNREGISTER_PBUF_RING,
28 io_uring_register_op_IORING_UNREGISTER_RING_FDS as IORING_UNREGISTER_RING_FDS, uapi,
29};
30use std::sync::atomic;
31
32pub fn sys_io_uring_setup(
33 current_task: &CurrentTask,
34 user_entries: UserValue<u32>,
35 user_params: UserRef<io_uring_params>,
36) -> Result<FdNumber, Errno> {
37 if !current_task.kernel().features.io_uring {
43 return error!(ENOSYS);
44 }
45
46 let limits = ¤t_task.kernel().system_limits;
48 match limits.io_uring_disabled.load(atomic::Ordering::Relaxed) {
49 0 => (),
50 1 => {
51 let io_uring_group = limits.io_uring_group.load(atomic::Ordering::Relaxed).try_into();
52 if io_uring_group.is_err()
53 || !current_task.current_creds().is_in_group(io_uring_group.unwrap())
54 {
55 security::check_task_capable(current_task, CAP_SYS_ADMIN)?;
56 }
57 }
58 _ => {
59 return error!(EPERM);
60 }
61 }
62
63 let entries = user_entries.validate(1..IORING_MAX_ENTRIES).ok_or_else(|| errno!(EINVAL))?;
64
65 let mut params = current_task.read_object(user_params)?;
66 for byte in params.resv {
67 if byte != 0 {
68 return error!(EINVAL);
69 }
70 }
71
72 let file = IoUringFileObject::new_file(current_task, entries, &mut params)?;
73
74 let fd = current_task.add_file(file, FdFlags::CLOEXEC)?;
76 current_task.write_object(user_params, ¶ms)?;
77 Ok(fd)
78}
79
80pub fn sys_io_uring_enter(
81 current_task: &CurrentTask,
82 fd: FdNumber,
83 to_submit: u32,
84 min_complete: u32,
85 flags: u32,
86 _sig: UserRef<SigSet>,
87 sigset_size: usize,
88) -> Result<u32, Errno> {
89 if !current_task.kernel().features.io_uring {
90 return error!(ENOSYS);
91 }
92 if !_sig.is_null() {
93 if sigset_size != std::mem::size_of::<SigSet>() {
94 return error!(EINVAL);
95 }
96 }
97 let file = current_task.files().get(fd)?;
98 let io_uring = file.downcast_file::<IoUringFileObject>().ok_or_else(|| errno!(EOPNOTSUPP))?;
99 io_uring.enter(current_task, to_submit, min_complete, flags)
101}
102
103pub fn sys_io_uring_register(
104 current_task: &CurrentTask,
105 fd: FdNumber,
106 opcode: u32,
107 arg: UserAddress,
108 nr_args: UserValue<u32>,
109) -> Result<SyscallResult, Errno> {
110 if !current_task.kernel().features.io_uring {
111 return error!(ENOSYS);
112 }
113 let file = current_task.files().get(fd)?;
114 let io_uring = file.downcast_file::<IoUringFileObject>().ok_or_else(|| errno!(EOPNOTSUPP))?;
115 match opcode {
116 IORING_REGISTER_BUFFERS => {
117 let iovec = IOVecPtr::new(current_task, arg);
119 let buffers = current_task.read_iovec(iovec, nr_args)?;
120 io_uring.register_buffers(buffers);
121 return Ok(SUCCESS);
122 }
123 IORING_UNREGISTER_BUFFERS => {
124 if !arg.is_null() {
125 return error!(EINVAL);
126 }
127 io_uring.unregister_buffers();
128 return Ok(SUCCESS);
129 }
130 IORING_REGISTER_IOWQ_MAX_WORKERS => {
131 track_stub!(
132 TODO("https://fxbug.dev/297431387"),
133 "io_uring_register IORING_REGISTER_IOWQ_MAX_WORKERS",
134 opcode
135 );
136 return Ok(SUCCESS);
138 }
139 IORING_REGISTER_RING_FDS => {
140 track_stub!(
141 TODO("https://fxbug.dev/297431387"),
142 "io_uring_register IORING_REGISTER_RING_FDS",
143 opcode
144 );
145 let nr_args: usize = nr_args.raw().try_into().map_err(|_| errno!(EINVAL))?;
149 if nr_args > 16 {
150 return error!(EINVAL);
151 }
152 let updates_addr = UserRef::<uapi::io_uring_rsrc_update>::from(arg);
153 let mut updates = current_task
154 .read_objects_to_smallvec::<uapi::io_uring_rsrc_update, 1>(updates_addr, nr_args)?;
155 let mut result = 0;
156 for update in updates.iter_mut() {
157 if update.offset == u32::MAX {
158 update.offset = update.data.try_into().map_err(|_| errno!(EINVAL))?;
159 result += 1;
160 }
161 }
162 current_task.write_objects(updates_addr, &updates)?;
163 return Ok(result.into());
164 }
165 IORING_UNREGISTER_RING_FDS => {
166 track_stub!(
167 TODO("https://fxbug.dev/297431387"),
168 "io_uring_register IORING_UNREGISTER_RING_FDS",
169 opcode
170 );
171 return Ok(SUCCESS);
173 }
174 IORING_REGISTER_PBUF_RING => {
175 let nr_args: usize = nr_args.raw().try_into().map_err(|_| errno!(EINVAL))?;
176 if nr_args != 1 {
177 return error!(EINVAL);
178 }
179 let buffer_definition: uapi::io_uring_buf_reg = current_task.read_object(arg.into())?;
180 io_uring.register_ring_buffers(buffer_definition)?;
181 return Ok(SUCCESS);
182 }
183
184 IORING_UNREGISTER_PBUF_RING => {
185 let nr_args: usize = nr_args.raw().try_into().map_err(|_| errno!(EINVAL))?;
186 if nr_args != 1 {
187 return error!(EINVAL);
188 }
189 let buffer_definition: uapi::io_uring_buf_reg = current_task.read_object(arg.into())?;
190 io_uring.unregister_ring_buffers(buffer_definition)?;
191 return Ok(SUCCESS);
192 }
193
194 IORING_REGISTER_PBUF_STATUS => {
195 let nr_args: usize = nr_args.raw().try_into().map_err(|_| errno!(EINVAL))?;
196 if nr_args != 1 {
197 return error!(EINVAL);
198 }
199 let buffer_status_addr = UserRef::<uapi::io_uring_buf_status>::from(arg);
200 let mut buffer_status: uapi::io_uring_buf_status =
201 current_task.read_object(buffer_status_addr)?;
202 io_uring.ring_buffer_status(&mut buffer_status)?;
203 current_task.write_object(buffer_status_addr, &buffer_status)?;
204 return Ok(SUCCESS);
205 }
206 IORING_REGISTER_PERSONALITY => {
207 track_stub!(
210 TODO("https://fxbug.dev/297431387"),
211 "io_uring_register unknown op",
212 opcode
213 );
214 return error!(EINVAL);
215 }
216 _ => {
217 track_stub!(
218 TODO("https://fxbug.dev/297431387"),
219 "io_uring_register unknown op",
220 opcode
221 );
222 return error!(EINVAL);
223 }
224 }
225}
226
227pub use sys_io_uring_enter as sys_arch32_io_uring_enter;
228pub use sys_io_uring_register as sys_arch32_io_uring_register;
229pub use sys_io_uring_setup as sys_arch32_io_uring_setup;