diff --git a/pkg/sentry/kernel/syscalls.go b/pkg/sentry/kernel/syscalls.go index 60e14dc0c..2c7f2bae5 100644 --- a/pkg/sentry/kernel/syscalls.go +++ b/pkg/sentry/kernel/syscalls.go @@ -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 diff --git a/pkg/sentry/kernel/task_clone.go b/pkg/sentry/kernel/task_clone.go index d5b3b181b..888ed0dde 100644 --- a/pkg/sentry/kernel/task_clone.go +++ b/pkg/sentry/kernel/task_clone.go @@ -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 diff --git a/pkg/sentry/kernel/task_exec.go b/pkg/sentry/kernel/task_exec.go index 49dd0e4e3..81eb028f4 100644 --- a/pkg/sentry/kernel/task_exec.go +++ b/pkg/sentry/kernel/task_exec.go @@ -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() diff --git a/pkg/sentry/kernel/task_exit.go b/pkg/sentry/kernel/task_exit.go index f0eebda40..684f67f12 100644 --- a/pkg/sentry/kernel/task_exit.go +++ b/pkg/sentry/kernel/task_exit.go @@ -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) diff --git a/pkg/sentry/kernel/task_syscall.go b/pkg/sentry/kernel/task_syscall.go index 48be595f2..10f89793c 100644 --- a/pkg/sentry/kernel/task_syscall.go +++ b/pkg/sentry/kernel/task_syscall.go @@ -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) }) } diff --git a/pkg/sentry/seccheck/BUILD b/pkg/sentry/seccheck/BUILD index 167214e5a..d82e67f65 100644 --- a/pkg/sentry/seccheck/BUILD +++ b/pkg/sentry/seccheck/BUILD @@ -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"], diff --git a/pkg/sentry/seccheck/config.go b/pkg/sentry/seccheck/config.go index 003d7864d..54a865457 100644 --- a/pkg/sentry/seccheck/config.go +++ b/pkg/sentry/seccheck/config.go @@ -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) diff --git a/pkg/sentry/seccheck/metadata.go b/pkg/sentry/seccheck/metadata.go index f7c8287a4..2e19ec65c 100644 --- a/pkg/sentry/seccheck/metadata.go +++ b/pkg/sentry/seccheck/metadata.go @@ -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. diff --git a/pkg/sentry/seccheck/seccheck.go b/pkg/sentry/seccheck/seccheck.go index 3aec5fecb..e56300a6b 100644 --- a/pkg/sentry/seccheck/seccheck.go +++ b/pkg/sentry/seccheck/seccheck.go @@ -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)<