Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions libcontainer/specconv/spec_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -1060,6 +1060,9 @@ next:
filemode = *d.FileMode &^ unix.S_IFMT
}
device := &devices.Device{
// NOTE despite the name this is not a device access rule
// (those live under cgroup), but merely a way to specify
// a device type and major:minor for mknod.
Rule: devices.Rule{
Type: dt,
Major: d.Major,
Expand Down
36 changes: 17 additions & 19 deletions libcontainer/specconv/spec_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -865,21 +865,22 @@ func TestNullProcess(t *testing.T) {
func TestCreateDevices(t *testing.T) {
spec := Example()

// dummy uid/gid for /dev/tty; will enable the test to check if createDevices()
// preferred the spec's device over the redundant default device
// Dummy uid/gid for /dev/tty; will enable the test to check if createDevices()
// preferred the spec's device over the redundant default device.
ttyUid := uint32(1000)
ttyGid := uint32(1000)
fm := os.FileMode(0o666)
ttyMode := os.FileMode(0o666)
ttyPath := "/dev/tty"

spec.Linux = &specs.Linux{
Devices: []specs.LinuxDevice{
{
// This is purposely redundant with one of runc's default devices
Path: "/dev/tty",
Path: ttyPath,
Type: "c",
Major: 5,
Minor: 0,
FileMode: &fm,
FileMode: &ttyMode,
UID: &ttyUid,
GID: &ttyGid,
},
Expand All @@ -900,14 +901,11 @@ func TestCreateDevices(t *testing.T) {
t.Errorf("failed to create devices: %v", err)
}

// Verify the returned default devices has the /dev/tty entry deduplicated
found := false
for _, d := range defaultDevs {
if d.Path == "/dev/tty" {
if found {
t.Errorf("createDevices failed: returned a duplicated device entry: %v", defaultDevs)
}
found = true
// Verify that /dev/tty is not in defaultDevs,
// because the one in spec is preferred.
for _, dev := range defaultDevs {
if dev.Path == ttyPath {
t.Errorf("%s should not be present in defaultDevs", ttyPath)
}
}

Expand All @@ -934,12 +932,12 @@ func TestCreateDevices(t *testing.T) {

// Verify that createDevices() deduplicated the /dev/tty entry in the config
for _, configDev := range conf.Devices {
if configDev.Path == "/dev/tty" {
if configDev.Path == ttyPath {
wantDev := &devices.Device{
Path: "/dev/tty",
FileMode: 0o666,
Uid: 1000,
Gid: 1000,
Path: ttyPath,
FileMode: ttyMode,
Uid: ttyUid,
Gid: ttyGid,
Rule: devices.Rule{
Type: devices.CharDevice,
Major: 5,
Expand All @@ -954,7 +952,7 @@ func TestCreateDevices(t *testing.T) {
}

// Verify that createDevices() added the entry for /dev/ram0 in the config
found = false
found := false
for _, configDev := range conf.Devices {
if configDev.Path == "/dev/ram0" {
found = true
Expand Down
30 changes: 30 additions & 0 deletions tests/integration/dev.bats
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,36 @@ function teardown() {
teardown_bundle
}

@test "runc run [redundant default /dev/full]" {
requires root # Rootless devices behave differently.

# 1. This is how a device from the default AllowedDevices should work as is.
# It's /dev/full so it should return "no space left on device" error.
update_config ' .process.args |= ["sh", "-c", "stat /dev/full; echo foo >/dev/full"]'
runc run test_dev
[ "$status" -eq 1 ]
[[ "$output" == *"Device type: 1,7"* ]]
[[ "$output" == *": No space left on device"* ]]

# 2. Add the device to linux.devices only (but not to linux.resources.devices).
# This way it will be excluded from the cgroup allow rules.
update_config ' .linux.devices += [{"path": "/dev/full", "type": "c", "major": 1, "minor": 7}]'
runc run test_dev
[ "$status" -eq 1 ]
[[ "$output" == *"Device type: 1,7"* ]]
[[ "$output" == *": Operation not permitted"* ]]

# 3. Also add it to cgroups list. Now it should work like the default one (see 1 above).
update_config ' .linux.resources.devices = [
{"allow": false, "access": "rwm"},
{"allow": true, "type": "c", "major": 1, "minor": 7, "access": "rw"}
]'
runc run test_dev
[ "$status" -eq 1 ]
[[ "$output" == *"Device type: 1,7"* ]]
[[ "$output" == *": No space left on device"* ]]
}

@test "runc run [redundant default /dev/tty]" {
update_config ' .linux.devices += [{"path": "/dev/tty", "type": "c", "major": 5, "minor": 0}]
| .process.args |= ["ls", "-lLn", "/dev/tty"]'
Expand Down
Loading