Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add runc_nosd build tag to opt out of systemd support #4547

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
2 changes: 2 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ jobs:
run: make BUILDTAGS=""
- name: compile with runc_nocriu build tag
run: make EXTRA_BUILDTAGS="runc_nocriu"
- name: compile with runc_nosd tag added
run: make EXTRA_BUILDTAGS="runc_nosd"

codespell:
runs-on: ubuntu-24.04
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ make EXTRA_BUILDTAGS="runc_nocriu"
|---------------|---------------------------------------|--------------------|---------------------|
| `seccomp` | Syscall filtering using `libseccomp`. | yes | `libseccomp` |
| `runc_nocriu` | **Disables** runc checkpoint/restore. | no | `criu` |
| `runc_nosd` | **Disables** systemd cgroup managers. | no | systemd |

The following build tags were used earlier, but are now obsoleted:
- **runc_nodmz** (since runc v1.2.1 runc dmz binary is dropped)
Expand Down
3 changes: 1 addition & 2 deletions libcontainer/cgroups/devices/devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ package devices

import (
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
)

func init() {
cgroups.DevicesSetV1 = setV1
cgroups.DevicesSetV2 = setV2
systemd.GenerateDeviceProps = systemdProperties
initSystemd()
}
5 changes: 5 additions & 0 deletions libcontainer/cgroups/devices/no_systemd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
//go:build linux && runc_nosd

package devices

func initSystemd() {}
20 changes: 13 additions & 7 deletions libcontainer/cgroups/devices/systemd.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux && !runc_nosd

package devices

