github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/control/logging.go (about)

     1  // Copyright 2019 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package control
    16  
    17  import (
    18  	"fmt"
    19  	"sync/atomic"
    20  
    21  	"github.com/SagerNet/gvisor/pkg/log"
    22  	"github.com/SagerNet/gvisor/pkg/sentry/strace"
    23  	"github.com/SagerNet/gvisor/pkg/tcpip/link/sniffer"
    24  )
    25  
    26  // LoggingArgs are the arguments to use for changing the logging
    27  // level and strace list.
    28  type LoggingArgs struct {
    29  	// SetLevel is a flag used to indicate that we should update
    30  	// the logging level. We should be able to change the strace
    31  	// list without affecting the logging level and vice versa.
    32  	SetLevel bool
    33  
    34  	// Level is the log level that will be set if SetLevel is true.
    35  	Level log.Level
    36  
    37  	// SetLogPackets indicates that we should update the log packets flag.
    38  	SetLogPackets bool
    39  
    40  	// LogPackets is the actual value to set for LogPackets.
    41  	// SetLogPackets must be enabled to indicate that we're changing
    42  	// the value.
    43  	LogPackets bool
    44  
    45  	// SetStrace is a flag used to indicate that strace related
    46  	// arguments were passed in.
    47  	SetStrace bool
    48  
    49  	// EnableStrace is a flag from the CLI that specifies whether to
    50  	// enable strace at all. If this flag is false then a completely
    51  	// pristine copy of the syscall table will be swapped in. This
    52  	// approach is used to remain consistent with an empty strace
    53  	// whitelist meaning trace all system calls.
    54  	EnableStrace bool
    55  
    56  	// Strace is the whitelist of syscalls to trace to log. If this
    57  	// and StraceEventWhitelist are empty trace all system calls.
    58  	StraceWhitelist []string
    59  
    60  	// SetEventStrace is a flag used to indicate that event strace
    61  	// related arguments were passed in.
    62  	SetEventStrace bool
    63  
    64  	// StraceEventWhitelist is the whitelist of syscalls to trace
    65  	// to event log.
    66  	StraceEventWhitelist []string
    67  }
    68  
    69  // Logging provides functions related to logging.
    70  type Logging struct{}
    71  
    72  // Change will change the log level and strace arguments. Although
    73  // this functions signature requires an error it never actually
    74  // returns an error. It's required by the URPC interface.
    75  // Additionally, it may look odd that this is the only method
    76  // attached to an empty struct but this is also part of how
    77  // URPC dispatches.
    78  func (l *Logging) Change(args *LoggingArgs, code *int) error {
    79  	if args.SetLevel {
    80  		// Logging uses an atomic for the level so this is thread safe.
    81  		log.SetLevel(args.Level)
    82  	}
    83  
    84  	if args.SetLogPackets {
    85  		if args.LogPackets {
    86  			atomic.StoreUint32(&sniffer.LogPackets, 1)
    87  		} else {
    88  			atomic.StoreUint32(&sniffer.LogPackets, 0)
    89  		}
    90  		log.Infof("LogPackets set to: %v", atomic.LoadUint32(&sniffer.LogPackets))
    91  	}
    92  
    93  	if args.SetStrace {
    94  		if err := l.configureStrace(args); err != nil {
    95  			return fmt.Errorf("error configuring strace: %v", err)
    96  		}
    97  	}
    98  
    99  	if args.SetEventStrace {
   100  		if err := l.configureEventStrace(args); err != nil {
   101  			return fmt.Errorf("error configuring event strace: %v", err)
   102  		}
   103  	}
   104  
   105  	return nil
   106  }
   107  
   108  func (l *Logging) configureStrace(args *LoggingArgs) error {
   109  	if args.EnableStrace {
   110  		// Install the whitelist specified.
   111  		if len(args.StraceWhitelist) > 0 {
   112  			if err := strace.Enable(args.StraceWhitelist, strace.SinkTypeLog); err != nil {
   113  				return err
   114  			}
   115  		} else {
   116  			// For convenience, if strace is enabled but whitelist
   117  			// is empty, enable everything to log.
   118  			strace.EnableAll(strace.SinkTypeLog)
   119  		}
   120  	} else {
   121  		// Uninstall all strace functions.
   122  		strace.Disable(strace.SinkTypeLog)
   123  	}
   124  	return nil
   125  }
   126  
   127  func (l *Logging) configureEventStrace(args *LoggingArgs) error {
   128  	if len(args.StraceEventWhitelist) > 0 {
   129  		if err := strace.Enable(args.StraceEventWhitelist, strace.SinkTypeEvent); err != nil {
   130  			return err
   131  		}
   132  	} else {
   133  		strace.Disable(strace.SinkTypeEvent)
   134  	}
   135  	return nil
   136  }