Skip to content

Commit 95a59bf

Browse files
committed
devices: correctly check device types
(mode&S_IFCHR == S_IFCHR) is the wrong way of checking the type of an inode because the S_IF* bits are actually not a bitmask and instead must be checked using S_IF*. This bug was neatly hidden behind a (major == 0) sanity-check but that was removed by [1]. In addition, add a test that makes sure that HostDevices() doesn't give rubbish results -- because we broke this and fixed this before[2]. [1]: 24388be ("configs: use different types for .Devices and .Resources.Devices") [2]: 3ed492a ("Handle non-devices correctly in DeviceFromPath") Fixes: b0d014d ("libcontainer: one more switch from syscall to x/sys/unix") Signed-off-by: Aleksa Sarai <[email protected]>
1 parent d65df61 commit 95a59bf

2 files changed

Lines changed: 48 additions & 4 deletions

File tree

libcontainer/devices/devices.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,12 @@ func DeviceFromPath(path, permissions string) (*configs.Device, error) {
3737
major = unix.Major(devNumber)
3838
minor = unix.Minor(devNumber)
3939
)
40-
switch {
41-
case mode&unix.S_IFBLK == unix.S_IFBLK:
40+
switch mode & unix.S_IFMT {
41+
case unix.S_IFBLK:
4242
devType = configs.BlockDevice
43-
case mode&unix.S_IFCHR == unix.S_IFCHR:
43+
case unix.S_IFCHR:
4444
devType = configs.CharDevice
45-
case mode&unix.S_IFIFO == unix.S_IFIFO:
45+
case unix.S_IFIFO:
4646
devType = configs.FifoDevice
4747
default:
4848
return nil, ErrNotADevice
@@ -104,6 +104,9 @@ func GetDevices(path string) ([]*configs.Device, error) {
104104
}
105105
return nil, err
106106
}
107+
if device.Type == configs.FifoDevice {
108+
continue
109+
}
107110
out = append(out, device)
108111
}
109112
return out, nil

libcontainer/devices/devices_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,27 @@ package devices
22

33
import (
44
"errors"
5+
"io/ioutil"
56
"os"
67
"testing"
78

9+
"github.com/opencontainers/runc/libcontainer/configs"
810
"golang.org/x/sys/unix"
911
)
1012

13+
func cleanupTest() {
14+
unixLstat = unix.Lstat
15+
ioutilReadDir = ioutil.ReadDir
16+
}
17+
1118
func TestDeviceFromPathLstatFailure(t *testing.T) {
1219
testError := errors.New("test error")
1320

1421
// Override unix.Lstat to inject error.
1522
unixLstat = func(path string, stat *unix.Stat_t) error {
1623
return testError
1724
}
25+
defer cleanupTest()
1826

1927
_, err := DeviceFromPath("", "")
2028
if err != testError {
@@ -29,6 +37,7 @@ func TestHostDevicesIoutilReadDirFailure(t *testing.T) {
2937
ioutilReadDir = func(dirname string) ([]os.FileInfo, error) {
3038
return nil, testError
3139
}
40+
defer cleanupTest()
3241

3342
_, err := HostDevices()
3443
if err != testError {
@@ -55,9 +64,41 @@ func TestHostDevicesIoutilReadDirDeepFailure(t *testing.T) {
5564

5665
return []os.FileInfo{fi}, nil
5766
}
67+
defer cleanupTest()
5868

5969
_, err := HostDevices()
6070
if err != testError {
6171
t.Fatalf("Unexpected error %v, expected %v", err, testError)
6272
}
6373
}
74+
75+
func TestHostDevicesAllValid(t *testing.T) {
76+
devices, err := HostDevices()
77+
if err != nil {
78+
t.Fatalf("failed to get host devices: %v", err)
79+
}
80+
81+
for _, device := range devices {
82+
// Devices can't have major number 0.
83+
if device.Major == 0 {
84+
t.Errorf("device entry %+v has zero major number", device)
85+
}
86+
// Devices should only have file modes that correspond to their type.
87+
var expectedType os.FileMode
88+
switch device.Type {
89+
case configs.BlockDevice:
90+
expectedType = unix.S_IFBLK
91+
case configs.CharDevice:
92+
expectedType = unix.S_IFCHR
93+
case configs.FifoDevice:
94+
t.Logf("fifo devices shouldn't show up from HostDevices")
95+
fallthrough
96+
default:
97+
t.Errorf("device entry %+v has unexpected type %v", device, device.Type)
98+
}
99+
gotType := device.FileMode & unix.S_IFMT
100+
if expectedType != gotType {
101+
t.Errorf("device entry %+v has mismatched types (expected %#x, got %#x)", device, expectedType, gotType)
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)