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