Skip to content

Commit

Permalink
fix: ensure containerd Base Dir lockfile is never accidentally deleted.
Browse files Browse the repository at this point in the history
The containerd Base Dir is the special path all other containerd-related
paths on the snap are derived from.

Under classic confinement and default settings, this path defaults
to the host's root (`/`), and thus extreme care must be taken to
not accidentally include it in k8sd's cleanup routine or the
k8s-snap's remove hook.

Signed-off-by: Nashwan Azhari <[email protected]>
  • Loading branch information
Nashwan Azhari committed Dec 10, 2024
1 parent 80cb072 commit 57f5b04
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 3 deletions.
12 changes: 10 additions & 2 deletions k8s/lib.sh
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,16 @@ k8s::remove::containerd() {
# this is to prevent removing containerd when it is not installed by the snap.
# NOTE: do NOT include .containerd-base-dir! By default, it will contain "/".
for file in "containerd-socket-path" "containerd-config-dir" "containerd-root-dir" "containerd-cni-bin-dir"; do
if [ -f "$SNAP_COMMON/lock/$file" ]; then
rm -rf $(cat "$SNAP_COMMON/lock/$file")
local lockpath="$SNAP_COMMON/lock/$file"
if [ -f "$lockpath" ]; then
local dirpath=$(cat "$SNAP_COMMON/lock/$file")

if [ $(readlink -m "$dirpath") = "/" ]; then
echo "WARN: lockfile '$lockpath' points to root ('/'). Skipping cleanup."
continue
fi

rm -rf "$dirpath"
fi
done
}
Expand Down
9 changes: 9 additions & 0 deletions src/k8s/pkg/k8sd/app/hooks_remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ func tryCleanupContainerdPaths(s snap.Snap) {
if _, err := os.Stat(dirpath); os.IsNotExist(err) {
log.Info("Containerd directory doesn't exist; skipping cleanup", "directory", dirpath)
} else {
// NOTE(aznashwan): because of the convoluted interfaced-based way the snap
// composes and creates the original lockfiles (see k8sd/setup/containerd.go)
// this check is meant to defend against accidental code/configuration errors which
// might lead to the root FS being deleted:
if dirpath == "/" {
log.Error(fmt.Errorf("There is some configuration/logic error in the current versions of the k8s-snap related to lockfile %q (meant to lock %q) which could lead to accidental wiping of the root file system.", lockpath, dirpath), "Please report this issue upstream immediately.")
continue
}

if err := os.RemoveAll(dirpath); err != nil {
log.Info("WARN: failed to remove containerd data directory", "directory", dirpath, "error", err)
continue // Avoid removing the lockfile path.
Expand Down
15 changes: 14 additions & 1 deletion src/k8s/pkg/k8sd/setup/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,19 @@ func Containerd(snap snap.Snap, extraContainerdConfig map[string]any, extraArgs
// ContainerdLockPathsForSnap returns a mapping between the absolute paths of
// the lockfiles within the k8s snap and the absolute paths of the containerd
// directory they lock.
//
// WARN: these lockfiles are meant to be used in later cleanup stages.
// DO NOT include any system paths which are not managed by the k8s-snap!
//
// It intentionally does NOT include the containerd base dir lockfile
// (which most of the rest of the paths are based on), as it is meant
// to indicate the root of the containerd install ('/' or '/var/snap/k8s/*').
func ContainerdLockPathsForSnap(s snap.Snap) map[string]string {
m := map[string]string{
"containerd-socket-path": s.ContainerdSocketDir(),
"containerd-config-dir": s.ContainerdConfigDir(),
"containerd-root-dir": s.ContainerdRootDir(),
"containerd-cni-bin-dir": s.CNIBinDir(),
snap.ContainerdBaseDir: s.GetContainerdBaseDir(),
}

prefixed := map[string]string{}
Expand All @@ -193,6 +199,13 @@ func saveSnapContainerdPaths(s snap.Snap) error {
return fmt.Errorf("failed to write %s: %w", lockpath, err)
}
}

// Save the Containerd Base Dir separately:
baseDirPath := filepath.Join(s.LockFilesDir(), snap.ContainerdBaseDir)
if err := utils.WriteFile(baseDirPath, []byte(s.GetContainerdBaseDir()), 0o600); err != nil {
return fmt.Errorf("failed to write %s: %w", baseDirPath, err)
}

return nil
}

Expand Down

0 comments on commit 57f5b04

Please sign in to comment.