mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
d9fcdc7714
This moves the initialization of `seccheck.Points` out of package-level `init` and instead moves it to an explicit `seccheck.Initialize()` function. On AMD64, this saves about 614KiB of heap memory that would otherwise always be live. PiperOrigin-RevId: 514813332
109 lines
3.1 KiB
Go
109 lines
3.1 KiB
Go
// 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 linux
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"reflect"
|
|
"runtime"
|
|
"strings"
|
|
"testing"
|
|
"unicode"
|
|
|
|
"gvisor.dev/gvisor/pkg/sentry/seccheck"
|
|
)
|
|
|
|
func findPoint(name string) (seccheck.PointDesc, bool) {
|
|
for _, pt := range seccheck.Points {
|
|
if pt.Name == name {
|
|
return pt, true
|
|
}
|
|
}
|
|
return seccheck.PointDesc{}, false
|
|
}
|
|
|
|
// TestSeccheckMax catches cases that a new syscall was added but seccheck raw
|
|
// syscall numbers (e.g. syscall/sysno/123) have not been updated.
|
|
func TestSeccheckMax(t *testing.T) {
|
|
max := uintptr(0)
|
|
for sysno := range archToTest.Table {
|
|
if sysno > max {
|
|
max = sysno
|
|
}
|
|
}
|
|
|
|
want := fmt.Sprintf("syscall/sysno/%d/enter", max)
|
|
if _, ok := findPoint(want); !ok {
|
|
t.Errorf("seccheck.PointDesc for syscall %d not found. Update pkg/sentry/seccheck/metadata_amd64.go", max)
|
|
}
|
|
}
|
|
|
|
// TestSeccheckSyscalls verifies that all syscalls registered with a point
|
|
// callback have the corresponding seccheck metadata created.
|
|
func TestSeccheckSyscalls(t *testing.T) {
|
|
for sysno, syscall := range archToTest.Table {
|
|
if syscall.PointCallback == nil {
|
|
continue
|
|
}
|
|
|
|
// For every syscall with a PointCallback, there must be a corresponding
|
|
// seccheck.PointDesc created.
|
|
funcName := runtime.FuncForPC(reflect.ValueOf(syscall.PointCallback).Pointer()).Name()
|
|
if idx := strings.LastIndex(funcName, "."); idx > -1 {
|
|
funcName = funcName[idx+1:]
|
|
}
|
|
t.Run(funcName, func(t *testing.T) {
|
|
if !strings.HasPrefix(funcName, "Point") {
|
|
t.Errorf("PointCallback function name must start with Point: %q", funcName)
|
|
}
|
|
funcName = strings.TrimPrefix(funcName, "Point")
|
|
if len(funcName) == 0 {
|
|
t.Errorf("PointCallback function name invalid: %q", funcName)
|
|
}
|
|
|
|
pointName := strings.ToLower(string(funcName[0]))
|
|
for _, c := range funcName[1:] {
|
|
if unicode.IsUpper(c) {
|
|
pointName += "_"
|
|
}
|
|
pointName += string(unicode.ToLower(c))
|
|
}
|
|
|
|
for _, flavor := range []struct {
|
|
suffix string
|
|
typ seccheck.SyscallType
|
|
}{
|
|
{suffix: "enter", typ: seccheck.SyscallEnter},
|
|
{suffix: "exit", typ: seccheck.SyscallExit},
|
|
} {
|
|
fullName := fmt.Sprintf("syscall/%s/%s", pointName, flavor.suffix)
|
|
pt, ok := findPoint(fullName)
|
|
if !ok {
|
|
t.Fatalf("seccheck.PointDesc %q not found.", fullName)
|
|
}
|
|
if want := seccheck.GetPointForSyscall(flavor.typ, sysno); want != pt.ID {
|
|
t.Errorf("seccheck.Point for syscall %q is wrong, want: %v, got: %v", pointName, want, pt.ID)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMain(m *testing.M) {
|
|
seccheck.Initialize()
|
|
os.Exit(m.Run())
|
|
}
|