mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Rename seccheck.checkers to seccheck.sinks
Makes the naming consistent with the public configuration. There is no behavior change. Updates #4805 PiperOrigin-RevId: 462448505
This commit is contained in:
committed by
gVisor bot
parent
3fe2b84bb4
commit
da267f435f
@@ -83,7 +83,7 @@ type Syscall struct {
|
||||
// URLs is set of URLs to any relevant bugs or issues.
|
||||
URLs []string
|
||||
// PointCallback is an optional callback that converts syscall arguments
|
||||
// to a proto that can be used with seccheck.Checker.
|
||||
// to a proto that can be used with seccheck.Sink.
|
||||
// Callback functions must follow this naming convention:
|
||||
// PointSyscallNameInCamelCase, e.g. PointReadat, PointRtSigaction.
|
||||
PointCallback SyscallToProto
|
||||
|
||||
@@ -253,7 +253,7 @@ func (t *Task) Clone(args *linux.CloneArgs) (ThreadID, *SyscallControl, error) {
|
||||
|
||||
if seccheck.Global.Enabled(seccheck.PointClone) {
|
||||
mask, info := getCloneSeccheckInfo(t, nt, args.Flags)
|
||||
if err := seccheck.Global.SendToCheckers(func(c seccheck.Checker) error {
|
||||
if err := seccheck.Global.SentToSinks(func(c seccheck.Sink) error {
|
||||
return c.Clone(t, mask, info)
|
||||
}); err != nil {
|
||||
// nt has been visible to the rest of the system since NewTask, so
|
||||
|
||||
@@ -97,7 +97,7 @@ func (t *Task) Execve(newImage *TaskImage, argv, env []string, executable fsbrid
|
||||
// We can't clearly hold kernel package locks while stat'ing executable.
|
||||
if seccheck.Global.Enabled(seccheck.PointExecve) {
|
||||
mask, info := getExecveSeccheckInfo(t, argv, env, executable, pathname)
|
||||
if err := seccheck.Global.SendToCheckers(func(c seccheck.Checker) error {
|
||||
if err := seccheck.Global.SentToSinks(func(c seccheck.Sink) error {
|
||||
return c.Execve(t, mask, info)
|
||||
}); err != nil {
|
||||
newImage.release()
|
||||
|
||||
@@ -214,7 +214,7 @@ func (*runExitMain) execute(t *Task) taskRunState {
|
||||
info.ContextData = &pb.ContextData{}
|
||||
LoadSeccheckData(t, fields.Context, info.ContextData)
|
||||
}
|
||||
seccheck.Global.SendToCheckers(func(c seccheck.Checker) error {
|
||||
seccheck.Global.SentToSinks(func(c seccheck.Sink) error {
|
||||
return c.TaskExit(t, fields, info)
|
||||
})
|
||||
}
|
||||
@@ -668,7 +668,7 @@ func (t *Task) exitNotifyLocked(fromPtraceDetach bool) {
|
||||
// Clone or Exec events for the initial process.
|
||||
if t.tg != t.k.globalInit && seccheck.Global.Enabled(seccheck.PointExitNotifyParent) {
|
||||
mask, info := getExitNotifyParentSeccheckInfo(t)
|
||||
if err := seccheck.Global.SendToCheckers(func(c seccheck.Checker) error {
|
||||
if err := seccheck.Global.SentToSinks(func(c seccheck.Sink) error {
|
||||
return c.ExitNotifyParent(t, mask, info)
|
||||
}); err != nil {
|
||||
log.Infof("Ignoring error from ExitNotifyParent point: %v", err)
|
||||
|
||||
@@ -105,7 +105,7 @@ func (t *Task) executeSyscall(sysno uintptr, args arch.SyscallArguments) (rval u
|
||||
info.ContextData = &pb.ContextData{}
|
||||
LoadSeccheckData(t, fields.Context, info.ContextData)
|
||||
}
|
||||
seccheck.Global.SendToCheckers(func(c seccheck.Checker) error {
|
||||
seccheck.Global.SentToSinks(func(c seccheck.Sink) error {
|
||||
return c.RawSyscall(t, fields, &info)
|
||||
})
|
||||
}
|
||||
@@ -122,7 +122,7 @@ func (t *Task) executeSyscall(sysno uintptr, args arch.SyscallArguments) (rval u
|
||||
}
|
||||
cb := t.SyscallTable().LookupSyscallToProto(sysno)
|
||||
msg, msgType := cb(t, fields, ctxData, info)
|
||||
seccheck.Global.SendToCheckers(func(c seccheck.Checker) error {
|
||||
seccheck.Global.SentToSinks(func(c seccheck.Sink) error {
|
||||
return c.Syscall(t, fields, ctxData, msgType, msg)
|
||||
})
|
||||
}
|
||||
@@ -177,7 +177,7 @@ func (t *Task) executeSyscall(sysno uintptr, args arch.SyscallArguments) (rval u
|
||||
info.ContextData = &pb.ContextData{}
|
||||
LoadSeccheckData(t, fields.Context, info.ContextData)
|
||||
}
|
||||
seccheck.Global.SendToCheckers(func(c seccheck.Checker) error {
|
||||
seccheck.Global.SentToSinks(func(c seccheck.Sink) error {
|
||||
return c.RawSyscall(t, fields, &info)
|
||||
})
|
||||
}
|
||||
@@ -197,7 +197,7 @@ func (t *Task) executeSyscall(sysno uintptr, args arch.SyscallArguments) (rval u
|
||||
}
|
||||
cb := t.SyscallTable().LookupSyscallToProto(sysno)
|
||||
msg, msgType := cb(t, fields, ctxData, info)
|
||||
seccheck.Global.SendToCheckers(func(c seccheck.Checker) error {
|
||||
seccheck.Global.SentToSinks(func(c seccheck.Sink) error {
|
||||
return c.Syscall(t, fields, ctxData, msgType, msg)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ load("//tools/go_generics:defs.bzl", "go_template_instance")
|
||||
licenses(["notice"])
|
||||
|
||||
go_template_instance(
|
||||
name = "seqatomic_checkerslice",
|
||||
out = "seqatomic_checkerslice_unsafe.go",
|
||||
name = "seqatomic_sinkslice",
|
||||
out = "seqatomic_sinkslice_unsafe.go",
|
||||
package = "seccheck",
|
||||
suffix = "CheckerSlice",
|
||||
suffix = "SinkSlice",
|
||||
template = "//pkg/sync/seqatomic:generic_seqatomic",
|
||||
types = {
|
||||
"Value": "[]Checker",
|
||||
"Value": "[]Sink",
|
||||
},
|
||||
)
|
||||
|
||||
@@ -22,7 +22,7 @@ go_library(
|
||||
"metadata_amd64.go",
|
||||
"metadata_arm64.go",
|
||||
"seccheck.go",
|
||||
"seqatomic_checkerslice_unsafe.go",
|
||||
"seqatomic_sinkslice_unsafe.go",
|
||||
"syscall.go",
|
||||
],
|
||||
visibility = ["//:sandbox"],
|
||||
|
||||
@@ -64,7 +64,7 @@ type SinkConfig struct {
|
||||
// failures will prevent the container from starting.
|
||||
IgnoreSetupError bool `json:"ignore_setup_error,omitempty"`
|
||||
// Status is the runtime status for the sink.
|
||||
Status CheckerStatus `json:"status,omitempty"`
|
||||
Status SinkStatus `json:"status,omitempty"`
|
||||
// FD is the endpoint returned from Setup. It may be nil.
|
||||
FD *fd.FD `json:"-"`
|
||||
}
|
||||
@@ -113,15 +113,15 @@ func Create(conf *SessionConfig, force bool) error {
|
||||
}
|
||||
|
||||
for _, sinkConfig := range conf.Sinks {
|
||||
sink, err := findSinkDesc(sinkConfig.Name)
|
||||
desc, err := findSinkDesc(sinkConfig.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
checker, err := sink.New(sinkConfig.Config, sinkConfig.FD)
|
||||
sink, err := desc.New(sinkConfig.Config, sinkConfig.FD)
|
||||
if err != nil {
|
||||
return fmt.Errorf("creating event sink: %w", err)
|
||||
}
|
||||
state.AppendChecker(checker, reqs)
|
||||
state.AppendSink(sink, reqs)
|
||||
}
|
||||
|
||||
sessions[conf.Name] = state
|
||||
@@ -173,7 +173,7 @@ func deleteLocked(name string) error {
|
||||
return fmt.Errorf("session %q not found", name)
|
||||
}
|
||||
|
||||
session.clearCheckers()
|
||||
session.clearSink()
|
||||
delete(sessions, name)
|
||||
return nil
|
||||
}
|
||||
@@ -186,10 +186,10 @@ func List(out *[]SessionConfig) {
|
||||
for name, state := range sessions {
|
||||
// Only report session name. Consider adding rest of the fields as needed.
|
||||
session := SessionConfig{Name: name}
|
||||
for _, checker := range state.getCheckers() {
|
||||
for _, sink := range state.getSinks() {
|
||||
session.Sinks = append(session.Sinks, SinkConfig{
|
||||
Name: checker.Name(),
|
||||
Status: checker.Status(),
|
||||
Name: sink.Name(),
|
||||
Status: sink.Status(),
|
||||
})
|
||||
}
|
||||
*out = append(*out, session)
|
||||
|
||||
@@ -117,7 +117,7 @@ type SinkDesc struct {
|
||||
// New creates a new sink. config is an opaque json object passed to the sink.
|
||||
// endpoing is a file descriptor to the file returned in Setup. It's set to -1
|
||||
// if Setup returned nil.
|
||||
New func(config map[string]interface{}, endpoint *fd.FD) (Checker, error)
|
||||
New func(config map[string]interface{}, endpoint *fd.FD) (Sink, error)
|
||||
}
|
||||
|
||||
// RegisterSink registers a new sink to make it discoverable.
|
||||
|
||||
@@ -85,22 +85,22 @@ func (fm *FieldMask) Empty() bool {
|
||||
return fm.mask == 0
|
||||
}
|
||||
|
||||
// A Checker performs security checks at checkpoints.
|
||||
// A Sink performs security checks at checkpoints.
|
||||
//
|
||||
// Each Checker method X is called at checkpoint X; if the method may return a
|
||||
// Each Sink method X is called at checkpoint X; if the method may return a
|
||||
// non-nil error and does so, it causes the checked operation to fail
|
||||
// immediately (without calling subsequent Checkers) and return the error. The
|
||||
// immediately (without calling subsequent Sinks) and return the error. The
|
||||
// info argument contains information relevant to the check. The mask argument
|
||||
// indicates what fields in info are valid; the mask should usually be a
|
||||
// superset of fields requested by the Checker's corresponding PointReq, but
|
||||
// may be missing requested fields in some cases (e.g. if the Checker is
|
||||
// superset of fields requested by the Sink's corresponding PointReq, but
|
||||
// may be missing requested fields in some cases (e.g. if the Sink is
|
||||
// registered concurrently with invocations of checkpoints).
|
||||
type Checker interface {
|
||||
// Name return the checker name.
|
||||
type Sink interface {
|
||||
// Name return the sink name.
|
||||
Name() string
|
||||
// Status returns the checker runtime status.
|
||||
Status() CheckerStatus
|
||||
// Stop requests the checker to stop.
|
||||
// Status returns the sink runtime status.
|
||||
Status() SinkStatus
|
||||
// Stop requests the sink to stop.
|
||||
Stop()
|
||||
|
||||
Clone(ctx context.Context, fields FieldSet, info *pb.CloneInfo) error
|
||||
@@ -114,71 +114,71 @@ type Checker interface {
|
||||
RawSyscall(context.Context, FieldSet, *pb.Syscall) error
|
||||
}
|
||||
|
||||
// CheckerStatus represents stats about each checker instance.
|
||||
type CheckerStatus struct {
|
||||
// SinkStatus represents stats about each Sink instance.
|
||||
type SinkStatus struct {
|
||||
// DroppedCount is the number of trace points dropped.
|
||||
DroppedCount uint64
|
||||
}
|
||||
|
||||
// CheckerDefaults may be embedded by implementations of Checker to obtain
|
||||
// no-op implementations of Checker methods that may be explicitly overridden.
|
||||
type CheckerDefaults struct{}
|
||||
// SinkDefaults may be embedded by implementations of Sink to obtain
|
||||
// no-op implementations of Sink methods that may be explicitly overridden.
|
||||
type SinkDefaults struct{}
|
||||
|
||||
// Add functions missing in CheckerDefaults to make it possible to check for the
|
||||
// Add functions missing in SinkDefaults to make it possible to check for the
|
||||
// implementation below to catch missing functions more easily.
|
||||
type checkerDefaultsImpl struct {
|
||||
CheckerDefaults
|
||||
type sinkDefaultsImpl struct {
|
||||
SinkDefaults
|
||||
}
|
||||
|
||||
// Name implements Checker.Name.
|
||||
func (checkerDefaultsImpl) Name() string { return "" }
|
||||
// Name implements Sink.Name.
|
||||
func (sinkDefaultsImpl) Name() string { return "" }
|
||||
|
||||
var _ Checker = (*checkerDefaultsImpl)(nil)
|
||||
var _ Sink = (*sinkDefaultsImpl)(nil)
|
||||
|
||||
// Status implements Checker.Status.
|
||||
func (CheckerDefaults) Status() CheckerStatus {
|
||||
return CheckerStatus{}
|
||||
// Status implements Sink.Status.
|
||||
func (SinkDefaults) Status() SinkStatus {
|
||||
return SinkStatus{}
|
||||
}
|
||||
|
||||
// Stop implements Checker.Stop.
|
||||
func (CheckerDefaults) Stop() {}
|
||||
// Stop implements Sink.Stop.
|
||||
func (SinkDefaults) Stop() {}
|
||||
|
||||
// Clone implements Checker.Clone.
|
||||
func (CheckerDefaults) Clone(context.Context, FieldSet, *pb.CloneInfo) error {
|
||||
// Clone implements Sink.Clone.
|
||||
func (SinkDefaults) Clone(context.Context, FieldSet, *pb.CloneInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execve implements Checker.Execve.
|
||||
func (CheckerDefaults) Execve(context.Context, FieldSet, *pb.ExecveInfo) error {
|
||||
// Execve implements Sink.Execve.
|
||||
func (SinkDefaults) Execve(context.Context, FieldSet, *pb.ExecveInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExitNotifyParent implements Checker.ExitNotifyParent.
|
||||
func (CheckerDefaults) ExitNotifyParent(context.Context, FieldSet, *pb.ExitNotifyParentInfo) error {
|
||||
// ExitNotifyParent implements Sink.ExitNotifyParent.
|
||||
func (SinkDefaults) ExitNotifyParent(context.Context, FieldSet, *pb.ExitNotifyParentInfo) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContainerStart implements Checker.ContainerStart.
|
||||
func (CheckerDefaults) ContainerStart(context.Context, FieldSet, *pb.Start) error {
|
||||
// ContainerStart implements Sink.ContainerStart.
|
||||
func (SinkDefaults) ContainerStart(context.Context, FieldSet, *pb.Start) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TaskExit implements Checker.TaskExit.
|
||||
func (CheckerDefaults) TaskExit(context.Context, FieldSet, *pb.TaskExit) error {
|
||||
// TaskExit implements Sink.TaskExit.
|
||||
func (SinkDefaults) TaskExit(context.Context, FieldSet, *pb.TaskExit) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawSyscall implements Checker.RawSyscall.
|
||||
func (CheckerDefaults) RawSyscall(context.Context, FieldSet, *pb.Syscall) error {
|
||||
// RawSyscall implements Sink.RawSyscall.
|
||||
func (SinkDefaults) RawSyscall(context.Context, FieldSet, *pb.Syscall) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Syscall implements Checker.Syscall.
|
||||
func (CheckerDefaults) Syscall(context.Context, FieldSet, *pb.ContextData, pb.MessageType, proto.Message) error {
|
||||
// Syscall implements Sink.Syscall.
|
||||
func (SinkDefaults) Syscall(context.Context, FieldSet, *pb.ContextData, pb.MessageType, proto.Message) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PointReq indicates what Point a corresponding Checker runs at, and what
|
||||
// PointReq indicates what Point a corresponding Sink runs at, and what
|
||||
// information it requires at those Points.
|
||||
type PointReq struct {
|
||||
Pt Point
|
||||
@@ -190,36 +190,36 @@ var Global State
|
||||
|
||||
// State is the type of global, and is separated out for testing.
|
||||
type State struct {
|
||||
// registrationMu serializes all changes to the set of registered Checkers
|
||||
// registrationMu serializes all changes to the set of registered Sinks
|
||||
// for all checkpoints.
|
||||
registrationMu sync.RWMutex
|
||||
|
||||
// enabledPoints is a bitmask of checkpoints for which at least one Checker
|
||||
// enabledPoints is a bitmask of checkpoints for which at least one Sink
|
||||
// is registered.
|
||||
//
|
||||
// Mutation of enabledPoints is serialized by registrationMu.
|
||||
enabledPoints [numPointBitmaskUint32s]atomicbitops.Uint32
|
||||
|
||||
// registrationSeq supports store-free atomic reads of registeredCheckers.
|
||||
// registrationSeq supports store-free atomic reads of registeredSinks.
|
||||
registrationSeq sync.SeqCount
|
||||
|
||||
// checkers is the set of all registered Checkers in order of execution.
|
||||
// sinks is the set of all registered Sinks in order of execution.
|
||||
//
|
||||
// checkers is accessed using instantiations of SeqAtomic functions.
|
||||
// Mutation of checkers is serialized by registrationMu.
|
||||
checkers []Checker
|
||||
// sinks is accessed using instantiations of SeqAtomic functions.
|
||||
// Mutation of sinks is serialized by registrationMu.
|
||||
sinks []Sink
|
||||
|
||||
pointFields map[Point]FieldSet
|
||||
}
|
||||
|
||||
// AppendChecker registers the given Checker to execute at checkpoints. The
|
||||
// Checker will execute after all previously-registered Checkers, and only if
|
||||
// those Checkers return a nil error.
|
||||
func (s *State) AppendChecker(c Checker, reqs []PointReq) {
|
||||
// AppendSink registers the given Sink to execute at checkpoints. The
|
||||
// Sink will execute after all previously-registered sinks, and only if
|
||||
// those Sinks return a nil error.
|
||||
func (s *State) AppendSink(c Sink, reqs []PointReq) {
|
||||
s.registrationMu.Lock()
|
||||
defer s.registrationMu.Unlock()
|
||||
|
||||
s.appendCheckerLocked(c)
|
||||
s.appendSinkLocked(c)
|
||||
if s.pointFields == nil {
|
||||
s.pointFields = make(map[Point]FieldSet)
|
||||
}
|
||||
@@ -231,7 +231,7 @@ func (s *State) AppendChecker(c Checker, reqs []PointReq) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *State) clearCheckers() {
|
||||
func (s *State) clearSink() {
|
||||
s.registrationMu.Lock()
|
||||
defer s.registrationMu.Unlock()
|
||||
|
||||
@@ -240,16 +240,16 @@ func (s *State) clearCheckers() {
|
||||
}
|
||||
s.pointFields = nil
|
||||
|
||||
oldCheckers := s.getCheckers()
|
||||
oldSinks := s.getSinks()
|
||||
s.registrationSeq.BeginWrite()
|
||||
s.checkers = nil
|
||||
s.sinks = nil
|
||||
s.registrationSeq.EndWrite()
|
||||
for _, checker := range oldCheckers {
|
||||
checker.Stop()
|
||||
for _, sink := range oldSinks {
|
||||
sink.Stop()
|
||||
}
|
||||
}
|
||||
|
||||
// Enabled returns true if any Checker is registered for the given checkpoint.
|
||||
// Enabled returns true if any Sink is registered for the given checkpoint.
|
||||
func (s *State) Enabled(p Point) bool {
|
||||
word, bit := p/32, p%32
|
||||
if int(word) >= len(s.enabledPoints) {
|
||||
@@ -258,20 +258,20 @@ func (s *State) Enabled(p Point) bool {
|
||||
return s.enabledPoints[word].Load()&(uint32(1)<<bit) != 0
|
||||
}
|
||||
|
||||
func (s *State) getCheckers() []Checker {
|
||||
return SeqAtomicLoadCheckerSlice(&s.registrationSeq, &s.checkers)
|
||||
func (s *State) getSinks() []Sink {
|
||||
return SeqAtomicLoadSinkSlice(&s.registrationSeq, &s.sinks)
|
||||
}
|
||||
|
||||
// Preconditions: s.registrationMu must be locked.
|
||||
func (s *State) appendCheckerLocked(c Checker) {
|
||||
func (s *State) appendSinkLocked(c Sink) {
|
||||
s.registrationSeq.BeginWrite()
|
||||
s.checkers = append(s.checkers, c)
|
||||
s.sinks = append(s.sinks, c)
|
||||
s.registrationSeq.EndWrite()
|
||||
}
|
||||
|
||||
// SendToCheckers iterates over all checkers and calls fn for each one of them.
|
||||
func (s *State) SendToCheckers(fn func(c Checker) error) error {
|
||||
for _, c := range s.getCheckers() {
|
||||
// SentToSinks iterates over all sinks and calls fn for each one of them.
|
||||
func (s *State) SentToSinks(fn func(c Sink) error) error {
|
||||
for _, c := range s.getSinks() {
|
||||
if err := fn(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -22,46 +22,46 @@ import (
|
||||
pb "gvisor.dev/gvisor/pkg/sentry/seccheck/points/points_go_proto"
|
||||
)
|
||||
|
||||
type testChecker struct {
|
||||
CheckerDefaults
|
||||
type testSink struct {
|
||||
SinkDefaults
|
||||
|
||||
onClone func(ctx context.Context, fields FieldSet, info *pb.CloneInfo) error
|
||||
}
|
||||
|
||||
// Name implements Checker.Name.
|
||||
func (c *testChecker) Name() string {
|
||||
return "test-checker"
|
||||
// Name implements Sink.Name.
|
||||
func (c *testSink) Name() string {
|
||||
return "test-sink"
|
||||
}
|
||||
|
||||
// Clone implements Checker.Clone.
|
||||
func (c *testChecker) Clone(ctx context.Context, fields FieldSet, info *pb.CloneInfo) error {
|
||||
// Clone implements Sink.Clone.
|
||||
func (c *testSink) Clone(ctx context.Context, fields FieldSet, info *pb.CloneInfo) error {
|
||||
if c.onClone == nil {
|
||||
return nil
|
||||
}
|
||||
return c.onClone(ctx, fields, info)
|
||||
}
|
||||
|
||||
func TestNoChecker(t *testing.T) {
|
||||
func TestNoSink(t *testing.T) {
|
||||
var s State
|
||||
if s.Enabled(PointClone) {
|
||||
t.Errorf("Enabled(PointClone): got true, wanted false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckerNotRegisteredForPoint(t *testing.T) {
|
||||
func TestSinkNotRegisteredForPoint(t *testing.T) {
|
||||
var s State
|
||||
s.AppendChecker(&testChecker{}, nil)
|
||||
s.AppendSink(&testSink{}, nil)
|
||||
if s.Enabled(PointClone) {
|
||||
t.Errorf("Enabled(PointClone): got true, wanted false")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckerRegistered(t *testing.T) {
|
||||
func TestSinkRegistered(t *testing.T) {
|
||||
var s State
|
||||
checkerCalled := false
|
||||
checker := &testChecker{
|
||||
sinkCalled := false
|
||||
sink := &testSink{
|
||||
onClone: func(context.Context, FieldSet, *pb.CloneInfo) error {
|
||||
checkerCalled = true
|
||||
sinkCalled = true
|
||||
return nil
|
||||
},
|
||||
}
|
||||
@@ -71,7 +71,7 @@ func TestCheckerRegistered(t *testing.T) {
|
||||
Fields: FieldSet{Context: MakeFieldMask(FieldCtxtCredentials)},
|
||||
},
|
||||
}
|
||||
s.AppendChecker(checker, req)
|
||||
s.AppendSink(sink, req)
|
||||
|
||||
if !s.Enabled(PointClone) {
|
||||
t.Errorf("Enabled(PointClone): got false, wanted true")
|
||||
@@ -80,96 +80,96 @@ func TestCheckerRegistered(t *testing.T) {
|
||||
if !fields.Context.Contains(FieldCtxtCredentials) {
|
||||
t.Errorf("fields.Context.Contains(PointContextCredentials): got false, wanted true")
|
||||
}
|
||||
if err := s.SendToCheckers(func(c Checker) error {
|
||||
if err := s.SentToSinks(func(c Sink) error {
|
||||
return c.Clone(context.Background(), fields, &pb.CloneInfo{})
|
||||
}); err != nil {
|
||||
t.Errorf("Clone(): got %v, wanted nil", err)
|
||||
}
|
||||
if !checkerCalled {
|
||||
t.Errorf("Clone() did not call Checker.Clone()")
|
||||
if !sinkCalled {
|
||||
t.Errorf("Clone() did not call Sink.Clone()")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultipleCheckersRegistered(t *testing.T) {
|
||||
func TestMultipleSinksRegistered(t *testing.T) {
|
||||
var s State
|
||||
checkersCalled := [2]bool{}
|
||||
checker := &testChecker{
|
||||
sinkCalled := [2]bool{}
|
||||
sink := &testSink{
|
||||
onClone: func(context.Context, FieldSet, *pb.CloneInfo) error {
|
||||
checkersCalled[0] = true
|
||||
sinkCalled[0] = true
|
||||
return nil
|
||||
},
|
||||
}
|
||||
reqs := []PointReq{
|
||||
{Pt: PointClone},
|
||||
}
|
||||
s.AppendChecker(checker, reqs)
|
||||
s.AppendSink(sink, reqs)
|
||||
|
||||
checker = &testChecker{onClone: func(context.Context, FieldSet, *pb.CloneInfo) error {
|
||||
checkersCalled[1] = true
|
||||
sink = &testSink{onClone: func(context.Context, FieldSet, *pb.CloneInfo) error {
|
||||
sinkCalled[1] = true
|
||||
return nil
|
||||
}}
|
||||
reqs = []PointReq{
|
||||
{Pt: PointClone},
|
||||
}
|
||||
s.AppendChecker(checker, reqs)
|
||||
s.AppendSink(sink, reqs)
|
||||
|
||||
if !s.Enabled(PointClone) {
|
||||
t.Errorf("Enabled(PointClone): got false, wanted true")
|
||||
}
|
||||
// CloneReq() should return the union of requested fields from all calls to
|
||||
// AppendChecker.
|
||||
// AppendSink.
|
||||
fields := s.GetFieldSet(PointClone)
|
||||
if err := s.SendToCheckers(func(c Checker) error {
|
||||
if err := s.SentToSinks(func(c Sink) error {
|
||||
return c.Clone(context.Background(), fields, &pb.CloneInfo{})
|
||||
}); err != nil {
|
||||
t.Errorf("Clone(): got %v, wanted nil", err)
|
||||
}
|
||||
for i := range checkersCalled {
|
||||
if !checkersCalled[i] {
|
||||
t.Errorf("Clone() did not call Checker.Clone() index %d", i)
|
||||
for i := range sinkCalled {
|
||||
if !sinkCalled[i] {
|
||||
t.Errorf("Clone() did not call Sink.Clone() index %d", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckpointReturnsFirstCheckerError(t *testing.T) {
|
||||
errFirstChecker := errors.New("first Checker error")
|
||||
errSecondChecker := errors.New("second Checker error")
|
||||
func TestCheckpointReturnsFirstSinkError(t *testing.T) {
|
||||
errFirstSink := errors.New("first Sink error")
|
||||
errSecondSink := errors.New("second Sink error")
|
||||
|
||||
var s State
|
||||
checkersCalled := [2]bool{}
|
||||
checker := &testChecker{
|
||||
sinkCalled := [2]bool{}
|
||||
sink := &testSink{
|
||||
onClone: func(context.Context, FieldSet, *pb.CloneInfo) error {
|
||||
checkersCalled[0] = true
|
||||
return errFirstChecker
|
||||
sinkCalled[0] = true
|
||||
return errFirstSink
|
||||
},
|
||||
}
|
||||
reqs := []PointReq{
|
||||
{Pt: PointClone},
|
||||
}
|
||||
|
||||
s.AppendChecker(checker, reqs)
|
||||
s.AppendSink(sink, reqs)
|
||||
|
||||
checker = &testChecker{
|
||||
sink = &testSink{
|
||||
onClone: func(context.Context, FieldSet, *pb.CloneInfo) error {
|
||||
checkersCalled[1] = true
|
||||
return errSecondChecker
|
||||
sinkCalled[1] = true
|
||||
return errSecondSink
|
||||
},
|
||||
}
|
||||
s.AppendChecker(checker, reqs)
|
||||
s.AppendSink(sink, reqs)
|
||||
|
||||
if !s.Enabled(PointClone) {
|
||||
t.Errorf("Enabled(PointClone): got false, wanted true")
|
||||
}
|
||||
if err := s.SendToCheckers(func(c Checker) error {
|
||||
if err := s.SentToSinks(func(c Sink) error {
|
||||
return c.Clone(context.Background(), FieldSet{}, &pb.CloneInfo{})
|
||||
}); err != errFirstChecker {
|
||||
t.Errorf("Clone(): got %v, wanted %v", err, errFirstChecker)
|
||||
}); err != errFirstSink {
|
||||
t.Errorf("Clone(): got %v, wanted %v", err, errFirstSink)
|
||||
}
|
||||
if !checkersCalled[0] {
|
||||
t.Errorf("Clone() did not call first Checker")
|
||||
if !sinkCalled[0] {
|
||||
t.Errorf("Clone() did not call first Sink")
|
||||
}
|
||||
if checkersCalled[1] {
|
||||
t.Errorf("Clone() called second Checker")
|
||||
if sinkCalled[1] {
|
||||
t.Errorf("Clone() called second Sink")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package null defines a seccheck.Checker that does nothing with the trace
|
||||
// Package null defines a seccheck.Sink that does nothing with the trace
|
||||
// points, akin to /dev/null.
|
||||
package null
|
||||
|
||||
@@ -32,12 +32,12 @@ func init() {
|
||||
|
||||
// null is a checker that does nothing with the trace points.
|
||||
type null struct {
|
||||
seccheck.CheckerDefaults
|
||||
seccheck.SinkDefaults
|
||||
}
|
||||
|
||||
var _ seccheck.Checker = (*null)(nil)
|
||||
var _ seccheck.Sink = (*null)(nil)
|
||||
|
||||
func new(_ map[string]interface{}, _ *fd.FD) (seccheck.Checker, error) {
|
||||
func new(_ map[string]interface{}, _ *fd.FD) (seccheck.Sink, error) {
|
||||
return &null{}, nil
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ go_library(
|
||||
"//pkg/fd",
|
||||
"//pkg/log",
|
||||
"//pkg/sentry/seccheck",
|
||||
"//pkg/sentry/seccheck/checkers/remote/wire",
|
||||
"//pkg/sentry/seccheck/points:points_go_proto",
|
||||
"//pkg/sentry/seccheck/sinks/remote/wire",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
"@org_golang_x_sys//unix:go_default_library",
|
||||
],
|
||||
@@ -31,9 +31,9 @@ go_test(
|
||||
deps = [
|
||||
"//pkg/fd",
|
||||
"//pkg/sentry/seccheck",
|
||||
"//pkg/sentry/seccheck/checkers/remote/test",
|
||||
"//pkg/sentry/seccheck/checkers/remote/wire",
|
||||
"//pkg/sentry/seccheck/points:points_go_proto",
|
||||
"//pkg/sentry/seccheck/sinks/remote/test",
|
||||
"//pkg/sentry/seccheck/sinks/remote/wire",
|
||||
"//pkg/test/testutil",
|
||||
"@com_github_cenkalti_backoff//:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
+15
-15
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package remote defines a seccheck.Checker that serializes points to a remote
|
||||
// Package remote defines a seccheck.Sink that serializes points to a remote
|
||||
// process. Points are serialized using the protobuf format, asynchronously.
|
||||
package remote
|
||||
|
||||
@@ -31,8 +31,8 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/fd"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/checkers/remote/wire"
|
||||
pb "gvisor.dev/gvisor/pkg/sentry/seccheck/points/points_go_proto"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/sinks/remote/wire"
|
||||
)
|
||||
|
||||
const name = "remote"
|
||||
@@ -60,7 +60,7 @@ type remote struct {
|
||||
maxBackoff time.Duration
|
||||
}
|
||||
|
||||
var _ seccheck.Checker = (*remote)(nil)
|
||||
var _ seccheck.Sink = (*remote)(nil)
|
||||
|
||||
// setupSink starts the connection to the remote process and returns a file that
|
||||
// can be used to communicate with it. The caller is responsible to close to
|
||||
@@ -149,8 +149,8 @@ func parseDuration(config map[string]interface{}, name string) (bool, time.Durat
|
||||
return true, rv, nil
|
||||
}
|
||||
|
||||
// new creates a new Remote checker.
|
||||
func new(config map[string]interface{}, endpoint *fd.FD) (seccheck.Checker, error) {
|
||||
// new creates a new Remote sink.
|
||||
func new(config map[string]interface{}, endpoint *fd.FD) (seccheck.Sink, error) {
|
||||
if endpoint == nil {
|
||||
return nil, fmt.Errorf("remote sink requires an endpoint")
|
||||
}
|
||||
@@ -191,13 +191,13 @@ func (*remote) Name() string {
|
||||
return name
|
||||
}
|
||||
|
||||
func (r *remote) Status() seccheck.CheckerStatus {
|
||||
return seccheck.CheckerStatus{
|
||||
func (r *remote) Status() seccheck.SinkStatus {
|
||||
return seccheck.SinkStatus{
|
||||
DroppedCount: uint64(r.droppedCount.Load()),
|
||||
}
|
||||
}
|
||||
|
||||
// Stop implements seccheck.Checker.
|
||||
// Stop implements seccheck.Sink.
|
||||
func (r *remote) Stop() {
|
||||
if r.endpoint != nil {
|
||||
// It's possible to race with Point firing, but in the worst case they will
|
||||
@@ -241,43 +241,43 @@ func (r *remote) write(msg proto.Message, msgType pb.MessageType) {
|
||||
}
|
||||
}
|
||||
|
||||
// Clone implements seccheck.Checker.
|
||||
// Clone implements seccheck.Sink.
|
||||
func (r *remote) Clone(_ context.Context, _ seccheck.FieldSet, info *pb.CloneInfo) error {
|
||||
r.write(info, pb.MessageType_MESSAGE_SENTRY_CLONE)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Execve implements seccheck.Checker.
|
||||
// Execve implements seccheck.Sink.
|
||||
func (r *remote) Execve(_ context.Context, _ seccheck.FieldSet, info *pb.ExecveInfo) error {
|
||||
r.write(info, pb.MessageType_MESSAGE_SENTRY_EXEC)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExitNotifyParent implements seccheck.Checker.
|
||||
// ExitNotifyParent implements seccheck.Sink.
|
||||
func (r *remote) ExitNotifyParent(_ context.Context, _ seccheck.FieldSet, info *pb.ExitNotifyParentInfo) error {
|
||||
r.write(info, pb.MessageType_MESSAGE_SENTRY_EXIT_NOTIFY_PARENT)
|
||||
return nil
|
||||
}
|
||||
|
||||
// TaskExit implements seccheck.Checker.
|
||||
// TaskExit implements seccheck.Sink.
|
||||
func (r *remote) TaskExit(_ context.Context, _ seccheck.FieldSet, info *pb.TaskExit) error {
|
||||
r.write(info, pb.MessageType_MESSAGE_SENTRY_TASK_EXIT)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ContainerStart implements seccheck.Checker.
|
||||
// ContainerStart implements seccheck.Sink.
|
||||
func (r *remote) ContainerStart(_ context.Context, _ seccheck.FieldSet, info *pb.Start) error {
|
||||
r.write(info, pb.MessageType_MESSAGE_CONTAINER_START)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RawSyscall implements seccheck.Checker.
|
||||
// RawSyscall implements seccheck.Sink.
|
||||
func (r *remote) RawSyscall(_ context.Context, _ seccheck.FieldSet, info *pb.Syscall) error {
|
||||
r.write(info, pb.MessageType_MESSAGE_SYSCALL_RAW)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Syscall implements seccheck.Checker.
|
||||
// Syscall implements seccheck.Sink.
|
||||
func (r *remote) Syscall(ctx context.Context, fields seccheck.FieldSet, ctxData *pb.ContextData, msgType pb.MessageType, msg proto.Message) error {
|
||||
r.write(msg, msgType)
|
||||
return nil
|
||||
+4
-4
@@ -30,9 +30,9 @@ import (
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"gvisor.dev/gvisor/pkg/fd"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/checkers/remote/test"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/checkers/remote/wire"
|
||||
pb "gvisor.dev/gvisor/pkg/sentry/seccheck/points/points_go_proto"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/sinks/remote/test"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/sinks/remote/wire"
|
||||
"gvisor.dev/gvisor/pkg/test/testutil"
|
||||
)
|
||||
|
||||
@@ -290,12 +290,12 @@ func TestConfig(t *testing.T) {
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var endpoint fd.FD
|
||||
checker, err := new(tc.config, &endpoint)
|
||||
sink, err := new(tc.config, &endpoint)
|
||||
if len(tc.err) == 0 {
|
||||
if err != nil {
|
||||
t.Fatalf("new(%q): %v", tc.config, err)
|
||||
}
|
||||
got := checker.(*remote)
|
||||
got := sink.(*remote)
|
||||
got.endpoint = nil
|
||||
if *got != *tc.want {
|
||||
t.Errorf("wrong remote: want: %+v, got: %+v", tc.want, got)
|
||||
+1
-1
@@ -9,8 +9,8 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/cleanup",
|
||||
"//pkg/log",
|
||||
"//pkg/sentry/seccheck/checkers/remote/wire",
|
||||
"//pkg/sentry/seccheck/points:points_go_proto",
|
||||
"//pkg/sentry/seccheck/sinks/remote/wire",
|
||||
"//pkg/sync",
|
||||
"//pkg/unet",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
+1
-1
@@ -26,8 +26,8 @@ import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
"gvisor.dev/gvisor/pkg/cleanup"
|
||||
"gvisor.dev/gvisor/pkg/log"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/checkers/remote/wire"
|
||||
pb "gvisor.dev/gvisor/pkg/sentry/seccheck/points/points_go_proto"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/sinks/remote/wire"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
"gvisor.dev/gvisor/pkg/unet"
|
||||
)
|
||||
+2
-2
@@ -8,9 +8,9 @@ go_library(
|
||||
srcs = ["server.go"],
|
||||
visibility = ["//:sandbox"],
|
||||
deps = [
|
||||
"//pkg/sentry/seccheck/checkers/remote/server",
|
||||
"//pkg/sentry/seccheck/checkers/remote/wire",
|
||||
"//pkg/sentry/seccheck/points:points_go_proto",
|
||||
"//pkg/sentry/seccheck/sinks/remote/server",
|
||||
"//pkg/sentry/seccheck/sinks/remote/wire",
|
||||
"//pkg/sync",
|
||||
],
|
||||
)
|
||||
+6
-6
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package test provides functionality used to test the remote checker.
|
||||
// Package test provides functionality used to test the remote sink.
|
||||
package test
|
||||
|
||||
import (
|
||||
@@ -20,14 +20,14 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/checkers/remote/server"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/checkers/remote/wire"
|
||||
pb "gvisor.dev/gvisor/pkg/sentry/seccheck/points/points_go_proto"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/sinks/remote/server"
|
||||
"gvisor.dev/gvisor/pkg/sentry/seccheck/sinks/remote/wire"
|
||||
"gvisor.dev/gvisor/pkg/sync"
|
||||
)
|
||||
|
||||
// Server is the counterpart to the checkers.Remote. It receives connections
|
||||
// remote checkers and stores all points that it receives.
|
||||
// Server is the counterpart to the sinks.Remote. It receives connections
|
||||
// remote sink and stores all points that it receives.
|
||||
type Server struct {
|
||||
server.CommonServer
|
||||
|
||||
@@ -42,7 +42,7 @@ type Server struct {
|
||||
version uint32
|
||||
}
|
||||
|
||||
// Message corresponds to a single message sent from checkers.Remote.
|
||||
// Message corresponds to a single message sent from sinks.Remote.
|
||||
type Message struct {
|
||||
// MsgType indicates what is the type of Msg.
|
||||
MsgType pb.MessageType
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user