hostinet: Allow more socket options to have variable-length buffers.

Most of these buffers can be truncated in the Sentry before returning to the
application.

IP_TOS is a bit funny, since it is interpreted as a 8, 16, or 32-bit int
depending on the buffer size, so simple truncation does not work. We allow all
sizes to be passed to the host.

PiperOrigin-RevId: 513880257
This commit is contained in:
Nicolas Lacasse
2023-03-04 00:24:17 -08:00
committed by Ayush Ranjan
parent 35937b7f61
commit da3c2bbb82
3 changed files with 31 additions and 13 deletions
+2 -6
View File
@@ -31,7 +31,7 @@ import (
)
func firstBytePtr(bs []byte) unsafe.Pointer {
if bs == nil {
if len(bs) == 0 {
return nil
}
return unsafe.Pointer(&bs[0])
@@ -222,11 +222,7 @@ func accept4(fd int, addr *byte, addrlen *uint32, flags int) (int, error) {
func getsockopt(fd int, level, name int, opt []byte) ([]byte, error) {
optlen32 := int32(len(opt))
var optPtr uintptr
if optlen32 > 0 {
optPtr = uintptr(firstBytePtr(opt))
}
_, _, errno := unix.Syscall6(unix.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), optPtr, uintptr(unsafe.Pointer(&optlen32)), 0)
_, _, errno := unix.Syscall6(unix.SYS_GETSOCKOPT, uintptr(fd), uintptr(level), uintptr(name), uintptr(firstBytePtr(opt)), uintptr(unsafe.Pointer(&optlen32)), 0)
if errno != 0 {
return nil, errno
}
+18 -7
View File
@@ -67,7 +67,7 @@ var SockOpts = []SockOpt{
{linux.SOL_IP, linux.IP_RECVORIGDSTADDR, sizeofInt32, true, true},
{linux.SOL_IP, linux.IP_RECVTOS, sizeofInt32, true, true},
{linux.SOL_IP, linux.IP_RECVTTL, sizeofInt32, true, true},
{linux.SOL_IP, linux.IP_TOS, sizeofInt32, true, true},
{linux.SOL_IP, linux.IP_TOS, 0 /* Can be 32, 16, or 8 bits */, true, true},
{linux.SOL_IP, linux.IP_TTL, sizeofInt32, true, true},
{linux.SOL_IPV6, linux.IPV6_MULTICAST_HOPS, sizeofInt32, true, true},
@@ -169,9 +169,21 @@ func (s *Socket) GetSockOpt(t *kernel.Task, level, name int, optValAddr hostarch
if sockOpt.Size > 0 {
// Validate size of input buffer.
if uint64(optLen) < sockOpt.Size {
// Special case for TCP_INFO. We allow smaller buffers, and
// only fill up what we can.
if level != linux.SOL_TCP || name != linux.TCP_INFO {
// Special case for options that allow smaller buffers.
//
// To keep the syscall filters simple and restrictive,
// we use the full buffer size when calling the host,
// but truncate before returning to the application.
switch {
case level == linux.SOL_TCP && name == linux.TCP_INFO:
// Allow smaller buffer.
case level == linux.SOL_ICMPV6 && name == linux.ICMPV6_FILTER:
// Allow smaller buffer.
case level == linux.SOL_IP && name == linux.IP_TTL:
// Allow smaller buffer.
case level == linux.SOL_IPV6 && name == linux.IPV6_TCLASS:
// Allow smaller buffer.
default:
return nil, syserr.ErrInvalidArgument
}
}
@@ -190,9 +202,8 @@ func (s *Socket) GetSockOpt(t *kernel.Task, level, name int, optValAddr hostarch
return nil, syserr.FromError(err)
}
opt = postGetSockOpt(t, level, name, opt)
// Special-case for TCP_INFO. We truncate the buffer to whatever size
// the user requested.
if level == linux.SOL_TCP && name == linux.TCP_INFO && uint64(optLen) < sockOpt.Size {
// If option allows a smaller buffer, truncate it to desired size.
if uint64(optLen) < sockOpt.Size {
opt = opt[:optLen]
}
optP := primitive.ByteSlice(opt)
+11
View File
@@ -738,6 +738,7 @@ syscall_test(
syscall_test(
size = "large",
add_hostinet = True,
container = True,
one_sandbox = False,
shard_count = most_shards,
@@ -746,6 +747,7 @@ syscall_test(
syscall_test(
size = "large",
add_hostinet = True,
shard_count = most_shards,
# Takes too long for TSAN. Creates a lot of TCP sockets.
tags = ["nogotsan"],
@@ -810,6 +812,7 @@ syscall_test(
syscall_test(
size = "medium",
add_hostinet = True,
test = "//test/syscalls/linux:socket_ipv6_udp_unbound_loopback_test",
)
@@ -831,11 +834,13 @@ syscall_test(
)
syscall_test(
add_hostinet = True,
shard_count = more_shards,
test = "//test/syscalls/linux:socket_ip_unbound_test",
)
syscall_test(
add_hostinet = True,
shard_count = more_shards,
test = "//test/syscalls/linux:socket_ipv6_unbound_test",
)
@@ -862,10 +867,12 @@ syscall_test(
)
syscall_test(
add_hostinet = True,
test = "//test/syscalls/linux:socket_blocking_local_test",
)
syscall_test(
add_hostinet = True,
test = "//test/syscalls/linux:socket_blocking_ip_test",
)
@@ -875,11 +882,13 @@ syscall_test(
)
syscall_test(
add_hostinet = True,
test = "//test/syscalls/linux:socket_non_stream_blocking_udp_test",
)
syscall_test(
size = "large",
add_hostinet = True,
test = "//test/syscalls/linux:socket_stream_blocking_local_test",
)
@@ -890,11 +899,13 @@ syscall_test(
syscall_test(
size = "medium",
add_hostinet = True,
test = "//test/syscalls/linux:socket_stream_local_test",
)
syscall_test(
size = "medium",
add_hostinet = True,
test = "//test/syscalls/linux:socket_stream_nonblock_local_test",
)