mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-07 03:03:59 +00:00
Move flag mapping to a separate function and unit test it
This commit is contained in:
parent
3e646cd8cf
commit
0e13fa24ae
@ -112,6 +112,31 @@ func (mounter *Mounter) hasSystemd() bool {
|
||||
return *mounter.withSystemd
|
||||
}
|
||||
|
||||
// Map unix.Statfs mount flags ro, nodev, noexec, nosuid, noatime, relatime,
|
||||
// nodiratime to mount option flag strings.
|
||||
func getUserNSBindMountOptions(path string, statfs func(path string, buf *unix.Statfs_t) (err error)) ([]string, error) {
|
||||
var s unix.Statfs_t
|
||||
var mountOpts []string
|
||||
if err := statfs(path, &s); err != nil {
|
||||
return nil, &os.PathError{Op: "statfs", Path: path, Err: err}
|
||||
}
|
||||
flagMapping := map[int]string{
|
||||
unix.MS_RDONLY: "ro",
|
||||
unix.MS_NODEV: "nodev",
|
||||
unix.MS_NOEXEC: "noexec",
|
||||
unix.MS_NOSUID: "nosuid",
|
||||
unix.MS_NOATIME: "noatime",
|
||||
unix.MS_RELATIME: "relatime",
|
||||
unix.MS_NODIRATIME: "nodiratime",
|
||||
}
|
||||
for k, v := range flagMapping {
|
||||
if int(s.Flags)&k == k {
|
||||
mountOpts = append(mountOpts, v)
|
||||
}
|
||||
}
|
||||
return mountOpts, nil
|
||||
}
|
||||
|
||||
// Do a bind mount including the needed remount for applying the bind opts.
|
||||
// If the remount fails and we are running in a user namespace
|
||||
// figure out if the source filesystem has the ro, nodev, noexec, nosuid,
|
||||
@ -128,25 +153,12 @@ func (mounter *Mounter) bindMountSensitive(mounterPath string, mountCmd string,
|
||||
}
|
||||
// Check if the source has ro, nodev, noexec, nosuid, noatime, relatime,
|
||||
// nodiratime flag...
|
||||
var s unix.Statfs_t
|
||||
if err := unix.Statfs(source, &s); err != nil {
|
||||
fixMountOpts, err := getUserNSBindMountOptions(source, unix.Statfs)
|
||||
if err != nil {
|
||||
return &os.PathError{Op: "statfs", Path: source, Err: err}
|
||||
}
|
||||
// ... and retry the mount with flags found above.
|
||||
flagMapping := map[int]string{
|
||||
unix.MS_RDONLY: "ro",
|
||||
unix.MS_NODEV: "nodev",
|
||||
unix.MS_NOEXEC: "noexec",
|
||||
unix.MS_NOSUID: "nosuid",
|
||||
unix.MS_NOATIME: "noatime",
|
||||
unix.MS_RELATIME: "relatime",
|
||||
unix.MS_NODIRATIME: "nodiratime",
|
||||
}
|
||||
for k, v := range flagMapping {
|
||||
if int(s.Flags)&k == k {
|
||||
bindRemountOpts = append(bindRemountOpts, v)
|
||||
}
|
||||
}
|
||||
bindRemountOpts = append(bindRemountOpts, fixMountOpts...)
|
||||
return mounter.doMount(mounterPath, defaultMountCommand, source, target, fstype, bindRemountOpts, bindRemountOptsSensitive, mountFlags, systemdMountRequired)
|
||||
} else {
|
||||
return err
|
||||
|
@ -25,11 +25,13 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
"github.com/stretchr/testify/assert"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
testexec "k8s.io/utils/exec/testing"
|
||||
@ -812,6 +814,43 @@ func TestFormatTimeout(t *testing.T) {
|
||||
mu.Unlock()
|
||||
}
|
||||
|
||||
func TestGetUserNSBindMountOptions(t *testing.T) {
|
||||
var testCases = map[string]struct {
|
||||
flags int64
|
||||
mountoptions string
|
||||
}{
|
||||
"ro": {flags: unix.MS_RDONLY, mountoptions: "ro"},
|
||||
"nodev": {flags: unix.MS_NODEV, mountoptions: "nodev"},
|
||||
"noexec": {flags: unix.MS_NOEXEC, mountoptions: "noexec"},
|
||||
"nosuid": {flags: unix.MS_NOSUID, mountoptions: "nosuid"},
|
||||
"noatime": {flags: unix.MS_NOATIME, mountoptions: "noatime"},
|
||||
"relatime": {flags: unix.MS_RELATIME, mountoptions: "relatime"},
|
||||
"nodiratime": {flags: unix.MS_NODIRATIME, mountoptions: "nodiratime"},
|
||||
"ronodev": {flags: unix.MS_RDONLY | unix.MS_NODEV, mountoptions: "nodev,ro"},
|
||||
"ronodevnoexec": {flags: unix.MS_RDONLY | unix.MS_NODEV | unix.MS_NOEXEC, mountoptions: "nodev,noexec,ro"},
|
||||
}
|
||||
|
||||
statfsMock := func(path string, buf *unix.Statfs_t) (err error) {
|
||||
*buf = unix.Statfs_t{Flags: testCases[path].flags}
|
||||
return nil
|
||||
}
|
||||
|
||||
testGetUserNSBindMountOptionsSingleCase := func(t *testing.T) {
|
||||
path := strings.Split(t.Name(), "/")[1]
|
||||
options, _ := getUserNSBindMountOptions(path, statfsMock)
|
||||
sort.Strings(options)
|
||||
optionString := strings.Join(options[:], ",")
|
||||
mountOptions := testCases[path].mountoptions
|
||||
if optionString != mountOptions {
|
||||
t.Fatalf(`Mountoptions differ. Wanted: %s, returned: %s`, mountOptions, optionString)
|
||||
}
|
||||
}
|
||||
|
||||
for k, _ := range testCases {
|
||||
t.Run(k, testGetUserNSBindMountOptionsSingleCase)
|
||||
}
|
||||
}
|
||||
|
||||
func makeFakeCommandAction(stdout string, err error, cmdFn func()) testexec.FakeCommandAction {
|
||||
c := testexec.FakeCmd{
|
||||
CombinedOutputScript: []testexec.FakeAction{
|
||||
|
Loading…
Reference in New Issue
Block a user