1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
|
// Copyright 2022 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 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}.
// Raw uses a generic schema that contains syscall number and 6 arguments. Each
// of these type have a corresponding enter and exit points. Exit points include
// return value and errno information.
type SyscallType int
const (
// SyscallEnter represents schematized/enter syscall.
SyscallEnter SyscallType = iota
// SyscallExit represents schematized/exit syscall.
SyscallExit
// SyscallRawEnter represents raw/enter syscall.
SyscallRawEnter
// SyscallRawExit represents raw/exit syscall.
SyscallRawExit
syscallTypesCount
)
// SyscallFlagListener is an interface that is notified when syscall point enablement changes.
//
// It is used to notify the kernel's syscall table about syscall points, without introducing a
// direct dependency on it.
type SyscallFlagListener interface {
// UpdateSecCheck is called each time the system call point enablement may have changed.
// This is called with seccheck.State.mu held, so it is expected to be fast and not re-entrant
// with seccheck.State functions that attempt to re-lock it.
UpdateSecCheck(state *State)
}
const (
syscallPoints = (sentry.MaxSyscallNum + 1) * int(syscallTypesCount)
)
// Fields that are common for many syscalls.
const (
// FieldSyscallPath is an optional field to collect path from an FD. Given
// that many syscalls operate on FDs, this const is used across syscalls.
FieldSyscallPath Field = iota
)
// Fields for execve*(2) syscalls.
const (
// FieldSyscallExecveEnvv is an optional field to collect list of environment
// variables. Start after FieldSyscallPath because execveat(2) can collect
// path from FD.
FieldSyscallExecveEnvv = FieldSyscallPath + 1
)
// GetPointForSyscall translates the syscall number to the corresponding Point.
func GetPointForSyscall(typ SyscallType, sysno uintptr) Point {
return Point(sysno)*Point(syscallTypesCount) + Point(typ) + pointLengthBeforeSyscalls
}
// SyscallEnabled checks if the corresponding point for the syscall is enabled.
func (s *State) SyscallEnabled(typ SyscallType, sysno uintptr) bool {
// Prevent overflow.
if sysno >= sentry.MaxSyscallNum {
return false
}
return s.Enabled(GetPointForSyscall(typ, sysno))
}
|