package systemd import ( "reflect" dbus "github.com/godbus/dbus/v5" "github.com/opencontainers/cgroups" ) // freezeBeforeSet answers whether there is a need to freeze the cgroup before // applying its systemd unit properties, and thaw after, while avoiding // unnecessary freezer state changes. // // The reason why we have to freeze is that systemd's application of device // rules is done disruptively, resulting in spurious errors to common devices // (unlike our fs driver, they will happily write deny-all rules to running // containers). So we have to freeze the container to avoid the container get // an occasional "permission denied" error. func (m *LegacyManager) freezeBeforeSet(unitName string, r *cgroups.Resources) (needsFreeze, needsThaw bool, err error) { // Special case for SkipDevices, as used by Kubernetes to create pod // cgroups with allow-all device policy). if r.SkipDevices { if r.SkipFreezeOnSet { // Both needsFreeze and needsThaw are false. return } // No need to freeze if SkipDevices is set, and either // (1) systemd unit does not (yet) exist, or // (2) it has DevicePolicy=auto and empty DeviceAllow list. // // Interestingly, (1) and (2) are the same here because // a non-existent unit returns default properties, // and settings in (2) are the defaults. // // Do not return errors from getUnitTypeProperty, as they alone // should not prevent Set from working. unitType := getUnitType(unitName) devPolicy, e := getUnitTypeProperty(m.dbus, unitName, unitType, "DevicePolicy") if e == nil && devPolicy.Value == dbus.MakeVariant("auto") { devAllow, e := getUnitTypeProperty(m.dbus, unitName, unitType, "DeviceAllow") if e == nil { if rv := reflect.ValueOf(devAllow.Value.Value()); rv.Kind() == reflect.Slice && rv.Len() == 0 { needsFreeze = false needsThaw = false return } } } } needsFreeze = true needsThaw = true // Check the current freezer state. freezerState, err := m.GetFreezerState() if err != nil { return } if freezerState == cgroups.Frozen { // Already frozen, and should stay frozen. needsFreeze = false needsThaw = false } if r.Freezer == cgroups.Frozen { // Will be frozen anyway -- no need to thaw. needsThaw = false } return }