starnix_core/vfs/socket/
socket_netlink.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::security::{self, AuditLogger, AuditMessage, AuditRequest};
6use crate::vfs::socket::{SockOptValue, SocketDomain};
7use futures::channel::mpsc::{
8    UnboundedReceiver, UnboundedSender, {self},
9};
10use linux_uapi::{AUDIT_GET, audit_status};
11use netlink::messaging::{
12    AccessControl, MessageWithPermission, NetlinkContext, NetlinkMessageWithCreds, Permission,
13    Sender, UnparsedNetlinkMessage,
14};
15use netlink::multicast_groups::{
16    InvalidLegacyGroupsError, InvalidModernGroupError, LegacyGroups, ModernGroup,
17    NoMappingFromModernToLegacyGroupError, SingleLegacyGroup,
18};
19use netlink::protocol_family::NetlinkClient;
20use netlink::protocol_family::route::NetlinkRouteClient;
21use netlink::protocol_family::sock_diag::NetlinkSockDiagClient;
22use netlink::{NETLINK_LOG_TAG, NewClientError};
23use netlink_packet_core::{
24    ErrorMessage, NETLINK_HEADER_LEN, NLMSG_ERROR, NetlinkBuffer, NetlinkDeserializable,
25    NetlinkHeader, NetlinkMessage, NetlinkPayload, NetlinkSerializable,
26};
27use netlink_packet_utils::{DecodeError, Emitable as _};
28use starnix_sync::{FileOpsCore, LockEqualOrBefore, Locked, Mutex};
29use std::marker::PhantomData;
30use std::num::{NonZeroI32, NonZeroU32};
31use std::sync::Arc;
32use zerocopy::{FromBytes, IntoBytes};
33
34use crate::device::kobject::{Device, UEventAction, UEventContext};
35use crate::device::{DeviceListener, DeviceListenerKey};
36use crate::task::{
37    CurrentTask, EventHandler, FullCredentials, Kernel, WaitCanceler, WaitQueue, Waiter,
38};
39use crate::vfs::buffers::{
40    AncillaryData, InputBuffer, Message, MessageQueue, MessageReadInfo, OutputBuffer,
41    UnixControlData, VecInputBuffer,
42};
43use crate::vfs::socket::{
44    GenericMessage, GenericNetlinkClientHandle, Socket, SocketAddress, SocketHandle,
45    SocketMessageFlags, SocketOps, SocketPeer, SocketShutdownFlags, SocketType,
46};
47use starnix_logging::{log_debug, log_error, log_warn, track_stub};
48use starnix_uapi::auth::{CAP_AUDIT_CONTROL, CAP_AUDIT_WRITE, CAP_NET_ADMIN};
49use starnix_uapi::errors::Errno;
50use starnix_uapi::vfs::FdEvents;
51use starnix_uapi::{
52    AF_NETLINK, NETLINK_ADD_MEMBERSHIP, NETLINK_AUDIT, NETLINK_CONNECTOR, NETLINK_CRYPTO,
53    NETLINK_DNRTMSG, NETLINK_DROP_MEMBERSHIP, NETLINK_ECRYPTFS, NETLINK_FIB_LOOKUP,
54    NETLINK_FIREWALL, NETLINK_GENERIC, NETLINK_IP6_FW, NETLINK_ISCSI, NETLINK_KOBJECT_UEVENT,
55    NETLINK_NETFILTER, NETLINK_NFLOG, NETLINK_RDMA, NETLINK_ROUTE, NETLINK_SCSITRANSPORT,
56    NETLINK_SELINUX, NETLINK_SMC, NETLINK_SOCK_DIAG, NETLINK_USERSOCK, NETLINK_XFRM, NLM_F_MULTI,
57    NLMSG_DONE, SO_PASSCRED, SO_PROTOCOL, SO_RCVBUF, SO_RCVBUFFORCE, SO_SNDBUF, SO_SNDBUFFORCE,
58    SO_TIMESTAMP, SOL_SOCKET, errno, error, nlmsghdr, sockaddr_nl, socklen_t, ucred,
59};
60
61// From netlink/socket.go in gVisor.
62pub const SOCKET_MIN_SIZE: usize = 4 << 10;
63pub const SOCKET_DEFAULT_SIZE: usize = 16 * 1024;
64pub const SOCKET_MAX_SIZE: usize = 4 << 20;
65
66// From linux/socket.go in gVisor.
67const SOL_NETLINK: u32 = 270;
68
69pub fn new_netlink_socket(
70    kernel: &Arc<Kernel>,
71    socket_type: SocketType,
72    family: NetlinkFamily,
73) -> Result<Box<dyn SocketOps>, Errno> {
74    log_debug!(tag = NETLINK_LOG_TAG; "Creating {:?} Netlink Socket", family);
75    if socket_type != SocketType::Datagram && socket_type != SocketType::Raw {
76        return error!(ESOCKTNOSUPPORT);
77    }
78
79    let ops: Box<dyn SocketOps> = match family {
80        NetlinkFamily::KobjectUevent => Box::new(UEventNetlinkSocket::default()),
81        NetlinkFamily::Route => Box::new(new_route_socket(kernel)?),
82        NetlinkFamily::Generic => Box::new(GenericNetlinkSocket::new(kernel)?),
83        NetlinkFamily::SockDiag => Box::new(new_sock_diag_socket(kernel)?),
84        NetlinkFamily::Audit => Box::new(AuditNetlinkSocket::new(kernel)?),
85        NetlinkFamily::Usersock
86        | NetlinkFamily::Firewall
87        | NetlinkFamily::Nflog
88        | NetlinkFamily::Xfrm
89        | NetlinkFamily::Selinux
90        | NetlinkFamily::Iscsi
91        | NetlinkFamily::FibLookup
92        | NetlinkFamily::Connector
93        | NetlinkFamily::Netfilter
94        | NetlinkFamily::Ip6Fw
95        | NetlinkFamily::Dnrtmsg
96        | NetlinkFamily::Scsitransport
97        | NetlinkFamily::Ecryptfs
98        | NetlinkFamily::Rdma
99        | NetlinkFamily::Crypto
100        | NetlinkFamily::Smc => Box::new(StubbedNetlinkSocket::new(family)),
101        NetlinkFamily::Invalid => return error!(EINVAL),
102    };
103    Ok(ops)
104}
105
106#[derive(Default, Debug, Clone, PartialEq, Eq)]
107#[repr(C)]
108pub struct NetlinkAddress {
109    pid: u32,
110    groups: u32,
111}
112
113impl NetlinkAddress {
114    pub fn new(pid: u32, groups: u32) -> Self {
115        NetlinkAddress { pid, groups }
116    }
117
118    pub fn set_pid_if_zero(&mut self, pid: i32) {
119        if self.pid == 0 {
120            self.pid = pid as u32;
121        }
122    }
123
124    pub fn to_bytes(&self) -> Vec<u8> {
125        sockaddr_nl { nl_family: AF_NETLINK, nl_pid: self.pid, nl_pad: 0, nl_groups: self.groups }
126            .as_bytes()
127            .to_vec()
128    }
129}
130
131#[derive(Debug, Hash, Eq, PartialEq, Clone)]
132pub enum NetlinkFamily {
133    Invalid,
134    Route,
135    Usersock,
136    Firewall,
137    SockDiag,
138    Nflog,
139    Xfrm,
140    Selinux,
141    Iscsi,
142    Audit,
143    FibLookup,
144    Connector,
145    Netfilter,
146    Ip6Fw,
147    Dnrtmsg,
148    KobjectUevent,
149    Generic,
150    Scsitransport,
151    Ecryptfs,
152    Rdma,
153    Crypto,
154    Smc,
155}
156
157impl NetlinkFamily {
158    pub fn from_raw(family: u32) -> Self {
159        match family {
160            NETLINK_ROUTE => NetlinkFamily::Route,
161            NETLINK_USERSOCK => NetlinkFamily::Usersock,
162            NETLINK_FIREWALL => NetlinkFamily::Firewall,
163            NETLINK_SOCK_DIAG => NetlinkFamily::SockDiag,
164            NETLINK_NFLOG => NetlinkFamily::Nflog,
165            NETLINK_XFRM => NetlinkFamily::Xfrm,
166            NETLINK_SELINUX => NetlinkFamily::Selinux,
167            NETLINK_ISCSI => NetlinkFamily::Iscsi,
168            NETLINK_AUDIT => NetlinkFamily::Audit,
169            NETLINK_FIB_LOOKUP => NetlinkFamily::FibLookup,
170            NETLINK_CONNECTOR => NetlinkFamily::Connector,
171            NETLINK_NETFILTER => NetlinkFamily::Netfilter,
172            NETLINK_IP6_FW => NetlinkFamily::Ip6Fw,
173            NETLINK_DNRTMSG => NetlinkFamily::Dnrtmsg,
174            NETLINK_KOBJECT_UEVENT => NetlinkFamily::KobjectUevent,
175            NETLINK_GENERIC => NetlinkFamily::Generic,
176            NETLINK_SCSITRANSPORT => NetlinkFamily::Scsitransport,
177            NETLINK_ECRYPTFS => NetlinkFamily::Ecryptfs,
178            NETLINK_RDMA => NetlinkFamily::Rdma,
179            NETLINK_CRYPTO => NetlinkFamily::Crypto,
180            NETLINK_SMC => NetlinkFamily::Smc,
181            _ => NetlinkFamily::Invalid,
182        }
183    }
184
185    pub fn as_raw(&self) -> u32 {
186        match self {
187            NetlinkFamily::Route => NETLINK_ROUTE,
188            NetlinkFamily::KobjectUevent => NETLINK_KOBJECT_UEVENT,
189            NetlinkFamily::Audit => NETLINK_AUDIT,
190            _ => 0,
191        }
192    }
193}
194
195struct NetlinkSocketInner {
196    /// The specific type of netlink socket.
197    family: NetlinkFamily,
198
199    /// The [`MessageQueue`] that contains messages from netlink to the client.
200    receive_buffer: MessageQueue,
201
202    /// The socket's send buffer size. Note, This value is only used
203    /// to serve getsockopt calls for `SO_SNDBUF`. It does not yet enforce a
204    /// limit on the number of messages netlink will buffer from the client.
205    /// TODO(https://fxbug.dev/285880057): Limit the size of the send buffer.
206    send_buf_size: usize,
207
208    /// This queue will be notified on reads, writes, disconnects etc.
209    waiters: WaitQueue,
210
211    /// The address of this socket.
212    address: Option<NetlinkAddress>,
213
214    /// See SO_PASSCRED.
215    pub passcred: bool,
216
217    /// See SO_TIMESTAMP.
218    pub timestamp: bool,
219}
220
221impl NetlinkSocketInner {
222    fn new(family: NetlinkFamily) -> Self {
223        Self {
224            family,
225            receive_buffer: MessageQueue::new(SOCKET_DEFAULT_SIZE),
226            send_buf_size: SOCKET_DEFAULT_SIZE,
227            waiters: WaitQueue::default(),
228            address: None,
229            passcred: false,
230            timestamp: false,
231        }
232    }
233
234    fn bind(
235        &mut self,
236        current_task: &CurrentTask,
237        socket_address: SocketAddress,
238    ) -> Result<(), Errno> {
239        if self.address.is_some() {
240            return error!(EINVAL);
241        }
242
243        let netlink_address = match socket_address {
244            SocketAddress::Netlink(mut netlink_address) => {
245                // TODO: Support distinct IDs for processes with multiple netlink sockets.
246                netlink_address.set_pid_if_zero(current_task.get_pid());
247                netlink_address
248            }
249            _ => return error!(EINVAL),
250        };
251
252        self.address = Some(netlink_address);
253        Ok(())
254    }
255
256    fn connect(&mut self, current_task: &CurrentTask, peer: SocketPeer) -> Result<(), Errno> {
257        let address = match peer {
258            SocketPeer::Address(address) => address,
259            _ => return error!(EINVAL),
260        };
261        // Connect is equivalent to bind, but error are ignored.
262        let _ = self.bind(current_task, address);
263        Ok(())
264    }
265
266    fn read_message(&mut self) -> Option<Message> {
267        let message = self.receive_buffer.read_message();
268        if message.is_some() {
269            self.waiters.notify_fd_events(FdEvents::POLLOUT);
270        }
271        message
272    }
273
274    fn read_datagram(
275        &mut self,
276        data: &mut dyn OutputBuffer,
277        flags: SocketMessageFlags,
278    ) -> Result<MessageReadInfo, Errno> {
279        let mut info = if flags.contains(SocketMessageFlags::PEEK) {
280            self.receive_buffer.peek_datagram(data)
281        } else {
282            self.receive_buffer.read_datagram(data)
283        }?;
284        if info.message_length == 0 {
285            return error!(EAGAIN);
286        }
287
288        if self.passcred {
289            track_stub!(TODO("https://fxbug.dev/297373991"), "SCM_CREDENTIALS/SO_PASSCRED");
290            info.ancillary_data.push(AncillaryData::Unix(UnixControlData::unknown_creds()));
291        }
292
293        Ok(info)
294    }
295
296    fn write_to_queue(
297        &mut self,
298        data: &mut dyn InputBuffer,
299        address: Option<NetlinkAddress>,
300        ancillary_data: &mut Vec<AncillaryData>,
301    ) -> Result<usize, Errno> {
302        let socket_address = match address {
303            Some(addr) => Some(SocketAddress::Netlink(addr)),
304            None => self.address.as_ref().map(|addr| SocketAddress::Netlink(addr.clone())),
305        };
306        let bytes_written =
307            self.receive_buffer.write_datagram(data, socket_address, ancillary_data)?;
308        if bytes_written > 0 {
309            self.waiters.notify_fd_events(FdEvents::POLLIN);
310        }
311        Ok(bytes_written)
312    }
313
314    fn wait_async(
315        &mut self,
316        waiter: &Waiter,
317        events: FdEvents,
318        handler: EventHandler,
319    ) -> WaitCanceler {
320        self.waiters.wait_async_fd_events(waiter, events, handler)
321    }
322
323    fn query_events(&self) -> FdEvents {
324        self.receive_buffer.query_events()
325    }
326
327    fn getsockname(&self) -> Result<SocketAddress, Errno> {
328        match &self.address {
329            Some(addr) => Ok(SocketAddress::Netlink(addr.clone())),
330            _ => Ok(SocketAddress::default_for_domain(SocketDomain::Netlink)),
331        }
332    }
333
334    fn getpeername(&self) -> Result<SocketAddress, Errno> {
335        match &self.address {
336            Some(addr) => Ok(SocketAddress::Netlink(addr.clone())),
337            _ => Ok(SocketAddress::default_for_domain(SocketDomain::Netlink)),
338        }
339    }
340
341    fn getsockopt(&self, level: u32, optname: u32) -> Result<Vec<u8>, Errno> {
342        let opt_value = match level {
343            SOL_SOCKET => match optname {
344                SO_PASSCRED => (self.passcred as u32).as_bytes().to_vec(),
345                SO_TIMESTAMP => (self.timestamp as u32).as_bytes().to_vec(),
346                SO_SNDBUF => (self.send_buf_size as socklen_t).to_ne_bytes().to_vec(),
347                SO_RCVBUF => (self.receive_buffer.capacity() as socklen_t).to_ne_bytes().to_vec(),
348                SO_SNDBUFFORCE => (self.send_buf_size as socklen_t).to_ne_bytes().to_vec(),
349                SO_RCVBUFFORCE => {
350                    (self.receive_buffer.capacity() as socklen_t).to_ne_bytes().to_vec()
351                }
352                SO_PROTOCOL => self.family.as_raw().as_bytes().to_vec(),
353                _ => return error!(ENOSYS),
354            },
355            _ => vec![],
356        };
357
358        Ok(opt_value)
359    }
360
361    fn setsockopt(
362        &mut self,
363        current_task: &CurrentTask,
364        level: u32,
365        optname: u32,
366        optval: SockOptValue,
367    ) -> Result<(), Errno> {
368        match level {
369            SOL_SOCKET => match optname {
370                SO_SNDBUF => {
371                    let requested_capacity: socklen_t = optval.read(current_task)?;
372                    // SO_SNDBUF doubles the requested capacity to leave space for bookkeeping.
373                    // See https://man7.org/linux/man-pages/man7/socket.7.html
374                    let capacity = usize::try_from(requested_capacity * 2).unwrap_or(usize::MAX);
375                    // TODO(https://fxbug.dev/322907334): Clamp to `wmem_max`.
376                    let capacity = capacity.clamp(SOCKET_MIN_SIZE, SOCKET_MAX_SIZE);
377                    self.send_buf_size = capacity;
378                }
379                SO_SNDBUFFORCE => {
380                    security::check_task_capable(current_task, CAP_NET_ADMIN)?;
381                    let requested_capacity: socklen_t = optval.read(current_task)?;
382                    // SO_SNDBUFFORE doubles the requested capacity to leave space for bookkeeping.
383                    // See https://man7.org/linux/man-pages/man7/socket.7.html
384                    let capacity = usize::try_from(requested_capacity * 2).unwrap_or(usize::MAX);
385                    self.send_buf_size = capacity;
386                }
387                SO_RCVBUF => {
388                    let requested_capacity: socklen_t = optval.read(current_task)?;
389                    // SO_RCVBUF doubles the requested capacity to leave space for bookkeeping.
390                    // See https://man7.org/linux/man-pages/man7/socket.7.html
391                    let capacity = usize::try_from(requested_capacity * 2).unwrap_or(usize::MAX);
392                    // TODO(https://fxbug.dev/322906968): Clamp to `rmem_max`.
393                    let capacity = capacity.clamp(SOCKET_MIN_SIZE, SOCKET_MAX_SIZE);
394                    self.receive_buffer.set_capacity(capacity)?;
395                }
396                SO_RCVBUFFORCE => {
397                    security::check_task_capable(current_task, CAP_NET_ADMIN)?;
398                    let requested_capacity: socklen_t = optval.read(current_task)?;
399                    // SO_RCVBUFFORE doubles the requested capacity to leave space for bookkeeping.
400                    // See https://man7.org/linux/man-pages/man7/socket.7.html
401                    let capacity = usize::try_from(requested_capacity * 2).unwrap_or(usize::MAX);
402                    self.receive_buffer.set_capacity(capacity)?;
403                }
404                SO_PASSCRED => {
405                    let passcred: u32 = optval.read(current_task)?;
406                    self.passcred = passcred != 0;
407                }
408                SO_TIMESTAMP => {
409                    let timestamp: u32 = optval.read(current_task)?;
410                    self.timestamp = timestamp != 0;
411                }
412                _ => return error!(ENOSYS),
413            },
414            _ => return error!(ENOSYS),
415        }
416
417        Ok(())
418    }
419}
420
421/// A fake Netlink socket that loops messages back to the client.
422///
423/// Used as a placeholder implementation for protocol families that lack a real
424/// implementation.
425struct StubbedNetlinkSocket {
426    inner: Mutex<NetlinkSocketInner>,
427}
428
429impl StubbedNetlinkSocket {
430    pub fn new(family: NetlinkFamily) -> Self {
431        track_stub!(
432            TODO("https://fxbug.dev/278565021"),
433            format!("Creating StubbedNetlinkSocket: {:?}", family).as_str()
434        );
435        StubbedNetlinkSocket { inner: Mutex::new(NetlinkSocketInner::new(family)) }
436    }
437
438    /// Locks and returns the inner state of the Socket.
439    fn lock(&self) -> starnix_sync::MutexGuard<'_, NetlinkSocketInner> {
440        self.inner.lock()
441    }
442}
443
444impl SocketOps for StubbedNetlinkSocket {
445    fn connect(
446        &self,
447        _locked: &mut Locked<FileOpsCore>,
448        _socket: &SocketHandle,
449        current_task: &CurrentTask,
450        peer: SocketPeer,
451    ) -> Result<(), Errno> {
452        self.lock().connect(current_task, peer)
453    }
454
455    fn listen(
456        &self,
457        _locked: &mut Locked<FileOpsCore>,
458        _socket: &Socket,
459        _backlog: i32,
460        _credentials: ucred,
461    ) -> Result<(), Errno> {
462        error!(EOPNOTSUPP)
463    }
464
465    fn accept(
466        &self,
467        _locked: &mut Locked<FileOpsCore>,
468        _socket: &Socket,
469        _current_task: &CurrentTask,
470    ) -> Result<SocketHandle, Errno> {
471        error!(EOPNOTSUPP)
472    }
473
474    fn bind(
475        &self,
476        _locked: &mut Locked<FileOpsCore>,
477        _socket: &Socket,
478        current_task: &CurrentTask,
479        socket_address: SocketAddress,
480    ) -> Result<(), Errno> {
481        self.lock().bind(current_task, socket_address)
482    }
483
484    fn read(
485        &self,
486        _locked: &mut Locked<FileOpsCore>,
487        _socket: &Socket,
488        _current_task: &CurrentTask,
489        data: &mut dyn OutputBuffer,
490        _flags: SocketMessageFlags,
491    ) -> Result<MessageReadInfo, Errno> {
492        let msg = self.lock().read_message();
493        match msg {
494            Some(message) => {
495                // Mark the message as complete and return it.
496                let (mut nl_msg, _) =
497                    nlmsghdr::read_from_prefix(&message.data).map_err(|_| errno!(EINVAL))?;
498                nl_msg.nlmsg_type = NLMSG_DONE as u16;
499                nl_msg.nlmsg_flags &= NLM_F_MULTI as u16;
500                let msg_bytes = nl_msg.as_bytes();
501                let bytes_read = data.write(msg_bytes)?;
502
503                let info = MessageReadInfo {
504                    bytes_read,
505                    message_length: msg_bytes.len(),
506                    address: Some(SocketAddress::Netlink(NetlinkAddress::default())),
507                    ancillary_data: vec![],
508                };
509                Ok(info)
510            }
511            None => Ok(MessageReadInfo::default()),
512        }
513    }
514
515    fn write(
516        &self,
517        _locked: &mut Locked<FileOpsCore>,
518        _socket: &Socket,
519        _current_task: &CurrentTask,
520        data: &mut dyn InputBuffer,
521        dest_address: &mut Option<SocketAddress>,
522        ancillary_data: &mut Vec<AncillaryData>,
523    ) -> Result<usize, Errno> {
524        let mut local_address = self.lock().address.clone();
525
526        let destination = match dest_address {
527            Some(SocketAddress::Netlink(addr)) => addr,
528            _ => match &mut local_address {
529                Some(addr) => addr,
530                _ => return Ok(data.drain()),
531            },
532        };
533
534        if destination.groups != 0 {
535            track_stub!(TODO("https://fxbug.dev/322874956"), "StubbedNetlinkSockets multicasting");
536            return Ok(data.drain());
537        }
538
539        self.lock().write_to_queue(data, Some(NetlinkAddress::default()), ancillary_data)
540    }
541
542    fn wait_async(
543        &self,
544        _locked: &mut Locked<FileOpsCore>,
545        _socket: &Socket,
546        _current_task: &CurrentTask,
547        waiter: &Waiter,
548        events: FdEvents,
549        handler: EventHandler,
550    ) -> WaitCanceler {
551        self.lock().wait_async(waiter, events, handler)
552    }
553
554    fn query_events(
555        &self,
556        _locked: &mut Locked<FileOpsCore>,
557        _socket: &Socket,
558        _current_task: &CurrentTask,
559    ) -> Result<FdEvents, Errno> {
560        Ok(self.lock().query_events() & FdEvents::POLLIN)
561    }
562
563    fn shutdown(
564        &self,
565        _locked: &mut Locked<FileOpsCore>,
566        _socket: &Socket,
567        _how: SocketShutdownFlags,
568    ) -> Result<(), Errno> {
569        track_stub!(TODO("https://fxbug.dev/322875507"), "StubbedNetlinkSocket::shutdown");
570        Ok(())
571    }
572
573    fn close(
574        &self,
575        _locked: &mut Locked<FileOpsCore>,
576        _current_task: &CurrentTask,
577        _socket: &Socket,
578    ) {
579    }
580
581    fn getsockname(
582        &self,
583        _locked: &mut Locked<FileOpsCore>,
584        _socket: &Socket,
585    ) -> Result<SocketAddress, Errno> {
586        self.lock().getsockname()
587    }
588
589    fn getpeername(
590        &self,
591        _locked: &mut Locked<FileOpsCore>,
592        _socket: &Socket,
593    ) -> Result<SocketAddress, Errno> {
594        self.lock().getpeername()
595    }
596
597    fn getsockopt(
598        &self,
599        _locked: &mut Locked<FileOpsCore>,
600        _socket: &Socket,
601        _current_task: &CurrentTask,
602        level: u32,
603        optname: u32,
604        _optlen: u32,
605    ) -> Result<Vec<u8>, Errno> {
606        self.lock().getsockopt(level, optname)
607    }
608
609    fn setsockopt(
610        &self,
611        _locked: &mut Locked<FileOpsCore>,
612        _socket: &Socket,
613        current_task: &CurrentTask,
614        level: u32,
615        optname: u32,
616        optval: SockOptValue,
617    ) -> Result<(), Errno> {
618        self.lock().setsockopt(current_task, level, optname, optval)
619    }
620}
621
622/// Socket implementation for the NETLINK_KOBJECT_UEVENT family of netlink sockets.
623struct UEventNetlinkSocket {
624    inner: Arc<Mutex<NetlinkSocketInner>>,
625    device_listener_key: Mutex<Option<DeviceListenerKey>>,
626}
627
628impl Default for UEventNetlinkSocket {
629    #[allow(clippy::let_and_return)]
630    fn default() -> Self {
631        let result = Self {
632            inner: Arc::new(Mutex::new(NetlinkSocketInner::new(NetlinkFamily::KobjectUevent))),
633            device_listener_key: Default::default(),
634        };
635        #[cfg(any(test, debug_assertions))]
636        {
637            let _l1 = result.device_listener_key.lock();
638            let _l2 = result.lock();
639        }
640        result
641    }
642}
643
644impl UEventNetlinkSocket {
645    /// Locks and returns the inner state of the Socket.
646    fn lock(&self) -> starnix_sync::MutexGuard<'_, NetlinkSocketInner> {
647        self.inner.lock()
648    }
649
650    fn register_listener<L>(
651        &self,
652        locked: &mut Locked<L>,
653        current_task: &CurrentTask,
654        state: starnix_sync::MutexGuard<'_, NetlinkSocketInner>,
655    ) where
656        L: LockEqualOrBefore<FileOpsCore>,
657    {
658        if state.address.is_none() {
659            return;
660        }
661        std::mem::drop(state);
662        let mut key_state = self.device_listener_key.lock();
663        if key_state.is_none() {
664            *key_state = Some(
665                current_task.kernel().device_registry.register_listener(locked, self.inner.clone()),
666            );
667        }
668    }
669}
670
671impl SocketOps for UEventNetlinkSocket {
672    fn connect(
673        &self,
674        locked: &mut Locked<FileOpsCore>,
675        _socket: &SocketHandle,
676        current_task: &CurrentTask,
677        peer: SocketPeer,
678    ) -> Result<(), Errno> {
679        let mut state = self.lock();
680        state.connect(current_task, peer)?;
681        self.register_listener(locked, current_task, state);
682        Ok(())
683    }
684
685    fn listen(
686        &self,
687        _locked: &mut Locked<FileOpsCore>,
688        _socket: &Socket,
689        _backlog: i32,
690        _credentials: ucred,
691    ) -> Result<(), Errno> {
692        error!(EOPNOTSUPP)
693    }
694
695    fn accept(
696        &self,
697        _locked: &mut Locked<FileOpsCore>,
698        _socket: &Socket,
699        _current_task: &CurrentTask,
700    ) -> Result<SocketHandle, Errno> {
701        error!(EOPNOTSUPP)
702    }
703
704    fn bind(
705        &self,
706        locked: &mut Locked<FileOpsCore>,
707        _socket: &Socket,
708        current_task: &CurrentTask,
709        socket_address: SocketAddress,
710    ) -> Result<(), Errno> {
711        let mut state = self.lock();
712        state.bind(current_task, socket_address)?;
713        self.register_listener(locked, current_task, state);
714        Ok(())
715    }
716
717    fn read(
718        &self,
719        _locked: &mut Locked<FileOpsCore>,
720        _socket: &Socket,
721        _current_task: &CurrentTask,
722        data: &mut dyn OutputBuffer,
723        flags: SocketMessageFlags,
724    ) -> Result<MessageReadInfo, Errno> {
725        self.lock().read_datagram(data, flags)
726    }
727
728    fn write(
729        &self,
730        _locked: &mut Locked<FileOpsCore>,
731        _socket: &Socket,
732        _current_task: &CurrentTask,
733        _data: &mut dyn InputBuffer,
734        _dest_address: &mut Option<SocketAddress>,
735        _ancillary_data: &mut Vec<AncillaryData>,
736    ) -> Result<usize, Errno> {
737        error!(EOPNOTSUPP)
738    }
739
740    fn wait_async(
741        &self,
742        _locked: &mut Locked<FileOpsCore>,
743        _socket: &Socket,
744        _current_task: &CurrentTask,
745        waiter: &Waiter,
746        events: FdEvents,
747        handler: EventHandler,
748    ) -> WaitCanceler {
749        self.lock().wait_async(waiter, events, handler)
750    }
751
752    fn query_events(
753        &self,
754        _locked: &mut Locked<FileOpsCore>,
755        _socket: &Socket,
756        _current_task: &CurrentTask,
757    ) -> Result<FdEvents, Errno> {
758        Ok(self.lock().query_events() & FdEvents::POLLIN)
759    }
760
761    fn shutdown(
762        &self,
763        _locked: &mut Locked<FileOpsCore>,
764        _socket: &Socket,
765        _how: SocketShutdownFlags,
766    ) -> Result<(), Errno> {
767        track_stub!(TODO("https://fxbug.dev/322875507"), "UEventNetlinkSocket::shutdown");
768        Ok(())
769    }
770
771    fn close(
772        &self,
773        locked: &mut Locked<FileOpsCore>,
774        current_task: &CurrentTask,
775        _socket: &Socket,
776    ) {
777        let id = self.device_listener_key.lock().take();
778        if let Some(id) = id {
779            current_task.kernel().device_registry.unregister_listener(locked, &id);
780        }
781    }
782
783    fn getsockname(
784        &self,
785        _locked: &mut Locked<FileOpsCore>,
786        _socket: &Socket,
787    ) -> Result<SocketAddress, Errno> {
788        self.lock().getsockname()
789    }
790
791    fn getpeername(
792        &self,
793        _locked: &mut Locked<FileOpsCore>,
794        _socket: &Socket,
795    ) -> Result<SocketAddress, Errno> {
796        self.lock().getpeername()
797    }
798
799    fn getsockopt(
800        &self,
801        _locked: &mut Locked<FileOpsCore>,
802        _socket: &Socket,
803        _current_task: &CurrentTask,
804        level: u32,
805        optname: u32,
806        _optlen: u32,
807    ) -> Result<Vec<u8>, Errno> {
808        self.lock().getsockopt(level, optname)
809    }
810
811    fn setsockopt(
812        &self,
813        _locked: &mut Locked<FileOpsCore>,
814        _socket: &Socket,
815        current_task: &CurrentTask,
816        level: u32,
817        optname: u32,
818        optval: SockOptValue,
819    ) -> Result<(), Errno> {
820        self.lock().setsockopt(current_task, level, optname, optval)
821    }
822}
823
824impl DeviceListener for Arc<Mutex<NetlinkSocketInner>> {
825    fn on_device_event(&self, action: UEventAction, device: Device, context: UEventContext) {
826        let path = device.path_from_depth(0);
827        let message = format!(
828            "{action}@/{path}\0\
829                            ACTION={action}\0\
830                            SEQNUM={seqnum}\0\
831                            {other_props}",
832            seqnum = context.seqnum,
833            other_props = device.uevent_properties('\0'),
834        );
835        let ancillary_data = AncillaryData::Unix(UnixControlData::Credentials(Default::default()));
836        let mut ancillary_data = vec![ancillary_data];
837        // Ignore write errors
838        let _ = self.lock().write_to_queue(
839            &mut VecInputBuffer::new(message.as_bytes()),
840            Some(NetlinkAddress { pid: 0, groups: 1 }),
841            &mut ancillary_data,
842        );
843    }
844}
845
846/// Type for sending messages from [`netlink::Netlink`] to an individual socket.
847#[derive(Clone)]
848pub struct NetlinkToClientSender<M> {
849    /// The inner socket implementation, which holds a message queue.
850    inner: Arc<Mutex<NetlinkSocketInner>>,
851
852    /// `PhantomData<fn(M) -> M>` is used instead of `PhantomData<M>` in order
853    /// to ensure that the type is invariant over `M` and that it implements
854    /// `Sync` even if `M` is not `Sync`.
855    _message_type: PhantomData<fn(M) -> M>,
856}
857
858impl<M> NetlinkToClientSender<M> {
859    fn new(inner: Arc<Mutex<NetlinkSocketInner>>) -> Self {
860        NetlinkToClientSender { _message_type: Default::default(), inner }
861    }
862}
863
864impl<M: Clone + NetlinkSerializable + Send> Sender<M> for NetlinkToClientSender<M> {
865    fn send(&mut self, message: NetlinkMessage<M>, group: Option<ModernGroup>) {
866        // Serialize the message
867        let mut buf = vec![0; message.buffer_len()];
868        message.emit(&mut buf);
869        let mut buf: VecInputBuffer = buf.into();
870        // Write the message into the inner socket buffer.
871        let NetlinkToClientSender { _message_type: _, inner } = self;
872        let mut guard = inner.lock();
873
874        // To avoid dropping messages when the receive buffer is
875        // full, grow the buffer on behalf of the client.
876        // This is a stop gap measure to avoid dropping messages
877        // when netlink produces a large response to a
878        // NLM_F_DUMP request.
879        //
880        // TODO(https://fxbug.dev/459883760): The memory
881        // implications of this may be problematic. It should be
882        // replaced with a proper mechanism to handle a backlog
883        // of NLM_F_DUMP responses.
884        let available = guard.receive_buffer.available_capacity();
885        let required = buf.available();
886        if available < required {
887            let delta = required - available;
888            let current_capacity = guard.receive_buffer.capacity();
889            let new_capacity = (current_capacity + delta).min(SOCKET_MAX_SIZE);
890            match guard.receive_buffer.set_capacity(new_capacity) {
891                Ok(()) => {}
892                Err(e) => {
893                    log_error!(
894                        tag = NETLINK_LOG_TAG;
895                        "Failed to increase receive buffer size: {:?}",
896                        e
897                    );
898                }
899            }
900        }
901
902        let _bytes_written: usize = guard
903            .write_to_queue(
904                &mut buf,
905                Some(NetlinkAddress {
906                    // All messages come from the "kernel" which has PID of 0.
907                    pid: 0,
908                    // If this is a multicast message, set the group the multicast
909                    // message is from.
910                    groups: group
911                        .map(SingleLegacyGroup::try_from)
912                        .and_then(Result::<_, NoMappingFromModernToLegacyGroupError>::ok)
913                        .map_or(0, |g| g.inner()),
914                }),
915                &mut Vec::new(),
916            )
917            .unwrap_or_else(|e| {
918                log_error!(
919                    tag = NETLINK_LOG_TAG;
920                    "Failed to write message into buffer for socket. Errno: {:?}",
921                    e
922                );
923                0
924            });
925    }
926}
927
928#[derive(Clone)]
929pub struct NetlinkAccessControl<'a> {
930    current_task: &'a CurrentTask,
931}
932
933impl<'a> NetlinkAccessControl<'a> {
934    pub fn new(current_task: &'a CurrentTask) -> Self {
935        Self { current_task }
936    }
937}
938
939impl<'a> AccessControl<FullCredentials> for NetlinkAccessControl<'a> {
940    fn grant_assess(
941        &self,
942        creds: &FullCredentials,
943        permission: Permission,
944    ) -> Result<(), netlink::Errno> {
945        let need_cap_net_admin = match permission {
946            Permission::NetlinkRouteRead => false,
947            Permission::NetlinkRouteWrite => true,
948            Permission::NetlinkSockDiagRead => false,
949            Permission::NetlinkSockDiagDestroy => true,
950        };
951        if !need_cap_net_admin {
952            return Ok(());
953        }
954
955        self.current_task.override_creds(creds.clone(), || {
956            security::check_task_capable(self.current_task, CAP_NET_ADMIN).map_err(|error| {
957                netlink::Errno::new(error.code.error_code() as i32)
958                    .expect("Errno::error_code() is expected to be in range [1..max_i32]")
959            })
960        })
961    }
962}
963pub struct NetlinkContextImpl;
964
965impl NetlinkContext for NetlinkContextImpl {
966    type Creds = FullCredentials;
967    type Sender<M: Clone + NetlinkSerializable + Send> = NetlinkToClientSender<M>;
968    type Receiver<
969        M: Send + MessageWithPermission + NetlinkDeserializable<Error: Into<DecodeError>>,
970    > = UnboundedReceiver<NetlinkMessageWithCreds<UnparsedNetlinkMessage<Vec<u8>, M>, Self::Creds>>;
971    type AccessControl<'a> = NetlinkAccessControl<'a>;
972}
973
974fn new_route_socket(kernel: &Arc<Kernel>) -> Result<NetlinkSocket<NetlinkRouteClient>, Errno> {
975    let inner = Arc::new(Mutex::new(NetlinkSocketInner::new(NetlinkFamily::Route)));
976    let (message_sender, message_receiver) = mpsc::unbounded();
977    let client = match kernel
978        .network_netlink()
979        .new_route_client(NetlinkToClientSender::new(inner.clone()), message_receiver)
980    {
981        Ok(client) => client,
982        Err(NewClientError::Disconnected) => {
983            log_error!(
984                tag = NETLINK_LOG_TAG;
985                "Netlink async worker is unexpectedly disconnected"
986            );
987            return error!(EPIPE);
988        }
989    };
990    Ok(NetlinkSocket { inner, client, message_sender })
991}
992
993fn new_sock_diag_socket(
994    kernel: &Arc<Kernel>,
995) -> Result<NetlinkSocket<NetlinkSockDiagClient>, Errno> {
996    let inner = Arc::new(Mutex::new(NetlinkSocketInner::new(NetlinkFamily::SockDiag)));
997    let (message_sender, message_receiver) = mpsc::unbounded();
998    let client = match kernel
999        .network_netlink()
1000        .new_sock_diag_client(NetlinkToClientSender::new(inner.clone()), message_receiver)
1001    {
1002        Ok(client) => client,
1003        Err(NewClientError::Disconnected) => {
1004            log_error!(
1005                tag = NETLINK_LOG_TAG;
1006                "Netlink async worker is unexpectedly disconnected"
1007            );
1008            return error!(EPIPE);
1009        }
1010    };
1011    Ok(NetlinkSocket { inner, client, message_sender })
1012}
1013
1014/// An abstraction over common networking-specific netlink sockets.
1015struct NetlinkSocket<C: NetlinkClient> {
1016    /// The inner Netlink socket implementation
1017    inner: Arc<Mutex<NetlinkSocketInner>>,
1018    /// The implementation of a client (socket connection) to NETLINK_ROUTE.
1019    client: C,
1020    /// The sender of messages from this socket to Netlink.
1021    // TODO(https://issuetracker.google.com/285880057): Bound the capacity of
1022    // the "send buffer".
1023    message_sender: UnboundedSender<
1024        NetlinkMessageWithCreds<UnparsedNetlinkMessage<Vec<u8>, C::Request>, FullCredentials>,
1025    >,
1026}
1027
1028impl<C: NetlinkClient + 'static> SocketOps for NetlinkSocket<C> {
1029    fn connect(
1030        &self,
1031        _locked: &mut Locked<FileOpsCore>,
1032        _socket: &SocketHandle,
1033        current_task: &CurrentTask,
1034        peer: SocketPeer,
1035    ) -> Result<(), Errno> {
1036        let NetlinkSocket { inner, client: _, message_sender: _ } = self;
1037        inner.lock().connect(current_task, peer)
1038    }
1039
1040    fn listen(
1041        &self,
1042        _locked: &mut Locked<FileOpsCore>,
1043        _socket: &Socket,
1044        _backlog: i32,
1045        _credentials: ucred,
1046    ) -> Result<(), Errno> {
1047        error!(EOPNOTSUPP)
1048    }
1049
1050    fn accept(
1051        &self,
1052        _locked: &mut Locked<FileOpsCore>,
1053        _socket: &Socket,
1054        _current_task: &CurrentTask,
1055    ) -> Result<SocketHandle, Errno> {
1056        error!(EOPNOTSUPP)
1057    }
1058
1059    fn bind(
1060        &self,
1061        _locked: &mut Locked<FileOpsCore>,
1062        _socket: &Socket,
1063        current_task: &CurrentTask,
1064        socket_address: SocketAddress,
1065    ) -> Result<(), Errno> {
1066        let NetlinkSocket { inner, client, message_sender: _ } = self;
1067
1068        let multicast_groups = match &socket_address {
1069            SocketAddress::Netlink(NetlinkAddress { pid: _, groups }) => *groups,
1070            _ => return error!(EINVAL),
1071        };
1072        let pid = {
1073            let mut inner = inner.lock();
1074            inner.bind(current_task, socket_address)?;
1075            inner
1076                .address
1077                .as_ref()
1078                .and_then(|NetlinkAddress { pid, groups: _ }| NonZeroU32::new(*pid))
1079        };
1080        if let Some(pid) = pid {
1081            client.set_pid(pid);
1082        }
1083        // This "blocks" in order to synchronize with the internal
1084        // state of the netlink worker, but we're not blocking on
1085        // the completion of any i/o or any expensive computation,
1086        // so there's no need to support interrupts here.
1087        client
1088            .set_legacy_memberships(LegacyGroups(multicast_groups))
1089            .map_err(|InvalidLegacyGroupsError {}| errno!(EPERM))?
1090            .wait_until_complete();
1091        Ok(())
1092    }
1093
1094    fn read(
1095        &self,
1096        _locked: &mut Locked<FileOpsCore>,
1097        _socket: &Socket,
1098        _current_task: &CurrentTask,
1099        data: &mut dyn OutputBuffer,
1100        flags: SocketMessageFlags,
1101    ) -> Result<MessageReadInfo, Errno> {
1102        let NetlinkSocket { inner, client: _, message_sender: _ } = self;
1103        inner.lock().read_datagram(data, flags)
1104    }
1105
1106    fn write(
1107        &self,
1108        _locked: &mut Locked<FileOpsCore>,
1109        socket: &Socket,
1110        current_task: &CurrentTask,
1111        data: &mut dyn InputBuffer,
1112        _dest_address: &mut Option<SocketAddress>,
1113        _ancillary_data: &mut Vec<AncillaryData>,
1114    ) -> Result<usize, Errno> {
1115        let NetlinkSocket { inner: _, client: _, message_sender } = self;
1116
1117        let bytes = data.peek_all()?;
1118        let bytes_len = bytes.len();
1119
1120        // Parse only the netlink header to send it through security check.
1121        match NetlinkBuffer::new(&bytes) {
1122            Ok(buffer) => {
1123                security::check_netlink_send_access(current_task, socket, buffer.message_type())?;
1124            }
1125            Err(e) => {
1126                // If we can't even decode the header of the netlink message,
1127                // then return early here as a stronger statement that we're not
1128                // going to accidentally operate on it and violate the security
1129                // check. The netlink crate would end up dropping this with no
1130                // response as well.
1131                log_warn!(tag = NETLINK_LOG_TAG;
1132                    "Failed to parse netlink header {e:?}"
1133                );
1134                data.drain();
1135                return Ok(bytes_len);
1136            }
1137        }
1138
1139        let msg = NetlinkMessageWithCreds::new(
1140            UnparsedNetlinkMessage::new(bytes),
1141            current_task.full_current_creds(),
1142        );
1143        message_sender.unbounded_send(msg).map_err(|e| {
1144            log_warn!(
1145                tag = NETLINK_LOG_TAG;
1146                "Netlink receiver unexpectedly disconnected for socket: {:?}",
1147                e
1148            );
1149            errno!(EPIPE)
1150        })?;
1151        data.drain();
1152        Ok(bytes_len)
1153    }
1154
1155    fn wait_async(
1156        &self,
1157        _locked: &mut Locked<FileOpsCore>,
1158        _socket: &Socket,
1159        _current_task: &CurrentTask,
1160        waiter: &Waiter,
1161        events: FdEvents,
1162        handler: EventHandler,
1163    ) -> WaitCanceler {
1164        let NetlinkSocket { inner, client: _, message_sender: _ } = self;
1165        inner.lock().wait_async(waiter, events, handler)
1166    }
1167
1168    fn query_events(
1169        &self,
1170        _locked: &mut Locked<FileOpsCore>,
1171        _socket: &Socket,
1172        _current_task: &CurrentTask,
1173    ) -> Result<FdEvents, Errno> {
1174        let NetlinkSocket { inner, client: _, message_sender: _ } = self;
1175        Ok(inner.lock().query_events() & FdEvents::POLLIN)
1176    }
1177
1178    fn shutdown(
1179        &self,
1180        _locked: &mut Locked<FileOpsCore>,
1181        _socket: &Socket,
1182        _how: SocketShutdownFlags,
1183    ) -> Result<(), Errno> {
1184        error!(EOPNOTSUPP)
1185    }
1186
1187    fn close(
1188        &self,
1189        _locked: &mut Locked<FileOpsCore>,
1190        _current_task: &CurrentTask,
1191        _socket: &Socket,
1192    ) {
1193        // Close the underlying channel to the Netlink worker.
1194        self.message_sender.close_channel();
1195    }
1196
1197    fn getsockname(
1198        &self,
1199        _locked: &mut Locked<FileOpsCore>,
1200        _socket: &Socket,
1201    ) -> Result<SocketAddress, Errno> {
1202        let NetlinkSocket { inner, client: _, message_sender: _ } = self;
1203        inner.lock().getsockname()
1204    }
1205
1206    fn getpeername(
1207        &self,
1208        _locked: &mut Locked<FileOpsCore>,
1209        _socket: &Socket,
1210    ) -> Result<SocketAddress, Errno> {
1211        self.inner.lock().getpeername()
1212    }
1213
1214    fn getsockopt(
1215        &self,
1216        _locked: &mut Locked<FileOpsCore>,
1217        _socket: &Socket,
1218        _current_task: &CurrentTask,
1219        level: u32,
1220        optname: u32,
1221        _optlen: u32,
1222    ) -> Result<Vec<u8>, Errno> {
1223        self.inner.lock().getsockopt(level, optname)
1224    }
1225
1226    fn setsockopt(
1227        &self,
1228        _locked: &mut Locked<FileOpsCore>,
1229        _socket: &Socket,
1230        current_task: &CurrentTask,
1231        level: u32,
1232        optname: u32,
1233        optval: SockOptValue,
1234    ) -> Result<(), Errno> {
1235        match (level, optname) {
1236            (SOL_NETLINK, NETLINK_ADD_MEMBERSHIP) => {
1237                let NetlinkSocket { inner: _, client, message_sender: _ } = self;
1238                let group: u32 = optval.read(current_task)?;
1239                let async_work = client
1240                    .add_membership(ModernGroup(group))
1241                    .map_err(|InvalidModernGroupError| errno!(EINVAL))?;
1242                // This "blocks" in order to synchronize with the internal
1243                // state of the rtnetlink worker, but we're not blocking on
1244                // the completion of any i/o or any expensive computation,
1245                // so there's no need to support interrupts here.
1246                async_work.wait_until_complete();
1247                Ok(())
1248            }
1249            (SOL_NETLINK, NETLINK_DROP_MEMBERSHIP) => {
1250                let NetlinkSocket { inner: _, client, message_sender: _ } = self;
1251                let group: u32 = optval.read(current_task)?;
1252                client
1253                    .del_membership(ModernGroup(group))
1254                    .map_err(|InvalidModernGroupError| errno!(EINVAL))?;
1255                Ok(())
1256            }
1257            _ => self.inner.lock().setsockopt(current_task, level, optname, optval),
1258        }
1259    }
1260}
1261
1262/// Socket implementation for the NETLINK_GENERIC family of netlink sockets.
1263struct GenericNetlinkSocket {
1264    inner: Arc<Mutex<NetlinkSocketInner>>,
1265    client: GenericNetlinkClientHandle<NetlinkToClientSender<GenericMessage>>,
1266    message_sender: mpsc::UnboundedSender<NetlinkMessage<GenericMessage>>,
1267}
1268
1269impl GenericNetlinkSocket {
1270    pub fn new(kernel: &Kernel) -> Result<Self, Errno> {
1271        let inner = Arc::new(Mutex::new(NetlinkSocketInner::new(NetlinkFamily::Generic)));
1272        let (message_sender, message_receiver) = mpsc::unbounded();
1273        match kernel
1274            .generic_netlink()
1275            .new_generic_client(NetlinkToClientSender::new(inner.clone()), message_receiver)
1276        {
1277            Ok(client) => Ok(Self { inner, client, message_sender }),
1278            Err(e) => {
1279                log_warn!(
1280                    tag = NETLINK_LOG_TAG;
1281                    "Failed to connect to generic netlink server. Errno: {:?}",
1282                    e
1283                );
1284                error!(EPIPE)
1285            }
1286        }
1287    }
1288
1289    /// Locks and returns the inner state of the Socket.
1290    fn lock(&self) -> starnix_sync::MutexGuard<'_, NetlinkSocketInner> {
1291        self.inner.lock()
1292    }
1293}
1294
1295impl SocketOps for GenericNetlinkSocket {
1296    fn connect(
1297        &self,
1298        _locked: &mut Locked<FileOpsCore>,
1299        _socket: &SocketHandle,
1300        current_task: &CurrentTask,
1301        peer: SocketPeer,
1302    ) -> Result<(), Errno> {
1303        let mut state = self.lock();
1304        state.connect(current_task, peer)
1305    }
1306
1307    fn listen(
1308        &self,
1309        _locked: &mut Locked<FileOpsCore>,
1310        _socket: &Socket,
1311        _backlog: i32,
1312        _credentials: ucred,
1313    ) -> Result<(), Errno> {
1314        error!(EOPNOTSUPP)
1315    }
1316
1317    fn accept(
1318        &self,
1319        _locked: &mut Locked<FileOpsCore>,
1320        _socket: &Socket,
1321        _current_task: &CurrentTask,
1322    ) -> Result<SocketHandle, Errno> {
1323        error!(EOPNOTSUPP)
1324    }
1325
1326    fn bind(
1327        &self,
1328        _locked: &mut Locked<FileOpsCore>,
1329        _socket: &Socket,
1330        current_task: &CurrentTask,
1331        socket_address: SocketAddress,
1332    ) -> Result<(), Errno> {
1333        let mut state = self.lock();
1334        state.bind(current_task, socket_address)
1335    }
1336
1337    fn read(
1338        &self,
1339        _locked: &mut Locked<FileOpsCore>,
1340        _socket: &Socket,
1341        _current_task: &CurrentTask,
1342        data: &mut dyn OutputBuffer,
1343        flags: SocketMessageFlags,
1344    ) -> Result<MessageReadInfo, Errno> {
1345        self.lock().read_datagram(data, flags)
1346    }
1347
1348    fn write(
1349        &self,
1350        _locked: &mut Locked<FileOpsCore>,
1351        _socket: &Socket,
1352        _current_task: &CurrentTask,
1353        data: &mut dyn InputBuffer,
1354        _dest_address: &mut Option<SocketAddress>,
1355        _ancillary_data: &mut Vec<AncillaryData>,
1356    ) -> Result<usize, Errno> {
1357        let bytes = data.read_all()?;
1358        match NetlinkMessage::<GenericMessage>::deserialize(&bytes) {
1359            Err(e) => {
1360                log_warn!("Failed to process write; data could not be deserialized: {:?}", e);
1361                error!(EINVAL)
1362            }
1363            Ok(msg) => match self.message_sender.unbounded_send(msg) {
1364                Ok(()) => Ok(bytes.len()),
1365                Err(e) => {
1366                    log_warn!("Netlink receiver unexpectedly disconnected for socket: {:?}", e);
1367                    error!(EPIPE)
1368                }
1369            },
1370        }
1371    }
1372
1373    fn wait_async(
1374        &self,
1375        _locked: &mut Locked<FileOpsCore>,
1376        _socket: &Socket,
1377        _current_task: &CurrentTask,
1378        waiter: &Waiter,
1379        events: FdEvents,
1380        handler: EventHandler,
1381    ) -> WaitCanceler {
1382        self.lock().wait_async(waiter, events, handler)
1383    }
1384
1385    fn query_events(
1386        &self,
1387        _locked: &mut Locked<FileOpsCore>,
1388        _socket: &Socket,
1389        _current_task: &CurrentTask,
1390    ) -> Result<FdEvents, Errno> {
1391        Ok(self.lock().query_events() & FdEvents::POLLIN)
1392    }
1393
1394    fn shutdown(
1395        &self,
1396        _locked: &mut Locked<FileOpsCore>,
1397        _socket: &Socket,
1398        _how: SocketShutdownFlags,
1399    ) -> Result<(), Errno> {
1400        track_stub!(TODO("https://fxbug.dev/322875507"), "GenericNetlinkSocket::shutdown");
1401        Ok(())
1402    }
1403
1404    fn close(
1405        &self,
1406        _locked: &mut Locked<FileOpsCore>,
1407        _current_task: &CurrentTask,
1408        _socket: &Socket,
1409    ) {
1410    }
1411
1412    fn getsockname(
1413        &self,
1414        _locked: &mut Locked<FileOpsCore>,
1415        _socket: &Socket,
1416    ) -> Result<SocketAddress, Errno> {
1417        self.lock().getsockname()
1418    }
1419
1420    fn getpeername(
1421        &self,
1422        _locked: &mut Locked<FileOpsCore>,
1423        _socket: &Socket,
1424    ) -> Result<SocketAddress, Errno> {
1425        self.lock().getpeername()
1426    }
1427
1428    fn getsockopt(
1429        &self,
1430        _locked: &mut Locked<FileOpsCore>,
1431        _socket: &Socket,
1432        _current_task: &CurrentTask,
1433        level: u32,
1434        optname: u32,
1435        _optlen: u32,
1436    ) -> Result<Vec<u8>, Errno> {
1437        self.lock().getsockopt(level, optname)
1438    }
1439
1440    fn setsockopt(
1441        &self,
1442        _locked: &mut Locked<FileOpsCore>,
1443        _socket: &Socket,
1444        current_task: &CurrentTask,
1445        level: u32,
1446        optname: u32,
1447        optval: SockOptValue,
1448    ) -> Result<(), Errno> {
1449        match (level, optname) {
1450            (SOL_NETLINK, NETLINK_ADD_MEMBERSHIP) => {
1451                let group_id: u32 = optval.read(current_task)?;
1452                self.client.add_membership(ModernGroup(group_id))
1453            }
1454            _ => self.lock().setsockopt(current_task, level, optname, optval),
1455        }
1456    }
1457}
1458
1459/// Audit client that can be attached to the `AuditLogger`.
1460pub struct AuditNetlinkClient {
1461    /// Reference to the `AuditLogger`.
1462    audit_logger: Arc<AuditLogger>,
1463    /// The waiters queue present in `AuditNetlinkSocket`.
1464    waiters: WaitQueue,
1465    /// Optional response from the `AuditLogger`.
1466    audit_response: Mutex<Option<NetlinkMessage<GenericMessage>>>,
1467}
1468
1469impl AuditNetlinkClient {
1470    fn new(audit_logger: Arc<AuditLogger>) -> Self {
1471        Self { audit_logger, waiters: Default::default(), audit_response: Mutex::new(None) }
1472    }
1473
1474    pub fn notify(&self) {
1475        self.waiters.notify_fd_events(FdEvents::POLLIN);
1476    }
1477
1478    /// Function to check the capabilities of the current task against CAP_AUDIT_*
1479    fn check_audit_access(
1480        &self,
1481        current_task: &CurrentTask,
1482        request_type: &AuditRequest,
1483    ) -> Result<(), Errno> {
1484        match request_type {
1485            AuditRequest::AuditGet | AuditRequest::AuditSet => {
1486                security::check_task_capable(current_task, CAP_AUDIT_CONTROL)
1487            }
1488            AuditRequest::AuditUser => security::check_task_capable(current_task, CAP_AUDIT_WRITE),
1489        }
1490    }
1491
1492    /// Function to process request coming from userspace, it returns the response after processing
1493    fn process_request(
1494        self: &Arc<Self>,
1495        current_task: &CurrentTask,
1496        nl_message: NetlinkMessage<GenericMessage>,
1497    ) -> Result<NetlinkMessage<GenericMessage>, Errno> {
1498        let (nl_header, nl_payload) = nl_message.into_parts();
1499        let audit_request_type = AuditRequest::try_from(nl_header.message_type as u32)?;
1500        self.check_audit_access(current_task, &audit_request_type)?;
1501
1502        // If there is no GenericMessage, return an ErrorMessage.
1503        let NetlinkPayload::InnerMessage(GenericMessage::Other { payload, .. }) = nl_payload else {
1504            return error!(EINVAL);
1505        };
1506        match audit_request_type {
1507            AuditRequest::AuditGet => self.process_get_status(nl_header.sequence_number),
1508            AuditRequest::AuditSet => self.process_set_status(current_task, nl_header, payload),
1509            AuditRequest::AuditUser => self.process_user_audit(nl_header, payload),
1510        }
1511    }
1512
1513    fn get_nl_response(&self, flags: SocketMessageFlags) -> Option<Vec<u8>> {
1514        if flags.contains(SocketMessageFlags::PEEK) {
1515            if let Some(message) = self.audit_response.lock().as_ref() {
1516                return Some(AuditNetlinkClient::serialize_nlmsg(message.clone()));
1517            }
1518        } else if let Some(message) = self.audit_response.lock().take() {
1519            return Some(AuditNetlinkClient::serialize_nlmsg(message));
1520        }
1521        None
1522    }
1523
1524    /// Function to read an audit message from `AuditLogger`.
1525    fn read_audit_log(self: &Arc<Self>) -> Option<Vec<u8>> {
1526        if let Some(AuditMessage { audit_type, message }) = self.audit_logger.read_audit_log(self) {
1527            return Some(AuditNetlinkClient::serialize_nlmsg(
1528                AuditNetlinkClient::build_audit_nlmsg(0, audit_type, message),
1529            ));
1530        }
1531        None
1532    }
1533
1534    /// Function to read the optional response if present or an audit message.
1535    fn read_nlmsg(self: &Arc<Self>, flags: SocketMessageFlags) -> Result<Vec<u8>, Errno> {
1536        // First check if there is a response and send it if present.
1537        // Send an audit message otherwise or return EAGAIN.
1538        self.get_nl_response(flags).or_else(|| self.read_audit_log()).ok_or_else(|| errno!(EAGAIN))
1539    }
1540
1541    fn process_get_status(
1542        &self,
1543        sequence_number: u32,
1544    ) -> Result<NetlinkMessage<GenericMessage>, Errno> {
1545        Ok(AuditNetlinkClient::build_audit_nlmsg(
1546            sequence_number,
1547            AUDIT_GET as u16,
1548            self.audit_logger.get_status().as_bytes().to_vec(),
1549        ))
1550    }
1551
1552    fn process_set_status(
1553        self: &Arc<Self>,
1554        current_task: &CurrentTask,
1555        nl_hdr: NetlinkHeader,
1556        nl_payload: Vec<u8>,
1557    ) -> Result<NetlinkMessage<GenericMessage>, Errno> {
1558        let Some(status) = audit_status::read_from_bytes(nl_payload.as_bytes()).ok() else {
1559            return error!(EINVAL);
1560        };
1561        self.audit_logger.set_status(current_task, status, self)?;
1562        Ok(AuditNetlinkClient::build_audit_ack(Ok(()), nl_hdr))
1563    }
1564
1565    fn process_user_audit(
1566        &self,
1567        nl_hdr: NetlinkHeader,
1568        nl_payload: Vec<u8>,
1569    ) -> Result<NetlinkMessage<GenericMessage>, Errno> {
1570        let audit_msg = String::from_utf8_lossy(nl_payload.as_bytes());
1571        self.audit_logger.audit_log(nl_hdr.message_type, move || audit_msg);
1572        Ok(AuditNetlinkClient::build_audit_ack(Ok(()), nl_hdr))
1573    }
1574
1575    fn query_events(self: &Arc<Self>) -> FdEvents {
1576        if self.audit_response.lock().is_some() || self.audit_logger.get_backlog_count(self) != 0 {
1577            return FdEvents::POLLIN;
1578        }
1579        FdEvents::empty()
1580    }
1581
1582    fn detach(self: &Arc<Self>) {
1583        self.audit_logger.detach_client(self);
1584    }
1585
1586    fn build_audit_nlmsg(
1587        seq_number: u32,
1588        msg_type: u16,
1589        payload: Vec<u8>,
1590    ) -> NetlinkMessage<GenericMessage> {
1591        // The family in GenericMessage can be used for message type, not only for the Netlink Family,
1592        // because after finalizing the message, the message type is equal to family.
1593        let nl_payload =
1594            NetlinkPayload::InnerMessage(GenericMessage::Other { family: msg_type, payload });
1595        let mut nl_header = NetlinkHeader::default();
1596        nl_header.sequence_number = seq_number;
1597        let mut message = NetlinkMessage::new(nl_header, nl_payload);
1598        message.finalize();
1599        message
1600    }
1601
1602    fn build_audit_ack(
1603        error: Result<(), Errno>,
1604        req_header: NetlinkHeader,
1605    ) -> NetlinkMessage<GenericMessage> {
1606        let error = {
1607            assert_eq!(req_header.buffer_len(), NETLINK_HEADER_LEN);
1608            let mut buffer = vec![0; NETLINK_HEADER_LEN];
1609            req_header.emit(&mut buffer);
1610
1611            let code = match error {
1612                Ok(()) => None,
1613                Err(e) => Some(
1614                    // Audit netlink errors are negative.
1615                    NonZeroI32::new(-(e.code.error_code() as i32))
1616                        .expect("Errno's code must be non-zero"),
1617                ),
1618            };
1619
1620            let mut error = ErrorMessage::default();
1621            error.code = code;
1622            error.header = buffer;
1623            error
1624        };
1625
1626        let payload = NetlinkPayload::<GenericMessage>::Error(error);
1627        let mut resp_header = NetlinkHeader::default();
1628        resp_header.message_type = NLMSG_ERROR;
1629        resp_header.sequence_number = req_header.sequence_number;
1630        let mut message = NetlinkMessage::new(resp_header, payload);
1631        message.finalize();
1632        message
1633    }
1634
1635    fn serialize_nlmsg(message: NetlinkMessage<GenericMessage>) -> Vec<u8> {
1636        let mut buf = vec![0; message.buffer_len()];
1637        message.serialize(&mut buf);
1638        buf
1639    }
1640}
1641
1642/// Audit Netlink Socket structure.
1643pub struct AuditNetlinkSocket {
1644    /// Reference to the `AuditNetlinkClient` associated with self.
1645    audit_client: Arc<AuditNetlinkClient>,
1646}
1647
1648impl AuditNetlinkSocket {
1649    pub fn new(kernel: &Kernel) -> Result<Self, Errno> {
1650        if kernel.audit_logger().is_disabled() {
1651            return error!(EPROTONOSUPPORT);
1652        }
1653        Ok(Self { audit_client: Arc::new(AuditNetlinkClient::new(kernel.audit_logger())) })
1654    }
1655}
1656
1657impl SocketOps for AuditNetlinkSocket {
1658    fn read(
1659        &self,
1660        _locked: &mut Locked<FileOpsCore>,
1661        _socket: &Socket,
1662        _current_task: &CurrentTask,
1663        data: &mut dyn OutputBuffer,
1664        flags: SocketMessageFlags,
1665    ) -> Result<MessageReadInfo, Errno> {
1666        let buf = self.audit_client.read_nlmsg(flags)?;
1667
1668        let size = data.write_all(buf.as_bytes())?;
1669        Ok(MessageReadInfo {
1670            bytes_read: size,
1671            message_length: size,
1672            address: Some(SocketAddress::Netlink(NetlinkAddress::default())),
1673            ancillary_data: vec![],
1674        })
1675    }
1676
1677    fn write(
1678        &self,
1679        _locked: &mut Locked<FileOpsCore>,
1680        socket: &Socket,
1681        current_task: &CurrentTask,
1682        data: &mut dyn InputBuffer,
1683        _dest_address: &mut Option<SocketAddress>,
1684        _ancillary_data: &mut Vec<AncillaryData>,
1685    ) -> Result<usize, Errno> {
1686        match NetlinkMessage::<GenericMessage>::deserialize(&(data.peek_all()?)) {
1687            Ok(nl_message) => {
1688                let header = nl_message.header;
1689                security::check_netlink_send_access(current_task, socket, header.message_type)?;
1690
1691                // Send request to the `AuditNetlinkClient`.
1692                let audit_ack = self
1693                    .audit_client
1694                    .process_request(current_task, nl_message)
1695                    .map_err(|e| AuditNetlinkClient::build_audit_ack(Err(e), header))
1696                    .unwrap_or_else(|nlerr| nlerr);
1697                *self.audit_client.audit_response.lock() = Some(audit_ack);
1698                data.drain();
1699                Ok(header.length as usize)
1700            }
1701            Err(e) => {
1702                log_warn!("Failed to process write; data could not be deserialized: {:?}", e);
1703                error!(EINVAL)
1704            }
1705        }
1706    }
1707
1708    fn wait_async(
1709        &self,
1710        _locked: &mut Locked<FileOpsCore>,
1711        _socket: &Socket,
1712        _current_task: &CurrentTask,
1713        waiter: &Waiter,
1714        events: FdEvents,
1715        handler: EventHandler,
1716    ) -> WaitCanceler {
1717        self.audit_client.waiters.wait_async_fd_events(waiter, events, handler)
1718    }
1719
1720    fn query_events(
1721        &self,
1722        _locked: &mut Locked<FileOpsCore>,
1723        _socket: &Socket,
1724        _current_task: &CurrentTask,
1725    ) -> Result<FdEvents, Errno> {
1726        Ok(self.audit_client.query_events() & FdEvents::POLLIN)
1727    }
1728
1729    fn close(
1730        &self,
1731        _locked: &mut Locked<FileOpsCore>,
1732        _current_task: &CurrentTask,
1733        _socket: &Socket,
1734    ) {
1735        // If the `AuditNetlinkClient` disconnects, detach it.
1736        self.audit_client.detach();
1737    }
1738
1739    fn shutdown(
1740        &self,
1741        _locked: &mut Locked<FileOpsCore>,
1742        _socket: &Socket,
1743        _how: SocketShutdownFlags,
1744    ) -> Result<(), Errno> {
1745        error!(EOPNOTSUPP)
1746    }
1747
1748    fn connect(
1749        &self,
1750        _locked: &mut Locked<FileOpsCore>,
1751        _socket: &SocketHandle,
1752        _current_task: &CurrentTask,
1753        _peer: SocketPeer,
1754    ) -> Result<(), Errno> {
1755        error!(EOPNOTSUPP)
1756    }
1757
1758    fn listen(
1759        &self,
1760        _locked: &mut Locked<FileOpsCore>,
1761        _socket: &Socket,
1762        _backlog: i32,
1763        _credentials: ucred,
1764    ) -> Result<(), Errno> {
1765        error!(EOPNOTSUPP)
1766    }
1767
1768    fn accept(
1769        &self,
1770        _locked: &mut Locked<FileOpsCore>,
1771        _socket: &Socket,
1772        _current_task: &CurrentTask,
1773    ) -> Result<SocketHandle, Errno> {
1774        error!(EOPNOTSUPP)
1775    }
1776
1777    fn bind(
1778        &self,
1779        _locked: &mut Locked<FileOpsCore>,
1780        _socket: &Socket,
1781        _current_task: &CurrentTask,
1782        _socket_address: SocketAddress,
1783    ) -> Result<(), Errno> {
1784        error!(EOPNOTSUPP)
1785    }
1786
1787    fn getsockname(
1788        &self,
1789        _locked: &mut Locked<FileOpsCore>,
1790        _socket: &Socket,
1791    ) -> Result<SocketAddress, Errno> {
1792        error!(EOPNOTSUPP)
1793    }
1794
1795    fn getpeername(
1796        &self,
1797        _locked: &mut Locked<FileOpsCore>,
1798        _socket: &Socket,
1799    ) -> Result<SocketAddress, Errno> {
1800        error!(EOPNOTSUPP)
1801    }
1802
1803    fn getsockopt(
1804        &self,
1805        _locked: &mut Locked<FileOpsCore>,
1806        _socket: &Socket,
1807        _current_task: &CurrentTask,
1808        _level: u32,
1809        _optname: u32,
1810        _optlen: u32,
1811    ) -> Result<Vec<u8>, Errno> {
1812        error!(EOPNOTSUPP)
1813    }
1814
1815    fn setsockopt(
1816        &self,
1817        _locked: &mut Locked<FileOpsCore>,
1818        _socket: &Socket,
1819        _current_task: &CurrentTask,
1820        _level: u32,
1821        _optname: u32,
1822        _optval: SockOptValue,
1823    ) -> Result<(), Errno> {
1824        error!(EOPNOTSUPP)
1825    }
1826}
1827
1828#[cfg(test)]
1829mod tests {
1830    use super::*;
1831
1832    use netlink_packet_route::RouteNetlinkMessage;
1833    use netlink_packet_route::route::RouteMessage;
1834    use test_case::test_case;
1835
1836    // Successfully send the message and observe it's stored in the queue.
1837    #[test_case(true; "sufficient_capacity")]
1838    // Attempting to send when the queue is full should succeed by increasing
1839    // the size of the queue.
1840    #[test_case(false; "insufficient_capacity")]
1841    fn test_netlink_to_client_sender(sufficient_capacity: bool) {
1842        const MODERN_GROUP: u32 = 5;
1843
1844        let mut message: NetlinkMessage<RouteNetlinkMessage> =
1845            RouteNetlinkMessage::NewRoute(RouteMessage::default()).into();
1846        message.finalize();
1847
1848        let (initial_queue_size, final_queue_size) = if sufficient_capacity {
1849            (SOCKET_DEFAULT_SIZE, SOCKET_DEFAULT_SIZE)
1850        } else {
1851            (0, message.buffer_len())
1852        };
1853
1854        let socket_inner = Arc::new(Mutex::new(NetlinkSocketInner {
1855            receive_buffer: MessageQueue::new(initial_queue_size),
1856            ..NetlinkSocketInner::new(NetlinkFamily::Route)
1857        }));
1858
1859        let mut sender = NetlinkToClientSender::<RouteNetlinkMessage>::new(socket_inner.clone());
1860        sender.send(message.clone(), Some(ModernGroup(MODERN_GROUP)));
1861        let Message { data, address, ancillary_data: _ } =
1862            socket_inner.lock().read_message().expect("should read message");
1863
1864        assert_eq!(
1865            address,
1866            Some(SocketAddress::Netlink(NetlinkAddress { pid: 0, groups: 1 << MODERN_GROUP }))
1867        );
1868        let actual_message = NetlinkMessage::<RouteNetlinkMessage>::deserialize(&data)
1869            .expect("message should deserialize into RtnlMessage");
1870        assert_eq!(actual_message, message);
1871        assert_eq!(socket_inner.lock().receive_buffer.capacity(), final_queue_size);
1872    }
1873
1874    fn getsockopt_u32(socket: &NetlinkSocketInner, level: u32, optname: u32) -> u32 {
1875        let byte_vec = socket.getsockopt(level, optname).expect("getsockopt should succeed");
1876        let bytes: [u8; 4] = byte_vec.as_slice().try_into().expect("expected 4 bytes");
1877        u32::from_ne_bytes(bytes)
1878    }
1879
1880    fn sock_opt_value(val: u32) -> SockOptValue {
1881        SockOptValue::Value(val.to_ne_bytes().to_vec())
1882    }
1883
1884    #[::fuchsia::test]
1885    async fn test_set_get_snd_rcv_buf() {
1886        crate::testing::spawn_kernel_and_run_sync(|_locked, current_task| {
1887            let mut socket = NetlinkSocketInner::new(NetlinkFamily::Route);
1888
1889            // Verify initialization uses the default value.
1890            let expected_default = u32::try_from(SOCKET_DEFAULT_SIZE).unwrap();
1891            assert_eq!(getsockopt_u32(&socket, SOL_SOCKET, SO_SNDBUF), expected_default);
1892            assert_eq!(getsockopt_u32(&socket, SOL_SOCKET, SO_RCVBUF), expected_default);
1893
1894            // Set new values and observe that they were applied.
1895            // Note that applied value is 2 times the requested value.
1896            const SNDBUF_SIZE: u32 = 12345;
1897            const RCVBUF_SIZE: u32 = 54321;
1898            socket
1899                .setsockopt(current_task, SOL_SOCKET, SO_SNDBUF, sock_opt_value(SNDBUF_SIZE))
1900                .expect("setsockopt should succeed");
1901            socket
1902                .setsockopt(current_task, SOL_SOCKET, SO_RCVBUF, sock_opt_value(RCVBUF_SIZE))
1903                .expect("setsockopt should succeed");
1904            assert_eq!(getsockopt_u32(&socket, SOL_SOCKET, SO_SNDBUF), SNDBUF_SIZE * 2);
1905            assert_eq!(getsockopt_u32(&socket, SOL_SOCKET, SO_RCVBUF), RCVBUF_SIZE * 2);
1906        })
1907        .await;
1908    }
1909
1910    #[::fuchsia::test]
1911    async fn test_snd_rcv_buf_limits() {
1912        crate::testing::spawn_kernel_and_run_sync(|_locked, current_task| {
1913            let mut socket = NetlinkSocketInner::new(NetlinkFamily::Route);
1914            let too_big = u32::try_from(SOCKET_MAX_SIZE).unwrap() + 1;
1915
1916            // SO_SNDBUF and SO_RCVBUF clamp the size to the limit.
1917            socket
1918                .setsockopt(current_task, SOL_SOCKET, SO_SNDBUF, sock_opt_value(too_big))
1919                .expect("setsockopt should succeed");
1920            socket
1921                .setsockopt(current_task, SOL_SOCKET, SO_RCVBUF, sock_opt_value(too_big))
1922                .expect("setsockopt should succeed");
1923            let expected_max = u32::try_from(SOCKET_MAX_SIZE).unwrap();
1924            assert_eq!(getsockopt_u32(&socket, SOL_SOCKET, SO_SNDBUF), expected_max);
1925            assert_eq!(getsockopt_u32(&socket, SOL_SOCKET, SO_RCVBUF), expected_max);
1926
1927            // SO_SNDBUFFORCE and SO_RCVBUFFORCE do not.
1928            // Note that the applied value is two times the requested value.
1929            socket
1930                .setsockopt(current_task, SOL_SOCKET, SO_SNDBUFFORCE, sock_opt_value(too_big))
1931                .expect("setsockopt should succeed");
1932            socket
1933                .setsockopt(current_task, SOL_SOCKET, SO_RCVBUFFORCE, sock_opt_value(too_big))
1934                .expect("setsockopt should succeed");
1935            assert_eq!(getsockopt_u32(&socket, SOL_SOCKET, SO_SNDBUF), too_big * 2);
1936            assert_eq!(getsockopt_u32(&socket, SOL_SOCKET, SO_RCVBUF), too_big * 2);
1937        })
1938        .await;
1939    }
1940}