1use 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
49const SOCKET_MIN_SIZE: usize = 4 << 10;
51const SOCKET_DEFAULT_SIZE: usize = 208 << 10;
52const SOCKET_MAX_SIZE: usize = 4 << 20;
53
54pub struct UnixSocket {
71 inner: LockDepMutex<UnixSocketInner, UnixSocketInnerLock>,
72 waiters: WaitQueue,
73}
74
75fn downcast_socket_to_unix(socket: &Socket) -> &UnixSocket {
76 socket.downcast_socket::<UnixSocket>().unwrap()
81}
82
83enum UnixSocketState {
84 Disconnected,
86
87 Listening(AcceptQueue),
89
90 Connected(SocketHandle),
92
93 Closed,
95}
96
97struct UnixSocketInner {
98 messages: MessageQueue,
100
101 address: Option<SocketAddress>,
103
104 is_shutdown: bool,
107
108 peer_closed_with_unread_data: bool,
111
112 linger: uapi::linger,
114
115 passcred: bool,
117
118 passsec: bool,
120
121 broadcast: bool,
123
124 no_check: bool,
126
127 reuseport: bool,
129
130 reuseaddr: bool,
132
133 keepalive: bool,
135
136 bpf_program: Option<UnixSocketFilter>,
138
139 credentials: Option<ucred>,
141
142 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 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 false,
195 )?;
196 let right = Socket::new(
197 locked,
198 current_task,
199 domain,
200 socket_type,
201 SocketProtocol::default(),
202 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 false,
214 )?;
215 let right = SocketFile::from_socket(
216 locked,
217 current_task,
218 right,
219 open_flags,
220 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 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 let _token = allow_subclass();
254 let mut listener = unix_socket_peer.lock();
255
256 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 self.messages.set_capacity(capacity).unwrap();
976 }
977
978 fn peer(&self) -> Option<&SocketHandle> {
981 match &self.state {
982 UnixSocketState::Connected(peer) => Some(peer),
983 _ => None,
984 }
985 }
986
987 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 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 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 creds_message = AncillaryData::Unix(UnixControlData::unknown_creds());
1041 }
1042 if self.passcred {
1043 info.ancillary_data.insert(0, creds_message);
1045 }
1046
1047 Ok(info)
1048 }
1049
1050 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 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#[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 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 ¤t_task,
1198 SocketDomain::Unix,
1199 SocketType::Stream,
1200 SocketProtocol::default(),
1201 false,
1202 )
1203 .expect("Failed to create socket.");
1204 socket
1205 .bind(locked, ¤t_task, SocketAddress::Unix(b"\0".into()))
1206 .expect("Failed to bind socket.");
1207 socket.listen(locked, ¤t_task, 10).expect("Failed to listen.");
1208 let connecting_socket = Socket::new(
1209 locked,
1210 ¤t_task,
1211 SocketDomain::Unix,
1212 SocketType::Stream,
1213 SocketProtocol::default(),
1214 false,
1215 )
1216 .expect("Failed to connect socket.");
1217 connecting_socket
1218 .ops
1219 .connect(
1220 locked.cast_locked(),
1221 &connecting_socket,
1222 ¤t_task,
1223 SocketPeer::Handle(socket.clone()),
1224 )
1225 .expect("Failed to connect socket.");
1226 assert_eq!(Ok(FdEvents::POLLIN), socket.query_events(locked, ¤t_task));
1227 let server_socket = socket.accept(locked, ¤t_task).unwrap();
1228
1229 let opt_size = std::mem::size_of::<socklen_t>();
1230 let user_address =
1231 map_memory(locked, ¤t_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, ¤t_task, SOL_SOCKET, SO_SNDBUF, user_buffer.into())
1237 .unwrap();
1238
1239 let opt_bytes =
1240 server_socket.getsockopt(locked, ¤t_task, SOL_SOCKET, SO_SNDBUF, 0).unwrap();
1241 let retrieved_capacity = socklen_t::from_ne_bytes(opt_bytes.try_into().unwrap());
1242 assert_eq!(2 * send_capacity, retrieved_capacity);
1244 })
1245 .await;
1246 }
1247}