From 5ccadb6253ea398e3f6db56117acbc2c89e255d8 Mon Sep 17 00:00:00 2001 From: Ruihan Li Date: Wed, 25 Jun 2025 23:55:42 +0800 Subject: [PATCH] Support SOCK_SEQPACKET --- .../src/net/socket/unix/stream/connected.rs | 59 ++++- kernel/src/net/socket/unix/stream/init.rs | 2 + kernel/src/net/socket/unix/stream/listener.rs | 40 ++- kernel/src/net/socket/unix/stream/socket.rs | 35 ++- kernel/src/syscall/socket.rs | 11 +- kernel/src/syscall/socketpair.rs | 9 +- kernel/src/util/ring_buffer.rs | 18 ++ test/src/apps/network/unix_seqpacket_err.c | 67 +++++ test/src/apps/network/unix_stream_err.c | 117 +++++++++ .../apps/network/unix_streamlike_epilogue.h | 19 ++ ...{unix_err.c => unix_streamlike_prologue.h} | 231 ++++-------------- test/src/apps/scripts/network.sh | 3 +- test/src/apps/test.h | 20 +- test/src/syscall/gvisor/Makefile | 3 + .../gvisor/blocklists/socket_unix_pair_test | 24 +- .../socket_unix_seqpacket_local_test | 13 + 16 files changed, 437 insertions(+), 234 deletions(-) create mode 100644 test/src/apps/network/unix_seqpacket_err.c create mode 100644 test/src/apps/network/unix_stream_err.c create mode 100644 test/src/apps/network/unix_streamlike_epilogue.h rename test/src/apps/network/{unix_err.c => unix_streamlike_prologue.h} (73%) create mode 100644 test/src/syscall/gvisor/blocklists/socket_unix_seqpacket_local_test diff --git a/kernel/src/net/socket/unix/stream/connected.rs b/kernel/src/net/socket/unix/stream/connected.rs index 7b420244d..ae8460306 100644 --- a/kernel/src/net/socket/unix/stream/connected.rs +++ b/kernel/src/net/socket/unix/stream/connected.rs @@ -99,8 +99,10 @@ impl Connected { pub(super) fn try_read( &self, writer: &mut dyn MultiWrite, + is_seqpacket: bool, ) -> Result<(usize, Vec)> { - if writer.is_empty() { + let is_empty = writer.is_empty(); + if is_empty && !is_seqpacket { if self.reader.lock().is_empty() { return_errno_with_message!(Errno::EAGAIN, "the channel is empty"); } @@ -158,9 +160,12 @@ impl Connected { } // Read the payload bytes of the current auxiliary data. - let read_res = self - .inner - .read_with(|| reader.read_fallible_with_max_len(writer, aux_len)); + let read_res = if !is_empty && aux_len > 0 { + self.inner + .read_with(|| reader.read_fallible_with_max_len(writer, aux_len)) + } else { + Ok(0) + }; let read_len = match read_res { Ok(read_len) => read_len, Err(_) if read_tot_len > 0 => break aux_prev_data.as_mut().unwrap(), @@ -168,8 +173,16 @@ impl Connected { }; read_tot_len += read_len; - // Record the current auxiliary data. Break if the read is incomplete. - if let Some(front) = aux_front { + // Record the current auxiliary data. Break if the read is incomplete or this is a + // `SOCK_SEQPACKET` socket. + if is_seqpacket { + aux_prev_data = Some(all_aux.pop_front().unwrap().data); + if read_len < aux_len { + warn!("setting MSG_TRUNC is not supported"); + reader.skip(aux_len - read_len); + } + break aux_prev_data.as_mut().unwrap(); + } else if let Some(front) = aux_front { if read_len < aux_len { front.start += read_len; break &mut front.data; @@ -186,7 +199,7 @@ impl Connected { drop(reader); let ctrl_msgs = aux_data.generate_control(is_pass_cred); - debug_assert_ne!(read_tot_len, 0); + debug_assert!(is_empty || read_tot_len != 0); peer_end .has_aux .store(!all_aux.is_empty(), Ordering::Relaxed); @@ -198,12 +211,20 @@ impl Connected { &self, reader: &mut dyn MultiRead, aux_data: &mut AuxiliaryData, + is_seqpacket: bool, ) -> Result { - if reader.is_empty() { + let is_empty = reader.is_empty(); + if is_empty { if self.inner.is_shutdown() { return_errno_with_message!(Errno::EPIPE, "the channel is shut down"); } - return Ok(0); + if !is_seqpacket { + return Ok(0); + } + } + + if is_seqpacket && reader.sum_lens() >= UNIX_STREAM_DEFAULT_BUF_SIZE { + return_errno_with_message!(Errno::EMSGSIZE, "the message is too large"); } let this_end = self.inner.this_end(); @@ -211,9 +232,14 @@ impl Connected { || self.inner.peer_end().is_pass_cred.load(Ordering::Relaxed); // Fast path: There are no auxiliary data to transmit. - if aux_data.is_empty() && !need_pass_cred { + if aux_data.is_empty() && !is_seqpacket && !need_pass_cred { let mut writer = self.writer.lock(); - return self.inner.write_with(move || writer.write_fallible(reader)); + return self.inner.write_with(move || { + if is_seqpacket && writer.free_len() < reader.sum_lens() { + return Ok(0); + } + writer.write_fallible(reader) + }); } let mut all_aux = this_end.all_aux.lock(); @@ -223,11 +249,18 @@ impl Connected { this_end.has_aux.store(true, Ordering::Relaxed); // Write the payload bytes. - let (write_start, write_res) = { + let (write_start, write_res) = if !is_empty { let mut writer = self.writer.lock(); let write_start = writer.tail(); - let write_res = self.inner.write_with(move || writer.write_fallible(reader)); + let write_res = self.inner.write_with(move || { + if is_seqpacket && writer.free_len() < reader.sum_lens() { + return Ok(0); + } + writer.write_fallible(reader) + }); (write_start, write_res) + } else { + (self.writer.lock().tail(), Ok(0)) }; let Ok(write_len) = write_res else { this_end diff --git a/kernel/src/net/socket/unix/stream/init.rs b/kernel/src/net/socket/unix/stream/init.rs index 94cb1c685..ddc9db26e 100644 --- a/kernel/src/net/socket/unix/stream/init.rs +++ b/kernel/src/net/socket/unix/stream/init.rs @@ -82,6 +82,7 @@ impl Init { self, backlog: usize, pollee: Pollee, + is_seqpacket: bool, ) -> core::result::Result { let Some(addr) = self.addr else { return Err(( @@ -98,6 +99,7 @@ impl Init { self.is_read_shutdown.into_inner(), self.is_write_shutdown.into_inner(), pollee, + is_seqpacket, )) } diff --git a/kernel/src/net/socket/unix/stream/listener.rs b/kernel/src/net/socket/unix/stream/listener.rs index b3c6c9c51..6ac435268 100644 --- a/kernel/src/net/socket/unix/stream/listener.rs +++ b/kernel/src/net/socket/unix/stream/listener.rs @@ -38,9 +38,10 @@ impl Listener { is_read_shutdown: bool, is_write_shutdown: bool, pollee: Pollee, + is_seqpacket: bool, ) -> Self { let backlog = BACKLOG_TABLE - .add_backlog(addr, pollee, backlog, is_read_shutdown) + .add_backlog(addr, pollee, backlog, is_read_shutdown, is_seqpacket) .unwrap(); Self { @@ -53,13 +54,13 @@ impl Listener { self.backlog.addr() } - pub(super) fn try_accept(&self) -> Result<(Arc, SocketAddr)> { + pub(super) fn try_accept(&self, is_seqpacket: bool) -> Result<(Arc, SocketAddr)> { let connected = self.backlog.pop_incoming()?; let peer_addr = connected.peer_addr().into(); // TODO: Update options for a newly-accepted socket let options = OptionSet::new(); - let socket = UnixStreamSocket::new_connected(connected, options, false); + let socket = UnixStreamSocket::new_connected(connected, options, false, is_seqpacket); Ok((socket, peer_addr)) } @@ -123,6 +124,7 @@ impl BacklogTable { pollee: Pollee, backlog: usize, is_shutdown: bool, + is_seqpacket: bool, ) -> Option> { let addr_key = addr.to_key(); @@ -132,7 +134,13 @@ impl BacklogTable { return None; } - let new_backlog = Arc::new(Backlog::new(addr, pollee, backlog, is_shutdown)); + let new_backlog = Arc::new(Backlog::new( + addr, + pollee, + backlog, + is_shutdown, + is_seqpacket, + )); backlog_sockets.insert(addr_key, new_backlog.clone()); Some(new_backlog) @@ -154,10 +162,17 @@ pub(super) struct Backlog { incoming_conns: SpinLock>>, wait_queue: WaitQueue, listener_cred: SocketCred, + is_seqpacket: bool, } impl Backlog { - fn new(addr: UnixSocketAddrBound, pollee: Pollee, backlog: usize, is_shutdown: bool) -> Self { + fn new( + addr: UnixSocketAddrBound, + pollee: Pollee, + backlog: usize, + is_shutdown: bool, + is_seqpacket: bool, + ) -> Self { let incoming_sockets = if is_shutdown { None } else { @@ -171,6 +186,7 @@ impl Backlog { incoming_conns: SpinLock::new(incoming_sockets), wait_queue: WaitQueue::new(), listener_cred: SocketCred::::new_current(), + is_seqpacket, } } @@ -235,7 +251,21 @@ impl Backlog { init: Init, pollee: Pollee, options: &SocketOptionSet, + is_seqpacket: bool, ) -> core::result::Result { + if is_seqpacket != self.is_seqpacket { + // FIXME: According to the Linux implementation, we should avoid this error by + // maintaining two socket tables for SOCK_STREAM sockets and SOCK_SEQPACKET sockets + // separately. + return Err(( + Error::with_message( + Errno::ECONNREFUSED, + "the listening socket has a different socket type", + ), + init, + )); + } + let mut locked_incoming_conns = self.incoming_conns.lock(); let Some(incoming_conns) = &mut *locked_incoming_conns else { diff --git a/kernel/src/net/socket/unix/stream/socket.rs b/kernel/src/net/socket/unix/stream/socket.rs index 6fc309977..8b2818c84 100644 --- a/kernel/src/net/socket/unix/stream/socket.rs +++ b/kernel/src/net/socket/unix/stream/socket.rs @@ -39,15 +39,18 @@ pub struct UnixStreamSocket { pollee: Pollee, is_nonblocking: AtomicBool, + + is_seqpacket: bool, } impl UnixStreamSocket { - pub(super) fn new_init(init: Init, is_nonblocking: bool) -> Arc { + pub(super) fn new_init(init: Init, is_nonblocking: bool, is_seqpacket: bool) -> Arc { Arc::new(Self { state: RwMutex::new(Takeable::new(State::Init(init))), options: RwMutex::new(OptionSet::new()), pollee: Pollee::new(), is_nonblocking: AtomicBool::new(is_nonblocking), + is_seqpacket, }) } @@ -55,6 +58,7 @@ impl UnixStreamSocket { connected: Connected, options: OptionSet, is_nonblocking: bool, + is_seqpacket: bool, ) -> Arc { let cloned_pollee = connected.cloned_pollee(); Arc::new(Self { @@ -62,6 +66,7 @@ impl UnixStreamSocket { options: RwMutex::new(options), pollee: cloned_pollee, is_nonblocking: AtomicBool::new(is_nonblocking), + is_seqpacket, }) } } @@ -155,11 +160,11 @@ impl OptionSet { } impl UnixStreamSocket { - pub fn new(is_nonblocking: bool) -> Arc { - Self::new_init(Init::new(), is_nonblocking) + pub fn new(is_nonblocking: bool, is_seqpacket: bool) -> Arc { + Self::new_init(Init::new(), is_nonblocking, is_seqpacket) } - pub fn new_pair(is_nonblocking: bool) -> (Arc, Arc) { + pub fn new_pair(is_nonblocking: bool, is_seqpacket: bool) -> (Arc, Arc) { let cred = SocketCred::::new_current(); let options = OptionSet::new(); @@ -173,8 +178,8 @@ impl UnixStreamSocket { &options.socket, ); ( - Self::new_connected(conn_a, options, is_nonblocking), - Self::new_connected(conn_b, OptionSet::new(), is_nonblocking), + Self::new_connected(conn_a, options, is_nonblocking, is_seqpacket), + Self::new_connected(conn_b, OptionSet::new(), is_nonblocking, is_seqpacket), ) } @@ -185,7 +190,7 @@ impl UnixStreamSocket { _flags: SendRecvFlags, ) -> Result { match self.state.read().as_ref() { - State::Connected(connected) => connected.try_write(buf, aux_data), + State::Connected(connected) => connected.try_write(buf, aux_data, self.is_seqpacket), State::Init(_) | State::Listen(_) => { return_errno_with_message!(Errno::ENOTCONN, "the socket is not connected") } @@ -198,7 +203,7 @@ impl UnixStreamSocket { _flags: SendRecvFlags, ) -> Result<(usize, Vec)> { match self.state.read().as_ref() { - State::Connected(connected) => connected.try_read(buf), + State::Connected(connected) => connected.try_read(buf, self.is_seqpacket), State::Init(_) | State::Listen(_) => { return_errno_with_message!(Errno::EINVAL, "the socket is not connected") } @@ -232,8 +237,12 @@ impl UnixStreamSocket { } }; - let connected = match backlog.push_incoming(init, self.pollee.clone(), &options.socket) - { + let connected = match backlog.push_incoming( + init, + self.pollee.clone(), + &options.socket, + self.is_seqpacket, + ) { Ok(connected) => connected, Err((err, init)) => return (State::Init(init), Err(err)), }; @@ -244,7 +253,7 @@ impl UnixStreamSocket { fn try_accept(&self) -> Result<(Arc, SocketAddr)> { match self.state.read().as_ref() { - State::Listen(listen) => listen.try_accept() as _, + State::Listen(listen) => listen.try_accept(self.is_seqpacket) as _, State::Init(_) | State::Connected(_) => { return_errno_with_message!(Errno::EINVAL, "the socket is not listening") } @@ -326,7 +335,7 @@ impl Socket for UnixStreamSocket { } }; - let listener = match init.listen(backlog, self.pollee.clone()) { + let listener = match init.listen(backlog, self.pollee.clone(), self.is_seqpacket) { Ok(listener) => listener, Err((err, init)) => { return (State::Init(init), Err(err)); @@ -391,7 +400,7 @@ impl Socket for UnixStreamSocket { // According to the Linux man pages, `EISCONN` _may_ be returned when the destination // address is specified for a connection-mode socket. In practice, `sendmsg` on UNIX stream // sockets will fail due to that. We follow the same behavior as the Linux implementation. - if addr.is_some() { + if !self.is_seqpacket && addr.is_some() { match self.state.read().as_ref() { State::Init(_) | State::Listen(_) => return_errno_with_message!( Errno::EOPNOTSUPP, diff --git a/kernel/src/syscall/socket.rs b/kernel/src/syscall/socket.rs index 78f027c7d..fd0a1414c 100644 --- a/kernel/src/syscall/socket.rs +++ b/kernel/src/syscall/socket.rs @@ -23,11 +23,14 @@ pub fn sys_socket(domain: i32, type_: i32, protocol: i32, ctx: &Context) -> Resu "domain = {:?}, sock_type = {:?}, sock_flags = {:?}", domain, sock_type, sock_flags ); + let is_nonblocking = sock_flags.contains(SockFlags::SOCK_NONBLOCK); let file_like = match (domain, sock_type) { - // FIXME: SOCK_SEQPACKET is added to run fcntl_test, not supported yet. - (CSocketAddrFamily::AF_UNIX, SockType::SOCK_STREAM | SockType::SOCK_SEQPACKET) => { - UnixStreamSocket::new(is_nonblocking) as Arc + (CSocketAddrFamily::AF_UNIX, SockType::SOCK_STREAM) => { + UnixStreamSocket::new(is_nonblocking, false) as Arc + } + (CSocketAddrFamily::AF_UNIX, SockType::SOCK_SEQPACKET) => { + UnixStreamSocket::new(is_nonblocking, true) as Arc } (CSocketAddrFamily::AF_INET, SockType::SOCK_STREAM) => { let protocol = Protocol::try_from(protocol)?; @@ -81,6 +84,7 @@ pub fn sys_socket(domain: i32, type_: i32, protocol: i32, ctx: &Context) -> Resu } _ => return_errno_with_message!(Errno::EAFNOSUPPORT, "unsupported domain"), }; + let fd = { let file_table = ctx.thread_local.borrow_file_table(); let mut file_table_locked = file_table.unwrap().write(); @@ -91,5 +95,6 @@ pub fn sys_socket(domain: i32, type_: i32, protocol: i32, ctx: &Context) -> Resu }; file_table_locked.insert(file_like, fd_flags) }; + Ok(SyscallReturn::Return(fd as _)) } diff --git a/kernel/src/syscall/socketpair.rs b/kernel/src/syscall/socketpair.rs index 71d11193f..0aad21e93 100644 --- a/kernel/src/syscall/socketpair.rs +++ b/kernel/src/syscall/socketpair.rs @@ -19,16 +19,19 @@ pub fn sys_socketpair( let sock_type = SockType::try_from(type_ & SOCK_TYPE_MASK)?; let sock_flags = SockFlags::from_bits_truncate(type_ & !SOCK_TYPE_MASK); let protocol = Protocol::try_from(protocol)?; - debug!( "domain = {:?}, sock_type = {:?}, sock_flags = {:?}, protocol = {:?}", domain, sock_type, sock_flags, protocol ); + // TODO: deal with all sock_flags and protocol let nonblocking = sock_flags.contains(SockFlags::SOCK_NONBLOCK); let (socket_a, socket_b) = match (domain, sock_type) { (CSocketAddrFamily::AF_UNIX, SockType::SOCK_STREAM) => { - UnixStreamSocket::new_pair(nonblocking) + UnixStreamSocket::new_pair(nonblocking, false) + } + (CSocketAddrFamily::AF_UNIX, SockType::SOCK_SEQPACKET) => { + UnixStreamSocket::new_pair(nonblocking, true) } _ => return_errno_with_message!( Errno::EAFNOSUPPORT, @@ -48,8 +51,8 @@ pub fn sys_socketpair( let fd_b = file_table_locked.insert(socket_b, fd_flags); SocketFds(fd_a, fd_b) }; - ctx.user_space().write_val(sv, &socket_fds)?; + Ok(SyscallReturn::Return(0)) } diff --git a/kernel/src/util/ring_buffer.rs b/kernel/src/util/ring_buffer.rs index fcf7c5973..9052d3b93 100644 --- a/kernel/src/util/ring_buffer.rs +++ b/kernel/src/util/ring_buffer.rs @@ -346,6 +346,8 @@ impl>> Producer { rb.advance_tail(tail, write_len); Ok(write_len) } + + // There is no counterpart to `Consumer::skip`. It does not make sense for the producer. } #[inherit_methods(from = "self.rb")] @@ -460,6 +462,22 @@ impl>> Consumer { rb.advance_head(head, read_len); Ok(read_len) } + + /// Skips `count` bytes in the `RingBuffer`. + /// + /// In other words, `count` bytes are read from the `RingBuffer` and discarded. + /// + /// # Panics + /// + /// This method will panic if the number of the available bytes to read is less than `count`. + pub fn skip(&mut self, count: usize) { + let rb = &self.rb; + let len = rb.len(); + assert!(len >= count); + + let head = rb.head(); + rb.advance_head(head, count); + } } #[inherit_methods(from = "self.rb")] diff --git a/test/src/apps/network/unix_seqpacket_err.c b/test/src/apps/network/unix_seqpacket_err.c new file mode 100644 index 000000000..e4bfa8a7b --- /dev/null +++ b/test/src/apps/network/unix_seqpacket_err.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: MPL-2.0 + +#define SOCK_TYPE SOCK_SEQPACKET +#include "unix_streamlike_prologue.h" + +FN_TEST(sendto) +{ + char buf[1] = { 'z' }; + + TEST_ERRNO(sendto(sk_unbound, buf, 1, 0, &LISTEN_ADDR, LISTEN_ADDRLEN), + ENOTCONN); + TEST_ERRNO(sendto(sk_bound, buf, 1, 0, &LISTEN_ADDR2, LISTEN_ADDRLEN2), + ENOTCONN); + TEST_ERRNO(sendto(sk_listen, buf, 1, 0, &BOUND_ADDR, BOUND_ADDRLEN), + ENOTCONN); +} +END_TEST() + +FN_TEST(send_recv_trunc) +{ + int fildes[2]; + char buf[1]; + + TEST_SUCC( + socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, fildes)); + + TEST_SUCC(send(fildes[0], "abc", 3, 0)); + TEST_SUCC(send(fildes[0], "def", 3, 0)); + TEST_SUCC(send(fildes[0], "hij", 3, 0)); + + TEST_RES(recv(fildes[1], buf, 1, 0), _ret == 1 && buf[0] == 'a'); + TEST_RES(recv(fildes[1], buf, 0, 0), _ret == 0); + TEST_RES(recv(fildes[1], buf, 1, 0), _ret == 1 && buf[0] == 'h'); + + TEST_SUCC(close(fildes[0])); + TEST_SUCC(close(fildes[1])); +} +END_TEST() + +FN_TEST(send_recv_zero) +{ + int fildes[2]; + char buf[1]; + + TEST_SUCC( + socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, fildes)); + + buf[0] = 'a'; + TEST_SUCC(send(fildes[0], buf, 1, 0)); + buf[0] = 'b'; + TEST_SUCC(send(fildes[0], buf, 0, 0)); + buf[0] = 'c'; + TEST_SUCC(send(fildes[0], buf, 0, 0)); + buf[0] = 'd'; + TEST_SUCC(send(fildes[0], buf, 1, 0)); + + TEST_RES(recv(fildes[1], buf, 1, 0), _ret == 1 && buf[0] == 'a'); + TEST_RES(recv(fildes[1], buf, 1, 0), _ret == 0 && buf[0] == 'a'); + TEST_RES(recv(fildes[1], buf, 1, 0), _ret == 0 && buf[0] == 'a'); + TEST_RES(recv(fildes[1], buf, 1, 0), _ret == 1 && buf[0] == 'd'); + + TEST_SUCC(close(fildes[0])); + TEST_SUCC(close(fildes[1])); +} +END_TEST() + +#include "unix_streamlike_epilogue.h" diff --git a/test/src/apps/network/unix_stream_err.c b/test/src/apps/network/unix_stream_err.c new file mode 100644 index 000000000..f6ee1c76a --- /dev/null +++ b/test/src/apps/network/unix_stream_err.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: MPL-2.0 + +#define SOCK_TYPE SOCK_STREAM +#include "unix_streamlike_prologue.h" + +FN_TEST(sendto) +{ + char buf[1] = { 'z' }; + + TEST_ERRNO(sendto(sk_unbound, buf, 1, 0, &LISTEN_ADDR, LISTEN_ADDRLEN), + EOPNOTSUPP); + TEST_ERRNO(sendto(sk_bound, buf, 1, 0, &LISTEN_ADDR2, LISTEN_ADDRLEN2), + EOPNOTSUPP); + TEST_ERRNO(sendto(sk_listen, buf, 1, 0, &BOUND_ADDR, BOUND_ADDRLEN), + EOPNOTSUPP); + TEST_ERRNO(sendto(sk_accepted, buf, 1, 0, &UNNAMED_ADDR, + UNNAMED_ADDRLEN), + EISCONN); +} +END_TEST() + +FN_TEST(scm_rights) +{ + int fildes[2]; + char buf[20] = "abcdefg"; + char cbuf[CMSG_SPACE(sizeof(int) * 3)]; + struct iovec iov; + struct msghdr mhdr; + struct cmsghdr *chdr; + int *cdata; + int cfds[2]; + + TEST_SUCC(socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fildes)); + + memset(&mhdr, 0, sizeof(mhdr)); + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = cbuf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(int) * 3); + + iov.iov_base = buf; + iov.iov_len = 1; + + chdr = CMSG_FIRSTHDR(&mhdr); + chdr->cmsg_level = SOL_SOCKET; + chdr->cmsg_type = SCM_RIGHTS; + chdr->cmsg_len = CMSG_SPACE(sizeof(int) * 3); + + cdata = (int *)CMSG_DATA(chdr); + TEST_SUCC(pipe(cfds)); + cdata[0] = cfds[0]; + cdata[1] = cfds[0]; + cdata[2] = cfds[1]; + + // Sending control messages with zero bytes to a stream socket + // seems to "succeed". However, no data or control messages can + // be transmitted. + mhdr.msg_iovlen = 0; + TEST_SUCC(sendmsg(fildes[0], &mhdr, 0)); + mhdr.msg_iovlen = 1; + + // > (1) sendmsg(2) of four bytes, with no ancillary data. + // > (2) sendmsg(2) of one byte, with ancillary data. + // > (3) sendmsg(2) of four bytes, with no ancillary data. + // -- https://man7.org/linux/man-pages/man7/unix.7.html + TEST_RES(send(fildes[0], buf, 4, 0), _ret == 4); + TEST_RES(sendmsg(fildes[0], &mhdr, 0), _ret == 1); + TEST_RES(send(fildes[0], buf, 4, 0), _ret == 4); + + memset(&mhdr, 0, sizeof(mhdr)); + mhdr.msg_iov = &iov; + mhdr.msg_iovlen = 1; + mhdr.msg_control = cbuf; + mhdr.msg_controllen = CMSG_SPACE(sizeof(int)); + + iov.iov_base = buf; + iov.iov_len = sizeof(buf); + + memset(cbuf, 0, sizeof(cbuf)); + + // > Suppose that the receiver now performs recvmsg(2) calls each with + // > a buffer size of 20 bytes. The first call will receive five bytes + // > of data, along with the ancillary data sent by the second + // > sendmsg(2) call. + TEST_RES(recvmsg(fildes[1], &mhdr, 0), + _ret == 5 && + mhdr.msg_controllen == CMSG_SPACE(sizeof(int) * 2) && + (chdr = CMSG_FIRSTHDR(&mhdr)) && + chdr->cmsg_level == SOL_SOCKET && + chdr->cmsg_type == SCM_RIGHTS && + chdr->cmsg_len == CMSG_SPACE(sizeof(int) * 2) && + (cdata = (int *)CMSG_DATA(chdr)) && + cdata[0] == cfds[1] + 1 && cdata[1] == cfds[1] + 2); + // > The next call will receive the remaining four + // > bytes of data. + TEST_RES(recv(fildes[1], buf, sizeof(buf), 0), _ret == 4); + + // The purpose of the tests below is to verify that the received file + // descriptors are functional. + TEST_RES(write(cfds[1], "x", 1), _ret == 1); + TEST_RES(read(cdata[0], buf, 1), _ret == 1 && buf[0] == 'x'); + TEST_RES(write(cfds[1], "y", 1), _ret == 1); + TEST_RES(read(cdata[1], buf, 1), _ret == 1 && buf[0] == 'y'); + + TEST_SUCC(close(cdata[0])); + TEST_SUCC(close(cdata[1])); + TEST_SUCC(close(cfds[0])); + + TEST_ERRNO(write(cfds[1], "y", 1), EPIPE); + TEST_SUCC(close(cfds[1])); + + TEST_SUCC(close(fildes[0])); + TEST_SUCC(close(fildes[1])); +} +END_TEST() + +#include "unix_streamlike_epilogue.h" diff --git a/test/src/apps/network/unix_streamlike_epilogue.h b/test/src/apps/network/unix_streamlike_epilogue.h new file mode 100644 index 000000000..9dbe9f782 --- /dev/null +++ b/test/src/apps/network/unix_streamlike_epilogue.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: MPL-2.0 */ + +FN_SETUP(cleanup) +{ + CHECK(close(sk_unbound)); + + CHECK(close(sk_bound)); + + CHECK(close(sk_listen)); + + CHECK(close(sk_connected)); + + CHECK(close(sk_accepted)); + + CHECK(unlink(BOUND_ADDR.sun_path)); + + CHECK(unlink(LISTEN_ADDR.sun_path)); +} +END_SETUP() diff --git a/test/src/apps/network/unix_err.c b/test/src/apps/network/unix_streamlike_prologue.h similarity index 73% rename from test/src/apps/network/unix_err.c rename to test/src/apps/network/unix_streamlike_prologue.h index 36e8f7eaa..4261d93d2 100644 --- a/test/src/apps/network/unix_err.c +++ b/test/src/apps/network/unix_streamlike_prologue.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MPL-2.0 +/* SPDX-License-Identifier: MPL-2.0 */ #define _GNU_SOURCE @@ -31,7 +31,7 @@ FN_TEST(socket_addresses) #define MAKE_TEST(path, path_copy_len, path_len_to_kernel, path_buf_len, \ path_len_from_kernel, path_from_kernel) \ - sk = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); \ + sk = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); \ \ memset(&addr, 0, sizeof(addr)); \ addr.sun_family = AF_UNIX; \ @@ -86,7 +86,7 @@ FN_TEST(socket_addresses) #undef LONG_PATH #undef MAKE_TEST - sk = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); + sk = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); TEST_ERRNO(bind(sk, (struct sockaddr *)&addr, -1), EINVAL); TEST_ERRNO(bind(sk, (struct sockaddr *)&addr, PATH_OFFSET - 1), EINVAL); @@ -120,13 +120,13 @@ static int sk_accepted; FN_SETUP(unbound) { - sk_unbound = CHECK(socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)); + sk_unbound = CHECK(socket(PF_UNIX, SOCK_TYPE | SOCK_NONBLOCK, 0)); } END_SETUP() FN_SETUP(bound) { - sk_bound = CHECK(socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)); + sk_bound = CHECK(socket(PF_UNIX, SOCK_TYPE | SOCK_NONBLOCK, 0)); CHECK(bind(sk_bound, (struct sockaddr *)&BOUND_ADDR, BOUND_ADDRLEN)); } @@ -134,7 +134,7 @@ END_SETUP() FN_SETUP(listen) { - sk_listen = CHECK(socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)); + sk_listen = CHECK(socket(PF_UNIX, SOCK_TYPE | SOCK_NONBLOCK, 0)); CHECK(bind(sk_listen, (struct sockaddr *)&LISTEN_ADDR, LISTEN_ADDRLEN)); @@ -144,7 +144,7 @@ END_SETUP() FN_SETUP(connected) { - sk_connected = CHECK(socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)); + sk_connected = CHECK(socket(PF_UNIX, SOCK_TYPE | SOCK_NONBLOCK, 0)); CHECK(connect(sk_connected, (struct sockaddr *)&LISTEN_ADDR2, LISTEN_ADDRLEN2)); @@ -242,7 +242,7 @@ FN_TEST(bind_connected) struct sockaddr_un addr; socklen_t addrlen; - TEST_SUCC(socketpair(PF_UNIX, SOCK_STREAM, 0, fildes)); + TEST_SUCC(socketpair(PF_UNIX, SOCK_TYPE, 0, fildes)); TEST_SUCC(bind(fildes[0], (struct sockaddr *)&UNIX_ADDR("\0X"), PATH_OFFSET + 2)); @@ -340,16 +340,6 @@ FN_TEST(send) TEST_ERRNO(send(sk_listen, buf, 0, 0), ENOTCONN); TEST_ERRNO(write(sk_listen, buf, 1), ENOTCONN); TEST_ERRNO(write(sk_listen, buf, 0), ENOTCONN); - - TEST_ERRNO(sendto(sk_unbound, buf, 1, 0, &LISTEN_ADDR, LISTEN_ADDRLEN), - EOPNOTSUPP); - TEST_ERRNO(sendto(sk_bound, buf, 1, 0, &LISTEN_ADDR2, LISTEN_ADDRLEN2), - EOPNOTSUPP); - TEST_ERRNO(sendto(sk_listen, buf, 1, 0, &BOUND_ADDR, BOUND_ADDRLEN), - EOPNOTSUPP); - TEST_ERRNO(sendto(sk_accepted, buf, 1, 0, &UNNAMED_ADDR, - UNNAMED_ADDRLEN), - EISCONN); } END_TEST() @@ -387,39 +377,39 @@ FN_TEST(blocking_connect) // Setup - sk = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); + sk = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); TEST_SUCC( bind(sk, (struct sockaddr *)&UNIX_ADDR("\0"), PATH_OFFSET + 1)); TEST_SUCC(listen(sk, 2)); for (i = 0; i < 3; ++i) { sks[i] = TEST_SUCC( - socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)); + socket(PF_UNIX, SOCK_TYPE | SOCK_NONBLOCK, 0)); TEST_SUCC(connect(sks[i], (struct sockaddr *)&UNIX_ADDR("\0"), PATH_OFFSET + 1)); } -#define MAKE_TEST(child, parent, errno) \ - sks[i] = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)); \ - TEST_ERRNO(connect(sks[i], (struct sockaddr *)&UNIX_ADDR("\0"), \ - PATH_OFFSET + 1), \ - EAGAIN); \ - TEST_SUCC(close(sks[i])); \ - \ - pid = TEST_SUCC(fork()); \ - if (pid == 0) { \ - usleep(300 * 1000); \ - CHECK(child); \ - exit(0); \ - } \ - TEST_SUCC(parent); \ - \ - sks[i] = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); \ - TEST_ERRNO(connect(sks[i], (struct sockaddr *)&UNIX_ADDR("\0"), \ - PATH_OFFSET + 1), \ - errno); \ - \ - TEST_SUCC(close(sks[i])); \ +#define MAKE_TEST(child, parent, errno) \ + sks[i] = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE | SOCK_NONBLOCK, 0)); \ + TEST_ERRNO(connect(sks[i], (struct sockaddr *)&UNIX_ADDR("\0"), \ + PATH_OFFSET + 1), \ + EAGAIN); \ + TEST_SUCC(close(sks[i])); \ + \ + pid = TEST_SUCC(fork()); \ + if (pid == 0) { \ + usleep(300 * 1000); \ + CHECK(child); \ + exit(0); \ + } \ + TEST_SUCC(parent); \ + \ + sks[i] = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); \ + TEST_ERRNO(connect(sks[i], (struct sockaddr *)&UNIX_ADDR("\0"), \ + PATH_OFFSET + 1), \ + errno); \ + \ + TEST_SUCC(close(sks[i])); \ TEST_SUCC(wait(NULL)); // Test 1: Accepting a connection resumes the blocked connection request @@ -474,14 +464,14 @@ FN_TEST(ns_abs) struct sockaddr_un addr; socklen_t addrlen; - sk = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); + sk = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); TEST_SUCC(bind(sk, (struct sockaddr *)&UNIX_ADDR(""), PATH_OFFSET)); addrlen = sizeof(addr); TEST_RES(getsockname(sk, (struct sockaddr *)&addr, &addrlen), addrlen == PATH_OFFSET + 6 && addr.sun_path[0] == '\0'); - sk2 = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); + sk2 = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); TEST_ERRNO(bind(sk2, (struct sockaddr *)&addr, addrlen), EADDRINUSE); TEST_ERRNO(connect(sk2, (struct sockaddr *)&addr, addrlen), @@ -492,7 +482,7 @@ FN_TEST(ns_abs) TEST_SUCC(close(sk)); TEST_SUCC(close(sk2)); - sk = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); + sk = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); TEST_ERRNO(connect(sk, (struct sockaddr *)&addr, addrlen), ECONNREFUSED); TEST_SUCC(bind(sk, (struct sockaddr *)&addr, addrlen)); @@ -504,7 +494,7 @@ FN_TEST(shutdown_connected) { int fildes[2]; - TEST_SUCC(socketpair(PF_UNIX, SOCK_STREAM, 0, fildes)); + TEST_SUCC(socketpair(PF_UNIX, SOCK_TYPE, 0, fildes)); TEST_SUCC(shutdown(fildes[0], SHUT_RD)); TEST_SUCC(shutdown(fildes[0], SHUT_WR)); @@ -524,7 +514,7 @@ FN_TEST(poll_unbound) int sk; struct pollfd pfd = { .events = POLLIN | POLLOUT | POLLRDHUP }; - sk = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); + sk = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); pfd.fd = sk; TEST_RES(poll(&pfd, 1, 0), pfd.revents == (POLLOUT | POLLHUP)); @@ -552,7 +542,7 @@ FN_TEST(poll_listen) int sk; struct pollfd pfd = { .events = POLLIN | POLLOUT | POLLRDHUP }; - sk = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); + sk = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); pfd.fd = sk; TEST_SUCC( @@ -577,7 +567,7 @@ FN_TEST(poll_connected_close) int fildes[2]; struct pollfd pfd = { .events = POLLIN | POLLOUT | POLLRDHUP }; - TEST_SUCC(socketpair(PF_UNIX, SOCK_STREAM, 0, fildes)); + TEST_SUCC(socketpair(PF_UNIX, SOCK_TYPE, 0, fildes)); pfd.fd = fildes[1]; TEST_RES(poll(&pfd, 1, 0), pfd.revents == POLLOUT); @@ -597,18 +587,18 @@ FN_TEST(poll_connected_shutdown) int fildes[2]; struct pollfd pfd = { .events = POLLIN | POLLOUT | POLLRDHUP }; -#define MAKE_TEST(shut, ev1, ev2) \ - TEST_SUCC(socketpair(PF_UNIX, SOCK_STREAM, 0, fildes)); \ - \ - TEST_SUCC(shutdown(fildes[0], shut)); \ - \ - pfd.fd = fildes[0]; \ - TEST_RES(poll(&pfd, 1, 0), pfd.revents == (ev1)); \ - \ - pfd.fd = fildes[1]; \ - TEST_RES(poll(&pfd, 1, 0), pfd.revents == (ev2)); \ - \ - TEST_SUCC(close(fildes[0])); \ +#define MAKE_TEST(shut, ev1, ev2) \ + TEST_SUCC(socketpair(PF_UNIX, SOCK_TYPE, 0, fildes)); \ + \ + TEST_SUCC(shutdown(fildes[0], shut)); \ + \ + pfd.fd = fildes[0]; \ + TEST_RES(poll(&pfd, 1, 0), pfd.revents == (ev1)); \ + \ + pfd.fd = fildes[1]; \ + TEST_RES(poll(&pfd, 1, 0), pfd.revents == (ev2)); \ + \ + TEST_SUCC(close(fildes[0])); \ TEST_SUCC(close(fildes[1])); MAKE_TEST(SHUT_RD, POLLIN | POLLOUT | POLLRDHUP, POLLOUT); @@ -630,8 +620,8 @@ FN_TEST(epoll) // Setup - sk2_listen = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); - sk2_connected = TEST_SUCC(socket(PF_UNIX, SOCK_STREAM, 0)); + sk2_listen = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); + sk2_connected = TEST_SUCC(socket(PF_UNIX, SOCK_TYPE, 0)); epfd_listen = TEST_SUCC(epoll_create1(0)); ev.events = EPOLLIN; @@ -677,31 +667,13 @@ FN_TEST(epoll) } END_TEST() -FN_SETUP(cleanup) -{ - CHECK(close(sk_unbound)); - - CHECK(close(sk_bound)); - - CHECK(close(sk_listen)); - - CHECK(close(sk_connected)); - - CHECK(close(sk_accepted)); - - CHECK(unlink(BOUND_ADDR.sun_path)); - - CHECK(unlink(LISTEN_ADDR.sun_path)); -} -END_SETUP() - // See also `zero_reads_always_succeed` in `pipe_err.c` FN_TEST(zero_recvs_may_fail) { int fildes[2]; char buf[1] = { 'z' }; - TEST_SUCC(socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fildes)); + TEST_SUCC(socketpair(AF_UNIX, SOCK_TYPE | SOCK_NONBLOCK, 0, fildes)); TEST_ERRNO(recv(fildes[0], buf, 0, 0), EAGAIN); @@ -719,7 +691,7 @@ FN_TEST(zero_sends_may_fail) int fildes[2]; char buf[1] = { 'z' }; - TEST_SUCC(socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fildes)); + TEST_SUCC(socketpair(AF_UNIX, SOCK_TYPE | SOCK_NONBLOCK, 0, fildes)); TEST_SUCC(send(fildes[1], buf, 0, 0)); @@ -729,98 +701,3 @@ FN_TEST(zero_sends_may_fail) TEST_SUCC(close(fildes[1])); } END_TEST() - -FN_TEST(scm_rights) -{ - int fildes[2]; - char buf[20] = "abcdefg"; - char cbuf[CMSG_SPACE(sizeof(int) * 3)]; - struct iovec iov; - struct msghdr mhdr; - struct cmsghdr *chdr; - int *cdata; - int cfds[2]; - - TEST_SUCC(socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0, fildes)); - - memset(&mhdr, 0, sizeof(mhdr)); - mhdr.msg_iov = &iov; - mhdr.msg_iovlen = 1; - mhdr.msg_control = cbuf; - mhdr.msg_controllen = CMSG_SPACE(sizeof(int) * 3); - - iov.iov_base = buf; - iov.iov_len = 1; - - chdr = CMSG_FIRSTHDR(&mhdr); - chdr->cmsg_level = SOL_SOCKET; - chdr->cmsg_type = SCM_RIGHTS; - chdr->cmsg_len = CMSG_SPACE(sizeof(int) * 3); - - cdata = (int *)CMSG_DATA(chdr); - TEST_SUCC(pipe(cfds)); - cdata[0] = cfds[0]; - cdata[1] = cfds[0]; - cdata[2] = cfds[1]; - - // Sending control messages with zero bytes to a stream socket - // seems to "succeed". However, no data or control messages can - // be transmitted. - mhdr.msg_iovlen = 0; - TEST_SUCC(sendmsg(fildes[0], &mhdr, 0)); - mhdr.msg_iovlen = 1; - - // > (1) sendmsg(2) of four bytes, with no ancillary data. - // > (2) sendmsg(2) of one byte, with ancillary data. - // > (3) sendmsg(2) of four bytes, with no ancillary data. - // -- https://man7.org/linux/man-pages/man7/unix.7.html - TEST_RES(send(fildes[0], buf, 4, 0), _ret == 4); - TEST_RES(sendmsg(fildes[0], &mhdr, 0), _ret == 1); - TEST_RES(send(fildes[0], buf, 4, 0), _ret == 4); - - memset(&mhdr, 0, sizeof(mhdr)); - mhdr.msg_iov = &iov; - mhdr.msg_iovlen = 1; - mhdr.msg_control = cbuf; - mhdr.msg_controllen = CMSG_SPACE(sizeof(int)); - - iov.iov_base = buf; - iov.iov_len = sizeof(buf); - - memset(cbuf, 0, sizeof(cbuf)); - - // > Suppose that the receiver now performs recvmsg(2) calls each with - // > a buffer size of 20 bytes. The first call will receive five bytes - // > of data, along with the ancillary data sent by the second - // > sendmsg(2) call. - TEST_RES(recvmsg(fildes[1], &mhdr, 0), - _ret == 5 && - mhdr.msg_controllen == CMSG_SPACE(sizeof(int) * 2) && - (chdr = CMSG_FIRSTHDR(&mhdr)) && - chdr->cmsg_level == SOL_SOCKET && - chdr->cmsg_type == SCM_RIGHTS && - chdr->cmsg_len == CMSG_SPACE(sizeof(int) * 2) && - (cdata = (int *)CMSG_DATA(chdr)) && - cdata[0] == cfds[1] + 1 && cdata[1] == cfds[1] + 2); - // > The next call will receive the remaining four - // > bytes of data. - TEST_RES(recv(fildes[1], buf, sizeof(buf), 0), _ret == 4); - - // The purpose of the tests below is to verify that the received file - // descriptors are functional. - TEST_RES(write(cfds[1], "x", 1), _ret == 1); - TEST_RES(read(cdata[0], buf, 1), _ret == 1 && buf[0] == 'x'); - TEST_RES(write(cfds[1], "y", 1), _ret == 1); - TEST_RES(read(cdata[1], buf, 1), _ret == 1 && buf[0] == 'y'); - - TEST_SUCC(close(cdata[0])); - TEST_SUCC(close(cdata[1])); - TEST_SUCC(close(cfds[0])); - - TEST_ERRNO(write(cfds[1], "y", 1), EPIPE); - TEST_SUCC(close(cfds[1])); - - TEST_SUCC(close(fildes[0])); - TEST_SUCC(close(fildes[1])); -} -END_TEST() diff --git a/test/src/apps/scripts/network.sh b/test/src/apps/scripts/network.sh index 4c8d89bb7..65f8d337f 100755 --- a/test/src/apps/scripts/network.sh +++ b/test/src/apps/scripts/network.sh @@ -33,7 +33,8 @@ sleep 0.2 ./tcp_err ./tcp_poll ./udp_err -./unix_err +./unix_stream_err +./unix_seqpacket_err ./netlink_route ./rtnl_err diff --git a/test/src/apps/test.h b/test/src/apps/test.h index 4c9badeca..65b088eae 100644 --- a/test/src/apps/test.h +++ b/test/src/apps/test.h @@ -37,10 +37,11 @@ #include /** Starts the definition of a setup function. */ -#define FN_SETUP(name) \ - void setup_##name(void) __attribute__((constructor(__LINE__ + 200))); \ - \ - void setup_##name(void) \ +#define FN_SETUP(name) \ + void setup_##name(void) \ + __attribute__((constructor(__COUNTER__ + 200))); \ + \ + void setup_##name(void) \ { /** Ends the definition of a setup function. */ #define END_SETUP() } @@ -84,11 +85,12 @@ static int __total_failures; /** Starts the definition of a test function. */ -#define FN_TEST(name) \ - void test_##name(void) __attribute__((constructor(__LINE__ + 200))); \ - \ - void test_##name(void) \ - { \ +#define FN_TEST(name) \ + void test_##name(void) \ + __attribute__((constructor(__COUNTER__ + 200))); \ + \ + void test_##name(void) \ + { \ int __tests_passed = 0, __tests_failed = 0; /** Ends the definition of a test function. */ diff --git a/test/src/syscall/gvisor/Makefile b/test/src/syscall/gvisor/Makefile index 87f97cf59..b47ce3a38 100644 --- a/test/src/syscall/gvisor/Makefile +++ b/test/src/syscall/gvisor/Makefile @@ -51,7 +51,10 @@ TESTS ?= \ signalfd_test \ socket_netlink_route_test \ socket_unix_pair_test \ + socket_unix_seqpacket_local_test \ socket_unix_stream_test \ + socket_unix_unbound_seqpacket_test \ + socket_unix_unbound_stream_test \ stat_test \ stat_times_test \ statfs_test \ diff --git a/test/src/syscall/gvisor/blocklists/socket_unix_pair_test b/test/src/syscall/gvisor/blocklists/socket_unix_pair_test index 228ad2bff..fe057a117 100644 --- a/test/src/syscall/gvisor/blocklists/socket_unix_pair_test +++ b/test/src/syscall/gvisor/blocklists/socket_unix_pair_test @@ -1,11 +1,3 @@ -# TODO: Support `SOCK_SEQPACKET` sockets -AllUnixDomainSockets/UnixSocketPairTest.BindToBadName/* -AllUnixDomainSockets/UnixSocketPairTest.BindToBadFamily/* -AllUnixDomainSockets/*/4 -AllUnixDomainSockets/*/5 -AllUnixDomainSockets/*/10 -AllUnixDomainSockets/*/11 - # TODO: Support `SOCK_DGRAM` sockets AllUnixDomainSockets/*/2 AllUnixDomainSockets/*/3 @@ -23,5 +15,17 @@ AllUnixDomainSockets/UnixSocketPairTest.NetdeviceIoctlsSucceed/* # TODO: Fix operations on `/proc/*/fd/*` AllUnixDomainSockets/UnixSocketPairTest.SocketReopenFromProcfs/* -# TODO: Support control messages -AllUnixDomainSockets/UnixSocketPairCmsgTest.* +# TODO: Report `MSG_(C)TRUNC` after truncating the (control) message +AllUnixDomainSockets/UnixSocketPairCmsgTest.BasicFDPassNoSpaceMsgCtrunc/* +AllUnixDomainSockets/UnixSocketPairCmsgTest.BasicFDPassNullControlMsgCtrunc/* +AllUnixDomainSockets/UnixSocketPairCmsgTest.BasicFDPassNotEnoughSpaceMsgCtrunc/* +AllUnixDomainSockets/UnixSocketPairCmsgTest.BasicThreeFDPassTruncationMsgCtrunc/* +AllUnixDomainSockets/UnixSocketPairCmsgTest.BasicTwoFDPassUnalignedRecvTruncationMsgTrunc/* +AllUnixDomainSockets/UnixSocketPairCmsgTest.CredPassNoSpaceMsgCtrunc/* +AllUnixDomainSockets/UnixSocketPairCmsgTest.CredPassTruncatedMsgCtrunc/* + +# TODO: Support `MSG_CMSG_CLOEXEC` +AllUnixDomainSockets/UnixSocketPairCmsgTest.CloexecRecvFDPass/* + +# TODO: Support `MSG_PEEK` +AllUnixDomainSockets/UnixSocketPairCmsgTest.FDPassPeek/* diff --git a/test/src/syscall/gvisor/blocklists/socket_unix_seqpacket_local_test b/test/src/syscall/gvisor/blocklists/socket_unix_seqpacket_local_test new file mode 100644 index 000000000..994228e29 --- /dev/null +++ b/test/src/syscall/gvisor/blocklists/socket_unix_seqpacket_local_test @@ -0,0 +1,13 @@ +# TODO: Support `MSG_DONTWAIT` and `MSG_PEEK` +SeqpacketUnixSockets/NonStreamSocketPairTest.SplitRecv/* +SeqpacketUnixSockets/NonStreamSocketPairTest.SinglePeek/* +SeqpacketUnixSockets/NonStreamSocketPairTest.RecvmsgTruncPeekDontwaitZeroLen/* + +# TODO: Support `SO_SNDTIMEO` +SeqpacketUnixSockets/UnixNonStreamSocketPairTest.SendTimeout/* + +# TODO: Support `MSG_TRUNC` +SeqpacketUnixSockets/NonStreamSocketPairTest.MsgTruncTruncation/* +SeqpacketUnixSockets/NonStreamSocketPairTest.MsgTruncTruncationRecvmsgMsghdrFlagMsgTrunc/* +SeqpacketUnixSockets/NonStreamSocketPairTest.RecvmsgMsgTruncZeroLen/* +SeqpacketUnixSockets/NonStreamSocketPairTest.RecvmsgMsgTruncMsgPeekZeroLen/*