1use super::{
6 NetlinkFamily, QipcrtrSocket, SocketAddress, SocketBpfState, SocketDomain, SocketFile,
7 SocketMessageFlags, SocketProtocol, SocketShutdownFlags, SocketType, UnixSocket, VsockSocket,
8 ZxioBackedSocket, new_netlink_socket,
9};
10use crate::mm::MemoryAccessorExt;
11use crate::security;
12use crate::syscalls::time::TimeValPtr;
13use crate::task::{CurrentTask, EventHandler, WaitCanceler, Waiter};
14use crate::vfs::buffers::{AncillaryData, InputBuffer, MessageReadInfo, OutputBuffer};
15use crate::vfs::{DowncastedFile, FileHandle, FileObject, FsNodeHandle};
16use starnix_logging::track_stub;
17use starnix_sync::{LockDepMutex, SocketStateLock};
18use starnix_syscalls::{SyscallArg, SyscallResult};
19use starnix_types::time::{duration_from_timeval, timeval_from_duration};
20use starnix_types::user_buffer::UserBuffer;
21use starnix_uapi::as_any::AsAny;
22use starnix_uapi::auth::{CAP_NET_ADMIN, CAP_NET_RAW};
23use starnix_uapi::errors::{ENOTTY, Errno};
24use starnix_uapi::user_address::MappingMultiArchUserRef;
25use starnix_uapi::vfs::FdEvents;
26use starnix_uapi::{
27 SO_DOMAIN, SO_PROTOCOL, SO_RCVTIMEO, SO_SNDTIMEO, SO_TYPE, SOL_SOCKET, errno, error, uapi,
28};
29use std::collections::VecDeque;
30use std::sync::atomic::Ordering;
31use std::sync::{Arc, OnceLock};
32use zerocopy::FromBytes;
33
34pub const DEFAULT_LISTEN_BACKLOG: usize = 1024;
35
36const SO_ANDROID_DROP_REASON: u32 = 0xAD01D01;
38const ANDROID_DROP_REASON_NONE: u64 = 0;
39
40pub trait SocketOps: Send + Sync + AsAny {
41 fn get_socket_info(&self) -> Result<(SocketDomain, SocketType, SocketProtocol), Errno> {
45 error!(EINVAL)
48 }
49
50 fn connect(
53 &self,
54 socket: &SocketHandle,
55 current_task: &CurrentTask,
56 peer: SocketPeer,
57 ) -> Result<(), Errno>;
58
59 fn listen(&self, socket: &Socket, backlog: i32, credentials: uapi::ucred) -> Result<(), Errno>;
61
62 fn accept(&self, socket: &Socket, current_task: &CurrentTask) -> Result<SocketHandle, Errno>;
65
66 fn bind(
70 &self,
71 socket: &Socket,
72 current_task: &CurrentTask,
73 socket_address: SocketAddress,
74 ) -> Result<(), Errno>;
75
76 fn read(
86 &self,
87 socket: &Socket,
88 current_task: &CurrentTask,
89 data: &mut dyn OutputBuffer,
90 flags: SocketMessageFlags,
91 ) -> Result<MessageReadInfo, Errno>;
92
93 fn read_and_append(
96 &self,
97 socket: &Socket,
98 current_task: &CurrentTask,
99 read_info: &mut MessageReadInfo,
100 data: &mut dyn OutputBuffer,
101 flags: SocketMessageFlags,
102 ) -> Result<bool, Errno> {
103 let mut info = self.read(socket, current_task, data, flags)?;
104 read_info.append(&mut info);
105 Ok(true)
106 }
107
108 fn write(
117 &self,
118 socket: &Socket,
119 current_task: &CurrentTask,
120 data: &mut dyn InputBuffer,
121 dest_address: &mut Option<SocketAddress>,
122 ancillary_data: &mut Vec<AncillaryData>,
123 ) -> Result<usize, Errno>;
124
125 fn wait_async(
136 &self,
137 socket: &Socket,
138 current_task: &CurrentTask,
139 waiter: &Waiter,
140 events: FdEvents,
141 handler: EventHandler,
142 ) -> WaitCanceler;
143
144 fn query_events(&self, socket: &Socket, current_task: &CurrentTask) -> Result<FdEvents, Errno>;
146
147 fn shutdown(&self, socket: &Socket, how: SocketShutdownFlags) -> Result<(), Errno>;
151
152 fn close(&self, current_task: &CurrentTask, socket: &Socket);
163
164 fn getsockname(&self, socket: &Socket) -> Result<SocketAddress, Errno>;
169
170 fn getpeername(&self, socket: &Socket) -> Result<SocketAddress, Errno>;
174
175 fn setsockopt(
177 &self,
178 _socket: &Socket,
179 _current_task: &CurrentTask,
180 _level: u32,
181 _optname: u32,
182 _optval: SockOptValue,
183 ) -> Result<(), Errno> {
184 error!(ENOPROTOOPT)
185 }
186
187 fn getsockopt(
189 &self,
190 _socket: &Socket,
191 _current_task: &CurrentTask,
192 _level: u32,
193 _optname: u32,
194 _optlen: u32,
195 ) -> Result<Vec<u8>, Errno> {
196 error!(ENOPROTOOPT)
197 }
198
199 fn ioctl(
201 &self,
202 _socket: &Socket,
203 _file: &FileObject,
204 _current_task: &CurrentTask,
205 _request: u32,
206 _arg: SyscallArg,
207 ) -> Result<SyscallResult, Errno> {
208 error!(ENOTTY)
209 }
210
211 fn to_handle(
215 &self,
216 _socket: &Socket,
217 _current_task: &CurrentTask,
218 ) -> Result<Option<zx::NullableHandle>, Errno> {
219 Ok(None)
220 }
221}
222
223pub struct Socket {
225 pub(super) ops: Box<dyn SocketOps>,
226
227 pub domain: SocketDomain,
229
230 pub socket_type: SocketType,
232
233 pub protocol: SocketProtocol,
235
236 state: LockDepMutex<SocketState, SocketStateLock>,
237
238 fs_node: OnceLock<FsNodeHandle>,
241
242 pub security: security::SocketState,
245}
246
247#[derive(Default)]
248struct SocketState {
249 receive_timeout: Option<zx::MonotonicDuration>,
251
252 send_timeout: Option<zx::MonotonicDuration>,
254
255 bpf_state: SocketBpfState,
259}
260
261pub type SocketHandle = Arc<Socket>;
262
263#[derive(Clone)]
264pub enum SocketPeer {
265 Handle(SocketHandle),
266 Address(SocketAddress),
267}
268
269fn resolve_protocol(
273 domain: SocketDomain,
274 socket_type: SocketType,
275 protocol: SocketProtocol,
276) -> SocketProtocol {
277 if domain.is_inet() && protocol.as_raw() == 0 {
278 match socket_type {
279 SocketType::Stream => SocketProtocol::TCP,
280 SocketType::Datagram => SocketProtocol::UDP,
281 _ => protocol,
282 }
283 } else {
284 protocol
285 }
286}
287
288fn create_socket_ops(
289 current_task: &CurrentTask,
290 domain: SocketDomain,
291 socket_type: SocketType,
292 protocol: SocketProtocol,
293) -> Result<Box<dyn SocketOps>, Errno> {
294 match domain {
295 SocketDomain::Unix => Ok(Box::new(UnixSocket::new(socket_type))),
296 SocketDomain::Vsock => Ok(Box::new(VsockSocket::new(socket_type))),
297 SocketDomain::Inet | SocketDomain::Inet6 => {
298 if socket_type == SocketType::Raw {
301 security::check_task_capable(current_task, CAP_NET_RAW)?;
302 }
303 Ok(Box::new(ZxioBackedSocket::new(current_task, domain, socket_type, protocol)?))
304 }
305 SocketDomain::Netlink => {
306 let netlink_family = NetlinkFamily::from_raw(protocol.as_raw());
307 new_netlink_socket(current_task.kernel(), socket_type, netlink_family)
308 }
309 SocketDomain::Packet => {
310 security::check_task_capable(current_task, CAP_NET_RAW)?;
313 Ok(Box::new(ZxioBackedSocket::new(current_task, domain, socket_type, protocol)?))
314 }
315 SocketDomain::Key => {
316 security::check_task_capable(current_task, CAP_NET_ADMIN)?;
320 track_stub!(
321 TODO("https://fxbug.dev/323365389"),
322 "Returning a UnixSocket instead of a KeySocket"
323 );
324 Ok(Box::new(UnixSocket::new(SocketType::Datagram)))
325 }
326 SocketDomain::Qipcrtr => Ok(Box::new(QipcrtrSocket::new(socket_type))),
327 }
328}
329
330#[derive(Debug)]
331pub enum SockOptValue {
332 Value(Vec<u8>),
333 User(UserBuffer),
334}
335
336impl From<Vec<u8>> for SockOptValue {
337 fn from(buffer: Vec<u8>) -> Self {
338 Self::Value(buffer)
339 }
340}
341
342impl From<UserBuffer> for SockOptValue {
343 fn from(buffer: UserBuffer) -> Self {
344 Self::User(buffer)
345 }
346}
347
348impl SockOptValue {
349 pub fn len(&self) -> usize {
350 match self {
351 Self::Value(buffer) => buffer.len(),
352 Self::User(user_buffer) => user_buffer.length,
353 }
354 }
355
356 pub fn read<T: FromBytes>(&self, current_task: &CurrentTask) -> Result<T, Errno> {
357 match self {
358 Self::Value(buffer) => {
359 T::read_from_prefix(&buffer).map_err(|_| errno!(EINVAL)).map(|(v, _)| v)
360 }
361 Self::User(user_buffer) => {
362 current_task.read_object::<T>(user_buffer.clone().try_into()?)
363 }
364 }
365 }
366
367 pub fn read_bytes(
368 &self,
369 current_task: &CurrentTask,
370 max_bytes: usize,
371 ) -> Result<Vec<u8>, Errno> {
372 match self {
373 Self::Value(buffer) => {
374 let bytes = std::cmp::min(max_bytes, buffer.len());
375 Ok(buffer[..bytes].to_owned())
376 }
377 Self::User(user_buffer) => {
378 let bytes = std::cmp::min(max_bytes, user_buffer.length);
379 current_task
380 .read_buffer(&UserBuffer { address: user_buffer.address, length: bytes })
381 }
382 }
383 }
384
385 pub fn to_vec(self, current_task: &CurrentTask) -> Result<Vec<u8>, Errno> {
386 match self {
387 Self::Value(buffer) => Ok(buffer),
388 Self::User(user_buffer) => current_task.read_buffer(&user_buffer),
389 }
390 }
391}
392
393pub trait ReadFromSockOptValue {
395 type Result;
396 fn read_from_sockopt_value(
397 current_task: &CurrentTask,
398 buffer: &SockOptValue,
399 ) -> Result<Self::Result, Errno>;
400}
401
402impl<T, T64, T32> ReadFromSockOptValue for MappingMultiArchUserRef<T, T64, T32>
403where
404 T64: FromBytes + TryInto<T>,
405 T32: FromBytes + TryInto<T>,
406{
407 type Result = T;
408 fn read_from_sockopt_value(
409 current_task: &CurrentTask,
410 buffer: &SockOptValue,
411 ) -> Result<T, Errno> {
412 match buffer {
413 SockOptValue::Value(buffer) => {
414 Self::read_from_prefix(current_task, &buffer).map_err(|_| errno!(EINVAL))
415 }
416 SockOptValue::User(user_buffer) => {
417 let user_ref = Self::new_with_ref(current_task, user_buffer.clone())?;
418 current_task.read_multi_arch_object(user_ref)
419 }
420 }
421 }
422}
423
424impl Socket {
425 pub fn new(
430 current_task: &CurrentTask,
431 domain: SocketDomain,
432 socket_type: SocketType,
433 protocol: SocketProtocol,
434 kernel_private: bool,
435 ) -> Result<SocketHandle, Errno> {
436 let protocol = resolve_protocol(domain, socket_type, protocol);
437 security::check_socket_create_access(
441 current_task,
442 domain,
443 socket_type,
444 protocol,
445 kernel_private,
446 )?;
447 let ops = create_socket_ops(current_task, domain, socket_type, protocol)?;
448 Ok(Self::new_with_ops_and_info(ops, domain, socket_type, protocol))
449 }
450
451 pub fn new_with_ops(ops: Box<dyn SocketOps>) -> Result<SocketHandle, Errno> {
452 let (domain, socket_type, protocol) = ops.get_socket_info()?;
453 Ok(Self::new_with_ops_and_info(ops, domain, socket_type, protocol))
454 }
455
456 pub fn new_with_ops_and_info(
457 ops: Box<dyn SocketOps>,
458 domain: SocketDomain,
459 socket_type: SocketType,
460 protocol: SocketProtocol,
461 ) -> SocketHandle {
462 Arc::new(Socket {
463 ops,
464 domain,
465 socket_type,
466 protocol,
467 state: Default::default(),
468 fs_node: OnceLock::new(),
469 security: security::SocketState::default(),
470 })
471 }
472
473 pub(super) fn set_fs_node(&self, node: &FsNodeHandle) {
474 assert!(self.fs_node.set(node.clone()).is_ok());
475 }
476
477 pub fn get_from_file(file: &FileHandle) -> Result<&SocketHandle, Errno> {
480 let socket_file = file.downcast_file::<SocketFile>().ok_or_else(|| errno!(ENOTSOCK))?;
481 Ok(&socket_file.socket)
482 }
483
484 pub fn downcast_socket<T>(&self) -> Option<&T>
485 where
486 T: 'static,
487 {
488 let ops = &*self.ops;
489 ops.as_any().downcast_ref::<T>()
490 }
491
492 pub fn getsockname(&self) -> Result<SocketAddress, Errno> {
493 self.ops.getsockname(self)
494 }
495
496 pub fn getpeername(&self) -> Result<SocketAddress, Errno> {
497 self.ops.getpeername(self)
498 }
499
500 pub fn setsockopt(
501 &self,
502 current_task: &CurrentTask,
503 level: u32,
504 optname: u32,
505 optval: SockOptValue,
506 ) -> Result<(), Errno> {
507 let read_timeval = || {
508 let timeval = TimeValPtr::read_from_sockopt_value(current_task, &optval)?;
509 let duration = duration_from_timeval(timeval)?;
510 Ok(if duration == zx::MonotonicDuration::default() { None } else { Some(duration) })
511 };
512
513 security::check_socket_setsockopt_access(current_task, self, level, optname)?;
514 match (level, optname) {
515 (SOL_SOCKET, SO_RCVTIMEO) => self.state.lock().receive_timeout = read_timeval()?,
516 (SOL_SOCKET, SO_SNDTIMEO) => self.state.lock().send_timeout = read_timeval()?,
517 _ => self.ops.setsockopt(self, current_task, level, optname, optval)?,
518 }
519 Ok(())
520 }
521
522 pub fn getsockopt(
523 &self,
524 current_task: &CurrentTask,
525 level: u32,
526 optname: u32,
527 optlen: u32,
528 ) -> Result<Vec<u8>, Errno> {
529 security::check_socket_getsockopt_access(current_task, self, level, optname)?;
530 let value = match level {
531 SOL_SOCKET => match optname {
532 SO_TYPE => self.socket_type.as_raw().to_ne_bytes().to_vec(),
533 SO_DOMAIN => {
534 let domain = self.domain.as_raw() as u32;
535 domain.to_ne_bytes().to_vec()
536 }
537 SO_PROTOCOL => self.protocol.as_raw().to_ne_bytes().to_vec(),
538 SO_RCVTIMEO => {
539 let duration = self.receive_timeout().unwrap_or_default();
540 TimeValPtr::into_bytes(current_task, timeval_from_duration(duration))
541 .map_err(|_| errno!(EINVAL))?
542 }
543 SO_SNDTIMEO => {
544 let duration = self.send_timeout().unwrap_or_default();
545 TimeValPtr::into_bytes(current_task, timeval_from_duration(duration))
546 .map_err(|_| errno!(EINVAL))?
547 }
548 SO_ANDROID_DROP_REASON => {
549 track_stub!(
550 TODO("https://fxbug.dev/477273398"),
551 "Faking SO_ANDROID_DROP_REASON"
552 );
553 ANDROID_DROP_REASON_NONE.to_ne_bytes().to_vec()
554 }
555 _ => self.ops.getsockopt(self, current_task, level, optname, optlen)?,
556 },
557 _ => self.ops.getsockopt(self, current_task, level, optname, optlen)?,
558 };
559 Ok(value)
560 }
561
562 pub fn receive_timeout(&self) -> Option<zx::MonotonicDuration> {
563 self.state.lock().receive_timeout
564 }
565
566 pub fn send_timeout(&self) -> Option<zx::MonotonicDuration> {
567 self.state.lock().send_timeout
568 }
569
570 pub fn ioctl(
571 &self,
572 file: &FileObject,
573 current_task: &CurrentTask,
574 request: u32,
575 arg: SyscallArg,
576 ) -> Result<SyscallResult, Errno> {
577 let res = super::netlink_ioctl::netlink_ioctl(current_task, request, arg);
578 match &res {
579 Err(e) if e.code == ENOTTY => {}
580 _ => return res,
581 }
582 self.ops.ioctl(self, file, current_task, request, arg)
583 }
584
585 pub fn bind(
586 &self,
587 current_task: &CurrentTask,
588 socket_address: SocketAddress,
589 ) -> Result<(), Errno> {
590 self.ops.bind(self, current_task, socket_address)
591 }
592
593 pub fn listen(&self, current_task: &CurrentTask, backlog: i32) -> Result<(), Errno> {
594 security::check_socket_listen_access(current_task, self, backlog)?;
595 let max_connections =
596 current_task.kernel().system_limits.socket.max_connections.load(Ordering::Relaxed);
597 let backlog = std::cmp::min(backlog, max_connections);
598 let credentials = current_task.current_ucred();
599 self.ops.listen(self, backlog, credentials)?;
600 self.state.lock().bpf_state = SocketBpfState::Listen;
601 Ok(())
602 }
603
604 pub fn accept(&self, current_task: &CurrentTask) -> Result<SocketHandle, Errno> {
605 let new_socket = self.ops.accept(self, current_task)?;
606 new_socket.state.lock().bpf_state = SocketBpfState::Established;
607 Ok(new_socket)
608 }
609
610 pub fn read(
611 &self,
612 current_task: &CurrentTask,
613 data: &mut dyn OutputBuffer,
614 flags: SocketMessageFlags,
615 ) -> Result<MessageReadInfo, Errno> {
616 security::check_socket_recvmsg_access(current_task, self)?;
617 self.ops.read(self, current_task, data, flags)
618 }
619
620 pub(super) fn read_and_append_unchecked(
621 &self,
622 current_task: &CurrentTask,
623 read_info: &mut MessageReadInfo,
624 data: &mut dyn OutputBuffer,
625 flags: SocketMessageFlags,
626 ) -> Result<bool, Errno> {
627 self.ops.read_and_append(self, current_task, read_info, data, flags)
628 }
629
630 pub fn write(
631 &self,
632 current_task: &CurrentTask,
633 data: &mut dyn InputBuffer,
634 dest_address: &mut Option<SocketAddress>,
635 ancillary_data: &mut Vec<AncillaryData>,
636 ) -> Result<usize, Errno> {
637 security::check_socket_sendmsg_access(current_task, self)?;
638 self.write_unchecked(current_task, data, dest_address, ancillary_data)
639 }
640
641 pub(super) fn write_unchecked(
642 &self,
643 current_task: &CurrentTask,
644 data: &mut dyn InputBuffer,
645 dest_address: &mut Option<SocketAddress>,
646 ancillary_data: &mut Vec<AncillaryData>,
647 ) -> Result<usize, Errno> {
648 self.ops.write(self, current_task, data, dest_address, ancillary_data)
649 }
650
651 pub fn wait_async(
652 &self,
653 current_task: &CurrentTask,
654 waiter: &Waiter,
655 events: FdEvents,
656 handler: EventHandler,
657 ) -> WaitCanceler {
658 self.ops.wait_async(self, current_task, waiter, events, handler)
659 }
660
661 pub fn query_events(&self, current_task: &CurrentTask) -> Result<FdEvents, Errno> {
662 self.ops.query_events(self, current_task)
663 }
664
665 pub fn shutdown(
666 &self,
667 current_task: &CurrentTask,
668 how: SocketShutdownFlags,
669 ) -> Result<(), Errno> {
670 security::check_socket_shutdown_access(current_task, self, how)?;
671 self.ops.shutdown(self, how)
672 }
673
674 pub fn close(&self, current_task: &CurrentTask) {
675 self.state.lock().bpf_state = SocketBpfState::Close;
676 self.ops.close(current_task, self)
677 }
678
679 pub fn to_handle(
680 &self,
681 _file: &FileObject,
682 current_task: &CurrentTask,
683 ) -> Result<Option<zx::NullableHandle>, Errno> {
684 self.ops.to_handle(self, current_task)
685 }
686
687 pub fn fs_node(&self) -> Option<&FsNodeHandle> {
691 self.fs_node.get()
692 }
693
694 pub fn bpf_state(&self) -> SocketBpfState {
695 self.state.lock().bpf_state
696 }
697
698 pub fn set_bpf_state(&self, state: SocketBpfState) {
699 self.state.lock().bpf_state = state;
700 }
701}
702
703impl DowncastedFile<'_, SocketFile> {
704 pub fn connect(self, current_task: &CurrentTask, peer: SocketPeer) -> Result<(), Errno> {
705 security::check_socket_connect_access(current_task, self, &peer)?;
706 let res = self.socket.ops.connect(&self.socket, current_task, peer);
707 if res.is_ok() || res == error!(EINPROGRESS) {
708 self.socket.state.lock().bpf_state = SocketBpfState::Established;
709 }
710 res
711 }
712}
713
714pub struct AcceptQueue {
715 pub sockets: VecDeque<SocketHandle>,
716 pub backlog: usize,
717}
718
719impl AcceptQueue {
720 pub fn new(backlog: usize) -> AcceptQueue {
721 AcceptQueue { sockets: VecDeque::with_capacity(backlog), backlog }
722 }
723
724 pub fn set_backlog(&mut self, backlog: usize) -> Result<(), Errno> {
725 if self.sockets.len() > backlog {
726 return error!(EINVAL);
727 }
728 self.backlog = backlog;
729 Ok(())
730 }
731}
732
733#[cfg(test)]
734mod tests {
735 use super::*;
736 use crate::testing::{map_memory, spawn_kernel_and_run};
737 use crate::vfs::{UnixControlData, VecInputBuffer, VecOutputBuffer};
738 use starnix_uapi::SO_PASSCRED;
739 use starnix_uapi::user_address::{UserAddress, UserRef};
740
741 #[fuchsia::test]
742 async fn test_dgram_socket() {
743 spawn_kernel_and_run(async |current_task| {
744 let bind_address = SocketAddress::Unix(b"dgram_test".into());
745 let rec_dgram = Socket::new(
746 ¤t_task,
747 SocketDomain::Unix,
748 SocketType::Datagram,
749 SocketProtocol::default(),
750 false,
751 )
752 .expect("Failed to create socket.");
753 let passcred: u32 = 1;
754 let opt_size = std::mem::size_of::<u32>();
755 let user_address = map_memory(¤t_task, UserAddress::default(), opt_size as u64);
756 let opt_ref = UserRef::<u32>::new(user_address);
757 current_task.write_object(opt_ref, &passcred).unwrap();
758 let opt_buf = UserBuffer { address: user_address, length: opt_size };
759 rec_dgram.setsockopt(¤t_task, SOL_SOCKET, SO_PASSCRED, opt_buf.into()).unwrap();
760
761 rec_dgram.bind(¤t_task, bind_address).expect("failed to bind datagram socket");
762
763 let xfer_value: u64 = 1234567819;
764 let xfer_bytes = xfer_value.to_ne_bytes();
765
766 let send = Socket::new(
767 ¤t_task,
768 SocketDomain::Unix,
769 SocketType::Datagram,
770 SocketProtocol::default(),
771 false,
772 )
773 .expect("Failed to connect socket.");
774 send.ops.connect(&send, ¤t_task, SocketPeer::Handle(rec_dgram.clone())).unwrap();
775 let mut source_iter = VecInputBuffer::new(&xfer_bytes);
776 send.write(¤t_task, &mut source_iter, &mut None, &mut vec![]).unwrap();
777 assert_eq!(source_iter.available(), 0);
778 send.close(¤t_task);
781
782 let mut rec_buffer = VecOutputBuffer::new(8);
783 let read_info = rec_dgram
784 .read(¤t_task, &mut rec_buffer, SocketMessageFlags::empty())
785 .unwrap();
786 assert_eq!(read_info.bytes_read, xfer_bytes.len());
787 assert_eq!(rec_buffer.data(), xfer_bytes);
788 assert_eq!(1, read_info.ancillary_data.len());
789 assert_eq!(
790 read_info.ancillary_data[0],
791 AncillaryData::Unix(UnixControlData::Credentials(uapi::ucred {
792 pid: current_task.get_pid(),
793 uid: 0,
794 gid: 0
795 }))
796 );
797
798 rec_dgram.close(¤t_task);
799 })
800 .await;
801 }
802}