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:
Andrei Vagin
2020-06-10 13:26:54 -07:00
committed by gVisor bot
parent fadbfd83d9
commit a5a4f80487
3 changed files with 50 additions and 8 deletions
+18 -8
View File
@@ -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
+14
View File
@@ -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>(