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 }