From e6de45d76c99cf4888e04870620c33f03abd60f8 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Wed, 10 Aug 2022 17:09:23 -0700 Subject: [PATCH] Fix failed exec after systemctl daemon-reload A regression reported for runc v1.1.3 says that after systemctl daemon-reload runc exec fails: > exec failed: unable to start container process: open /dev/pts/0: operation not permitted: unknown Apparently, with commit 7219387eb7db69b we are no longer adding "DeviceAllow=char-pts rwm" rule (because os.Stat("char-pts") returns ENOENT). The bug can only be seen after "systemctl daemon-reload" because runc also applies the same rules manually (by writing to devices.allow for cgroup v1), and apparently reloading systemd leads to re-applying the rules that systemd has (thus removing the char-pts access). The fix is to do os.Stat only for "/dev" paths. Also, emit a warning that the path was skipped. Since the original idea was to emit less warnings, demote the level to debug. Fixes: https://github.com/opencontainers/runc/issues/3551 Fixes: 7219387eb7db69b4dae740c9d37d973d9a735801 Signed-off-by: Kir Kolyshkin --- libcontainer/cgroups/systemd/common.go | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/libcontainer/cgroups/systemd/common.go b/libcontainer/cgroups/systemd/common.go index 5a68a3cf394..45744c15c0a 100644 --- a/libcontainer/cgroups/systemd/common.go +++ b/libcontainer/cgroups/systemd/common.go @@ -288,14 +288,16 @@ func generateDeviceProperties(r *configs.Resources) ([]systemdDbus.Property, err case devices.CharDevice: entry.Path = fmt.Sprintf("/dev/char/%d:%d", rule.Major, rule.Minor) } + // systemd will issue a warning if the path we give here doesn't exist. + // Since all of this logic is best-effort anyway (we manually set these + // rules separately to systemd) we can safely skip entries that don't + // have a corresponding path. + if _, err := os.Stat(entry.Path); err != nil { + logrus.Debugf("skipping device %s for systemd: %s", entry.Path, err) + continue + } } - // systemd will issue a warning if the path we give here doesn't exist. - // Since all of this logic is best-effort anyway (we manually set these - // rules separately to systemd) we can safely skip entries that don't - // have a corresponding path. - if _, err := os.Stat(entry.Path); err == nil { - deviceAllowList = append(deviceAllowList, entry) - } + deviceAllowList = append(deviceAllowList, entry) } properties = append(properties, newProp("DeviceAllow", deviceAllowList))