1use std::ffi::CString;
2use std::mem::MaybeUninit;
3use std::ops::{Deref, DerefMut};
4
5use linux_api::errno::Errno;
6use shadow_shim_helper_rs::syscall_types::ForeignPtr;
7
8use crate::host::memory_manager::MemoryManager;
9use crate::host::syscall::types::ForeignArrayPtr;
10use crate::utility::sockaddr::SockaddrStorage;
11
12pub fn write_sockaddr_and_len(
20 mem: &mut MemoryManager,
21 addr: Option<&SockaddrStorage>,
22 plugin_addr: ForeignPtr<u8>,
23 plugin_addr_len: ForeignPtr<libc::socklen_t>,
24) -> Result<(), Errno> {
25 let addr = match addr {
26 Some(x) => x,
27 None => {
28 mem.write(plugin_addr_len, &0)?;
29 return Ok(());
30 }
31 };
32
33 let from_addr_slice = addr.as_slice();
34 let from_len: u32 = from_addr_slice.len().try_into().unwrap();
35
36 let plugin_addr_len = {
38 let mut plugin_addr_len = mem.memory_ref_mut(ForeignArrayPtr::new(plugin_addr_len, 1))?;
39 let plugin_addr_len_value = plugin_addr_len.get_mut(0).unwrap();
40
41 let plugin_addr_len_copy = *plugin_addr_len_value;
43
44 *plugin_addr_len_value = from_len;
45
46 plugin_addr_len.flush()?;
47 plugin_addr_len_copy
48 };
49
50 if plugin_addr_len == 0 {
52 return Ok(());
53 }
54
55 let len_to_copy = std::cmp::min(from_len, plugin_addr_len).try_into().unwrap();
57
58 let plugin_addr = ForeignArrayPtr::new(plugin_addr.cast::<MaybeUninit<u8>>(), len_to_copy);
59 mem.copy_to_ptr(plugin_addr, &from_addr_slice[..len_to_copy])?;
60
61 Ok(())
62}
63
64pub fn write_sockaddr(
69 mem: &mut MemoryManager,
70 addr: &SockaddrStorage,
71 plugin_addr: ForeignPtr<u8>,
72 plugin_addr_len: libc::socklen_t,
73) -> Result<libc::socklen_t, Errno> {
74 let from_addr_slice = addr.as_slice();
75 let from_len: u32 = from_addr_slice.len().try_into().unwrap();
76
77 if plugin_addr_len == 0 {
79 return Ok(from_len);
80 }
81
82 let len_to_copy = std::cmp::min(from_len, plugin_addr_len).try_into().unwrap();
84
85 let plugin_addr = ForeignArrayPtr::new(plugin_addr.cast::<MaybeUninit<u8>>(), len_to_copy);
86 mem.copy_to_ptr(plugin_addr, &from_addr_slice[..len_to_copy])?;
87
88 Ok(from_len)
89}
90
91pub fn read_sockaddr(
92 mem: &MemoryManager,
93 addr_ptr: ForeignPtr<u8>,
94 addr_len: libc::socklen_t,
95) -> Result<Option<SockaddrStorage>, Errno> {
96 if addr_ptr.is_null() {
97 return Ok(None);
98 }
99
100 let addr_len_usize: usize = addr_len.try_into().unwrap();
101
102 let mut addr_buf = [MaybeUninit::new(0u8); std::mem::size_of::<libc::sockaddr_storage>()];
105
106 if addr_len_usize > std::mem::size_of_val(&addr_buf) {
108 log::warn!(
109 "Shadow does not support the address length {}, which is larger than {}",
110 addr_len,
111 std::mem::size_of_val(&addr_buf),
112 );
113 return Err(Errno::EINVAL);
114 }
115
116 let addr_buf = &mut addr_buf[..addr_len_usize];
117
118 mem.copy_from_ptr(
119 addr_buf,
120 ForeignArrayPtr::new(addr_ptr.cast::<MaybeUninit<u8>>(), addr_len_usize),
121 )?;
122
123 let addr = unsafe { SockaddrStorage::from_bytes(addr_buf).ok_or(Errno::EINVAL)? };
124
125 Ok(Some(addr))
126}
127
128pub fn write_partial<T: shadow_pod::Pod>(
146 mem: &mut MemoryManager,
147 val: &T,
148 val_ptr: ForeignPtr<T>,
149 val_len_bytes: usize,
150) -> Result<usize, Errno> {
151 let val_len_bytes = std::cmp::min(val_len_bytes, std::mem::size_of_val(val));
152
153 let val = &shadow_pod::as_u8_slice(val)[..val_len_bytes];
154
155 let val_ptr = val_ptr.cast::<MaybeUninit<u8>>();
156 let val_ptr = ForeignArrayPtr::new(val_ptr, val_len_bytes);
157
158 mem.copy_to_ptr(val_ptr, val)?;
159
160 Ok(val_len_bytes)
161}
162
163pub struct MsgHdr {
165 pub name: ForeignPtr<u8>,
166 pub name_len: libc::socklen_t,
167 pub iovs: Vec<IoVec>,
168 pub control: ForeignPtr<u8>,
169 pub control_len: libc::size_t,
170 pub flags: std::ffi::c_int,
171}
172
173#[derive(Copy, Clone, PartialEq, Eq)]
175pub struct IoVec {
176 pub base: ForeignPtr<u8>,
177 pub len: libc::size_t,
178}
179
180impl From<IoVec> for ForeignArrayPtr<u8> {
181 fn from(iov: IoVec) -> Self {
182 Self::new(iov.base, iov.len)
183 }
184}
185
186impl From<ForeignArrayPtr<u8>> for IoVec {
187 fn from(ptr: ForeignArrayPtr<u8>) -> Self {
188 IoVec {
189 base: ptr.ptr(),
190 len: ptr.len(),
191 }
192 }
193}
194
195pub struct IoVecReader<'a, I> {
205 iovs: I,
206 mem: &'a MemoryManager,
207 current_src: Option<ForeignArrayPtr<u8>>,
209}
210
211impl<'a, I> IoVecReader<'a, I> {
212 pub fn new<'b>(
213 iovs: impl IntoIterator<Item = &'b IoVec, IntoIter = I>,
214 mem: &'a MemoryManager,
215 ) -> Self {
216 Self {
217 iovs: iovs.into_iter(),
218 mem,
219 current_src: None,
220 }
221 }
222}
223
224impl<'a, I: Iterator<Item = &'a IoVec>> std::io::Read for IoVecReader<'a, I> {
225 fn read(&mut self, mut buf: &mut [u8]) -> std::io::Result<usize> {
226 let mut bytes_read = 0;
227
228 loop {
229 if buf.is_empty() {
231 break;
232 }
233
234 if let Some(ref mut src) = self.current_src {
235 let num_to_read = std::cmp::min(src.len(), buf.len());
236 let result = self
237 .mem
238 .copy_from_ptr(&mut buf[..num_to_read], src.slice(..num_to_read));
239
240 match (result, bytes_read) {
241 (Ok(()), _) => {}
243 (Err(e), 0) => return Err(e.into()),
245 (Err(_), _) => break,
247 }
248
249 bytes_read += num_to_read;
250 buf = &mut buf[num_to_read..];
251 *src = src.slice(num_to_read..);
252
253 if src.is_empty() {
254 self.current_src = None;
256 }
257 } else {
258 let Some(next_iov) = self.iovs.next() else {
259 break;
261 };
262 self.current_src = Some((*next_iov).into());
263 }
264 }
265
266 Ok(bytes_read)
267 }
268}
269
270pub struct IoVecWriter<'a, I> {
280 iovs: I,
281 mem: &'a mut MemoryManager,
282 current_dst: Option<ForeignArrayPtr<u8>>,
284}
285
286impl<'a, I> IoVecWriter<'a, I> {
287 pub fn new<'b>(
288 iovs: impl IntoIterator<Item = &'b IoVec, IntoIter = I>,
289 mem: &'a mut MemoryManager,
290 ) -> Self {
291 Self {
292 iovs: iovs.into_iter(),
293 mem,
294 current_dst: None,
295 }
296 }
297}
298
299impl<'a, I: Iterator<Item = &'a IoVec>> std::io::Write for IoVecWriter<'a, I> {
300 fn write(&mut self, mut buf: &[u8]) -> std::io::Result<usize> {
301 let mut bytes_written = 0;
302
303 loop {
304 if buf.is_empty() {
306 break;
307 }
308
309 if let Some(ref mut dst) = self.current_dst {
310 let num_to_write = std::cmp::min(dst.len(), buf.len());
311 let result = self
312 .mem
313 .copy_to_ptr(dst.slice(..num_to_write), &buf[..num_to_write]);
314
315 match (result, bytes_written) {
316 (Ok(()), _) => {}
318 (Err(e), 0) => return Err(e.into()),
320 (Err(_), _) => break,
322 }
323
324 bytes_written += num_to_write;
325 buf = &buf[num_to_write..];
326 *dst = dst.slice(num_to_write..);
327
328 if dst.is_empty() {
329 self.current_dst = None;
331 }
332 } else {
333 let Some(next_iov) = self.iovs.next() else {
334 break;
336 };
337 self.current_dst = Some((*next_iov).into());
338 }
339 }
340
341 Ok(bytes_written)
342 }
343
344 fn flush(&mut self) -> std::io::Result<()> {
345 Ok(())
346 }
347}
348
349pub fn read_iovecs(
351 mem: &MemoryManager,
352 iov_ptr: ForeignPtr<libc::iovec>,
353 count: usize,
354) -> Result<Vec<IoVec>, Errno> {
355 if count > libc::UIO_MAXIOV.try_into().unwrap() {
356 return Err(Errno::EINVAL);
357 }
358
359 let mut iovs = Vec::with_capacity(count);
360
361 let iov_ptr = ForeignArrayPtr::new(iov_ptr, count);
362 let mem_ref = mem.memory_ref(iov_ptr)?;
363 let plugin_iovs = mem_ref.deref();
364
365 for plugin_iov in plugin_iovs {
366 iovs.push(IoVec {
367 base: ForeignPtr::from_raw_ptr(plugin_iov.iov_base as *mut u8),
368 len: plugin_iov.iov_len,
369 });
370 }
371
372 Ok(iovs)
373}
374
375pub fn read_msghdr(
377 mem: &MemoryManager,
378 msg_ptr: ForeignPtr<libc::msghdr>,
379) -> Result<MsgHdr, Errno> {
380 let msg_ptr = ForeignArrayPtr::new(msg_ptr, 1);
381 let mem_ref = mem.memory_ref(msg_ptr)?;
382 let plugin_msg = mem_ref.deref()[0];
383
384 msghdr_to_rust(&plugin_msg, mem)
385}
386
387pub fn update_msghdr(
391 mem: &mut MemoryManager,
392 msg_ptr: ForeignPtr<libc::msghdr>,
393 msg: MsgHdr,
394) -> Result<(), Errno> {
395 let msg_ptr = ForeignArrayPtr::new(msg_ptr, 1);
396 let mut mem_ref = mem.memory_ref_mut(msg_ptr)?;
397 let plugin_msg = &mut mem_ref.deref_mut()[0];
398
399 plugin_msg.msg_namelen = msg.name_len;
401 plugin_msg.msg_controllen = msg.control_len;
402 plugin_msg.msg_flags = msg.flags;
403
404 mem_ref.flush()?;
405
406 Ok(())
407}
408
409fn msghdr_to_rust(msg: &libc::msghdr, mem: &MemoryManager) -> Result<MsgHdr, Errno> {
413 let iovs = read_iovecs(mem, ForeignPtr::from_raw_ptr(msg.msg_iov), msg.msg_iovlen)?;
414 assert_eq!(iovs.len(), msg.msg_iovlen);
415
416 Ok(MsgHdr {
417 name: ForeignPtr::from_raw_ptr(msg.msg_name as *mut u8),
418 name_len: msg.msg_namelen,
419 iovs,
420 control: ForeignPtr::from_raw_ptr(msg.msg_control as *mut u8),
421 control_len: msg.msg_controllen,
422 flags: msg.msg_flags,
423 })
424}
425
426pub fn read_cstring_vec(
430 mem: &MemoryManager,
431 mut ptr_ptr: ForeignPtr<ForeignPtr<i8>>,
432) -> Result<Vec<CString>, Errno> {
433 let mut res = Vec::new();
434
435 let mut arg_buf = [0; linux_api::limits::ARG_MAX];
441
442 loop {
443 let ptr = mem.read(ptr_ptr)?;
444 ptr_ptr = ptr_ptr.add(1);
445 if ptr.is_null() {
446 break;
447 }
448 let cstr = mem.copy_str_from_ptr(
449 &mut arg_buf,
450 ForeignArrayPtr::new(ptr.cast::<u8>(), linux_api::limits::ARG_MAX),
451 )?;
452 res.push(cstr.to_owned());
453 }
454 Ok(res)
455}