github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/runsc/cmd/capability.go (about)

     1  // Copyright 2018 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 cmd
    16  
    17  import (
    18  	"fmt"
    19  
    20  	specs "github.com/opencontainers/runtime-spec/specs-go"
    21  	"github.com/syndtr/gocapability/capability"
    22  	"github.com/metacubex/gvisor/pkg/log"
    23  )
    24  
    25  var allCapTypes = []capability.CapType{
    26  	capability.BOUNDS,
    27  	capability.EFFECTIVE,
    28  	capability.PERMITTED,
    29  	capability.INHERITABLE,
    30  	capability.AMBIENT,
    31  }
    32  
    33  // applyCaps applies the capabilities in the spec to the current thread.
    34  //
    35  // Note that it must be called with current thread locked.
    36  func applyCaps(caps *specs.LinuxCapabilities) error {
    37  	// Load current capabilities to trim the ones not permitted.
    38  	curCaps, err := capability.NewPid2(0)
    39  	if err != nil {
    40  		return err
    41  	}
    42  	if err := curCaps.Load(); err != nil {
    43  		return err
    44  	}
    45  
    46  	// Create an empty capability set to populate.
    47  	newCaps, err := capability.NewPid2(0)
    48  	if err != nil {
    49  		return err
    50  	}
    51  
    52  	for _, c := range allCapTypes {
    53  		if !newCaps.Empty(c) {
    54  			panic("unloaded capabilities must be empty")
    55  		}
    56  		set, err := trimCaps(getCaps(c, caps), curCaps)
    57  		if err != nil {
    58  			return err
    59  		}
    60  		newCaps.Set(c, set...)
    61  	}
    62  
    63  	if err := newCaps.Apply(capability.CAPS | capability.BOUNDS | capability.AMBS); err != nil {
    64  		return err
    65  	}
    66  	log.Infof("Capabilities applied: %+v", newCaps)
    67  	return nil
    68  }
    69  
    70  func getCaps(which capability.CapType, caps *specs.LinuxCapabilities) []string {
    71  	switch which {
    72  	case capability.BOUNDS:
    73  		return caps.Bounding
    74  	case capability.EFFECTIVE:
    75  		return caps.Effective
    76  	case capability.PERMITTED:
    77  		return caps.Permitted
    78  	case capability.INHERITABLE:
    79  		return caps.Inheritable
    80  	case capability.AMBIENT:
    81  		return caps.Ambient
    82  	}
    83  	panic(fmt.Sprint("invalid capability type:", which))
    84  }
    85  
    86  func trimCaps(names []string, setter capability.Capabilities) ([]capability.Cap, error) {
    87  	wantedCaps, err := capsFromNames(names)
    88  	if err != nil {
    89  		return nil, err
    90  	}
    91  
    92  	// Trim down capabilities that aren't possible to acquire.
    93  	var caps []capability.Cap
    94  	for _, c := range wantedCaps {
    95  		// Capability rules are more complicated than this, but this catches most
    96  		// problems with tests running with non-privileged user.
    97  		if setter.Get(capability.PERMITTED, c) {
    98  			caps = append(caps, c)
    99  		} else {
   100  			log.Warningf("Capability %q is not permitted, dropping it.", c)
   101  		}
   102  	}
   103  	return caps, nil
   104  }
   105  
   106  func capsFromNames(names []string) ([]capability.Cap, error) {
   107  	var caps []capability.Cap
   108  	for _, name := range names {
   109  		cap, ok := capFromName[name]
   110  		if !ok {
   111  			return nil, fmt.Errorf("invalid capability %q", name)
   112  		}
   113  		caps = append(caps, cap)
   114  	}
   115  	return caps, nil
   116  }
   117  
   118  var capFromName = map[string]capability.Cap{
   119  	"CAP_CHOWN":              capability.CAP_CHOWN,
   120  	"CAP_DAC_OVERRIDE":       capability.CAP_DAC_OVERRIDE,
   121  	"CAP_DAC_READ_SEARCH":    capability.CAP_DAC_READ_SEARCH,
   122  	"CAP_FOWNER":             capability.CAP_FOWNER,
   123  	"CAP_FSETID":             capability.CAP_FSETID,
   124  	"CAP_KILL":               capability.CAP_KILL,
   125  	"CAP_SETGID":             capability.CAP_SETGID,
   126  	"CAP_SETUID":             capability.CAP_SETUID,
   127  	"CAP_SETPCAP":            capability.CAP_SETPCAP,
   128  	"CAP_LINUX_IMMUTABLE":    capability.CAP_LINUX_IMMUTABLE,
   129  	"CAP_NET_BIND_SERVICE":   capability.CAP_NET_BIND_SERVICE,
   130  	"CAP_NET_BROADCAST":      capability.CAP_NET_BROADCAST,
   131  	"CAP_NET_ADMIN":          capability.CAP_NET_ADMIN,
   132  	"CAP_NET_RAW":            capability.CAP_NET_RAW,
   133  	"CAP_IPC_LOCK":           capability.CAP_IPC_LOCK,
   134  	"CAP_IPC_OWNER":          capability.CAP_IPC_OWNER,
   135  	"CAP_SYS_MODULE":         capability.CAP_SYS_MODULE,
   136  	"CAP_SYS_RAWIO":          capability.CAP_SYS_RAWIO,
   137  	"CAP_SYS_CHROOT":         capability.CAP_SYS_CHROOT,
   138  	"CAP_SYS_PTRACE":         capability.CAP_SYS_PTRACE,
   139  	"CAP_SYS_PACCT":          capability.CAP_SYS_PACCT,
   140  	"CAP_SYS_ADMIN":          capability.CAP_SYS_ADMIN,
   141  	"CAP_SYS_BOOT":           capability.CAP_SYS_BOOT,
   142  	"CAP_SYS_NICE":           capability.CAP_SYS_NICE,
   143  	"CAP_SYS_RESOURCE":       capability.CAP_SYS_RESOURCE,
   144  	"CAP_SYS_TIME":           capability.CAP_SYS_TIME,
   145  	"CAP_SYS_TTY_CONFIG":     capability.CAP_SYS_TTY_CONFIG,
   146  	"CAP_MKNOD":              capability.CAP_MKNOD,
   147  	"CAP_LEASE":              capability.CAP_LEASE,
   148  	"CAP_AUDIT_WRITE":        capability.CAP_AUDIT_WRITE,
   149  	"CAP_AUDIT_CONTROL":      capability.CAP_AUDIT_CONTROL,
   150  	"CAP_SETFCAP":            capability.CAP_SETFCAP,
   151  	"CAP_MAC_OVERRIDE":       capability.CAP_MAC_OVERRIDE,
   152  	"CAP_MAC_ADMIN":          capability.CAP_MAC_ADMIN,
   153  	"CAP_SYSLOG":             capability.CAP_SYSLOG,
   154  	"CAP_WAKE_ALARM":         capability.CAP_WAKE_ALARM,
   155  	"CAP_BLOCK_SUSPEND":      capability.CAP_BLOCK_SUSPEND,
   156  	"CAP_AUDIT_READ":         capability.CAP_AUDIT_READ,
   157  	"CAP_PERFMON":            capability.CAP_PERFMON,
   158  	"CAP_BPF":                capability.CAP_BPF,
   159  	"CAP_CHECKPOINT_RESTORE": capability.CAP_CHECKPOINT_RESTORE,
   160  }