mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
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:
committed by
gVisor bot
parent
1b7a4e2a05
commit
e4ece21634
@@ -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{}{}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user