Skip to main content

starnix_core/vfs/socket/
socket_unix.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5use crate::bpf::context::EbpfRunContextImpl;
6use crate::bpf::fs::get_bpf_object;
7use crate::mm::MemoryAccessorExt;
8use crate::security;
9use crate::task::{CurrentTask, EventHandler, WaitCanceler, WaitQueue, Waiter};
10use crate::vfs::buffers::{
11    AncillaryData, InputBuffer, MessageQueue, MessageReadInfo, OutputBuffer, PasscredMode,
12    UnixControlData,
13};
14use crate::vfs::socket::{
15    AcceptQueue, DEFAULT_LISTEN_BACKLOG, SockOptValue, Socket, SocketAddress, SocketBpfState,
16    SocketDomain, SocketFile, SocketHandle, SocketMessageFlags, SocketOps, SocketPeer,
17    SocketProtocol, SocketShutdownFlags, SocketType,
18};
19use crate::vfs::{
20    AccessCheck, FdNumber, FileHandle, FileObject, FsNodeHandle, FsStr, LookupContext, Message,
21    UcredPtr,
22};
23use ebpf::{
24    BpfProgramContext, BpfValue, CbpfConfig, DataWidth, EbpfProgram, Packet, ProgramArgument, Type,
25};
26use ebpf_api::{
27    LoadBytesBase, PacketWithLoadBytes, PinnedMap, ProgramType, SOCKET_FILTER_CBPF_CONFIG,
28    SOCKET_FILTER_SK_BUF_TYPE, SocketFilterProgramContext, SocketRef,
29};
30use starnix_logging::track_stub;
31use starnix_sync::{LockDepGuard, LockDepMutex, UnixSocketInnerLock, allow_subclass};
32use starnix_syscalls::{SUCCESS, SyscallArg, SyscallResult};
33use starnix_uapi::errors::{EACCES, ECONNREFUSED, EINTR, EPERM, Errno};
34use starnix_uapi::file_mode::Access;
35use starnix_uapi::open_flags::OpenFlags;
36use starnix_uapi::user_address::{UserAddress, UserRef};
37use starnix_uapi::vfs::FdEvents;
38use starnix_uapi::{
39    __sk_buff, FIONREAD, SO_ACCEPTCONN, SO_ATTACH_BPF, SO_BROADCAST, SO_ERROR, SO_KEEPALIVE,
40    SO_LINGER, SO_NO_CHECK, SO_PASSCRED, SO_PASSSEC, SO_PEERCRED, SO_PEERSEC, SO_RCVBUF,
41    SO_REUSEADDR, SO_REUSEPORT, SO_SNDBUF, SOL_SOCKET, errno, error, gid_t, socklen_t, uapi, ucred,
42    uid_t,
43};
44use std::sync::Arc;
45use zerocopy::IntoBytes;
46
47// From unix.go in gVisor.
48const SOCKET_MIN_SIZE: usize = 4 << 10;
49const SOCKET_DEFAULT_SIZE: usize = 208 << 10;
50const SOCKET_MAX_SIZE: usize = 4 << 20;
51
52/// The data of a socket is stored in the "Inner" struct. Because both ends have separate locks,
53/// care must be taken to avoid taking both locks since there is no way to tell what order to
54/// take them in.
55///
56/// When writing, data is buffered in the "other" end of the socket's Inner.MessageQueue:
57///
58///            UnixSocket end #1          UnixSocket end #2
59///            +---------------+          +---------------+
60///            |               |          |   +-------+   |
61///   Writes -------------------------------->| Inner |------> Reads
62///            |               |          |   +-------+   |
63///            |   +-------+   |          |               |
64///   Reads <------| Inner |<-------------------------------- Writes
65///            |   +-------+   |          |               |
66///            +---------------+          +---------------+
67///
68pub struct UnixSocket {
69    inner: LockDepMutex<UnixSocketInner, UnixSocketInnerLock>,
70    waiters: WaitQueue,
71}
72
73fn downcast_socket_to_unix(socket: &Socket) -> &UnixSocket {
74    // It is a programing error if we are downcasting
75    // a different type of socket as sockets from different families
76    // should not communicate, so unwrapping here
77    // will let us know that.
78    socket.downcast_socket::<UnixSocket>().unwrap()
79}
80
81enum UnixSocketState {
82    /// The socket has not been connected.
83    Disconnected,
84
85    /// The socket has had `listen` called and can accept incoming connections.
86    Listening(AcceptQueue),
87
88    /// The socket is connected to a peer.
89    Connected(SocketHandle),
90
91    /// The socket is closed.
92    Closed,
93}
94
95struct UnixSocketInner {
96    /// The `MessageQueue` that contains messages sent to this socket.
97    messages: MessageQueue,
98
99    /// The address that this socket has been bound to, if it has been bound.
100    address: Option<SocketAddress>,
101
102    /// The `FsNode` that this socket has been bound to in the filesystem, if any.
103    ///
104    /// Retaining a strong reference while the socket is open prevents the `FsNode` (and its
105    /// `bound_socket` association) from being evicted from `FsNodeCache` when its `DirEntry` is
106    /// purged from a bounded `DirEntryCache::Lru` (e.g. on `RemoteFs`). This forms a `Socket` <->
107    /// `FsNode` cycle that only `close()` breaks, so callers must close bound sockets.
108    fs_node: Option<FsNodeHandle>,
109
110    /// Whether this end of the socket has been shut down and can no longer receive message. It is
111    /// still possible to send messages to the peer, if it exists and hasn't also been shut down.
112    is_read_shutdown: bool,
113
114    /// Whether this end of the socket has been shut down and can no longer send messages.
115    is_write_shutdown: bool,
116
117    /// Whether the peer had unread data when it was closed. In this case, reads should return
118    /// ECONNRESET instead of 0 (eof).
119    peer_closed_with_unread_data: bool,
120
121    /// See SO_LINGER.
122    linger: uapi::linger,
123
124    /// See SO_PASSCRED.
125    passcred: PasscredMode,
126
127    /// See SO_PASSSEC.
128    passsec: bool,
129
130    /// See SO_BROADCAST.
131    broadcast: bool,
132
133    /// See SO_NO_CHECK.
134    no_check: bool,
135
136    /// See SO_REUSEPORT.
137    reuseport: bool,
138
139    /// See SO_REUSEADDR.
140    reuseaddr: bool,
141
142    /// See SO_KEEPALIVE.
143    keepalive: bool,
144
145    /// See SO_ATTACH_BPF.
146    bpf_program: Option<UnixSocketFilter>,
147
148    /// Unix credentials of the peer of this socket, or of the listening socket itself, for
149    /// SO_PEERCRED.
150    credentials: Option<ucred>,
151
152    /// Socket state: a queue if this is a listening socket, or a peer if this is a connected
153    /// socket.
154    state: UnixSocketState,
155}
156
157impl UnixSocket {
158    pub fn new(_socket_type: SocketType) -> UnixSocket {
159        UnixSocket {
160            inner: UnixSocketInner {
161                messages: MessageQueue::new(SOCKET_DEFAULT_SIZE),
162                address: None,
163                fs_node: None,
164                is_read_shutdown: false,
165                is_write_shutdown: false,
166                peer_closed_with_unread_data: false,
167                linger: uapi::linger::default(),
168                passcred: PasscredMode::Disabled,
169                passsec: false,
170                broadcast: false,
171                no_check: false,
172                reuseaddr: false,
173                reuseport: false,
174                keepalive: false,
175                bpf_program: None,
176                credentials: None,
177                state: UnixSocketState::Disconnected,
178            }
179            .into(),
180            waiters: WaitQueue::default(),
181        }
182    }
183
184    /// Creates a pair of connected sockets.
185    ///
186    /// # Parameters
187    /// - `domain`: The domain of the socket (e.g., `AF_UNIX`).
188    /// - `socket_type`: The type of the socket (e.g., `SOCK_STREAM`).
189    pub fn new_pair(
190        current_task: &CurrentTask,
191        domain: SocketDomain,
192        socket_type: SocketType,
193        open_flags: OpenFlags,
194    ) -> Result<(FileHandle, FileHandle), Errno> {
195        let credentials = current_task.current_ucred();
196        let left = Socket::new(
197            current_task,
198            domain,
199            socket_type,
200            SocketProtocol::default(),
201            /* kernel_private = */ false,
202        )?;
203        let right = Socket::new(
204            current_task,
205            domain,
206            socket_type,
207            SocketProtocol::default(),
208            /* kernel_private = */ false,
209        )?;
210        downcast_socket_to_unix(&left).lock().state = UnixSocketState::Connected(right.clone());
211        downcast_socket_to_unix(&left).lock().credentials = Some(credentials.clone());
212        downcast_socket_to_unix(&right).lock().state = UnixSocketState::Connected(left.clone());
213        downcast_socket_to_unix(&right).lock().credentials = Some(credentials);
214        left.set_bpf_state(SocketBpfState::Established);
215        right.set_bpf_state(SocketBpfState::Established);
216        let left = SocketFile::from_socket(
217            current_task,
218            left,
219            open_flags,
220            /* kernel_private= */ false,
221        )?;
222        let right = SocketFile::from_socket(
223            current_task,
224            right,
225            open_flags,
226            /* kernel_private= */ false,
227        )?;
228        let left_socket = SocketFile::get_from_file(&left)?;
229        let right_socket = SocketFile::get_from_file(&right)?;
230
231        security::socket_socketpair(current_task, left_socket, right_socket)?;
232        Ok((left, right))
233    }
234
235    fn connect_stream(
236        &self,
237        socket: &SocketHandle,
238        current_task: &CurrentTask,
239        peer: &SocketHandle,
240    ) -> Result<(), Errno> {
241        // Only hold one lock at a time until we make sure the lock ordering
242        // is right: client before listener
243        match downcast_socket_to_unix(peer).lock().state {
244            UnixSocketState::Listening(_) => {}
245            _ => return error!(ECONNREFUSED),
246        }
247
248        let mut client = downcast_socket_to_unix(socket).lock();
249        match client.state {
250            UnixSocketState::Disconnected => {}
251            UnixSocketState::Connected(_) => return error!(EISCONN),
252            _ => return error!(EINVAL),
253        };
254
255        let unix_socket_peer = downcast_socket_to_unix(peer);
256        {
257            // Lock ordering is client before listener.
258            let _token = allow_subclass();
259            let mut listener = unix_socket_peer.lock();
260
261            // Must check this again because we released the listener lock for a moment
262            let queue = match &listener.state {
263                UnixSocketState::Listening(queue) => queue,
264                _ => return error!(ECONNREFUSED),
265            };
266
267            self.check_type_for_connect(socket, peer, &listener.address)?;
268
269            if queue.sockets.len() > queue.backlog {
270                return error!(EAGAIN);
271            }
272
273            let server = Socket::new(
274                current_task,
275                peer.domain,
276                peer.socket_type,
277                SocketProtocol::default(),
278                /* kernel_private = */ true,
279            )?;
280            security::unix_stream_connect(current_task, socket, peer, &server)?;
281            client.state = UnixSocketState::Connected(server.clone());
282            client.credentials = listener.credentials.clone();
283            {
284                // This allow_subclass is safe because `server` is a newly created socket
285                // that hasn't been added to any public table or returned to the user yet.
286                // It is unreachable by other threads, making lock ordering cycles impossible.
287                let _token = allow_subclass();
288                let mut server = downcast_socket_to_unix(&server).lock();
289                server.state = UnixSocketState::Connected(socket.clone());
290                server.address = listener.address.clone();
291                server.messages.set_capacity(listener.messages.capacity())?;
292                server.credentials = Some(current_task.current_ucred());
293                server.passcred = listener.passcred;
294                server.passsec = listener.passsec;
295            }
296
297            // We already checked that the socket is in Listening state...but the borrow checker cannot
298            // be convinced that it's ok to combine these checks
299            let queue = match listener.state {
300                UnixSocketState::Listening(ref mut queue) => queue,
301                _ => panic!("something changed the server socket state while I held a lock on it"),
302            };
303            queue.sockets.push_back(server);
304        }
305        unix_socket_peer.waiters.notify_fd_events(FdEvents::POLLIN);
306        Ok(())
307    }
308
309    fn connect_datagram(
310        &self,
311        socket: &SocketHandle,
312        current_task: &CurrentTask,
313        peer: &SocketHandle,
314    ) -> Result<(), Errno> {
315        {
316            let unix_socket = socket.downcast_socket::<UnixSocket>().unwrap();
317            let peer_inner = unix_socket.lock();
318            self.check_type_for_connect(socket, peer, &peer_inner.address)?;
319        }
320        security::unix_may_send(current_task, socket, peer)?;
321        let unix_socket = socket.downcast_socket::<UnixSocket>().unwrap();
322        unix_socket.lock().state = UnixSocketState::Connected(peer.clone());
323        Ok(())
324    }
325
326    pub fn check_type_for_connect(
327        &self,
328        socket: &Socket,
329        peer: &Socket,
330        peer_address: &Option<SocketAddress>,
331    ) -> Result<(), Errno> {
332        if socket.domain != peer.domain || socket.socket_type != peer.socket_type {
333            // According to ConnectWithWrongType in accept_bind_test, abstract
334            // UNIX domain sockets return ECONNREFUSED rather than EPROTOTYPE.
335            if let Some(address) = peer_address {
336                if address.is_abstract_unix() {
337                    return error!(ECONNREFUSED);
338                }
339            }
340            return error!(EPROTOTYPE);
341        }
342        Ok(())
343    }
344
345    /// Locks and returns the inner state of the Socket.
346    fn lock(&self) -> LockDepGuard<'_, UnixSocketInner> {
347        self.inner.lock()
348    }
349
350    fn is_listening(&self, _socket: &Socket) -> bool {
351        matches!(self.lock().state, UnixSocketState::Listening(_))
352    }
353
354    fn get_receive_capacity(&self) -> usize {
355        self.lock().messages.capacity()
356    }
357
358    fn set_receive_capacity(&self, requested_capacity: usize) {
359        self.lock().set_capacity(requested_capacity);
360    }
361
362    fn get_send_capacity(&self) -> usize {
363        let peer = {
364            if let Some(peer) = self.lock().peer() {
365                peer.clone()
366            } else {
367                return 0;
368            }
369        };
370        let unix_socket = downcast_socket_to_unix(&peer);
371        let capacity = unix_socket.lock().messages.capacity();
372        capacity
373    }
374
375    fn set_send_capacity(&self, requested_capacity: usize) {
376        let peer = {
377            if let Some(peer) = self.lock().peer() {
378                peer.clone()
379            } else {
380                return;
381            }
382        };
383        let unix_socket = downcast_socket_to_unix(&peer);
384        unix_socket.lock().set_capacity(requested_capacity);
385    }
386
387    fn get_linger(&self) -> uapi::linger {
388        let inner = self.lock();
389        inner.linger
390    }
391
392    fn set_linger(&self, linger: uapi::linger) {
393        let mut inner = self.lock();
394        inner.linger = linger;
395    }
396
397    fn get_passcred(&self) -> PasscredMode {
398        let inner = self.lock();
399        inner.passcred
400    }
401
402    fn set_passcred(&self, passcred: PasscredMode) {
403        let mut inner = self.lock();
404        inner.passcred = passcred;
405    }
406
407    fn get_passsec(&self) -> bool {
408        let inner = self.lock();
409        inner.passsec
410    }
411
412    fn set_passsec(&self, passsec: bool) {
413        let mut inner = self.lock();
414        inner.passsec = passsec;
415    }
416
417    fn get_broadcast(&self) -> bool {
418        let inner = self.lock();
419        inner.broadcast
420    }
421
422    fn set_broadcast(&self, broadcast: bool) {
423        let mut inner = self.lock();
424        inner.broadcast = broadcast;
425    }
426
427    fn get_no_check(&self) -> bool {
428        let inner = self.lock();
429        inner.no_check
430    }
431
432    fn set_no_check(&self, no_check: bool) {
433        let mut inner = self.lock();
434        inner.no_check = no_check;
435    }
436
437    fn get_reuseaddr(&self) -> bool {
438        let inner = self.lock();
439        inner.reuseaddr
440    }
441
442    fn set_reuseaddr(&self, reuseaddr: bool) {
443        let mut inner = self.lock();
444        inner.reuseaddr = reuseaddr;
445    }
446
447    fn get_reuseport(&self) -> bool {
448        let inner = self.lock();
449        inner.reuseport
450    }
451
452    fn set_reuseport(&self, reuseport: bool) {
453        let mut inner = self.lock();
454        inner.reuseport = reuseport;
455    }
456
457    fn get_keepalive(&self) -> bool {
458        let inner = self.lock();
459        inner.keepalive
460    }
461
462    fn set_keepalive(&self, keepalive: bool) {
463        let mut inner = self.lock();
464        inner.keepalive = keepalive;
465    }
466
467    fn set_bpf_program(&self, program: Option<UnixSocketFilter>) {
468        let mut inner = self.lock();
469        inner.bpf_program = program;
470    }
471
472    fn peer_cred(&self) -> Option<ucred> {
473        self.lock().credentials.clone()
474    }
475
476    pub fn bind_socket_to_node(
477        &self,
478        socket: &SocketHandle,
479        address: SocketAddress,
480        node: &FsNodeHandle,
481    ) -> Result<(), Errno> {
482        let unix_socket = downcast_socket_to_unix(socket);
483        let mut inner = unix_socket.lock();
484        inner.bind(address)?;
485        inner.fs_node = Some(node.clone());
486        node.set_bound_socket(socket.clone());
487        Ok(())
488    }
489
490    fn notify_shutdown(&self) {
491        self.waiters.notify_fd_events(FdEvents::POLLIN | FdEvents::POLLOUT | FdEvents::POLLHUP);
492    }
493}
494
495impl SocketOps for UnixSocket {
496    fn connect(
497        &self,
498        socket: &SocketHandle,
499        current_task: &CurrentTask,
500        peer: SocketPeer,
501    ) -> Result<(), Errno> {
502        let peer = match peer {
503            SocketPeer::Handle(handle) => handle,
504            SocketPeer::Address(SocketAddress::Unspecified) => {
505                if socket.socket_type == SocketType::Datagram {
506                    let unix_socket = socket.downcast_socket::<UnixSocket>().unwrap();
507                    unix_socket.lock().state = UnixSocketState::Disconnected;
508                    return Ok(());
509                }
510                return error!(EINVAL);
511            }
512            SocketPeer::Address(_) => return error!(EINVAL),
513        };
514        match socket.socket_type {
515            SocketType::Stream | SocketType::SeqPacket => {
516                self.connect_stream(socket, current_task, &peer)
517            }
518            SocketType::Datagram | SocketType::Raw => {
519                self.connect_datagram(socket, current_task, &peer)
520            }
521            _ => error!(EINVAL),
522        }
523    }
524
525    fn listen(&self, socket: &Socket, backlog: i32, credentials: ucred) -> Result<(), Errno> {
526        match socket.socket_type {
527            SocketType::Stream | SocketType::SeqPacket => {}
528            _ => return error!(EOPNOTSUPP),
529        }
530        let mut inner = self.lock();
531        let is_bound = inner.address.is_some();
532        let backlog = if backlog < 0 { DEFAULT_LISTEN_BACKLOG } else { backlog as usize };
533        match &mut inner.state {
534            UnixSocketState::Disconnected if is_bound => {
535                inner.state = UnixSocketState::Listening(AcceptQueue::new(backlog));
536            }
537            UnixSocketState::Listening(queue) => {
538                queue.set_backlog(backlog)?;
539            }
540            _ => return error!(EINVAL),
541        }
542        inner.credentials = Some(credentials);
543        Ok(())
544    }
545
546    fn accept(&self, socket: &Socket, _current_task: &CurrentTask) -> Result<SocketHandle, Errno> {
547        match socket.socket_type {
548            SocketType::Stream | SocketType::SeqPacket => {}
549            _ => return error!(EOPNOTSUPP),
550        }
551        let mut inner = self.lock();
552        let queue = match &mut inner.state {
553            UnixSocketState::Listening(queue) => queue,
554            _ => return error!(EINVAL),
555        };
556        queue.sockets.pop_front().ok_or_else(|| errno!(EAGAIN))
557    }
558
559    fn bind(
560        &self,
561        _socket: &Socket,
562        _current_task: &CurrentTask,
563        socket_address: SocketAddress,
564    ) -> Result<(), Errno> {
565        match socket_address {
566            SocketAddress::Unix(_) => {}
567            _ => return error!(EINVAL),
568        }
569        self.lock().bind(socket_address)
570    }
571
572    fn read(
573        &self,
574        socket: &Socket,
575        current_task: &CurrentTask,
576        data: &mut dyn OutputBuffer,
577        flags: SocketMessageFlags,
578    ) -> Result<MessageReadInfo, Errno> {
579        let mut info = MessageReadInfo::default();
580        self.read_and_append(socket, current_task, &mut info, data, flags)?;
581        Ok(info)
582    }
583
584    fn read_and_append(
585        &self,
586        socket: &Socket,
587        _current_task: &CurrentTask,
588        read_info: &mut MessageReadInfo,
589        data: &mut dyn OutputBuffer,
590        flags: SocketMessageFlags,
591    ) -> Result<bool, Errno> {
592        let bytes_read_before = read_info.bytes_read;
593        let (can_coalesce, peer) = {
594            let mut inner = self.lock();
595            let can_coalesce = inner.read_and_append(read_info, data, socket.socket_type, flags)?;
596            let peer =
597                (read_info.bytes_read > bytes_read_before).then(|| inner.peer().cloned()).flatten();
598            (can_coalesce, peer)
599        };
600        if let Some(socket) = peer {
601            if let Some(socket) = socket.downcast_socket::<UnixSocket>() {
602                socket.waiters.notify_fd_events(FdEvents::POLLOUT);
603            }
604        }
605        Ok(can_coalesce)
606    }
607
608    fn write(
609        &self,
610        socket: &Socket,
611        current_task: &CurrentTask,
612        data: &mut dyn InputBuffer,
613        dest_address: &mut Option<SocketAddress>,
614        ancillary_data: &mut Vec<AncillaryData>,
615    ) -> Result<usize, Errno> {
616        let (connected_peer, local_address, local_passcred, is_write_shutdown) = {
617            let inner = self.lock();
618            (
619                inner.peer().map(|p| p.clone()),
620                inner.address.clone(),
621                inner.passcred,
622                inner.is_write_shutdown,
623            )
624        };
625
626        if is_write_shutdown {
627            return error!(EPIPE);
628        }
629
630        let peer = match (connected_peer, dest_address, socket.socket_type) {
631            (Some(peer), None, _) => peer,
632            (Some(peer), Some(_), SocketType::SeqPacket) => peer,
633            (None, Some(_), SocketType::Stream) => return error!(EOPNOTSUPP),
634            (None, Some(_), SocketType::SeqPacket) => return error!(ENOTCONN),
635            (Some(_), Some(_), SocketType::Stream) => return error!(EISCONN),
636            (_, Some(SocketAddress::Unix(name)), _) => {
637                if name.is_empty() {
638                    return error!(EINVAL);
639                }
640                resolve_unix_socket_address(current_task, name.as_ref())?
641            }
642            (_, Some(_), _) => return error!(EINVAL),
643            (None, None, _) => return error!(ENOTCONN),
644        };
645
646        let dgram_security_context = if socket.socket_type == SocketType::Datagram {
647            security::unix_may_send(current_task, socket, &peer)?;
648            // TODO: https://fxbug.dev/364568855 - Store the opaque LSM property value, and expand
649            // it to a string upon readmsg.
650            Some(security::socket_getpeersec_dgram(current_task, socket))
651        } else {
652            None
653        };
654
655        let peer_unaccepted = peer.fs_node().is_none();
656        let unix_socket = downcast_socket_to_unix(&peer);
657        let write_result = {
658            let mut peer = unix_socket.lock();
659            let default_creds =
660                (local_passcred.is_enabled() || peer.passcred.is_enabled() || peer_unaccepted)
661                    .then(|| current_task.current_ucred());
662            peer.write(
663                current_task,
664                data,
665                local_address,
666                default_creds,
667                dgram_security_context,
668                ancillary_data,
669                socket,
670            )
671        };
672
673        if let Err(ref err) = write_result {
674            if err.code == ECONNREFUSED && socket.socket_type == SocketType::Datagram {
675                let mut inner = self.lock();
676                if let UnixSocketState::Connected(ref connected_peer) = inner.state {
677                    if Arc::ptr_eq(connected_peer, &peer) {
678                        inner.state = UnixSocketState::Disconnected;
679                        self.waiters.notify_fd_events(FdEvents::POLLOUT | FdEvents::POLLHUP);
680                    }
681                }
682            }
683        }
684
685        let bytes_written = write_result?;
686        if bytes_written > 0 {
687            unix_socket.waiters.notify_fd_events(FdEvents::POLLIN);
688        }
689        Ok(bytes_written)
690    }
691
692    fn wait_async(
693        &self,
694        _socket: &Socket,
695        _current_task: &CurrentTask,
696        waiter: &Waiter,
697        events: FdEvents,
698        handler: EventHandler,
699    ) -> WaitCanceler {
700        self.waiters.wait_async_fd_events(waiter, events, handler)
701    }
702
703    fn query_events(
704        &self,
705        socket: &Socket,
706        _current_task: &CurrentTask,
707    ) -> Result<FdEvents, Errno> {
708        // Note that self.lock() must be dropped before acquiring peer.inner.lock() to avoid
709        // potential deadlocks.
710        let (
711            mut events,
712            peer,
713            local_is_read_shutdown,
714            local_is_write_shutdown,
715            is_closed,
716            is_disconnected,
717        ) = {
718            let inner = self.lock();
719
720            let mut events = FdEvents::empty();
721            let local_events = inner.messages.query_events();
722            if local_events.contains(FdEvents::POLLIN) {
723                events |= FdEvents::POLLIN;
724            }
725
726            // Listening socket gets POLLIN when there are pending connections.
727            if let UnixSocketState::Listening(queue) = &inner.state {
728                if !queue.sockets.is_empty() {
729                    events |= FdEvents::POLLIN;
730                }
731            }
732
733            (
734                events,
735                inner.peer().cloned(),
736                inner.is_read_shutdown,
737                inner.is_write_shutdown,
738                matches!(inner.state, UnixSocketState::Closed),
739                matches!(inner.state, UnixSocketState::Disconnected),
740            )
741        };
742
743        let connection_oriented = socket.socket_type.is_connection_oriented();
744
745        let mut read_dead = local_is_read_shutdown || is_closed;
746        let mut write_dead = local_is_write_shutdown || is_closed;
747        let mut force_pollout = is_closed || is_disconnected;
748        let mut force_pollhup = false;
749
750        if connection_oriented && is_disconnected {
751            force_pollhup = true;
752            write_dead = true;
753        }
754
755        if let Some(peer) = peer {
756            let unix_socket = downcast_socket_to_unix(&peer);
757            let peer_inner = unix_socket.lock();
758
759            if peer_inner.is_read_shutdown {
760                write_dead = true;
761            }
762            if matches!(peer_inner.state, UnixSocketState::Closed) {
763                read_dead = true;
764                write_dead = true;
765                force_pollout = true;
766            }
767
768            let peer_events = peer_inner.messages.query_events();
769            if peer_events.contains(FdEvents::POLLOUT) {
770                events |= FdEvents::POLLOUT;
771            }
772        }
773
774        if force_pollout {
775            events |= FdEvents::POLLOUT;
776        }
777
778        if read_dead {
779            events |= FdEvents::POLLIN | FdEvents::POLLRDHUP;
780        }
781        if (read_dead && write_dead) || force_pollhup {
782            events |= FdEvents::POLLHUP;
783        }
784
785        Ok(events)
786    }
787
788    /// Shuts down reception and/or transmission on this socket according to `how`
789    /// ([`SocketShutdownFlags`]), notifying waiters with the resulting [`FdEvents`].
790    ///
791    /// Used by the `shutdown(2)` syscall.
792    fn shutdown(&self, socket: &Socket, how: SocketShutdownFlags) -> Result<(), Errno> {
793        // Acquire and release `self.lock()` before locking `peer` below to avoid ABBA deadlocks
794        // when both endpoints call `shutdown(2)` concurrently.
795        let (peer, self_notify_events) = {
796            let mut inner = self.lock();
797            let events = inner.shutdown(how);
798            (inner.peer().cloned(), events)
799        };
800        let mut peer_notify_events = FdEvents::empty();
801        if let Some(peer) = &peer {
802            if socket.socket_type.is_connection_oriented() {
803                // For a connected `AF_UNIX` pair `(self, peer)`, the two unidirectional
804                // channels are:
805                //   - `self -> peer`: controlled by `(self.is_write_shutdown, peer.is_read_shutdown)`
806                //   - `peer -> self`: controlled by `(peer.is_write_shutdown, self.is_read_shutdown)`
807                //
808                // Transposing `READ` <-> `WRITE` on `peer` ensures that `SHUT_WR` on `self` shuts
809                // down reads on `peer` (`peer_inner.is_read_shutdown`) and `SHUT_RD` on `self`
810                // shuts down writes on `peer` (`peer_inner.is_write_shutdown`).
811                let mut peer_how = SocketShutdownFlags::empty();
812                if how.contains(SocketShutdownFlags::WRITE) {
813                    peer_how |= SocketShutdownFlags::READ;
814                }
815                if how.contains(SocketShutdownFlags::READ) {
816                    peer_how |= SocketShutdownFlags::WRITE;
817                }
818                let peer_socket = downcast_socket_to_unix(peer);
819                peer_notify_events = peer_socket.lock().shutdown(peer_how);
820            }
821        }
822        if !self_notify_events.is_empty() {
823            self.waiters.notify_fd_events(self_notify_events);
824        }
825        if !peer_notify_events.is_empty() {
826            if let Some(peer) = &peer {
827                let peer_socket = downcast_socket_to_unix(peer);
828                peer_socket.waiters.notify_fd_events(peer_notify_events);
829            }
830        }
831        Ok(())
832    }
833
834    /// Close this socket.
835    ///
836    /// Called by SocketFile when the file descriptor that is holding this
837    /// socket is closed.
838    ///
839    /// Close differs from shutdown in two ways. First, close will call
840    /// mark_peer_closed_with_unread_data if this socket has unread data,
841    /// which changes how read() behaves on that socket. Second, close
842    /// transitions the internal state of this socket to Closed and releases
843    /// any bound filesystem node, which breaks the reference cycles that exist
844    /// in the connected and bound states.
845    fn close(&self, _current_task: &CurrentTask, socket: &Socket) {
846        // Keep `_maybe_fs_node` in the tuple so that it is dropped outside of `self.lock()`.
847        let (maybe_peer, has_unread, _maybe_fs_node) = {
848            let mut inner = self.lock();
849            let maybe_peer = inner.peer().map(Arc::clone);
850            inner.is_read_shutdown = true;
851            inner.state = UnixSocketState::Closed;
852            (maybe_peer, !inner.messages.is_empty(), inner.fs_node.take())
853        };
854        self.notify_shutdown();
855        // If this is a connected socket type, also shut down the connected peer.
856        if socket.socket_type.is_connection_oriented() {
857            if let Some(peer) = maybe_peer {
858                let unix_socket = downcast_socket_to_unix(&peer);
859
860                {
861                    let mut peer_inner = unix_socket.lock();
862                    if has_unread {
863                        peer_inner.peer_closed_with_unread_data = true;
864                    }
865                    peer_inner.is_read_shutdown = true;
866                }
867                unix_socket.notify_shutdown();
868            }
869        }
870    }
871
872    /// Returns the name of this socket.
873    ///
874    /// The name is derived from the address and domain. A socket
875    /// will always have a name, even if it is not bound to an address.
876    fn getsockname(&self, socket: &Socket) -> Result<SocketAddress, Errno> {
877        let inner = self.lock();
878        if let Some(address) = &inner.address {
879            Ok(address.clone())
880        } else {
881            Ok(SocketAddress::default_for_domain(socket.domain))
882        }
883    }
884
885    /// Returns the name of the peer of this socket, if such a peer exists.
886    ///
887    /// Returns an error if the socket is not connected.
888    fn getpeername(&self, _socket: &Socket) -> Result<SocketAddress, Errno> {
889        let peer = self.lock().peer().ok_or_else(|| errno!(ENOTCONN))?.clone();
890        peer.getsockname()
891    }
892
893    fn setsockopt(
894        &self,
895        _socket: &Socket,
896        current_task: &CurrentTask,
897        level: u32,
898        optname: u32,
899        optval: SockOptValue,
900    ) -> Result<(), Errno> {
901        match level {
902            SOL_SOCKET => match optname {
903                SO_SNDBUF => {
904                    let requested_capacity: socklen_t = optval.read(current_task)?;
905                    // See StreamUnixSocketPairTest.SetSocketSendBuf for why we multiply by 2 here.
906                    self.set_send_capacity(requested_capacity as usize * 2);
907                }
908                SO_RCVBUF => {
909                    let requested_capacity: socklen_t = optval.read(current_task)?;
910                    self.set_receive_capacity(requested_capacity as usize);
911                }
912                SO_LINGER => {
913                    let mut linger: uapi::linger = optval.read(current_task)?;
914                    if linger.l_onoff != 0 {
915                        linger.l_onoff = 1;
916                    }
917                    self.set_linger(linger);
918                }
919                SO_PASSCRED => {
920                    let passcred: u32 = optval.read(current_task)?;
921                    self.set_passcred(PasscredMode::from(passcred != 0));
922                }
923                SO_PASSSEC => {
924                    let passsec: u32 = optval.read(current_task)?;
925                    self.set_passsec(passsec != 0);
926                }
927                SO_BROADCAST => {
928                    let broadcast: u32 = optval.read(current_task)?;
929                    self.set_broadcast(broadcast != 0);
930                }
931                SO_NO_CHECK => {
932                    let no_check: u32 = optval.read(current_task)?;
933                    self.set_no_check(no_check != 0);
934                }
935                SO_REUSEADDR => {
936                    let reuseaddr: u32 = optval.read(current_task)?;
937                    self.set_reuseaddr(reuseaddr != 0);
938                }
939                SO_REUSEPORT => {
940                    let reuseport: u32 = optval.read(current_task)?;
941                    self.set_reuseport(reuseport != 0);
942                }
943                SO_KEEPALIVE => {
944                    let keepalive: u32 = optval.read(current_task)?;
945                    self.set_keepalive(keepalive != 0);
946                }
947                SO_ATTACH_BPF => {
948                    let fd: FdNumber = optval.read(current_task)?;
949                    let object = get_bpf_object(current_task, fd)?;
950                    let program = object.as_program()?;
951
952                    let linked_program = program.link(ProgramType::SocketFilter)?;
953
954                    self.set_bpf_program(Some(linked_program));
955                }
956                _ => return error!(ENOPROTOOPT),
957            },
958            _ => return error!(ENOPROTOOPT),
959        }
960        Ok(())
961    }
962
963    fn getsockopt(
964        &self,
965        socket: &Socket,
966        current_task: &CurrentTask,
967        level: u32,
968        optname: u32,
969        _optlen: u32,
970    ) -> Result<Vec<u8>, Errno> {
971        match level {
972            SOL_SOCKET => match optname {
973                SO_PEERCRED => Ok(UcredPtr::into_bytes(
974                    current_task,
975                    self.peer_cred().unwrap_or(ucred { pid: 0, uid: uid_t::MAX, gid: gid_t::MAX }),
976                )
977                .map_err(|_| errno!(EINVAL))?),
978                SO_PEERSEC => match socket.socket_type {
979                    SocketType::Stream => security::socket_getpeersec_stream(current_task, socket),
980                    _ => error!(ENOPROTOOPT),
981                },
982                SO_ACCEPTCONN =>
983                {
984                    #[allow(clippy::bool_to_int_with_if)]
985                    Ok(if self.is_listening(socket) { 1u32 } else { 0u32 }.to_ne_bytes().to_vec())
986                }
987                SO_SNDBUF => Ok((self.get_send_capacity() as socklen_t).to_ne_bytes().to_vec()),
988                SO_RCVBUF => Ok((self.get_receive_capacity() as socklen_t).to_ne_bytes().to_vec()),
989                SO_LINGER => Ok(self.get_linger().as_bytes().to_vec()),
990                SO_PASSCRED => Ok((self.get_passcred().is_enabled() as u32).as_bytes().to_vec()),
991                SO_PASSSEC => Ok((self.get_passsec() as u32).as_bytes().to_vec()),
992                SO_BROADCAST => Ok((self.get_broadcast() as u32).as_bytes().to_vec()),
993                SO_NO_CHECK => Ok((self.get_no_check() as u32).as_bytes().to_vec()),
994                SO_REUSEADDR => Ok((self.get_reuseaddr() as u32).as_bytes().to_vec()),
995                SO_REUSEPORT => Ok((self.get_reuseport() as u32).as_bytes().to_vec()),
996                SO_KEEPALIVE => Ok((self.get_keepalive() as u32).as_bytes().to_vec()),
997                SO_ERROR => Ok((0u32).as_bytes().to_vec()),
998                _ => error!(ENOPROTOOPT),
999            },
1000            _ => error!(ENOPROTOOPT),
1001        }
1002    }
1003
1004    fn ioctl(
1005        &self,
1006        socket: &Socket,
1007        _file: &FileObject,
1008        current_task: &CurrentTask,
1009        request: u32,
1010        arg: SyscallArg,
1011    ) -> Result<SyscallResult, Errno> {
1012        let user_addr = UserAddress::from(arg);
1013        match request {
1014            FIONREAD if socket.socket_type == SocketType::Stream => {
1015                let length: i32 =
1016                    self.lock().messages.len().try_into().map_err(|_| errno!(EINVAL))?;
1017                current_task.write_object(UserRef::<i32>::new(user_addr), &length)?;
1018                Ok(SUCCESS)
1019            }
1020            _ => error!(ENOTTY),
1021        }
1022    }
1023}
1024
1025impl UnixSocketInner {
1026    fn bind(&mut self, socket_address: SocketAddress) -> Result<(), Errno> {
1027        if self.address.is_some() {
1028            return error!(EINVAL);
1029        }
1030        self.address = Some(socket_address);
1031        Ok(())
1032    }
1033
1034    /// Shuts down the local endpoint directions specified by `how` ([`SocketShutdownFlags`])
1035    /// and returns the [`FdEvents`] to notify on this endpoint's wait queue.
1036    ///
1037    /// Per `shutdown(2)`:
1038    /// > "The `shutdown()` call causes all or part of a full-duplex connection on
1039    /// > the socket associated with `sockfd` to be shut down. If `how` is `SHUT_RD`,
1040    /// > further receptions will be disallowed. If `how` is `SHUT_WR`, further
1041    /// > transmissions will be disallowed. If `how` is `SHUT_RDWR`, further
1042    /// > receptions and transmissions will be disallowed."
1043    ///
1044    /// Per `poll(2)`:
1045    /// > "`POLLHUP`: Hang up (only returned in `revents`; ignored in `events`).
1046    /// > Note that when reading from a channel such as a pipe or a stream socket,
1047    /// > this event merely indicates that the peer closed its end of the channel."
1048    /// > "`POLLRDHUP` (since Linux 2.6.17): Stream socket peer closed connection,
1049    /// > or shut down writing half of connection."
1050    fn shutdown(&mut self, how: SocketShutdownFlags) -> FdEvents {
1051        let mut notify_events = FdEvents::empty();
1052        if how.contains(SocketShutdownFlags::READ) {
1053            self.is_read_shutdown = true;
1054            notify_events |= FdEvents::POLLIN | FdEvents::POLLRDHUP;
1055        }
1056        if how.contains(SocketShutdownFlags::WRITE) {
1057            self.is_write_shutdown = true;
1058            notify_events |= FdEvents::POLLOUT;
1059        }
1060        if self.is_read_shutdown && self.is_write_shutdown {
1061            notify_events |= FdEvents::POLLHUP;
1062        }
1063        notify_events
1064    }
1065
1066    fn set_capacity(&mut self, requested_capacity: usize) {
1067        let capacity = requested_capacity.clamp(SOCKET_MIN_SIZE, SOCKET_MAX_SIZE);
1068        let capacity = std::cmp::max(capacity, self.messages.len());
1069        // We have validated capacity sufficiently that set_capacity should always succeed.
1070        self.messages.set_capacity(capacity).unwrap();
1071    }
1072
1073    /// Returns the socket that is connected to this socket, if such a peer exists. Returns
1074    /// ENOTCONN otherwise.
1075    fn peer(&self) -> Option<&SocketHandle> {
1076        match &self.state {
1077            UnixSocketState::Connected(peer) => Some(peer),
1078            _ => None,
1079        }
1080    }
1081
1082    /// Reads the the contents of this socket into `InputBuffer`.
1083    ///
1084    /// Will stop reading if a message with ancillary data is encountered (after the message with
1085    /// ancillary data has been read).
1086    ///
1087    /// # Parameters
1088    /// - `data`: The `OutputBuffer` to write the data to.
1089    ///
1090    /// Returns the number of bytes that were read into the buffer, and any ancillary data that was
1091    /// read from the socket.
1092    fn read(
1093        &mut self,
1094        data: &mut dyn OutputBuffer,
1095        socket_type: SocketType,
1096        flags: SocketMessageFlags,
1097    ) -> Result<MessageReadInfo, Errno> {
1098        let (mut info, has_message) = if socket_type == SocketType::Stream {
1099            if flags.contains(SocketMessageFlags::PEEK) {
1100                self.messages.peek_stream(data, self.passcred)?
1101            } else {
1102                self.messages.read_stream_with_passcred(data, self.passcred)?
1103            }
1104        } else if flags.contains(SocketMessageFlags::PEEK) {
1105            self.messages.peek_datagram(data)?
1106        } else {
1107            self.messages.read_datagram(data)?
1108        };
1109        if !has_message {
1110            if self.peer_closed_with_unread_data {
1111                // Reset the flag
1112                self.peer_closed_with_unread_data = false;
1113                return error!(ECONNRESET);
1114            }
1115            if !self.is_read_shutdown {
1116                return error!(EAGAIN);
1117            }
1118        }
1119
1120        if self.passcred.is_enabled() {
1121            let creds = info.credentials.unwrap_or_else(UnixControlData::unknown_ucred);
1122            info.credentials = Some(creds);
1123            // Allow credentials to take priority if they are enabled, so insert at 0.
1124            info.ancillary_data.insert(0, AncillaryData::Unix(UnixControlData::Credentials(creds)));
1125        } else {
1126            info.credentials = None;
1127        }
1128
1129        // Security labels are only delivered if passsec is currently enabled on this socket.
1130        if !self.passsec {
1131            info.ancillary_data
1132                .retain(|m| !matches!(m, AncillaryData::Unix(UnixControlData::Security(..))));
1133        }
1134
1135        Ok(info)
1136    }
1137
1138    fn read_and_append(
1139        &mut self,
1140        read_info: &mut MessageReadInfo,
1141        data: &mut dyn OutputBuffer,
1142        socket_type: SocketType,
1143        flags: SocketMessageFlags,
1144    ) -> Result<bool, Errno> {
1145        if socket_type == SocketType::Stream
1146            && !self.messages.can_coalesce_with(read_info, self.passcred)
1147        {
1148            return Ok(false);
1149        }
1150        let mut info = self.read(data, socket_type, flags)?;
1151        let bytes_read = info.bytes_read;
1152        read_info.append(&mut info);
1153        if socket_type != SocketType::Stream || bytes_read == 0 {
1154            return Ok(false);
1155        }
1156        Ok(self.messages.can_coalesce_with(read_info, self.passcred))
1157    }
1158
1159    /// Writes the the contents of `InputBuffer` into this socket.
1160    ///
1161    /// # Parameters
1162    /// - `data`: The `InputBuffer` to read the data from.
1163    /// - `ancillary_data`: Any ancillary data to write to the socket. Note that the ancillary data
1164    ///                     will only be written if the entirety of the requested write completes.
1165    ///
1166    /// Returns the number of bytes that were written to the socket.
1167    fn write(
1168        &mut self,
1169        current_task: &CurrentTask,
1170        data: &mut dyn InputBuffer,
1171        address: Option<SocketAddress>,
1172        default_credentials: Option<ucred>,
1173        dgram_security_context: Option<Vec<u8>>,
1174        ancillary_data: &mut Vec<AncillaryData>,
1175        socket: &Socket,
1176    ) -> Result<usize, Errno> {
1177        if matches!(self.state, UnixSocketState::Closed) {
1178            if !socket.socket_type.is_connection_oriented() {
1179                return error!(ECONNREFUSED);
1180            } else {
1181                return error!(EPIPE);
1182            }
1183        }
1184        if self.is_read_shutdown {
1185            return error!(EPIPE);
1186        }
1187        let filter = |mut message: Message| {
1188            if let Some(context) = dgram_security_context {
1189                message
1190                    .ancillary_data
1191                    .push(AncillaryData::Unix(UnixControlData::Security(context.into())));
1192            }
1193            let Some(bpf_program) = self.bpf_program.as_ref() else {
1194                return Some(message);
1195            };
1196
1197            // TODO(https://fxbug.dev/385015056): Fill in SkBuf.
1198            let mut sk_buf = SkBuf::default();
1199
1200            let mut context = EbpfRunContextImpl::<'_>::new(current_task);
1201            let s = bpf_program.run(&mut context, &mut sk_buf);
1202            if s == 0 {
1203                None
1204            } else {
1205                message.truncate(s as usize);
1206                Some(message)
1207            }
1208        };
1209        let bytes_written = if socket.socket_type == SocketType::Stream {
1210            self.messages.write_stream_with_filter(
1211                data,
1212                address,
1213                default_credentials,
1214                ancillary_data,
1215                filter,
1216            )?
1217        } else {
1218            self.messages.write_datagram_with_filter(
1219                data,
1220                address,
1221                default_credentials,
1222                ancillary_data,
1223                filter,
1224            )?
1225        };
1226        Ok(bytes_written)
1227    }
1228}
1229
1230pub fn resolve_unix_socket_address(
1231    current_task: &CurrentTask,
1232    name: &FsStr,
1233) -> Result<SocketHandle, Errno> {
1234    if name[0] == b'\0' {
1235        current_task.running_state().abstract_socket_namespace.lookup(name)
1236    } else {
1237        let mut context = LookupContext::default();
1238        let (parent, basename) =
1239            current_task.lookup_parent_at(&mut context, FdNumber::AT_FDCWD, name)?;
1240        let name = parent.lookup_child(current_task, &mut context, basename).map_err(|errno| {
1241            if matches!(errno.code, EACCES | EPERM | EINTR) { errno } else { errno!(ECONNREFUSED) }
1242        })?;
1243        name.check_access(current_task, AccessCheck::for_internal(Access::WRITE))?;
1244        name.entry.node.bound_socket().map(|s| s.clone()).ok_or_else(|| errno!(ECONNREFUSED))
1245    }
1246}
1247
1248// Packet buffer representation used for eBPF filters.
1249#[repr(C)]
1250#[derive(Default)]
1251struct SkBuf {
1252    sk_buff: __sk_buff,
1253}
1254
1255impl Packet for &mut SkBuf {
1256    fn load(&self, _offset: i32, _width: DataWidth) -> Option<BpfValue> {
1257        // TODO(https://fxbug.dev/385015056): Implement packet access.
1258        None
1259    }
1260}
1261
1262impl<'a> PacketWithLoadBytes for &'a mut SkBuf {
1263    fn load_bytes_relative(
1264        &self,
1265        _base: LoadBytesBase,
1266        _offset: usize,
1267        _buf: ebpf::EbpfBufferPtr<'_>,
1268    ) -> i64 {
1269        track_stub!(TODO("https://fxbug.dev/385015056"), "bpf_load_bytes_relative");
1270        -1
1271    }
1272}
1273
1274impl ProgramArgument for &'_ mut SkBuf {
1275    fn get_type() -> &'static Type {
1276        &*SOCKET_FILTER_SK_BUF_TYPE
1277    }
1278}
1279
1280impl SocketRef for &'_ mut SkBuf {
1281    fn get_socket_cookie(&self) -> Option<u64> {
1282        track_stub!(TODO("https://fxbug.dev/385015056"), "bpf_get_socket_cookie");
1283        None
1284    }
1285
1286    fn get_socket_uid(&self) -> Option<uid_t> {
1287        track_stub!(TODO("https://fxbug.dev/385015056"), "bpf_get_socket_uid");
1288        None
1289    }
1290}
1291
1292struct UnixSocketEbpfContext {}
1293impl BpfProgramContext for UnixSocketEbpfContext {
1294    type RunContext<'a> = EbpfRunContextImpl<'a>;
1295    type Packet<'a> = &'a mut SkBuf;
1296    type Map = PinnedMap;
1297    const CBPF_CONFIG: &'static CbpfConfig = &SOCKET_FILTER_CBPF_CONFIG;
1298}
1299
1300ebpf_api::ebpf_program_context_type!(UnixSocketEbpfContext, SocketFilterProgramContext);
1301
1302type UnixSocketFilter = EbpfProgram<UnixSocketEbpfContext>;
1303
1304#[cfg(test)]
1305mod tests {
1306    use super::*;
1307    use crate::mm::MemoryAccessor;
1308    use crate::testing::{map_memory, spawn_kernel_and_run};
1309    use crate::vfs::{DirectoryMode, UnlinkKind};
1310    use starnix_types::user_buffer::UserBuffer;
1311    use starnix_uapi::file_mode::mode;
1312
1313    #[::fuchsia::test]
1314    async fn test_socket_send_capacity() {
1315        spawn_kernel_and_run(async |current_task| {
1316            let _kernel = current_task.kernel();
1317            let socket = Socket::new(
1318                &current_task,
1319                SocketDomain::Unix,
1320                SocketType::Stream,
1321                SocketProtocol::default(),
1322                /* kernel_private = */ false,
1323            )
1324            .expect("Failed to create socket.");
1325            socket
1326                .bind(&current_task, SocketAddress::Unix(b"\0".into()))
1327                .expect("Failed to bind socket.");
1328            socket.listen(&current_task, 10).expect("Failed to listen.");
1329            let connecting_socket = Socket::new(
1330                &current_task,
1331                SocketDomain::Unix,
1332                SocketType::Stream,
1333                SocketProtocol::default(),
1334                /* kernel_private = */ false,
1335            )
1336            .expect("Failed to connect socket.");
1337            connecting_socket
1338                .ops
1339                .connect(&connecting_socket, &current_task, SocketPeer::Handle(socket.clone()))
1340                .expect("Failed to connect socket.");
1341            assert_eq!(Ok(FdEvents::POLLIN), socket.query_events(&current_task));
1342            let server_socket = socket.accept(&current_task).unwrap();
1343
1344            let opt_size = std::mem::size_of::<socklen_t>();
1345            let user_address = map_memory(&current_task, UserAddress::default(), opt_size as u64);
1346            let send_capacity: socklen_t = 4 * 4096;
1347            current_task.write_memory(user_address, &send_capacity.to_ne_bytes()).unwrap();
1348            let user_buffer = UserBuffer { address: user_address, length: opt_size };
1349            server_socket
1350                .setsockopt(&current_task, SOL_SOCKET, SO_SNDBUF, user_buffer.into())
1351                .unwrap();
1352
1353            let opt_bytes =
1354                server_socket.getsockopt(&current_task, SOL_SOCKET, SO_SNDBUF, 0).unwrap();
1355            let retrieved_capacity = socklen_t::from_ne_bytes(opt_bytes.try_into().unwrap());
1356            // Setting SO_SNDBUF actually sets it to double the size
1357            assert_eq!(2 * send_capacity, retrieved_capacity);
1358        })
1359        .await;
1360    }
1361
1362    #[::fuchsia::test]
1363    async fn test_datagram_socket_disconnect_af_unspec() {
1364        spawn_kernel_and_run(async |current_task| {
1365            let socket1 = Socket::new(
1366                &current_task,
1367                SocketDomain::Unix,
1368                SocketType::Datagram,
1369                SocketProtocol::default(),
1370                /* kernel_private = */ false,
1371            )
1372            .expect("Failed to create socket 1.");
1373            socket1
1374                .bind(&current_task, SocketAddress::Unix(b"\0sock1".into()))
1375                .expect("Failed to bind socket 1.");
1376
1377            let socket2 = Socket::new(
1378                &current_task,
1379                SocketDomain::Unix,
1380                SocketType::Datagram,
1381                SocketProtocol::default(),
1382                /* kernel_private = */ false,
1383            )
1384            .expect("Failed to create socket 2.");
1385            socket2
1386                .bind(&current_task, SocketAddress::Unix(b"\0sock2".into()))
1387                .expect("Failed to bind socket 2.");
1388
1389            // Connect socket1 to socket2.
1390            socket1
1391                .ops
1392                .connect(&socket1, &current_task, SocketPeer::Handle(socket2.clone()))
1393                .expect("Failed to connect socket1 to socket2.");
1394
1395            // Disconnect socket1 using AF_UNSPEC.
1396            socket1
1397                .ops
1398                .connect(&socket1, &current_task, SocketPeer::Address(SocketAddress::Unspecified))
1399                .expect("Failed to disconnect socket1 with AF_UNSPEC.");
1400        })
1401        .await;
1402    }
1403
1404    #[::fuchsia::test]
1405    async fn test_bind_socket_retains_fs_node_until_close() {
1406        spawn_kernel_and_run(async |current_task| {
1407            let socket = Socket::new(
1408                &current_task,
1409                SocketDomain::Unix,
1410                SocketType::Stream,
1411                SocketProtocol::default(),
1412                /* kernel_private = */ false,
1413            )
1414            .expect("Failed to create socket.");
1415
1416            let root = current_task.fs().root();
1417            let bound_node = root
1418                .bind_socket(
1419                    &current_task,
1420                    "test_sock".into(),
1421                    socket.clone(),
1422                    SocketAddress::Unix("test_sock".into()),
1423                    mode!(IFSOCK, 0o777),
1424                )
1425                .expect("Failed to bind socket to node.");
1426            let weak_fs_node = Arc::downgrade(&bound_node.entry.node);
1427            std::mem::drop(bound_node);
1428
1429            // Unlink the directory entry so that `TmpFs`'s permanent `DirEntryCache` drops its
1430            // reference to the `DirEntry` and `FsNode`, simulating `DirEntryCache::Lru` eviction on
1431            // cached filesystems (such as `RemoteFs`).
1432            root.unlink(
1433                &current_task,
1434                "test_sock".into(),
1435                UnlinkKind::NonDirectory,
1436                DirectoryMode::AllowAny,
1437            )
1438            .expect("Failed to unlink socket.");
1439            current_task.trigger_delayed_releaser();
1440
1441            // While the socket remains open, it must retain the bound `FsNode` and its
1442            // `bound_socket` association.
1443            let fs_node =
1444                weak_fs_node.upgrade().expect("FsNode should remain alive while socket is open");
1445            assert!(fs_node.bound_socket().is_some());
1446            std::mem::drop(fs_node);
1447
1448            // Closing the socket must release its reference to the `FsNode`, breaking the
1449            // `Socket` <-> `FsNode` reference cycle so both can be freed.
1450            let weak_socket = Arc::downgrade(&socket);
1451            socket.close(&current_task);
1452            std::mem::drop(socket);
1453            current_task.trigger_delayed_releaser();
1454
1455            assert!(weak_fs_node.upgrade().is_none());
1456            assert!(weak_socket.upgrade().is_none());
1457        })
1458        .await;
1459    }
1460}