mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add seccomp filters for TPU proxying and stub out accel fd methods.
PiperOrigin-RevId: 549718797
This commit is contained in:
committed by
gVisor bot
parent
5eb44a9431
commit
d4510e760b
@@ -34,6 +34,13 @@ const (
|
||||
defaultLabel = "default_action"
|
||||
)
|
||||
|
||||
// NonNegativeFDCheck ensures an FD argument is a non-negative int.
|
||||
func NonNegativeFDCheck() LessThanOrEqual {
|
||||
// Negative int32 has the MSB (31st bit) set. So the raw uint FD value must
|
||||
// be less than or equal to 0x7fffffff.
|
||||
return LessThanOrEqual(0x7fffffff)
|
||||
}
|
||||
|
||||
// Install generates BPF code based on the set of syscalls provided. It only
|
||||
// allows syscalls that conform to the specification. Syscalls that violate the
|
||||
// specification will trigger RET_KILL_PROCESS. If RET_KILL_PROCESS is not
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
load("//tools:defs.bzl", "go_library")
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
go_library(
|
||||
name = "accel",
|
||||
srcs = [
|
||||
"accel.go",
|
||||
"seccomp_filters.go",
|
||||
],
|
||||
visibility = ["//pkg/sentry:internal"],
|
||||
deps = [
|
||||
"//pkg/abi/gasket",
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/context",
|
||||
"//pkg/errors/linuxerr",
|
||||
"//pkg/seccomp",
|
||||
"//pkg/sentry/arch",
|
||||
"//pkg/sentry/vfs",
|
||||
"//pkg/usermem",
|
||||
"//pkg/waiter",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,64 @@
|
||||
// Copyright 2023 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package accel implements proxying for hardware accelerators.
|
||||
package accel
|
||||
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/context"
|
||||
"gvisor.dev/gvisor/pkg/errors/linuxerr"
|
||||
"gvisor.dev/gvisor/pkg/sentry/arch"
|
||||
"gvisor.dev/gvisor/pkg/sentry/vfs"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
"gvisor.dev/gvisor/pkg/waiter"
|
||||
)
|
||||
|
||||
// accelFD implements vfs.FileDescriptionImpl for /dev/accel[0-9]+.
|
||||
//
|
||||
// accelFD is not savable; we do not implement save/restore of accelerator
|
||||
// state.
|
||||
type accelFD struct {
|
||||
vfsfd vfs.FileDescription
|
||||
vfs.FileDescriptionDefaultImpl
|
||||
vfs.DentryMetadataFileDescriptionImpl
|
||||
vfs.NoLockFD
|
||||
}
|
||||
|
||||
// Release implements vfs.FileDescriptionImpl.Release.
|
||||
func (fd *accelFD) Release(context.Context) {
|
||||
}
|
||||
|
||||
// EventRegister implements waiter.Waitable.EventRegister.
|
||||
func (fd *accelFD) EventRegister(e *waiter.Entry) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// EventUnregister implements waiter.Waitable.EventUnregister.
|
||||
func (fd *accelFD) EventUnregister(e *waiter.Entry) {
|
||||
}
|
||||
|
||||
// Readiness implements waiter.Waitable.Readiness.
|
||||
func (fd *accelFD) Readiness(mask waiter.EventMask) waiter.EventMask {
|
||||
return waiter.EventErr
|
||||
}
|
||||
|
||||
// Epollable implements vfs.FileDescriptionImpl.Epollable.
|
||||
func (fd *accelFD) Epollable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Ioctl implements vfs.FileDescriptionImpl.Ioctl.
|
||||
func (fd *accelFD) Ioctl(ctx context.Context, uio usermem.IO, sysno uintptr, args arch.SyscallArguments) (uintptr, error) {
|
||||
return 0, linuxerr.ENOSYS
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
// Copyright 2023 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package accel
|
||||
|
||||
import (
|
||||
"golang.org/x/sys/unix"
|
||||
"gvisor.dev/gvisor/pkg/abi/gasket"
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/seccomp"
|
||||
)
|
||||
|
||||
// Filters returns seccomp-bpf filters for this package.
|
||||
func Filters() seccomp.SyscallRules {
|
||||
nonNegativeFD := seccomp.NonNegativeFDCheck()
|
||||
return seccomp.SyscallRules{
|
||||
unix.SYS_OPENAT: []seccomp.Rule{
|
||||
{
|
||||
// All paths that we openat() are absolute, so we pass a dirfd
|
||||
// of -1 (which is invalid for relative paths, but ignored for
|
||||
// absolute paths) to hedge against bugs involving AT_FDCWD or
|
||||
// real dirfds.
|
||||
seccomp.EqualTo(^uintptr(0)),
|
||||
seccomp.MatchAny{},
|
||||
seccomp.MaskedEqual(unix.O_CREAT|unix.O_NOFOLLOW, unix.O_NOFOLLOW),
|
||||
seccomp.MatchAny{},
|
||||
},
|
||||
},
|
||||
unix.SYS_GETDENTS64: {},
|
||||
unix.SYS_IOCTL: []seccomp.Rule{
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_RESET),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_SET_EVENTFD),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_CLEAR_EVENTFD),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_NUMBER_PAGE_TABLES),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_PAGE_TABLE_SIZE),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_SIMPLE_PAGE_TABLE_SIZE),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_PARTITION_PAGE_TABLE),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_MAP_BUFFER),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_UNMAP_BUFFER),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_CLEAR_INTERRUPT_COUNTS),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_REGISTER_INTERRUPT),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_UNREGISTER_INTERRUPT),
|
||||
},
|
||||
{
|
||||
nonNegativeFD,
|
||||
seccomp.EqualTo(gasket.GASKET_IOCTL_MAP_DMA_BUF),
|
||||
},
|
||||
},
|
||||
unix.SYS_EVENTFD2: []seccomp.Rule{
|
||||
{
|
||||
seccomp.MatchAny{},
|
||||
seccomp.EqualTo(linux.EFD_NONBLOCK),
|
||||
},
|
||||
{
|
||||
seccomp.MatchAny{},
|
||||
seccomp.EqualTo(linux.EFD_NONBLOCK | linux.EFD_SEMAPHORE),
|
||||
},
|
||||
},
|
||||
unix.SYS_MREMAP: []seccomp.Rule{
|
||||
{
|
||||
seccomp.MatchAny{},
|
||||
seccomp.EqualTo(0), /* old_size */
|
||||
seccomp.MatchAny{},
|
||||
seccomp.EqualTo(linux.MREMAP_MAYMOVE | linux.MREMAP_FIXED),
|
||||
seccomp.MatchAny{},
|
||||
seccomp.EqualTo(0),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import (
|
||||
|
||||
// Filters returns seccomp-bpf filters for this package.
|
||||
func Filters() seccomp.SyscallRules {
|
||||
nonNegativeFD := seccomp.LessThanOrEqual(0x7fff_ffff /* max int32 */)
|
||||
nonNegativeFD := seccomp.NonNegativeFDCheck()
|
||||
notIocSizeMask := ^(((uintptr(1) << linux.IOC_SIZEBITS) - 1) << linux.IOC_SIZESHIFT) // for ioctls taking arbitrary size
|
||||
return seccomp.SyscallRules{
|
||||
unix.SYS_OPENAT: []seccomp.Rule{
|
||||
|
||||
@@ -28,6 +28,7 @@ go_library(
|
||||
"//pkg/abi/linux",
|
||||
"//pkg/log",
|
||||
"//pkg/seccomp",
|
||||
"//pkg/sentry/devices/accel",
|
||||
"//pkg/sentry/devices/nvproxy",
|
||||
"//pkg/sentry/platform",
|
||||
"//pkg/sentry/socket/hostinet",
|
||||
|
||||
@@ -368,19 +368,13 @@ func controlServerFilters(fd int) seccomp.SyscallRules {
|
||||
}
|
||||
}
|
||||
|
||||
func nonNegativeFDCheck() seccomp.LessThanOrEqual {
|
||||
// Negative int32 has the MSB (31st bit) set. So the raw uint FD value must
|
||||
// be less than or equal to 0x7fffffff.
|
||||
return seccomp.LessThanOrEqual(0x7fffffff)
|
||||
}
|
||||
|
||||
// hostFilesystemFilters contains syscalls that are needed by directfs.
|
||||
func hostFilesystemFilters() seccomp.SyscallRules {
|
||||
// Directfs allows FD-based filesystem syscalls. We deny these syscalls with
|
||||
// negative FD values (like AT_FDCWD or invalid FD numbers). We try to be as
|
||||
// restrictive as possible because any restriction here improves security. We
|
||||
// don't know what set of arguments will trigger a future vulnerability.
|
||||
validFDCheck := nonNegativeFDCheck()
|
||||
validFDCheck := seccomp.NonNegativeFDCheck()
|
||||
return seccomp.SyscallRules{
|
||||
unix.SYS_FCHOWNAT: []seccomp.Rule{
|
||||
{
|
||||
|
||||
@@ -20,6 +20,7 @@ package filter
|
||||
import (
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/seccomp"
|
||||
"gvisor.dev/gvisor/pkg/sentry/devices/accel"
|
||||
"gvisor.dev/gvisor/pkg/sentry/devices/nvproxy"
|
||||
"gvisor.dev/gvisor/pkg/sentry/platform"
|
||||
)
|
||||
@@ -32,6 +33,7 @@ type Options struct {
|
||||
HostFilesystem bool
|
||||
ProfileEnable bool
|
||||
NVProxy bool
|
||||
TPUProxy bool
|
||||
ControllerFD int
|
||||
}
|
||||
|
||||
@@ -64,6 +66,10 @@ func Install(opt Options) error {
|
||||
Report("Nvidia GPU driver proxy enabled: syscall filters less restrictive!")
|
||||
s.Merge(nvproxy.Filters())
|
||||
}
|
||||
if opt.TPUProxy {
|
||||
Report("TPU device proxy enabled: syscall filters less restrictive!")
|
||||
s.Merge(accel.Filters())
|
||||
}
|
||||
|
||||
s.Merge(opt.Platform.SyscallFilters())
|
||||
|
||||
|
||||
@@ -649,6 +649,7 @@ func (l *Loader) installSeccompFilters() error {
|
||||
HostFilesystem: l.root.conf.DirectFS,
|
||||
ProfileEnable: l.root.conf.ProfileEnable,
|
||||
NVProxy: l.root.conf.NVProxy,
|
||||
TPUProxy: l.root.conf.TPUProxy,
|
||||
ControllerFD: l.ctrl.srv.FD(),
|
||||
}
|
||||
if err := filter.Install(opts); err != nil {
|
||||
|
||||
Reference in New Issue
Block a user