hostinet: Implement packet sockets.

Two of the tests are still disabled for now. There is an existing issue with
poll in hostinet that I need to look into.

PiperOrigin-RevId: 513936838
This commit is contained in:
Nicolas Lacasse
2023-03-04 00:48:57 -08:00
committed by gVisor bot
parent 1b7a4e2a05
commit e4ece21634
6 changed files with 53 additions and 10 deletions
+29 -7
View File
@@ -51,11 +51,18 @@ const (
// AllowedSocketType is a tuple of socket family, type, and protocol.
type AllowedSocketType struct {
Family int
Type int
Family int
Type int
// Protocol of AllowAllProtocols indicates that all protocols are
// allowed.
Protocol int
}
// AllowAllProtocols indicates that all protocols are allowed by the stack and
// in the syscall filters.
var AllowAllProtocols = -1
// AllowedSocketTypes are the socket types which are supported by hostinet.
// These are used to validate the arguments to socket(), and also to generate
// syscall filters.
@@ -82,6 +89,9 @@ var AllowedRawSocketTypes = []AllowedSocketType{
{unix.AF_INET6, unix.SOCK_RAW, unix.IPPROTO_TCP},
{unix.AF_INET6, unix.SOCK_RAW, unix.IPPROTO_UDP},
{unix.AF_INET6, unix.SOCK_RAW, unix.IPPROTO_ICMPV6},
{unix.AF_PACKET, unix.SOCK_DGRAM, AllowAllProtocols},
{unix.AF_PACKET, unix.SOCK_RAW, AllowAllProtocols},
}
// Socket implements socket.Socket (and by extension, vfs.FileDescriptionImpl)
@@ -212,8 +222,8 @@ func (p *socketProvider) Socket(t *kernel.Task, stypeflags linux.SockType, proto
stype := stypeflags & linux.SOCK_TYPE_MASK
// Raw sockets require CAP_NET_RAW.
if stype == linux.SOCK_RAW {
// Raw and packet sockets require CAP_NET_RAW.
if stype == linux.SOCK_RAW || p.family == linux.AF_PACKET {
if creds := auth.CredentialsFromContext(t); !creds.HasCapability(linux.CAP_NET_RAW) {
return nil, syserr.ErrNotPermitted
}
@@ -233,7 +243,10 @@ func (p *socketProvider) Socket(t *kernel.Task, stypeflags linux.SockType, proto
// Validate the socket based on family, type, and protocol.
var supported bool
for _, allowed := range stack.allowedSocketTypes {
if p.family == allowed.Family && int(stype) == allowed.Type && protocol == allowed.Protocol {
isAllowedFamily := p.family == allowed.Family
isAllowedType := int(stype) == allowed.Type
isAllowedProtocol := protocol == allowed.Protocol || allowed.Protocol == AllowAllProtocols
if isAllowedFamily && isAllowedType && isAllowedProtocol {
supported = true
break
}
@@ -770,7 +783,16 @@ func (s *Socket) Type() (family int, skType linux.SockType, protocol int) {
}
func init() {
for _, family := range []int{unix.AF_INET, unix.AF_INET6} {
socket.RegisterProvider(family, &socketProvider{family})
// Register all families in AllowedSocketTypes and AllowedRawSocket
// types. If we don't allow raw sockets, they will be rejected in the
// Socket call.
registered := make(map[int]struct{})
for _, sockType := range append(AllowedSocketTypes, AllowedRawSocketTypes...) {
fam := sockType.Family
if _, ok := registered[fam]; ok {
continue
}
socket.RegisterProvider(fam, &socketProvider{fam})
registered[fam] = struct{}{}
}
}
+4
View File
@@ -432,6 +432,10 @@ func UnmarshalSockAddr(family int, data []byte) linux.SockAddr {
var addr linux.SockAddrNetlink
addr.UnmarshalUnsafe(data)
return &addr
case unix.AF_PACKET:
var addr linux.SockAddrLink
addr.UnmarshalUnsafe(data)
return &addr
default:
panic(fmt.Sprintf("Unsupported socket family %v", family))
}
+9 -3
View File
@@ -85,12 +85,18 @@ func hostInetFilters(allowRawSockets bool) seccomp.SyscallRules {
stypes = append(stypes, hostinet.AllowedRawSocketTypes...)
}
for _, sock := range stypes {
socketRules = append(socketRules, seccomp.Rule{
rule := seccomp.Rule{
seccomp.EqualTo(sock.Family),
// We always set SOCK_NONBLOCK and SOCK_CLOEXEC
// We always set SOCK_NONBLOCK and SOCK_CLOEXEC.
seccomp.EqualTo(sock.Type | linux.SOCK_NONBLOCK | linux.SOCK_CLOEXEC),
// Match specific protocol by default.
seccomp.EqualTo(sock.Protocol),
})
}
if sock.Protocol == hostinet.AllowAllProtocols {
// Change protocol filter to MatchAny.
rule[2] = seccomp.MatchAny{}
}
socketRules = append(socketRules, rule)
}
rules[unix.SYS_SOCKET] = socketRules
+3
View File
@@ -425,14 +425,17 @@ syscall_test(
)
syscall_test(
add_hostinet = True,
test = "//test/syscalls/linux:packet_socket_dgram_test",
)
syscall_test(
add_hostinet = True,
test = "//test/syscalls/linux:packet_socket_raw_test",
)
syscall_test(
add_hostinet = True,
test = "//test/syscalls/linux:packet_socket_test",
)
@@ -226,6 +226,10 @@ TEST_P(CookedPacketTest, Receive) {
// Send via a packet socket.
TEST_P(CookedPacketTest, Send) {
// TODO(b/267210840): Fix this test for hostinet. Something is wrong with
// poll().
SKIP_IF(IsRunningWithHostinet());
// Let's send a UDP packet and receive it using a regular UDP socket.
FileDescriptor udp_sock =
ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0));
+4
View File
@@ -205,6 +205,10 @@ TEST_P(RawPacketTest, Receive) {
// Send via a packet socket.
TEST_P(RawPacketTest, Send) {
// TODO(b/267210840): Fix this test for hostinet. Something is wrong with
// poll().
SKIP_IF(IsRunningWithHostinet());
// Let's send a UDP packet and receive it using a regular UDP socket.
FileDescriptor udp_sock =
ASSERT_NO_ERRNO_AND_VALUE(Socket(AF_INET, SOCK_DGRAM, 0));