Skip to content

Commit

Permalink
Warn if /sys mount propagation is not shared
Browse files Browse the repository at this point in the history
  • Loading branch information
bschimke95 committed Feb 27, 2024
1 parent a6e1a8b commit 35f5166
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 17 deletions.
11 changes: 11 additions & 0 deletions src/k8s/pkg/component/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,17 @@ func EnableNetworkComponent(ctx context.Context, s snap.Snap, podCIDR string) er
},
"hostRoot": cgrMnt,
}
} else {
p, err := utils.GetMountPropagation("/sys")
if err != nil {
return fmt.Errorf("failed to get mount propagation for %s: %w", p, err)
}
if p == "private" {
if s.OnLXD(ctx) {
return fmt.Errorf("Please update the LXD version on the host to at least 5.0.2")
}
return fmt.Errorf("/sys is not a shared mount")
}
}

if err := manager.Enable("network", values); err != nil {
Expand Down
8 changes: 5 additions & 3 deletions src/k8s/pkg/snap/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import (

// Snap abstracts file system paths and interacting with the k8s services.
type Snap interface {
Strict() bool // Strict returns true if the snap is installed with strict confinement.
UID() int // UID is the user ID to set on config files.
GID() int // GID is the group ID to set on config files.
Strict() bool // Strict returns true if the snap is installed with strict confinement.
OnLXD(context.Context) bool // OnLXD returns true if the host runs on LXD.

UID() int // UID is the user ID to set on config files.
GID() int // GID is the group ID to set on config files.

StartService(ctx context.Context, serviceName string) error // snapctl start $service
StopService(ctx context.Context, serviceName string) error // snapctl stop $service
Expand Down
4 changes: 4 additions & 0 deletions src/k8s/pkg/snap/mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

type Mock struct {
Strict bool
OnLXD bool
UID int
GID int
KubernetesConfigDir string
Expand Down Expand Up @@ -76,6 +77,9 @@ func (s *Snap) RestartService(ctx context.Context, name string) error {
func (s *Snap) Strict() bool {
return s.Mock.Strict
}
func (s *Snap) OnLXD(context.Context) bool {
return s.Mock.OnLXD
}
func (s *Snap) UID() int {
return s.Mock.UID
}
Expand Down
4 changes: 4 additions & 0 deletions src/k8s/pkg/snap/snap.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ func (s *snap) Strict() bool {
return meta.Confinement == "strict"
}

func (s *snap) OnLXD(ctx context.Context) bool {
return utils.RunCommand(ctx, "grep", "-qa", "container=lxc", "/proc/1/environ") == nil
}

func (s *snap) UID() int {
return 0
}
Expand Down
50 changes: 36 additions & 14 deletions src/k8s/pkg/utils/file.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package utils

import (
"bufio"
"errors"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -104,20 +105,6 @@ func CopyFile(srcFile, dstFile string) error {

return nil
}

// GetMountPath returns the first mountpath for a given filesystem type.
func GetMountPath(fsType string) (string, error) {
mounts, err := mountinfo.GetMounts(mountinfo.FSTypeFilter(fsType))
if err != nil {
return "", fmt.Errorf("failed to find the mount info for %s: %w", fsType, err)
}
if len(mounts) == 0 {
return "", fmt.Errorf("could not find any %s filesystem mount", fsType)
}

return mounts[0].Mountpoint, nil
}

func FileExists(path ...string) (bool, error) {
if _, err := os.Stat(filepath.Join(path...)); err != nil {
if !os.IsNotExist(err) {
Expand All @@ -138,3 +125,38 @@ func ValueInSlice[T comparable](key T, list []T) bool {

return false
}

var ErrUnknownMount = errors.New("mount is unknown")

// GetMountPath returns the first mountpath for a given filesystem type.
// GetMountPath returns ErrUnkownMount if the mount path does not exist.
func GetMountPath(fsType string) (string, error) {
mounts, err := mountinfo.GetMounts(mountinfo.FSTypeFilter(fsType))
if err != nil {
return "", fmt.Errorf("failed to find the mount info for %s: %w", fsType, err)
}
if len(mounts) == 0 {
return "", ErrUnknownMount
}

return mounts[0].Mountpoint, nil
}

// GetMountPropagation returns the propagation type (shared or private)
// GetMountPropagation returns ErrUnkownMount if the mount path does not exist.
func GetMountPropagation(path string) (string, error) {
mounts, err := mountinfo.GetMounts(mountinfo.SingleEntryFilter(path))
if err != nil {
return "", fmt.Errorf("failed to get mounts: %w", err)
}

if len(mounts) == 0 {
return "", ErrUnknownMount
}

mount := mounts[0]
if strings.Contains(mount.Optional, "shared") {
return "shared", nil
}
return "private", nil
}
13 changes: 13 additions & 0 deletions src/k8s/pkg/utils/file_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package utils_test

import (
"errors"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -159,3 +160,15 @@ func TestFileExists(t *testing.T) {
g.Expect(err).To(BeNil())
g.Expect(fileExists).To(BeFalse())
}

func TestGetMountPropagation(t *testing.T) {
g := NewWithT(t)

mountType, err := utils.GetMountPropagation("/randommount")
g.Expect(errors.Is(err, utils.ErrUnknownMount)).To(BeTrue())
g.Expect(mountType).To(Equal(""))

mountType, err = utils.GetMountPropagation("/sys")
g.Expect(err).To(BeNil())
g.Expect(mountType).To(Equal("shared"))
}

0 comments on commit 35f5166

Please sign in to comment.