From 6c4cf83e087db6c76de8652184b433130fb43958 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 12 Apr 2019 13:18:50 +0200 Subject: [PATCH] runroot: add check that it is on volatile storage Make sure the runroot won't persist after a reboot, if it happens then we can carry wrong information on the current active mounts. Closes: https://github.com/containers/libpod/issues/2150 Signed-off-by: Giuseppe Scrivano --- errors.go | 2 ++ pkg/mount/mountinfo_freebsd.go | 5 +++++ pkg/mount/mountinfo_linux.go | 16 ++++++++++++++++ pkg/mount/mountinfo_solaris.go | 5 +++++ pkg/mount/mountinfo_unsupported.go | 5 +++++ pkg/mount/mountinfo_windows.go | 5 +++++ store.go | 9 +++++++++ 7 files changed, 47 insertions(+) diff --git a/errors.go b/errors.go index 63cb9ab74d..d81206e432 100644 --- a/errors.go +++ b/errors.go @@ -53,4 +53,6 @@ var ( ErrDigestUnknown = errors.New("could not compute digest of item") // ErrLayerNotMounted is returned when the requested information can only be computed for a mounted layer, and the layer is not mounted. ErrLayerNotMounted = errors.New("layer is not mounted") + // ErrTargetNotVolatile is returned when a path must be on volatile storage. + ErrTargetNotVolatile = errors.New("the target is not on tmpfs") ) diff --git a/pkg/mount/mountinfo_freebsd.go b/pkg/mount/mountinfo_freebsd.go index 4f32edcd90..a7665e204c 100644 --- a/pkg/mount/mountinfo_freebsd.go +++ b/pkg/mount/mountinfo_freebsd.go @@ -39,3 +39,8 @@ func parseMountTable() ([]*Info, error) { } return out, nil } + +// IsOnVolatileStorage returns whether the specified target is on tmpfs. +func IsOnVolatileStorage(target string) (bool, error) { + return true, nil +} diff --git a/pkg/mount/mountinfo_linux.go b/pkg/mount/mountinfo_linux.go index be69fee1d7..27451a8fee 100644 --- a/pkg/mount/mountinfo_linux.go +++ b/pkg/mount/mountinfo_linux.go @@ -8,6 +8,9 @@ import ( "io" "os" "strings" + + "github.com/pkg/errors" + "golang.org/x/sys/unix" ) const ( @@ -26,6 +29,8 @@ const ( (10) mount source: filesystem specific information or "none" (11) super options: per super block options*/ mountinfoFormat = "%d %d %d:%d %s %s %s %s" + + TMPFS_MAGIC = 0x1021994 ) // Parse /proc/self/mountinfo because comparing Dev and ino does not work from @@ -93,3 +98,14 @@ func PidMountInfo(pid int) ([]*Info, error) { return parseInfoFile(f) } + +// IsOnVolatileStorage returns whether the specified target is on tmpfs. +func IsOnVolatileStorage(target string) (bool, error) { + var fs unix.Statfs_t + // Make sure it's read-only. + if err := unix.Statfs(target, &fs); err != nil { + return false, errors.Wrapf(err, "error statfs %s", target) + } + + return fs.Type == TMPFS_MAGIC, nil +} diff --git a/pkg/mount/mountinfo_solaris.go b/pkg/mount/mountinfo_solaris.go index ad9ab57f8b..e3be8eba2c 100644 --- a/pkg/mount/mountinfo_solaris.go +++ b/pkg/mount/mountinfo_solaris.go @@ -35,3 +35,8 @@ func parseMountTable() ([]*Info, error) { C.fclose(mnttab) return out, nil } + +// IsOnVolatileStorage returns whether the specified target is on tmpfs. +func IsOnVolatileStorage(target string) (bool, error) { + return true, nil +} diff --git a/pkg/mount/mountinfo_unsupported.go b/pkg/mount/mountinfo_unsupported.go index 7fbcf19214..b2966c0675 100644 --- a/pkg/mount/mountinfo_unsupported.go +++ b/pkg/mount/mountinfo_unsupported.go @@ -10,3 +10,8 @@ import ( func parseMountTable() ([]*Info, error) { return nil, fmt.Errorf("mount.parseMountTable is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) } + +// IsOnVolatileStorage returns whether the specified target is on tmpfs. +func IsOnVolatileStorage(target string) (bool, error) { + return true, nil +} diff --git a/pkg/mount/mountinfo_windows.go b/pkg/mount/mountinfo_windows.go index dab8a37ed0..63fe149119 100644 --- a/pkg/mount/mountinfo_windows.go +++ b/pkg/mount/mountinfo_windows.go @@ -4,3 +4,8 @@ func parseMountTable() ([]*Info, error) { // Do NOT return an error! return nil, nil } + +// IsOnVolatileStorage returns whether the specified target is on tmpfs. +func IsOnVolatileStorage(target string) (bool, error) { + return true, nil +} diff --git a/store.go b/store.go index 34df10babb..50132fe281 100644 --- a/store.go +++ b/store.go @@ -22,6 +22,7 @@ import ( "github.com/containers/storage/pkg/directory" "github.com/containers/storage/pkg/idtools" "github.com/containers/storage/pkg/ioutils" + "github.com/containers/storage/pkg/mount" "github.com/containers/storage/pkg/parsers" "github.com/containers/storage/pkg/stringid" "github.com/containers/storage/pkg/stringutils" @@ -600,6 +601,14 @@ func GetStore(options StoreOptions) (Store, error) { } } + if onTmpfs, err := mount.IsOnVolatileStorage(options.RunRoot); err != nil || !onTmpfs { + if err != nil { + return nil, errors.Wrapf(err, "cannot check if %s is on tmpfs", options.RunRoot) + } else { + return nil, errors.Wrapf(ErrTargetNotVolatile, "%s must be on tmpfs", options.RunRoot) + } + } + graphLock, err := GetLockfile(filepath.Join(options.GraphRoot, "storage.lock")) if err != nil { return nil, err