Move max syscall number out of kernel package.

Also add "num" at the end of it so make it clear that it's an *inclusive*
limit. Fix the uses of it which didn't treat it as inclusive.

No strong opinion on where it should go, but having it available in
other places of the codebase is helpful. It's already in two places,
and I'd like to have it available in two more places:

 - In the seccomp program compiler, so that it knows how many syscalls
   it should check for deterministic-ness and caching the results.
 - In the seccomp fuzzer, to build an initial syscall corpus.

PiperOrigin-RevId: 576660986
This commit is contained in:
Etienne Perot
2023-10-25 15:22:54 -07:00
committed by gVisor bot
parent cffce1a94a
commit 80ee2d3acc
7 changed files with 71 additions and 25 deletions
+15
View File
@@ -0,0 +1,15 @@
load("//tools:defs.bzl", "go_library")
package(
default_applicable_licenses = ["//:license"],
licenses = ["notice"],
)
go_library(
name = "sentry",
srcs = [
"sentry.go",
"syscall.go",
],
visibility = ["//:sandbox"],
)
+16
View File
@@ -0,0 +1,16 @@
// 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 sentry contains ABI-related constants for the gVisor sentry.
package sentry
+20
View File
@@ -0,0 +1,20 @@
// 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 sentry
// MaxSyscallNum is the largest-numbered syscall that is supported.
// Having this as a constant allows allocating per-syscall data structures
// that are of fixed size throughout the codebase.
const MaxSyscallNum = 2000
+1
View File
@@ -317,6 +317,7 @@ go_library(
"//pkg/abi",
"//pkg/abi/linux",
"//pkg/abi/linux/errno",
"//pkg/abi/sentry",
"//pkg/atomicbitops",
"//pkg/bitmap",
"//pkg/bits",
+11 -21
View File
@@ -20,6 +20,7 @@ import (
"google.golang.org/protobuf/proto"
"gvisor.dev/gvisor/pkg/abi"
"gvisor.dev/gvisor/pkg/abi/sentry"
"gvisor.dev/gvisor/pkg/atomicbitops"
"gvisor.dev/gvisor/pkg/bits"
"gvisor.dev/gvisor/pkg/hostarch"
@@ -30,17 +31,6 @@ import (
"gvisor.dev/gvisor/pkg/sync"
)
const (
// maxSyscallNum is the highest supported syscall number.
//
// The types below create fast lookup slices for all syscalls. This maximum
// serves as a sanity check that we don't allocate huge slices for a very large
// syscall. This is checked during registration.
// LINT.IfChange
maxSyscallNum = 2000
// LINT.ThenChange(../seccheck/syscall.go)
)
// outOfRangeSyscallNumber is used to represent a syscall number that is out of the
// range [0, maxSyscallNum] in monitoring.
var outOfRangeSyscallNumber = []*metric.FieldValue{&metric.FieldValue{"-1"}}
@@ -149,7 +139,7 @@ type SyscallFlagsTable struct {
//
// missing syscalls have the same value in enable as missingEnable to
// avoid an extra branch in Word.
enable [maxSyscallNum + 1]atomicbitops.Uint32
enable [sentry.MaxSyscallNum + 1]atomicbitops.Uint32
// missingEnable contains the enable bits for missing syscalls.
missingEnable atomicbitops.Uint32
@@ -173,7 +163,7 @@ func (e *SyscallFlagsTable) init(table map[uintptr]Syscall) {
func (e *SyscallFlagsTable) UpdateSecCheck(state *seccheck.State) {
e.mu.Lock()
defer e.mu.Unlock()
for sysno := uintptr(0); sysno < maxSyscallNum; sysno++ {
for sysno := uintptr(0); sysno <= sentry.MaxSyscallNum; sysno++ {
oldFlags := e.enable[sysno].Load()
if !bits.IsOn32(oldFlags, syscallPresent) {
continue
@@ -207,7 +197,7 @@ func (e *SyscallFlagsTable) UpdateSecCheck(state *seccheck.State) {
// Word returns the enable bitfield for sysno.
func (e *SyscallFlagsTable) Word(sysno uintptr) uint32 {
if sysno <= maxSyscallNum {
if sysno <= sentry.MaxSyscallNum {
return e.enable[sysno].Load()
}
return e.missingEnable.Load()
@@ -308,12 +298,12 @@ type SyscallTable struct {
// lookup is a fixed-size array that holds the syscalls (indexed by
// their numbers). It is used for fast look ups.
lookup [maxSyscallNum + 1]SyscallFn
lookup [sentry.MaxSyscallNum + 1]SyscallFn
// pointCallbacks is a fixed-size array that holds SyscallToProto callbacks
// (indexed by syscall numbers). It is used for fast lookups when
// seccheck.Point is enabled for the syscall.
pointCallbacks [maxSyscallNum + 1]SyscallToProto
pointCallbacks [sentry.MaxSyscallNum + 1]SyscallToProto
// Emulate is a collection of instruction addresses to emulate. The
// keys are addresses, and the values are system call numbers.
@@ -386,7 +376,7 @@ func LookupSyscallTable(os abi.OS, a arch.Arch) (*SyscallTable, bool) {
// RegisterSyscallTable registers a new syscall table for use by a Kernel.
func RegisterSyscallTable(s *SyscallTable) {
if max := s.MaxSysno(); max > maxSyscallNum {
if max := s.MaxSysno(); max > sentry.MaxSyscallNum {
panic(fmt.Sprintf("SyscallTable %+v contains too large syscall number %d", s, max))
}
if _, ok := LookupSyscallTable(s.OS, s.Arch); ok {
@@ -394,9 +384,9 @@ func RegisterSyscallTable(s *SyscallTable) {
}
allSyscallTables = append(allSyscallTables, s)
unimplementedSyscallCounterInit.Do(func() {
allowedValues := make([]*metric.FieldValue, maxSyscallNum+2)
allowedValues := make([]*metric.FieldValue, sentry.MaxSyscallNum+2)
unimplementedSyscallNumbers = make(map[uintptr][]*metric.FieldValue, len(allowedValues))
for i := uintptr(0); i <= maxSyscallNum; i++ {
for i := uintptr(0); i <= sentry.MaxSyscallNum; i++ {
s := &metric.FieldValue{strconv.Itoa(int(i))}
allowedValues[i] = s
unimplementedSyscallNumbers[i] = []*metric.FieldValue{s}
@@ -434,7 +424,7 @@ func (s *SyscallTable) Init() {
// Lookup returns the syscall implementation, if one exists.
func (s *SyscallTable) Lookup(sysno uintptr) SyscallFn {
if sysno <= maxSyscallNum {
if sysno <= sentry.MaxSyscallNum {
return s.lookup[sysno]
}
return nil
@@ -476,7 +466,7 @@ func (s *SyscallTable) mapLookup(sysno uintptr) SyscallFn {
// LookupSyscallToProto looks up the SyscallToProto callback for the given
// syscall. It may return nil if none is registered.
func (s *SyscallTable) LookupSyscallToProto(sysno uintptr) SyscallToProto {
if sysno > maxSyscallNum {
if sysno > sentry.MaxSyscallNum {
return nil
}
return s.pointCallbacks[sysno]
+2
View File
@@ -29,7 +29,9 @@ go_library(
],
visibility = ["//:sandbox"],
deps = [
"//pkg/abi",
"//pkg/abi/linux",
"//pkg/abi/sentry",
"//pkg/atomicbitops",
"//pkg/context",
"//pkg/fd",
+6 -4
View File
@@ -14,6 +14,10 @@
package seccheck
import (
"gvisor.dev/gvisor/pkg/abi/sentry"
)
// SyscallType is an enum that denotes different types of syscall points. There
// are 2 types of syscall point: fully-schematized and raw. Schematizes are
// points that have syscall specific format, e.g. open => {path, flags, mode}.
@@ -47,9 +51,7 @@ type SyscallFlagListener interface {
}
const (
// Copied from kernel.maxSyscallNum to avoid reverse dependency.
syscallsMax = 2000
syscallPoints = syscallsMax * int(syscallTypesCount)
syscallPoints = (sentry.MaxSyscallNum + 1) * int(syscallTypesCount)
)
// Fields that are common for many syscalls.
@@ -75,7 +77,7 @@ func GetPointForSyscall(typ SyscallType, sysno uintptr) Point {
// SyscallEnabled checks if the corresponding point for the syscall is enabled.
func (s *State) SyscallEnabled(typ SyscallType, sysno uintptr) bool {
// Prevent overflow.
if sysno >= syscallsMax {
if sysno >= sentry.MaxSyscallNum {
return false
}
return s.Enabled(GetPointForSyscall(typ, sysno))