Skip to content

Commit 462e719

Browse files
committed
Fixes inability to use /dev/null when inside a container
This is a forward port of opencontainers#3620 The original code depended on the origin filesystem to have /dev/{block,char} populated. This is done by udev normally and while is very common non-containerized systemd installs, it's very easy to start systemd in a container created by runc itself and not have /dev/{block,char} populated. When this occurs, the following error output is observed: $ docker run hello-world docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error reopening /dev/null inside container: open /dev/null: operation not permitted: unknown. /dev/null can't be opened because it was not added to the deviceAllowList, as there was no /dev/char directory. The change here utilizes the fact that when sysfs in in use, there is a /sys/dev/{block,char} that is kernel maintained that we can check. Signed-off-by: Evan Phoenix <[email protected]>
1 parent 526d3b3 commit 462e719

File tree

1 file changed

+12
-2
lines changed

1 file changed

+12
-2
lines changed

libcontainer/cgroups/devices/systemd.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,18 @@ func systemdProperties(r *configs.Resources) ([]systemdDbus.Property, error) {
133133
// rules separately to systemd) we can safely skip entries that don't
134134
// have a corresponding path.
135135
if _, err := os.Stat(entry.Path); err != nil {
136-
logrus.Debugf("skipping device %s for systemd: %s", entry.Path, err)
137-
continue
136+
// Also check /sys/dev so that we don't depend on /dev/{block,char}
137+
// being populated. (/dev/{block,char} is populated by udev, which
138+
// isn't strictly required for systemd). Ironically, this happens most
139+
// easily when starting containerd within a runc created container
140+
// itself.
141+
142+
// We don't bother with securejoin here because we create entry.Path
143+
// right above here, so we know it's safe.
144+
if _, err := os.Stat("/sys" + entry.Path); err != nil {
145+
logrus.Warnf("skipping device %s for systemd: %s", entry.Path, err)
146+
continue
147+
}
138148
}
139149
}
140150
deviceAllowList = append(deviceAllowList, entry)

0 commit comments

Comments
 (0)