github.com/opencontainers/runc@v1.2.0-rc.1.0.20240520010911-492dc558cdd6/libcontainer/cgroups/systemd/devices.go (about)

     1  package systemd
     2  
     3  import (
     4  	"reflect"
     5  
     6  	dbus "github.com/godbus/dbus/v5"
     7  
     8  	"github.com/opencontainers/runc/libcontainer/configs"
     9  )
    10  
    11  // freezeBeforeSet answers whether there is a need to freeze the cgroup before
    12  // applying its systemd unit properties, and thaw after, while avoiding
    13  // unnecessary freezer state changes.
    14  //
    15  // The reason why we have to freeze is that systemd's application of device
    16  // rules is done disruptively, resulting in spurious errors to common devices
    17  // (unlike our fs driver, they will happily write deny-all rules to running
    18  // containers). So we have to freeze the container to avoid the container get
    19  // an occasional "permission denied" error.
    20  func (m *LegacyManager) freezeBeforeSet(unitName string, r *configs.Resources) (needsFreeze, needsThaw bool, err error) {
    21  	// Special case for SkipDevices, as used by Kubernetes to create pod
    22  	// cgroups with allow-all device policy).
    23  	if r.SkipDevices {
    24  		if r.SkipFreezeOnSet {
    25  			// Both needsFreeze and needsThaw are false.
    26  			return
    27  		}
    28  
    29  		// No need to freeze if SkipDevices is set, and either
    30  		// (1) systemd unit does not (yet) exist, or
    31  		// (2) it has DevicePolicy=auto and empty DeviceAllow list.
    32  		//
    33  		// Interestingly, (1) and (2) are the same here because
    34  		// a non-existent unit returns default properties,
    35  		// and settings in (2) are the defaults.
    36  		//
    37  		// Do not return errors from getUnitTypeProperty, as they alone
    38  		// should not prevent Set from working.
    39  
    40  		unitType := getUnitType(unitName)
    41  
    42  		devPolicy, e := getUnitTypeProperty(m.dbus, unitName, unitType, "DevicePolicy")
    43  		if e == nil && devPolicy.Value == dbus.MakeVariant("auto") {
    44  			devAllow, e := getUnitTypeProperty(m.dbus, unitName, unitType, "DeviceAllow")
    45  			if e == nil {
    46  				if rv := reflect.ValueOf(devAllow.Value.Value()); rv.Kind() == reflect.Slice && rv.Len() == 0 {
    47  					needsFreeze = false
    48  					needsThaw = false
    49  					return
    50  				}
    51  			}
    52  		}
    53  	}
    54  
    55  	needsFreeze = true
    56  	needsThaw = true
    57  
    58  	// Check the current freezer state.
    59  	freezerState, err := m.GetFreezerState()
    60  	if err != nil {
    61  		return
    62  	}
    63  	if freezerState == configs.Frozen {
    64  		// Already frozen, and should stay frozen.
    65  		needsFreeze = false
    66  		needsThaw = false
    67  	}
    68  
    69  	if r.Freezer == configs.Frozen {
    70  		// Will be frozen anyway -- no need to thaw.
    71  		needsThaw = false
    72  	}
    73  	return
    74  }