diff --git a/go.mod b/go.mod index 0cb39a63d..9785db74e 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/cyphar/filepath-securejoin v0.7.0 github.com/google/uuid v1.6.0 github.com/moby/sys/devices v0.1.1 - github.com/moby/sys/mountinfo v0.7.2 + github.com/moby/sys/mountinfo v0.7.3 github.com/moby/sys/reexec v0.1.0 github.com/moby/sys/symlink v0.3.0 github.com/opencontainers/cgroups v0.1.0 diff --git a/go.sum b/go.sum index 080fdf003..07ebf0dc0 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/knqyf263/go-plugin v0.9.0 h1:CQs2+lOPIlkZVtcb835ZYDEoyyWJWLbSTWeCs0Ew github.com/knqyf263/go-plugin v0.9.0/go.mod h1:2z5lCO1/pez6qGo8CvCxSlBFSEat4MEp1DrnA+f7w8Q= github.com/moby/sys/devices v0.1.1 h1:BhY4BsFgUKIGVMgke3/CMrOCxy2RXUrl7SJwKh3VVV8= github.com/moby/sys/devices v0.1.1/go.mod h1:nIV6AO7t0DY2ObAm1GfL4AX9mBRqzxzHwGfvNCR9lfI= -github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= -github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= +github.com/moby/sys/mountinfo v0.7.3 h1:e0lin8d05kLgtUES/4cS/F70KlbZX/G3aZjLsV7WAgA= +github.com/moby/sys/mountinfo v0.7.3/go.mod h1:dEJRr+H+hx0lNG0BE+Smz95u/FDzjJv4/RjA2I456Iw= github.com/moby/sys/reexec v0.1.0 h1:RrBi8e0EBTLEgfruBOFcxtElzRGTEUkeIFaVXgU7wok= github.com/moby/sys/reexec v0.1.0/go.mod h1:EqjBg8F3X7iZe5pU6nRZnYCMUTXoxsjiIfHup5wYIN8= github.com/moby/sys/symlink v0.3.0 h1:GZX89mEZ9u53f97npBy4Rc3vJKj7JBDj/PN2I22GrNU= diff --git a/vendor/github.com/moby/sys/mountinfo/mounted_unix.go b/vendor/github.com/moby/sys/mountinfo/mounted_unix.go index c7b7678f9..c2b266ed2 100644 --- a/vendor/github.com/moby/sys/mountinfo/mounted_unix.go +++ b/vendor/github.com/moby/sys/mountinfo/mounted_unix.go @@ -1,5 +1,4 @@ //go:build linux || freebsd || openbsd || darwin -// +build linux freebsd openbsd darwin package mountinfo diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go index 8420f58c7..d92ef22af 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_bsd.go @@ -1,5 +1,4 @@ //go:build freebsd || openbsd || darwin -// +build freebsd openbsd darwin package mountinfo diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go index 16079c3c5..037f47ba0 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_filters.go @@ -23,7 +23,7 @@ type FilterFunc func(*Info) (skip, stop bool) // "/foo" and "/foo/bar", and discards "/foobar". func PrefixFilter(prefix string) FilterFunc { return func(m *Info) (bool, bool) { - skip := !strings.HasPrefix(m.Mountpoint+"/", prefix+"/") + skip := prefix != "/" && !strings.HasPrefix(m.Mountpoint+"/", prefix+"/") return skip, false } } @@ -40,12 +40,16 @@ func SingleEntryFilter(mp string) FilterFunc { // ParentsFilter returns all entries whose mount points // can be parents of a path specified, discarding others. +// The path must be absolute, have all symlinks resolved, +// and cleaned (i.e. no extra slashes or dots). // // For example, given /var/lib/docker/something, entries -// like /var/lib/docker, /var and / are returned. +// like /var/lib/docker, /var and / are returned, while +// /var/lib/dock is discarded. func ParentsFilter(path string) FilterFunc { return func(m *Info) (bool, bool) { - skip := !strings.HasPrefix(path, m.Mountpoint) + mp := m.Mountpoint + skip := mp != "/" && mp != path && !strings.HasPrefix(path, mp+"/") return skip, false } } diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_freebsdlike.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_freebsdlike.go index ecaaa7a9c..0bc7b98c5 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo_freebsdlike.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_freebsdlike.go @@ -1,5 +1,4 @@ //go:build freebsd || darwin -// +build freebsd darwin package mountinfo diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go index b32b5c9b1..54674b755 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_linux.go @@ -24,8 +24,6 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) { s := bufio.NewScanner(r) out := []*Info{} for s.Scan() { - var err error - /* See http://man7.org/linux/man-pages/man5/proc.5.html @@ -75,42 +73,25 @@ func GetMountsFromReader(r io.Reader, filter FilterFunc) ([]*Info, error) { } } - p := &Info{} - - p.Mountpoint, err = unescape(fields[4]) - if err != nil { - return nil, fmt.Errorf("parsing '%s' failed: mount point: %w", fields[4], err) - } - p.FSType, err = unescape(fields[sepIdx+1]) - if err != nil { - return nil, fmt.Errorf("parsing '%s' failed: fstype: %w", fields[sepIdx+1], err) - } - p.Source, err = unescape(fields[sepIdx+2]) - if err != nil { - return nil, fmt.Errorf("parsing '%s' failed: source: %w", fields[sepIdx+2], err) + major, minor, ok := strings.Cut(fields[2], ":") + if !ok { + return nil, fmt.Errorf("parsing '%s' failed: unexpected major:minor pair %s", text, fields[2]) } - p.VFSOptions = fields[sepIdx+3] - - // ignore any numbers parsing errors, as there should not be any - p.ID, _ = strconv.Atoi(fields[0]) - p.Parent, _ = strconv.Atoi(fields[1]) - mm := strings.SplitN(fields[2], ":", 3) - if len(mm) != 2 { - return nil, fmt.Errorf("parsing '%s' failed: unexpected major:minor pair %s", text, mm) - } - p.Major, _ = strconv.Atoi(mm[0]) - p.Minor, _ = strconv.Atoi(mm[1]) - p.Root, err = unescape(fields[3]) - if err != nil { - return nil, fmt.Errorf("parsing '%s' failed: root: %w", fields[3], err) + p := &Info{ + ID: toInt(fields[0]), + Parent: toInt(fields[1]), + Major: toInt(major), + Minor: toInt(minor), + Root: unescape(fields[3]), + Mountpoint: unescape(fields[4]), + Options: fields[5], + Optional: strings.Join(fields[6:sepIdx], " "), // zero or more optional fields + FSType: unescape(fields[sepIdx+1]), + Source: unescape(fields[sepIdx+2]), + VFSOptions: fields[sepIdx+3], } - p.Options = fields[5] - - // zero or more optional fields - p.Optional = strings.Join(fields[6:sepIdx], " ") - // Run the filter after parsing all fields. var skip, stop bool if filter != nil { @@ -191,60 +172,56 @@ func PidMountInfo(pid int) ([]*Info, error) { return GetMountsFromReader(f, nil) } -// A few specific characters in mountinfo path entries (root and mountpoint) -// are escaped using a backslash followed by a character's ascii code in octal. +// Some characters in some mountinfo fields may be escaped using a backslash +// followed by a three octal digits of the character's ASCII code \NNN, where +// N is 0-7, for example: // // space -- as \040 // tab (aka \t) -- as \011 // newline (aka \n) -- as \012 // backslash (aka \\) -- as \134 +// hash (aka #) -- as \043 // -// This function converts path from mountinfo back, i.e. it unescapes the above sequences. -func unescape(path string) (string, error) { - // try to avoid copying +// This function converts all such escape sequences back to ASCII, and returns +// the unescaped string. +func unescape(path string) string { + // Try to avoid copying. if strings.IndexByte(path, '\\') == -1 { - return path, nil + return path } // The following code is UTF-8 transparent as it only looks for some - // specific characters (backslash and 0..7) with values < utf8.RuneSelf, - // and everything else is passed through as is. + // specific characters (backslash and 0..7) with values less than + // utf8.RuneSelf, and everything else is passed through as is. buf := make([]byte, len(path)) bufLen := 0 for i := 0; i < len(path); i++ { - if path[i] != '\\' { - buf[bufLen] = path[i] - bufLen++ - continue - } - s := path[i:] - if len(s) < 4 { - // too short - return "", fmt.Errorf("bad escape sequence %q: too short", s) - } - c := s[1] - switch c { - case '0', '1', '2', '3', '4', '5', '6', '7': - v := c - '0' - for j := 2; j < 4; j++ { // one digit already; two more - if s[j] < '0' || s[j] > '7' { - return "", fmt.Errorf("bad escape sequence %q: not a digit", s[:3]) - } - x := s[j] - '0' - v = (v << 3) | x - } - if v > 255 { - return "", fmt.Errorf("bad escape sequence %q: out of range" + s[:3]) - } - buf[bufLen] = v - bufLen++ + c := path[i] + // Look for \NNN, i.e. a backslash followed by three octal + // digits. Maximum value is 177 (equals utf8.RuneSelf-1). + if c == '\\' && i+3 < len(path) && + (path[i+1] == '0' || path[i+1] == '1') && + (path[i+2] >= '0' && path[i+2] <= '7') && + (path[i+3] >= '0' && path[i+3] <= '7') { + // Convert from ASCII to numeric values. + c1 := path[i+1] - '0' + c2 := path[i+2] - '0' + c3 := path[i+3] - '0' + // Each octal digit is three bits, thus the shift value. + c = c1<<6 | c2<<3 | c3 + // We read three extra bytes of input. i += 3 - continue - default: - return "", fmt.Errorf("bad escape sequence %q: not a digit" + s[:3]) - } + buf[bufLen] = c + bufLen++ } - return string(buf[:bufLen]), nil + return string(buf[:bufLen]) +} + +// toInt converts a string to an int, and ignores any numbers parsing errors, +// as there should not be any. +func toInt(s string) int { + i, _ := strconv.Atoi(s) + return i } diff --git a/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go b/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go index c2e64bc81..b4e692b72 100644 --- a/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go +++ b/vendor/github.com/moby/sys/mountinfo/mountinfo_unsupported.go @@ -1,5 +1,4 @@ //go:build !windows && !linux && !freebsd && !openbsd && !darwin -// +build !windows,!linux,!freebsd,!openbsd,!darwin package mountinfo diff --git a/vendor/modules.txt b/vendor/modules.txt index 1fe826b1e..2d3fc5d9c 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -64,8 +64,8 @@ github.com/knqyf263/go-plugin/wasm # github.com/moby/sys/devices v0.1.1 ## explicit; go 1.24 github.com/moby/sys/devices -# github.com/moby/sys/mountinfo v0.7.2 -## explicit; go 1.17 +# github.com/moby/sys/mountinfo v0.7.3 +## explicit; go 1.18 github.com/moby/sys/mountinfo # github.com/moby/sys/reexec v0.1.0 ## explicit; go 1.18