mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
socket/unix: handle sendto address argument for connected sockets
In case of SOCK_SEQPACKET, it has to be ignored. In case of SOCK_STREAM, EISCONN or EOPNOTSUPP has to be returned. PiperOrigin-RevId: 315755972
This commit is contained in:
@@ -459,15 +459,25 @@ func (s *socketOpsCommon) SendMsg(t *kernel.Task, src usermem.IOSequence, to []b
|
||||
To: nil,
|
||||
}
|
||||
if len(to) > 0 {
|
||||
ep, err := extractEndpoint(t, to)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer ep.Release()
|
||||
w.To = ep
|
||||
switch s.stype {
|
||||
case linux.SOCK_SEQPACKET:
|
||||
to = nil
|
||||
case linux.SOCK_STREAM:
|
||||
if s.State() == linux.SS_CONNECTED {
|
||||
return 0, syserr.ErrAlreadyConnected
|
||||
}
|
||||
return 0, syserr.ErrNotSupported
|
||||
default:
|
||||
ep, err := extractEndpoint(t, to)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer ep.Release()
|
||||
w.To = ep
|
||||
|
||||
if ep.Passcred() && w.Control.Credentials == nil {
|
||||
w.Control.Credentials = control.MakeCreds(t)
|
||||
if ep.Passcred() && w.Control.Credentials == nil {
|
||||
w.Control.Credentials = control.MakeCreds(t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,24 @@ TEST_P(SeqpacketUnixSocketPairTest, ReadOneSideClosed) {
|
||||
SyscallSucceedsWithValue(0));
|
||||
}
|
||||
|
||||
TEST_P(SeqpacketUnixSocketPairTest, Sendto) {
|
||||
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
|
||||
|
||||
struct sockaddr_un addr = {};
|
||||
addr.sun_family = AF_UNIX;
|
||||
constexpr char kPath[] = "\0nonexistent";
|
||||
memcpy(addr.sun_path, kPath, sizeof(kPath));
|
||||
|
||||
constexpr char kStr[] = "abc";
|
||||
ASSERT_THAT(sendto(sockets->second_fd(), kStr, 3, 0, (struct sockaddr*)&addr,
|
||||
sizeof(addr)),
|
||||
SyscallSucceedsWithValue(3));
|
||||
|
||||
char data[10] = {};
|
||||
ASSERT_THAT(read(sockets->first_fd(), data, sizeof(data)),
|
||||
SyscallSucceedsWithValue(3));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace testing
|
||||
|
||||
@@ -89,6 +89,20 @@ TEST_P(StreamUnixSocketPairTest, ReadOneSideClosedWithUnreadData) {
|
||||
SyscallFailsWithErrno(ECONNRESET));
|
||||
}
|
||||
|
||||
TEST_P(StreamUnixSocketPairTest, Sendto) {
|
||||
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
|
||||
|
||||
struct sockaddr_un addr = {};
|
||||
addr.sun_family = AF_UNIX;
|
||||
constexpr char kPath[] = "\0nonexistent";
|
||||
memcpy(addr.sun_path, kPath, sizeof(kPath));
|
||||
|
||||
constexpr char kStr[] = "abc";
|
||||
ASSERT_THAT(sendto(sockets->second_fd(), kStr, 3, 0, (struct sockaddr*)&addr,
|
||||
sizeof(addr)),
|
||||
SyscallFailsWithErrno(EISCONN));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
AllUnixDomainSockets, StreamUnixSocketPairTest,
|
||||
::testing::ValuesIn(IncludeReversals(VecCat<SocketPairKind>(
|
||||
|
||||
Reference in New Issue
Block a user