mirror of https://github.com/k3s-io/k3s
Add GetSELinuxSupport to mounter.
parent
c2b4fc99df
commit
598ca5accc
|
@ -116,6 +116,10 @@ func (mi *fakeMountInterface) GetFSGroup(pathname string) (int64, error) {
|
|||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mi *fakeMountInterface) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func fakeContainerMgrMountInt() mount.Interface {
|
||||
return &fakeMountInterface{
|
||||
[]mount.MountPoint{
|
||||
|
|
|
@ -159,3 +159,7 @@ func (m *execMounter) GetMountRefs(pathname string) ([]string, error) {
|
|||
func (m *execMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return m.wrappedMounter.GetFSGroup(pathname)
|
||||
}
|
||||
|
||||
func (m *execMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return m.wrappedMounter.GetSELinuxSupport(pathname)
|
||||
}
|
||||
|
|
|
@ -172,3 +172,7 @@ func (fm *fakeMounter) GetMountRefs(pathname string) ([]string, error) {
|
|||
func (fm *fakeMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (fm *fakeMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
|
|
@ -106,3 +106,7 @@ func (mounter *execMounter) GetMountRefs(pathname string) ([]string, error) {
|
|||
func (mounter *execMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *execMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
|
|
@ -228,3 +228,7 @@ func (f *FakeMounter) GetMountRefs(pathname string) ([]string, error) {
|
|||
func (f *FakeMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("GetFSGroup not implemented")
|
||||
}
|
||||
|
||||
func (f *FakeMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("GetSELinuxSupport not implemented")
|
||||
}
|
||||
|
|
|
@ -114,6 +114,9 @@ type Interface interface {
|
|||
GetMountRefs(pathname string) ([]string, error)
|
||||
// GetFSGroup returns FSGroup of the path.
|
||||
GetFSGroup(pathname string) (int64, error)
|
||||
// GetSELinuxSupport returns true if given path is on a mount that supports
|
||||
// SELinux.
|
||||
GetSELinuxSupport(pathname string) (bool, error)
|
||||
}
|
||||
|
||||
type Subpath struct {
|
||||
|
|
|
@ -591,25 +591,12 @@ func (mounter *SafeFormatAndMount) GetDiskFormat(disk string) (string, error) {
|
|||
|
||||
// isShared returns true, if given path is on a mount point that has shared
|
||||
// mount propagation.
|
||||
func isShared(path string, filename string) (bool, error) {
|
||||
infos, err := parseMountInfo(filename)
|
||||
func isShared(mount string, mountInfoPath string) (bool, error) {
|
||||
info, err := findMountInfo(mount, mountInfoPath)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// process /proc/xxx/mountinfo in backward order and find the first mount
|
||||
// point that is prefix of 'path' - that's the mount where path resides
|
||||
var info *mountInfo
|
||||
for i := len(infos) - 1; i >= 0; i-- {
|
||||
if strings.HasPrefix(path, infos[i].mountPoint) {
|
||||
info = &infos[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if info == nil {
|
||||
return false, fmt.Errorf("cannot find mount point for %q", path)
|
||||
}
|
||||
|
||||
// parse optional parameters
|
||||
for _, opt := range info.optional {
|
||||
if strings.HasPrefix(opt, "shared:") {
|
||||
|
@ -624,6 +611,10 @@ type mountInfo struct {
|
|||
mountPoint string
|
||||
// list of "optional parameters", mount propagation is one of them
|
||||
optional []string
|
||||
// mount options
|
||||
mountOptions []string
|
||||
// super options: per-superblock options.
|
||||
superOptions []string
|
||||
}
|
||||
|
||||
// parseMountInfo parses /proc/xxx/mountinfo.
|
||||
|
@ -642,22 +633,46 @@ func parseMountInfo(filename string) ([]mountInfo, error) {
|
|||
}
|
||||
// See `man proc` for authoritative description of format of the file.
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 7 {
|
||||
return nil, fmt.Errorf("wrong number of fields in (expected %d, got %d): %s", 8, len(fields), line)
|
||||
if len(fields) < 10 {
|
||||
return nil, fmt.Errorf("wrong number of fields in (expected %d, got %d): %s", 10, len(fields), line)
|
||||
}
|
||||
info := mountInfo{
|
||||
mountPoint: fields[4],
|
||||
optional: []string{},
|
||||
mountPoint: fields[4],
|
||||
mountOptions: strings.Split(fields[5], ","),
|
||||
optional: []string{},
|
||||
}
|
||||
// All fields until "-" are "optional fields".
|
||||
for i := 6; i < len(fields) && fields[i] != "-"; i++ {
|
||||
info.optional = append(info.optional, fields[i])
|
||||
}
|
||||
superOpts := fields[len(fields)-1]
|
||||
info.superOptions = strings.Split(superOpts, ",")
|
||||
infos = append(infos, info)
|
||||
}
|
||||
return infos, nil
|
||||
}
|
||||
|
||||
func findMountInfo(path, mountInfoPath string) (mountInfo, error) {
|
||||
infos, err := parseMountInfo(mountInfoPath)
|
||||
if err != nil {
|
||||
return mountInfo{}, err
|
||||
}
|
||||
|
||||
// process /proc/xxx/mountinfo in backward order and find the first mount
|
||||
// point that is prefix of 'path' - that's the mount where path resides
|
||||
var info *mountInfo
|
||||
for i := len(infos) - 1; i >= 0; i-- {
|
||||
if pathWithinBase(path, infos[i].mountPoint) {
|
||||
info = &infos[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
if info == nil {
|
||||
return mountInfo{}, fmt.Errorf("cannot find mount point for %q", path)
|
||||
}
|
||||
return *info, nil
|
||||
}
|
||||
|
||||
// doMakeRShared is common implementation of MakeRShared on Linux. It checks if
|
||||
// path is shared and bind-mounts it as rshared if needed. mountCmd and
|
||||
// mountArgs are expected to contain mount-like command, doMakeRShared will add
|
||||
|
@ -686,6 +701,27 @@ func doMakeRShared(path string, mountInfoFilename string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// getSELinuxSupport is common implementation of GetSELinuxSupport on Linux.
|
||||
func getSELinuxSupport(path string, mountInfoFilename string) (bool, error) {
|
||||
info, err := findMountInfo(path, mountInfoFilename)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// "seclabel" can be both in mount options and super options.
|
||||
for _, opt := range info.superOptions {
|
||||
if opt == "seclabel" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
for _, opt := range info.mountOptions {
|
||||
if opt == "seclabel" {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) PrepareSafeSubpath(subPath Subpath) (newHostPath string, cleanupAction func(), err error) {
|
||||
newHostPath, err = doBindSubPath(mounter, subPath, os.Getpid())
|
||||
// There is no action when the container starts. Bind-mount will be cleaned
|
||||
|
@ -934,6 +970,10 @@ func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
|||
return getMountRefsByDev(mounter, realpath)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return getSELinuxSupport(pathname, procMountInfoPath)
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
|
||||
realpath, err := filepath.EvalSymlinks(pathname)
|
||||
if err != nil {
|
||||
|
|
|
@ -1399,8 +1399,10 @@ func TestParseMountInfo(t *testing.T) {
|
|||
"simple bind mount",
|
||||
"/var/lib/kubelet",
|
||||
mountInfo{
|
||||
mountPoint: "/var/lib/kubelet",
|
||||
optional: []string{"shared:30"},
|
||||
mountPoint: "/var/lib/kubelet",
|
||||
optional: []string{"shared:30"},
|
||||
mountOptions: []string{"rw", "relatime"},
|
||||
superOptions: []string{"rw", "commit=30", "data=ordered"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -1427,6 +1429,53 @@ func TestParseMountInfo(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestGetSELinuxSupport(t *testing.T) {
|
||||
info :=
|
||||
`62 0 253:0 / / rw,relatime shared:1 - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered
|
||||
78 62 0:41 / /tmp rw,nosuid,nodev shared:30 - tmpfs tmpfs rw,seclabel
|
||||
83 63 0:44 / /var/lib/bar rw,relatime - tmpfs tmpfs rw
|
||||
227 62 253:0 /var/lib/docker/devicemapper /var/lib/docker/devicemapper rw,relatime - ext4 /dev/mapper/ssd-root rw,seclabel,data=ordered
|
||||
150 23 1:58 / /media/nfs_vol rw,relatime shared:89 - nfs4 172.18.4.223:/srv/nfs rw,vers=4.0,rsize=524288,wsize=524288,namlen=255,hard,proto=tcp,port=0,timeo=600,retrans=2,sec=sys,clientaddr=172.18.4.223,local_lock=none,addr=172.18.4.223
|
||||
`
|
||||
tempDir, filename, err := writeFile(info)
|
||||
if err != nil {
|
||||
t.Fatalf("cannot create temporary file: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(tempDir)
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
mountPoint string
|
||||
expectedResult bool
|
||||
}{
|
||||
{
|
||||
"ext4 on /",
|
||||
"/",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"tmpfs on /var/lib/bar",
|
||||
"/var/lib/bar",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"nfsv4",
|
||||
"/media/nfs_vol",
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
out, err := getSELinuxSupport(test.mountPoint, filename)
|
||||
if err != nil {
|
||||
t.Errorf("Test %s failed with error: %s", test.name, err)
|
||||
}
|
||||
if test.expectedResult != out {
|
||||
t.Errorf("Test %s failed: expected %v, got %v", test.name, test.expectedResult, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSafeOpen(t *testing.T) {
|
||||
defaultPerm := os.FileMode(0750)
|
||||
|
||||
|
|
|
@ -134,3 +134,7 @@ func (mounter *Mounter) GetMountRefs(pathname string) ([]string, error) {
|
|||
func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
|
|
@ -456,6 +456,11 @@ func (mounter *Mounter) GetFSGroup(pathname string) (int64, error) {
|
|||
return 0, nil
|
||||
}
|
||||
|
||||
func (mounter *Mounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
// Windows does not support SELinux.
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// SafeMakeDir makes sure that the created directory does not escape given base directory mis-using symlinks.
|
||||
func (mounter *Mounter) SafeMakeDir(pathname string, base string, perm os.FileMode) error {
|
||||
return doSafeMakeDir(pathname, base, perm)
|
||||
|
|
|
@ -343,3 +343,7 @@ func (mounter *NsenterMounter) GetFSGroup(pathname string) (int64, error) {
|
|||
}
|
||||
return getFSGroup(kubeletpath)
|
||||
}
|
||||
|
||||
func (mounter *NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return getSELinuxSupport(pathname, procMountInfoPath)
|
||||
}
|
||||
|
|
|
@ -106,3 +106,7 @@ func (*NsenterMounter) GetMountRefs(pathname string) ([]string, error) {
|
|||
func (*NsenterMounter) GetFSGroup(pathname string) (int64, error) {
|
||||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (*NsenterMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
|
|
@ -99,6 +99,10 @@ func (mounter *fakeMounter) GetFSGroup(pathname string) (int64, error) {
|
|||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *fakeMounter) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (mounter *fakeMounter) IsLikelyNotMountPoint(file string) (bool, error) {
|
||||
name := path.Base(file)
|
||||
if strings.HasPrefix(name, "mount") {
|
||||
|
|
|
@ -397,6 +397,10 @@ func (fftc *fakeFileTypeChecker) GetFSGroup(pathname string) (int64, error) {
|
|||
return -1, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (fftc *fakeFileTypeChecker) GetSELinuxSupport(pathname string) (bool, error) {
|
||||
return false, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func setUp() error {
|
||||
err := os.MkdirAll("/tmp/ExistingFolder", os.FileMode(0755))
|
||||
if err != nil {
|
||||
|
|
|
@ -131,6 +131,7 @@ type Mounter interface {
|
|||
// idempotent.
|
||||
SetUpAt(dir string, fsGroup *int64) error
|
||||
// GetAttributes returns the attributes of the mounter.
|
||||
// This function is called after SetUp()/SetUpAt().
|
||||
GetAttributes() Attributes
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue