From 9e6e627ec80b07c2ad9df6ffda7c4c99d79bd126 Mon Sep 17 00:00:00 2001 From: Jamie Strandboge Date: Wed, 9 Mar 2022 16:11:54 -0600 Subject: [PATCH] [disk][linux] add HOST_PROC_MOUNTINFO, closes #1271 The changes to gopsutil for reading /proc/1/mountinfo affected applications running under restricted environments that disallows access to /proc/1/mountinfo. #1159 was filed for android but other restricted environments are also affected (eg, snaps)). The fix for #1159 addressed the application behavior to work under confinement for non-android as well. However, depending on the system, the attempt to read /proc/1/mountinfo could cause a sandbox denial in the logs which can be quite noisy if using gopsutil as part of a monitoring solution that polls often. This introduces HOST_PROC_MOUNTINFO to force reading from the parent dir of the specified path instead of first trying /proc/1. When unset, retain the current behavior with fallback. This allows people, for example, to set HOST_PROC_MOUNTINFO=/proc/self/mountinfo when gopsutil is running under these restricted environments. This change updates the private readMountFile() to use a root path instead of a root subpath, and adjusts PartitionsWithContext() to set the root path to /proc/1 initially and falling back to /proc/self. When HOST_PROC_MOUNTINFO is not empty, set the root path to the parent directory of HOST_PROC_MOUNTINFO. --- README.md | 3 +++ disk/disk_linux.go | 25 +++++++++++++++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 191f3c7fb..b661c89d9 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,9 @@ environment variable. You can set an alternative location to `/dev` by setting the `HOST_DEV` environment variable. +You can set an alternative location to `/proc/N/mountinfo` by setting the +`HOST_PROC_MOUNTINFO` environment variable. + ## Documentation see http://godoc.org/github.com/shirou/gopsutil diff --git a/disk/disk_linux.go b/disk/disk_linux.go index 7accc8f3a..f087b86aa 100644 --- a/disk/disk_linux.go +++ b/disk/disk_linux.go @@ -235,9 +235,10 @@ var fsTypeMap = map[int64]string{ ZFS_SUPER_MAGIC: "zfs", /* 0x2FC12FC1 local */ } -// readMountFile reads mountinfo or mounts file under /proc/1 or /proc/self +// readMountFile reads mountinfo or mounts file under the specified root path +// (eg, /proc/1, /proc/self, etc) func readMountFile(root string) (lines []string, useMounts bool, filename string, err error) { - filename = common.HostProc(path.Join(root, "mountinfo")) + filename = path.Join(root, "mountinfo") lines, err = common.ReadLines(filename) if err != nil { var pathErr *os.PathError @@ -246,7 +247,7 @@ func readMountFile(root string) (lines []string, useMounts bool, filename string } // if kernel does not support 1/mountinfo, fallback to 1/mounts (<2.6.26) useMounts = true - filename = common.HostProc(path.Join(root, "mounts")) + filename = path.Join(root, "mounts") lines, err = common.ReadLines(filename) if err != nil { return @@ -257,10 +258,22 @@ func readMountFile(root string) (lines []string, useMounts bool, filename string } func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { - lines, useMounts, filename, err := readMountFile("1") + // by default, try "/proc/1/..." first + root := common.HostProc(path.Join("1")) + + // force preference for dirname of HOST_PROC_MOUNTINFO, if set #1271 + hpmPath := os.Getenv("HOST_PROC_MOUNTINFO") + if hpmPath != "" { + root = filepath.Dir(hpmPath) + } + + lines, useMounts, filename, err := readMountFile(root) if err != nil { - // fallback to "/proc/self/mountinfo" #1159 - lines, useMounts, filename, err = readMountFile("self") + if hpmPath != "" { // don't fallback with HOST_PROC_MOUNTINFO + return nil, err + } + // fallback to "/proc/self/..." #1159 + lines, useMounts, filename, err = readMountFile(common.HostProc(path.Join("self"))) if err != nil { return nil, err }