From 1cd1925acd6c36ccdca51aca62ca6b24b2559a6f Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Wed, 17 Feb 2021 14:55:50 +0100 Subject: [PATCH] oci.Device() fix FileMode to match runtime spec The runtime spec expects the FileMode field to only hold file permissions, however `unix.Stat_t.Mode` contains both file type and mode. This patch strips file type so that only file mode is included in the Device. Thanks to Iceber Gu, who noticed the same issue in containerd and runc. Signed-off-by: Sebastiaan van Stijn --- oci/devices_linux.go | 3 ++- oci/devices_linux_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 oci/devices_linux_test.go diff --git a/oci/devices_linux.go b/oci/devices_linux.go index ff00ea8fa9..c0dfc28ce3 100644 --- a/oci/devices_linux.go +++ b/oci/devices_linux.go @@ -9,6 +9,7 @@ import ( "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/devices" specs "github.com/opencontainers/runtime-spec/specs-go" + "golang.org/x/sys/unix" ) // Device transforms a libcontainer configs.Device to a specs.LinuxDevice object. @@ -18,7 +19,7 @@ func Device(d *configs.Device) specs.LinuxDevice { Path: d.Path, Major: d.Major, Minor: d.Minor, - FileMode: fmPtr(int64(d.FileMode)), + FileMode: fmPtr(int64(d.FileMode &^ unix.S_IFMT)), // strip file type, as OCI spec only expects file-mode to be included UID: u32Ptr(int64(d.Uid)), GID: u32Ptr(int64(d.Gid)), } diff --git a/oci/devices_linux_test.go b/oci/devices_linux_test.go new file mode 100644 index 0000000000..ebc032597b --- /dev/null +++ b/oci/devices_linux_test.go @@ -0,0 +1,31 @@ +package oci + +import ( + "os" + "testing" + + "github.com/opencontainers/runc/libcontainer/configs" + "golang.org/x/sys/unix" + "gotest.tools/v3/assert" +) + +func TestDeviceMode(t *testing.T) { + tests := []struct { + name string + in os.FileMode + out os.FileMode + }{ + {name: "regular permissions", in: 0777, out: 0777}, + {name: "block device", in: 0777 | unix.S_IFBLK, out: 0777}, + {name: "character device", in: 0777 | unix.S_IFCHR, out: 0777}, + {name: "fifo device", in: 0777 | unix.S_IFIFO, out: 0777}, + } + + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + d := Device(&configs.Device{FileMode: tc.in}) + assert.Equal(t, *d.FileMode, tc.out) + }) + } +}