mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Clear msghdr flags on successful recvmsg.
.net sets these flags to -1 and then uses their result, especting it to be zero. Does not set actual flags (e.g. MSG_TRUNC), but setting to zero is more correct than what we did before. PiperOrigin-RevId: 239657951 Change-Id: I89c5f84bc9b94a2cd8ff84e8ecfea09e01142030
This commit is contained in:
@@ -57,6 +57,10 @@ const nameLenOffset = 8
|
||||
// to the ControlLen field.
|
||||
const controlLenOffset = 40
|
||||
|
||||
// flagsOffset is the offset form the start of the MessageHeader64 struct
|
||||
// to the Flags field.
|
||||
const flagsOffset = 48
|
||||
|
||||
// messageHeader64Len is the length of a MessageHeader64 struct.
|
||||
var messageHeader64Len = uint64(binary.Size(MessageHeader64{}))
|
||||
|
||||
@@ -743,6 +747,16 @@ func recvSingleMsg(t *kernel.Task, s socket.Socket, msgPtr usermem.Addr, flags i
|
||||
return 0, syserror.ConvertIntr(err.ToError(), kernel.ERESTARTSYS)
|
||||
}
|
||||
cms.Unix.Release()
|
||||
|
||||
if msg.Flags != 0 {
|
||||
// Copy out the flags to the caller.
|
||||
//
|
||||
// TODO: Plumb through actual flags.
|
||||
if _, err := t.CopyOut(msgPtr+flagsOffset, int32(0)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
}
|
||||
|
||||
return uintptr(n), nil
|
||||
}
|
||||
|
||||
@@ -787,6 +801,13 @@ func recvSingleMsg(t *kernel.Task, s socket.Socket, msgPtr usermem.Addr, flags i
|
||||
}
|
||||
}
|
||||
|
||||
// Copy out the flags to the caller.
|
||||
//
|
||||
// TODO: Plumb through actual flags.
|
||||
if _, err := t.CopyOut(msgPtr+flagsOffset, int32(0)); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return uintptr(n), nil
|
||||
}
|
||||
|
||||
|
||||
@@ -183,6 +183,80 @@ TEST_P(AllSocketPairTest, SendmsgRecvmsg16KB) {
|
||||
memcmp(sent_data.data(), received_data.data(), sent_data.size()));
|
||||
}
|
||||
|
||||
TEST_P(AllSocketPairTest, RecvmsgMsghdrFlagsNotClearedOnFailure) {
|
||||
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
|
||||
|
||||
char received_data[10] = {};
|
||||
|
||||
struct iovec iov;
|
||||
iov.iov_base = received_data;
|
||||
iov.iov_len = sizeof(received_data);
|
||||
struct msghdr msg = {};
|
||||
msg.msg_flags = -1;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
ASSERT_THAT(RetryEINTR(recvmsg)(sockets->second_fd(), &msg, MSG_DONTWAIT),
|
||||
SyscallFailsWithErrno(EAGAIN));
|
||||
|
||||
// Check that msghdr flags were not changed.
|
||||
EXPECT_EQ(msg.msg_flags, -1);
|
||||
}
|
||||
|
||||
TEST_P(AllSocketPairTest, RecvmsgMsghdrFlagsCleared) {
|
||||
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
|
||||
|
||||
char sent_data[10];
|
||||
RandomizeBuffer(sent_data, sizeof(sent_data));
|
||||
ASSERT_THAT(
|
||||
RetryEINTR(send)(sockets->first_fd(), sent_data, sizeof(sent_data), 0),
|
||||
SyscallSucceedsWithValue(sizeof(sent_data)));
|
||||
|
||||
char received_data[sizeof(sent_data)] = {};
|
||||
|
||||
struct iovec iov;
|
||||
iov.iov_base = received_data;
|
||||
iov.iov_len = sizeof(received_data);
|
||||
struct msghdr msg = {};
|
||||
msg.msg_flags = -1;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
ASSERT_THAT(RetryEINTR(recvmsg)(sockets->second_fd(), &msg, 0),
|
||||
SyscallSucceedsWithValue(sizeof(sent_data)));
|
||||
EXPECT_EQ(0, memcmp(received_data, sent_data, sizeof(sent_data)));
|
||||
|
||||
// Check that msghdr flags were cleared.
|
||||
EXPECT_EQ(msg.msg_flags, 0);
|
||||
}
|
||||
|
||||
TEST_P(AllSocketPairTest, RecvmsgPeekMsghdrFlagsCleared) {
|
||||
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
|
||||
|
||||
char sent_data[10];
|
||||
RandomizeBuffer(sent_data, sizeof(sent_data));
|
||||
ASSERT_THAT(
|
||||
RetryEINTR(send)(sockets->first_fd(), sent_data, sizeof(sent_data), 0),
|
||||
SyscallSucceedsWithValue(sizeof(sent_data)));
|
||||
|
||||
char received_data[sizeof(sent_data)] = {};
|
||||
|
||||
struct iovec iov;
|
||||
iov.iov_base = received_data;
|
||||
iov.iov_len = sizeof(received_data);
|
||||
struct msghdr msg = {};
|
||||
msg.msg_flags = -1;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
ASSERT_THAT(RetryEINTR(recvmsg)(sockets->second_fd(), &msg, MSG_PEEK),
|
||||
SyscallSucceedsWithValue(sizeof(sent_data)));
|
||||
EXPECT_EQ(0, memcmp(received_data, sent_data, sizeof(sent_data)));
|
||||
|
||||
// Check that msghdr flags were cleared.
|
||||
EXPECT_EQ(msg.msg_flags, 0);
|
||||
}
|
||||
|
||||
TEST_P(AllSocketPairTest, RecvmmsgInvalidTimeout) {
|
||||
auto sockets = ASSERT_NO_ERRNO_AND_VALUE(NewSocketPair());
|
||||
char buf[10];
|
||||
|
||||
Reference in New Issue
Block a user