gvisor/pkg/sentry/control/logging.go

137 lines
4.1 KiB
Go

// Copyright 2019 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 control
import (
"fmt"
"sync/atomic"
"gvisor.dev/gvisor/pkg/log"
"gvisor.dev/gvisor/pkg/sentry/strace"
"gvisor.dev/gvisor/pkg/tcpip/link/sniffer"
)
// LoggingArgs are the arguments to use for changing the logging
// level and strace list.
type LoggingArgs struct {
// SetLevel is a flag used to indicate that we should update
// the logging level. We should be able to change the strace
// list without affecting the logging level and vice versa.
SetLevel bool
// Level is the log level that will be set if SetLevel is true.
Level log.Level
// SetLogPackets indicates that we should update the log packets flag.
SetLogPackets bool
// LogPackets is the actual value to set for LogPackets.
// SetLogPackets must be enabled to indicate that we're changing
// the value.
LogPackets bool
// SetStrace is a flag used to indicate that strace related
// arguments were passed in.
SetStrace bool
// EnableStrace is a flag from the CLI that specifies whether to
// enable strace at all. If this flag is false then a completely
// pristine copy of the syscall table will be swapped in. This
// approach is used to remain consistent with an empty strace
// whitelist meaning trace all system calls.
EnableStrace bool
// Strace is the whitelist of syscalls to trace to log. If this
// and StraceEventWhitelist are empty trace all system calls.
StraceWhitelist []string
// SetEventStrace is a flag used to indicate that event strace
// related arguments were passed in.
SetEventStrace bool
// StraceEventWhitelist is the whitelist of syscalls to trace
// to event log.
StraceEventWhitelist []string
}
// Logging provides functions related to logging.
type Logging struct{}
// Change will change the log level and strace arguments. Although
// this functions signature requires an error it never acctually
// return san error. It's required by the URPC interface.
// Additionally, it may look odd that this is the only method
// attached to an empty struct but this is also part of how
// URPC dispatches.
func (l *Logging) Change(args *LoggingArgs, code *int) error {
if args.SetLevel {
// Logging uses an atomic for the level so this is thread safe.
log.SetLevel(args.Level)
}
if args.SetLogPackets {
if args.LogPackets {
atomic.StoreUint32(&sniffer.LogPackets, 1)
} else {
atomic.StoreUint32(&sniffer.LogPackets, 0)
}
log.Infof("LogPackets set to: %v", atomic.LoadUint32(&sniffer.LogPackets))
}
if args.SetStrace {
if err := l.configureStrace(args); err != nil {
return fmt.Errorf("error configuring strace: %v", err)
}
}
if args.SetEventStrace {
if err := l.configureEventStrace(args); err != nil {
return fmt.Errorf("error configuring event strace: %v", err)
}
}
return nil
}
func (l *Logging) configureStrace(args *LoggingArgs) error {
if args.EnableStrace {
// Install the whitelist specified.
if len(args.StraceWhitelist) > 0 {
if err := strace.Enable(args.StraceWhitelist, strace.SinkTypeLog); err != nil {
return err
}
} else {
// For convenience, if strace is enabled but whitelist
// is empty, enable everything to log.
strace.EnableAll(strace.SinkTypeLog)
}
} else {
// Uninstall all strace functions.
strace.Disable(strace.SinkTypeLog)
}
return nil
}
func (l *Logging) configureEventStrace(args *LoggingArgs) error {
if len(args.StraceEventWhitelist) > 0 {
if err := strace.Enable(args.StraceEventWhitelist, strace.SinkTypeEvent); err != nil {
return err
}
} else {
strace.Disable(strace.SinkTypeEvent)
}
return nil
}