Add seccomp filters for TPU proxying and stub out accel fd methods.

PiperOrigin-RevId: 549718797
This commit is contained in:
Lucas Manning
2023-07-20 13:16:46 -07:00
committed by gVisor bot
parent 5eb44a9431
commit d4510e760b
9 changed files with 221 additions and 8 deletions
+7
View File
@@ -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
+24
View File
@@ -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",
],
)
+64
View File
@@ -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
}
+116
View File
@@ -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{
+1
View File
@@ -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",
+1 -7
View File
@@ -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{
{
+6
View File
@@ -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())
+1
View File
@@ -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 {