diff --git a/pkg/sentry/socket/hostinet/socket_unsafe.go b/pkg/sentry/socket/hostinet/socket_unsafe.go index 2ee703207..a6a03f70c 100644 --- a/pkg/sentry/socket/hostinet/socket_unsafe.go +++ b/pkg/sentry/socket/hostinet/socket_unsafe.go @@ -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 } diff --git a/pkg/sentry/socket/hostinet/sockopt.go b/pkg/sentry/socket/hostinet/sockopt.go index b9b0d747d..def062af4 100644 --- a/pkg/sentry/socket/hostinet/sockopt.go +++ b/pkg/sentry/socket/hostinet/sockopt.go @@ -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) diff --git a/test/syscalls/BUILD b/test/syscalls/BUILD index 32e573aef..a029b45db 100644 --- a/test/syscalls/BUILD +++ b/test/syscalls/BUILD @@ -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", )