Fix slice bounds out of range panic in parsing socket control message.

Panic found by syzakller.

PiperOrigin-RevId: 288799046
This commit is contained in:
Ting-Yu Wang
2020-01-08 16:32:34 -08:00
committed by gVisor bot
parent 1c24201467
commit b3ae8a62cf
2 changed files with 39 additions and 0 deletions
+6
View File
@@ -471,6 +471,9 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte) (socket.Con
case linux.SOL_IP:
switch h.Type {
case linux.IP_TOS:
if length < linux.SizeOfControlMessageTOS {
return socket.ControlMessages{}, syserror.EINVAL
}
cmsgs.IP.HasTOS = true
binary.Unmarshal(buf[i:i+linux.SizeOfControlMessageTOS], usermem.ByteOrder, &cmsgs.IP.TOS)
i += AlignUp(length, width)
@@ -481,6 +484,9 @@ func Parse(t *kernel.Task, socketOrEndpoint interface{}, buf []byte) (socket.Con
case linux.SOL_IPV6:
switch h.Type {
case linux.IPV6_TCLASS:
if length < linux.SizeOfControlMessageTClass {
return socket.ControlMessages{}, syserror.EINVAL
}
cmsgs.IP.HasTClass = true
binary.Unmarshal(buf[i:i+linux.SizeOfControlMessageTClass], usermem.ByteOrder, &cmsgs.IP.TClass)
i += AlignUp(length, width)
+33
View File
@@ -129,6 +129,7 @@ TEST_P(IPUnboundSocketTest, InvalidNegativeTtl) {
struct TOSOption {
int level;
int option;
int cmsg_level;
};
constexpr int INET_ECN_MASK = 3;
@@ -139,10 +140,12 @@ static TOSOption GetTOSOption(int domain) {
case AF_INET:
opt.level = IPPROTO_IP;
opt.option = IP_TOS;
opt.cmsg_level = SOL_IP;
break;
case AF_INET6:
opt.level = IPPROTO_IPV6;
opt.option = IPV6_TCLASS;
opt.cmsg_level = SOL_IPV6;
break;
}
return opt;
@@ -386,6 +389,36 @@ TEST_P(IPUnboundSocketTest, NullTOS) {
SyscallFailsWithErrno(EFAULT));
}
TEST_P(IPUnboundSocketTest, InsufficientBufferTOS) {
SKIP_IF(GetParam().protocol == IPPROTO_TCP);
auto socket = ASSERT_NO_ERRNO_AND_VALUE(NewSocket());
TOSOption t = GetTOSOption(GetParam().domain);
in_addr addr4;
in6_addr addr6;
ASSERT_THAT(inet_pton(AF_INET, "127.0.0.1", &addr4), ::testing::Eq(1));
ASSERT_THAT(inet_pton(AF_INET6, "fe80::", &addr6), ::testing::Eq(1));
cmsghdr cmsg = {};
cmsg.cmsg_len = sizeof(cmsg);
cmsg.cmsg_level = t.cmsg_level;
cmsg.cmsg_type = t.option;
msghdr msg = {};
msg.msg_control = &cmsg;
msg.msg_controllen = sizeof(cmsg);
if (GetParam().domain == AF_INET) {
msg.msg_name = &addr4;
msg.msg_namelen = sizeof(addr4);
} else {
msg.msg_name = &addr6;
msg.msg_namelen = sizeof(addr6);
}
EXPECT_THAT(sendmsg(socket->get(), &msg, 0), SyscallFailsWithErrno(EINVAL));
}
INSTANTIATE_TEST_SUITE_P(
IPUnboundSockets, IPUnboundSocketTest,
::testing::ValuesIn(VecCat<SocketKind>(VecCat<SocketKind>(