import (
Expand All @@ -7,22 +9,22 @@ import (
"strconv"
"strings"

systemdDbus "github.com/coreos/go-systemd/v22/dbus"
"github.com/godbus/dbus/v5"
"github.com/sirupsen/logrus"

"github.com/opencontainers/runc/libcontainer/cgroups/systemd"
"github.com/opencontainers/runc/libcontainer/configs"
"github.com/opencontainers/runc/libcontainer/devices"
)

// systemdProperties takes the configured device rules and generates a
// corresponding set of systemd properties to configure the devices correctly.
func systemdProperties(r *configs.Resources, sdVer int) ([]systemdDbus.Property, error) {
func systemdProperties(r *configs.Resources, sdVer int) (configs.SdProperties, error) {
if r.SkipDevices {
return nil, nil
}

properties := []systemdDbus.Property{
properties := configs.SdProperties{
// Always run in the strictest white-list mode.
newProp("DevicePolicy", "strict"),
// Empty the DeviceAllow array before filling it.
Expand Down Expand Up @@ -158,8 +160,8 @@ func systemdProperties(r *configs.Resources, sdVer int) ([]systemdDbus.Property,
return properties, nil
}

func newProp(name string, units interface{}) systemdDbus.Property {
return systemdDbus.Property{
func newProp(name string, units interface{}) configs.SdProperty {
return configs.SdProperty{
Name: name,
Value: dbus.MakeVariant(units),
}
Expand Down Expand Up @@ -235,11 +237,15 @@ type deviceAllowEntry struct {
Perms string
}

func allowAllDevices() []systemdDbus.Property {
func allowAllDevices() configs.SdProperties {
// Setting mode to auto and removing all DeviceAllow rules
// results in allowing access to all devices.
return []systemdDbus.Property{
return configs.SdProperties{
newProp("DevicePolicy", "auto"),
newProp("DeviceAllow", []deviceAllowEntry{}),
}
}

func initSystemd() {
systemd.GenerateDeviceProps = systemdProperties
}
22 changes: 12 additions & 10 deletions libcontainer/cgroups/systemd/common.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux && !runc_nosd

package systemd

import (
Expand Down Expand Up @@ -38,7 +40,7 @@ var (
// [github.com/opencontainers/runc/libcontainer/cgroups/devices]
// package is imported, it is set to nil, so cgroup managers can't
// configure devices.
GenerateDeviceProps func(r *configs.Resources, sdVer int) ([]systemdDbus.Property, error)
GenerateDeviceProps func(r *configs.Resources, sdVer int) (configs.SdProperties, error)
)

// NOTE: This function comes from package github.com/coreos/go-systemd/util
Expand Down Expand Up @@ -90,8 +92,8 @@ func ExpandSlice(slice string) (string, error) {
return path, nil
}

func newProp(name string, units interface{}) systemdDbus.Property {
return systemdDbus.Property{
func newProp(name string, units interface{}) configs.SdProperty {
return configs.SdProperty{
Name: name,
Value: dbus.MakeVariant(units),
}
Expand Down Expand Up @@ -129,7 +131,7 @@ func isUnitExists(err error) bool {
return isDbusError(err, "org.freedesktop.systemd1.UnitExists")
}

func startUnit(cm *dbusConnManager, unitName string, properties []systemdDbus.Property, ignoreExist bool) error {
func startUnit(cm *dbusConnManager, unitName string, properties configs.SdProperties, ignoreExist bool) error {
statusChan := make(chan string, 1)
retry := true

Expand Down Expand Up @@ -215,16 +217,16 @@ func resetFailedUnit(cm *dbusConnManager, name string) error {
})
}

func getUnitTypeProperty(cm *dbusConnManager, unitName string, unitType string, propertyName string) (*systemdDbus.Property, error) {
var prop *systemdDbus.Property
func getUnitTypeProperty(cm *dbusConnManager, unitName string, unitType string, propertyName string) (*configs.SdProperty, error) {
var prop *configs.SdProperty
err := cm.retryOnDisconnect(func(c *systemdDbus.Conn) (Err error) {
prop, Err = c.GetUnitTypePropertyContext(context.TODO(), unitName, unitType, propertyName)
return Err
})
return prop, err
}

func setUnitProperties(cm *dbusConnManager, name string, properties ...systemdDbus.Property) error {
func setUnitProperties(cm *dbusConnManager, name string, properties ...configs.SdProperty) error {
return cm.retryOnDisconnect(func(c *systemdDbus.Conn) error {
return c.SetUnitPropertiesContext(context.TODO(), name, true, properties...)
})
Expand Down Expand Up @@ -281,7 +283,7 @@ func systemdVersionAtoi(str string) (int, error) {
return ver, nil
}

func addCpuQuota(cm *dbusConnManager, properties *[]systemdDbus.Property, quota int64, period uint64) {
func addCPUQuota(cm *dbusConnManager, properties *configs.SdProperties, quota int64, period uint64) {
if period != 0 {
// systemd only supports CPUQuotaPeriodUSec since v242
sdVer := systemdVersion(cm)
Expand Down Expand Up @@ -315,7 +317,7 @@ func addCpuQuota(cm *dbusConnManager, properties *[]systemdDbus.Property, quota
}
}

func addCpuset(cm *dbusConnManager, props *[]systemdDbus.Property, cpus, mems string) error {
func addCpuset(cm *dbusConnManager, props *configs.SdProperties, cpus, mems string) error {
if cpus == "" && mems == "" {
return nil
}
Expand Down Expand Up @@ -351,7 +353,7 @@ func addCpuset(cm *dbusConnManager, props *[]systemdDbus.Property, cpus, mems st

// generateDeviceProperties takes the configured device rules and generates a
// corresponding set of systemd properties to configure the devices correctly.
func generateDeviceProperties(r *configs.Resources, cm *dbusConnManager) ([]systemdDbus.Property, error) {
func generateDeviceProperties(r *configs.Resources, cm *dbusConnManager) (configs.SdProperties, error) {
if GenerateDeviceProps == nil {
if len(r.Devices) > 0 {
return nil, cgroups.ErrDevicesUnsupported
Expand Down
2 changes: 2 additions & 0 deletions libcontainer/cgroups/systemd/dbus.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux && !runc_nosd

package systemd

import (
Expand Down
2 changes: 2 additions & 0 deletions libcontainer/cgroups/systemd/devices.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux && !runc_nosd

package systemd

import (
Expand Down
22 changes: 22 additions & 0 deletions libcontainer/cgroups/systemd/no_systemd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//go:build linux && runc_nosd

package systemd

import (
"errors"

"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs"
)

func IsRunningSystemd() bool {
return false
}

func NewUnifiedManager(config *configs.Cgroup, path string) (cgroups.Manager, error) {
return nil, errors.New("no systemd support")
}

func NewLegacyManager(cg *configs.Cgroup, paths map[string]string) (cgroups.Manager, error) {
return nil, errors.New("no systemd support")
}
11 changes: 6 additions & 5 deletions libcontainer/cgroups/systemd/systemd_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
//go:build linux && !runc_nosd

package systemd

import (
"os"
"reflect"
"testing"

systemdDbus "github.com/coreos/go-systemd/v22/dbus"
"github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/opencontainers/runc/libcontainer/configs"
)
Expand Down Expand Up @@ -113,7 +114,7 @@ func TestUnifiedResToSystemdProps(t *testing.T) {
minVer int
res map[string]string
expError bool
expProps []systemdDbus.Property
expProps configs.SdProperties
}{
{
name: "empty map",
Expand All @@ -125,7 +126,7 @@ func TestUnifiedResToSystemdProps(t *testing.T) {
res: map[string]string{
"cpu.idle": "1",
},
expProps: []systemdDbus.Property{
expProps: configs.SdProperties{
newProp("CPUWeight", uint64(0)),
},
},
Expand All @@ -143,7 +144,7 @@ func TestUnifiedResToSystemdProps(t *testing.T) {
"cpu.idle": "1",
"cpu.weight": "1000",
},
expProps: []systemdDbus.Property{
expProps: configs.SdProperties{
newProp("CPUWeight", uint64(0)),
},
},
Expand All @@ -154,7 +155,7 @@ func TestUnifiedResToSystemdProps(t *testing.T) {
"cpu.idle": "0",
"cpu.weight": "1000",
},
expProps: []systemdDbus.Property{
expProps: configs.SdProperties{
newProp("CPUWeight", uint64(1000)),
},
},
Expand Down
2 changes: 2 additions & 0 deletions libcontainer/cgroups/systemd/user.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux && !runc_nosd

package systemd

import (
Expand Down
10 changes: 6 additions & 4 deletions libcontainer/cgroups/systemd/v1.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux && !runc_nosd

package systemd

import (
Expand Down Expand Up @@ -72,8 +74,8 @@ var legacySubsystems = []subsystem{
&fs.NameGroup{GroupName: "misc"},
}

func genV1ResourcesProperties(r *configs.Resources, cm *dbusConnManager) ([]systemdDbus.Property, error) {
var properties []systemdDbus.Property
func genV1ResourcesProperties(r *configs.Resources, cm *dbusConnManager) (configs.SdProperties, error) {
var properties configs.SdProperties

deviceProperties, err := generateDeviceProperties(r, cm)
if err != nil {
Expand All @@ -91,7 +93,7 @@ func genV1ResourcesProperties(r *configs.Resources, cm *dbusConnManager) ([]syst
newProp("CPUShares", r.CpuShares))
}

addCpuQuota(cm, &properties, r.CpuQuota, r.CpuPeriod)
addCPUQuota(cm, &properties, r.CpuQuota, r.CpuPeriod)

if r.BlkioWeight != 0 {
properties = append(properties,
Expand Down Expand Up @@ -163,7 +165,7 @@ func (m *LegacyManager) Apply(pid int) error {
c = m.cgroups
unitName = getUnitName(c)
slice = "system.slice"
properties []systemdDbus.Property
properties configs.SdProperties
)

m.mu.Lock()
Expand Down
16 changes: 9 additions & 7 deletions libcontainer/cgroups/systemd/v2.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//go:build linux && !runc_nosd

package systemd

import (
Expand Down Expand Up @@ -69,7 +71,7 @@ func shouldSetCPUIdle(cm *dbusConnManager, v string) bool {
// For the list of keys, see https://www.kernel.org/doc/Documentation/cgroup-v2.txt
//
// For the list of systemd unit properties, see systemd.resource-control(5).
func unifiedResToSystemdProps(cm *dbusConnManager, res map[string]string) (props []systemdDbus.Property, _ error) {
func unifiedResToSystemdProps(cm *dbusConnManager, res map[string]string) (props configs.SdProperties, _ error) {
var err error

for k, v := range res {
Expand All @@ -94,7 +96,7 @@ func unifiedResToSystemdProps(cm *dbusConnManager, res map[string]string) (props

case "cpu.max":
// value: quota [period]
quota := int64(0) // 0 means "unlimited" for addCpuQuota, if period is set
quota := int64(0) // 0 means "unlimited" for addCPUQuota, if period is set
period := defCPUQuotaPeriod
sv := strings.Fields(v)
if len(sv) < 1 || len(sv) > 2 {
Expand All @@ -114,7 +116,7 @@ func unifiedResToSystemdProps(cm *dbusConnManager, res map[string]string) (props
return nil, fmt.Errorf("unified resource %q quota value conversion error: %w", k, err)
}
}
addCpuQuota(cm, &props, quota, period)
addCPUQuota(cm, &props, quota, period)

case "cpu.weight":
if shouldSetCPUIdle(cm, strings.TrimSpace(res["cpu.idle"])) {
Expand Down Expand Up @@ -199,15 +201,15 @@ func unifiedResToSystemdProps(cm *dbusConnManager, res map[string]string) (props
return props, nil
}

func genV2ResourcesProperties(dirPath string, r *configs.Resources, cm *dbusConnManager) ([]systemdDbus.Property, error) {
func genV2ResourcesProperties(dirPath string, r *configs.Resources, cm *dbusConnManager) (configs.SdProperties, error) {
// We need this check before setting systemd properties, otherwise
// the container is OOM-killed and the systemd unit is removed
// before we get to fsMgr.Set().
if err := fs2.CheckMemoryUsage(dirPath, r); err != nil {
return nil, err
}

var properties []systemdDbus.Property
var properties configs.SdProperties

// NOTE: This is of questionable correctness because we insert our own
// devices eBPF program later. Two programs with identical rules
Expand Down Expand Up @@ -255,7 +257,7 @@ func genV2ResourcesProperties(dirPath string, r *configs.Resources, cm *dbusConn
}
}

addCpuQuota(cm, &properties, r.CpuQuota, r.CpuPeriod)
addCPUQuota(cm, &properties, r.CpuQuota, r.CpuPeriod)

if r.PidsLimit > 0 || r.PidsLimit == -1 {
properties = append(properties,
Expand Down Expand Up @@ -285,7 +287,7 @@ func (m *UnifiedManager) Apply(pid int) error {
var (
c = m.cgroups
unitName = getUnitName(c)
properties []systemdDbus.Property
properties configs.SdProperties
)

slice := "system.slice"
Expand Down
3 changes: 1 addition & 2 deletions libcontainer/configs/cgroup_linux.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package configs

import (
systemdDbus "github.com/coreos/go-systemd/v22/dbus"
"github.com/opencontainers/runc/libcontainer/devices"
)

Expand Down Expand Up @@ -37,7 +36,7 @@ type Cgroup struct {
// SystemdProps are any additional properties for systemd,
// derived from org.systemd.property.xxx annotations.
// Ignored unless systemd is used for managing cgroups.
SystemdProps []systemdDbus.Property `json:"-"`
SystemdProps SdProperties `json:"-"`

// Rootless tells if rootless cgroups should be used.
Rootless bool
Expand Down
8 changes: 8 additions & 0 deletions libcontainer/configs/no_systemd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//go:build linux && runc_nosd

package configs

type (
SdProperty = int
SdProperties = int
)
Loading
Loading