Skip to content

Commit 8288672

Browse files
committed
Ensure that filemode is set for device nodes
This change ensures that the filemode for a CDI device is properly set from the host device node when adding devices to the CDI spec. Without this the device node permissions are 000 in the container under certain conditions (such as Kata). Signed-off-by: Evan Lezar <[email protected]>
1 parent 6436901 commit 8288672

File tree

2 files changed

+55
-19
lines changed

2 files changed

+55
-19
lines changed

pkg/cdi/container-edits_test.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package cdi
1818

1919
import (
20+
"os"
2021
"runtime"
2122
"testing"
2223

@@ -306,6 +307,9 @@ func TestValidateContainerEdits(t *testing.T) {
306307
func TestApplyContainerEdits(t *testing.T) {
307308
nullDeviceMajor := int64(1)
308309
nullDeviceMinor := int64(3)
310+
311+
mode := uint32(0666)
312+
nullDeviceFileMode := (*os.FileMode)(&mode)
309313
if runtime.GOOS == "darwin" {
310314
nullDeviceMajor = 3
311315
nullDeviceMinor = 2
@@ -352,10 +356,11 @@ func TestApplyContainerEdits(t *testing.T) {
352356
Linux: &oci.Linux{
353357
Devices: []oci.LinuxDevice{
354358
{
355-
Path: "/dev/null",
356-
Type: "c",
357-
Major: nullDeviceMajor,
358-
Minor: nullDeviceMinor,
359+
Path: "/dev/null",
360+
Type: "c",
361+
Major: nullDeviceMajor,
362+
Minor: nullDeviceMinor,
363+
FileMode: nullDeviceFileMode,
359364
},
360365
},
361366
Resources: &oci.LinuxResources{
@@ -395,10 +400,11 @@ func TestApplyContainerEdits(t *testing.T) {
395400
Linux: &oci.Linux{
396401
Devices: []oci.LinuxDevice{
397402
{
398-
Path: "/dev/null",
399-
Type: "c",
400-
Major: nullDeviceMajor,
401-
Minor: nullDeviceMinor,
403+
Path: "/dev/null",
404+
Type: "c",
405+
Major: nullDeviceMajor,
406+
Minor: nullDeviceMinor,
407+
FileMode: nullDeviceFileMode,
402408
},
403409
},
404410
Resources: &oci.LinuxResources{

pkg/cdi/container-edits_unix.go

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ package cdi
2121
import (
2222
"errors"
2323
"fmt"
24+
"os"
2425

2526
"golang.org/x/sys/unix"
2627
)
@@ -31,16 +32,28 @@ const (
3132
fifoDevice = "p"
3233
)
3334

35+
type deviceInfo struct {
36+
// cgroup properties
37+
deviceType string
38+
major int64
39+
minor int64
40+
41+
// device node properties
42+
fileMode os.FileMode
43+
}
44+
3445
// deviceInfoFromPath takes the path to a device and returns its type,
3546
// major and minor device numbers.
3647
//
3748
// It was adapted from https://github.com/opencontainers/runc/blob/v1.1.9/libcontainer/devices/device_unix.go#L30-L69
38-
func deviceInfoFromPath(path string) (devType string, major, minor int64, _ error) {
49+
func deviceInfoFromPath(path string) (*deviceInfo, error) {
3950
var stat unix.Stat_t
4051
err := unix.Lstat(path, &stat)
4152
if err != nil {
42-
return "", 0, 0, err
53+
return nil, err
4354
}
55+
56+
var devType string
4457
switch stat.Mode & unix.S_IFMT {
4558
case unix.S_IFBLK:
4659
devType = blockDevice
@@ -49,10 +62,18 @@ func deviceInfoFromPath(path string) (devType string, major, minor int64, _ erro
4962
case unix.S_IFIFO:
5063
devType = fifoDevice
5164
default:
52-
return "", 0, 0, errors.New("not a device node")
65+
return nil, errors.New("not a device node")
5366
}
5467
devNumber := uint64(stat.Rdev) //nolint:unconvert // Rdev is uint32 on e.g. MIPS.
55-
return devType, int64(unix.Major(devNumber)), int64(unix.Minor(devNumber)), nil
68+
69+
di := deviceInfo{
70+
deviceType: devType,
71+
major: int64(unix.Major(devNumber)),
72+
minor: int64(unix.Minor(devNumber)),
73+
fileMode: os.FileMode(stat.Mode &^ unix.S_IFMT),
74+
}
75+
76+
return &di, nil
5677
}
5778

5879
// fillMissingInfo fills in missing mandatory attributes from the host device.
@@ -65,22 +86,31 @@ func (d *DeviceNode) fillMissingInfo() error {
6586
return nil
6687
}
6788

68-
deviceType, major, minor, err := deviceInfoFromPath(d.HostPath)
89+
di, err := deviceInfoFromPath(d.HostPath)
6990
if err != nil {
7091
return fmt.Errorf("failed to stat CDI host device %q: %w", d.HostPath, err)
7192
}
7293

7394
if d.Type == "" {
74-
d.Type = deviceType
95+
d.Type = di.deviceType
7596
} else {
76-
if d.Type != deviceType {
97+
if d.Type != di.deviceType {
7798
return fmt.Errorf("CDI device (%q, %q), host type mismatch (%s, %s)",
78-
d.Path, d.HostPath, d.Type, deviceType)
99+
d.Path, d.HostPath, d.Type, di.deviceType)
79100
}
80101
}
81-
if d.Major == 0 && d.Type != "p" {
82-
d.Major = major
83-
d.Minor = minor
102+
103+
if d.FileMode == nil {
104+
d.FileMode = &di.fileMode
105+
}
106+
107+
if d.Type == "p" {
108+
return nil
109+
}
110+
111+
if d.Major == 0 {
112+
d.Major = di.major
113+
d.Minor = di.minor
84114
}
85115

86116
return nil

0 commit comments

Comments
 (0)