setsockopt on raw IPv6 socket ignores opt_len on Linux
ghananigans opened this issue · comments
Ghanan commented
It seems like linux does not check the passed length of an option in calls to setsockopt on a raw IPv6 socket before copying an "int" from userspace:
TEST(RawIPv6SocketTest, IPv6Checksum) {
int fd;
ASSERT_GE(fd = socket(AF_INET6, SOCK_RAW, IPPROTO_UDP), 0) << strerror(errno);
// Even though we specify a smaller than int value, Linux seems to read
// the full int.
int intV = std::numeric_limits<int>::max();
if (intV & 1) {
intV--;
}
ASSERT_EQ(
setsockopt(fd, SOL_IPV6, IPV6_CHECKSUM, &intV, sizeof(intV) - 1),
0) << strerror(errno);
{
int got;
socklen_t got_len = sizeof(got);
ASSERT_EQ(getsockopt(fd, SOL_IPV6, IPV6_CHECKSUM, &got, &got_len),
0) <<strerror(errno);
ASSERT_EQ(got_len, sizeof(got));
EXPECT_EQ(got, intV);
}
// If we have pass a pointer that points to memory less than the size of an
// int, we get a bad address error.
std::unique_ptr<uint8_t> u8V;
// Linux seems to assume a full int but doesn't check the passed length.
//
// https://github.com/torvalds/linux/blob/a52a8e9eaf4a12dd58953fc622bb2bc08fd1d32c/net/ipv6/raw.c#L1023
// shows that Linux copies optVal to an int without first checking optLen.
ASSERT_EQ(
setsockopt(fd, SOL_IPV6, IPV6_CHECKSUM, u8V.get(), sizeof(*u8V)), -1);
EXPECT_THAT(errno, EFAULT) << strerror(errno);
}
Should we match this behaviour?
github-actions commented
A friendly reminder that this issue had no activity for 120 days.
github-actions commented
This issue has been closed due to lack of activity.