diff --git a/go.mod b/go.mod index 19e7f606c3..65ae93554f 100644 --- a/go.mod +++ b/go.mod @@ -56,7 +56,7 @@ require ( github.com/opencontainers/selinux v1.14.1 github.com/openshift/imagebuilder v1.2.21 github.com/rootless-containers/rootlesskit/v2 v2.3.6 - github.com/shirou/gopsutil/v4 v4.26.4 + github.com/shirou/gopsutil/v4 v4.26.5 github.com/sirupsen/logrus v1.9.4 github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.10 diff --git a/go.sum b/go.sum index e20a276a16..96dddd902e 100644 --- a/go.sum +++ b/go.sum @@ -333,8 +333,8 @@ github.com/secure-systems-lab/go-securesystemslib v0.11.0 h1:iuCR9kcMFD4QurdKrGv github.com/secure-systems-lab/go-securesystemslib v0.11.0/go.mod h1:+PMOTjUGwHj2vcZ+TFKlb1tXRbrdWE1LYDT5i9JC80Q= github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/shirou/gopsutil/v4 v4.26.4 h1:B4SXVbcwTyrocPHEmWBC4uCYr4Xcu3MK1TXqbprAOWY= -github.com/shirou/gopsutil/v4 v4.26.4/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= +github.com/shirou/gopsutil/v4 v4.26.5 h1:RPcBXkpz7kOj9PqGFQOlBPZHsyaPvPVQc098y9RmCNM= +github.com/shirou/gopsutil/v4 v4.26.5/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= github.com/sigstore/fulcio v1.8.5 h1:HYTD1/L5wlBp8JxsWxUf8hmfaNBBF/x3r3p5l6tZwbA= github.com/sigstore/fulcio v1.8.5/go.mod h1:tSLYK3JsKvJpDW1BsIsVHZgHj+f8TjXARzqIUWSsSPQ= github.com/sigstore/protobuf-specs v0.5.0 h1:F8YTI65xOHw70NrvPwJ5PhAzsvTnuJMGLkA4FIkofAY= diff --git a/vendor/github.com/shirou/gopsutil/v4/net/net.go b/vendor/github.com/shirou/gopsutil/v4/net/net.go index 1d1f9f08b0..384e5673a0 100644 --- a/vendor/github.com/shirou/gopsutil/v4/net/net.go +++ b/vendor/github.com/shirou/gopsutil/v4/net/net.go @@ -286,12 +286,25 @@ func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { return IOCountersByFileWithContext(context.Background(), pernic, filename) } -// ProtoCounters returns network statistics for the entire system +// ProtoCounters returns network statistics for the entire system. // If protocols is empty then all protocols are returned, otherwise // just the protocols in the list are returned. +// // Available protocols: // [ip,icmp,icmpmsg,tcp,udp,udplite] -// Not Implemented for FreeBSD, Windows, OpenBSD, Darwin +// +// Key naming contract: +// The keys of the returned Stats map use MIB-II (RFC 1213) identifier +// names — e.g. "InSegs", "OutSegs", "RetransSegs", "ActiveOpens", +// "InDatagrams", "NoPorts". This contract was established by the +// original Linux implementation, which sources its keys from +// /proc/net/snmp (whose headers are MIB-II names). Per-platform +// implementations are expected to map their native counter sources +// (e.g. AIX `netstat -s`, BSD sysctl) to these MIB-II names. +// Native counters that have no MIB-II equivalent are not exposed +// through this API. +// +// Not Implemented for FreeBSD, Windows, OpenBSD, Darwin, Solaris. func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { return ProtoCountersWithContext(context.Background(), protocols) } diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go b/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go index 35c34adb3d..6e1d0ce373 100644 --- a/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go +++ b/vendor/github.com/shirou/gopsutil/v4/process/process_darwin.go @@ -375,29 +375,49 @@ func (p *Process) cmdlineSlice() ([]string, error) { if err != nil { return nil, err } - // The first bytes hold the nargs int, skip it. - args := bytes.Split((pargs)[unsafe.Sizeof(int(0)):], []byte{0}) - var argStr string - // The first element is the actual binary/command path. - // command := args[0] - var argSlice []string - // var envSlice []string - // All other, non-zero elements are arguments. The first "nargs" elements - // are the arguments. Everything else in the slice is then the environment - // of the process. - for _, arg := range args[1:] { - argStr = string(arg) - if argStr != "" { - if nargs > 0 { - argSlice = append(argSlice, argStr) - nargs-- - continue - } - break - // envSlice = append(envSlice, argStr) - } - } - return argSlice, err + // procArgs reads nargs as a 4-byte uint32; skip exactly those 4 bytes + // (matches Apple's ps using sizeof(nargs)). The previous code used + // unsafe.Sizeof(int(0)) which is 8 on 64-bit and would discard the + // first 4 bytes of exec_path — harmless only because chunks[0] is + // dropped, but logically wrong. + return parseCmdline(pargs[4:], nargs), nil +} + +// parseCmdline extracts argv from the kern.procargs2 buffer with the leading +// nargs int already stripped. Layout: +// +// exec_path \0 [padding \0...] argv[0] \0 ... argv[nargs-1] \0 envp[0] \0 ... +// +// Empty argv elements within the nargs count are preserved — skipping them +// would advance past argv[nargs-1] into envp, leaking environment values +// (potentially secrets) into Cmdline output. +// +// Known limitation: a process whose argv[0] is itself an empty string is +// indistinguishable from padding by this parser, since XNU does not expose +// the exec/argv alignment boundary. Such a process will still see one envp +// entry leak. Fixing it requires libgetargv-style alignment math against +// the XNU exec layout, which is out of scope for this change. +func parseCmdline(args []byte, nargs int) []string { + chunks := bytes.Split(args, []byte{0}) + if len(chunks) <= 1 { + return nil + } + // Skip exec_path (chunks[0]) and any padding NULs before argv[0]. + i := 1 + for ; i < len(chunks) && len(chunks[i]) == 0; i++ { + } + if nargs > len(chunks)-i { + nargs = len(chunks) - i + } + if nargs < 0 { + nargs = 0 + } + argSlice := make([]string, 0, nargs) + for ; nargs > 0; nargs-- { + argSlice = append(argSlice, string(chunks[i])) + i++ + } + return argSlice } // cmdNameWithContext returns the command name (including spaces) without any arguments diff --git a/vendor/github.com/shirou/gopsutil/v4/process/process_windows.go b/vendor/github.com/shirou/gopsutil/v4/process/process_windows.go index a1e28be698..19020e1ff9 100644 --- a/vendor/github.com/shirou/gopsutil/v4/process/process_windows.go +++ b/vendor/github.com/shirou/gopsutil/v4/process/process_windows.go @@ -324,6 +324,9 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) { if p.Pid == 0 { return "System Idle Process", nil } + if p.name != "" { + return p.name, nil + } if p.Pid == 4 { return "System", nil } @@ -333,7 +336,9 @@ func (p *Process) NameWithContext(ctx context.Context) (string, error) { return "", fmt.Errorf("could not get Name: %w", err) } - return filepath.Base(exe), nil + name := filepath.Base(exe) + p.name = name + return name, nil } func (*Process) TgidWithContext(_ context.Context) (int32, error) { @@ -598,6 +603,8 @@ func (p *Process) NumThreadsWithContext(_ context.Context) (int32, error) { p.setPpid(ppid) } + p.numThreads = ret + return ret, nil } @@ -900,6 +907,32 @@ func getFromSnapProcess(pid int32) (int32, int32, string, error) { //nolint:unpa return 0, 0, "", fmt.Errorf("couldn't find pid: %d", pid) } +func buildSnapProcessMap() (map[uint32]windows.ProcessEntry32, error) { + snap, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0) + if err != nil { + return nil, err + } + defer windows.CloseHandle(snap) + + var pe32 windows.ProcessEntry32 + pe32.Size = uint32(unsafe.Sizeof(pe32)) + if err := windows.Process32First(snap, &pe32); err != nil { + return nil, err + } + + snapMap := make(map[uint32]windows.ProcessEntry32) + for { + snapMap[pe32.ProcessID] = pe32 + if err := windows.Process32Next(snap, &pe32); err != nil { + if errors.Is(err, windows.ERROR_NO_MORE_FILES) { + break + } + return nil, err + } + } + return snapMap, nil +} + func ProcessesWithContext(ctx context.Context) ([]*Process, error) { out := []*Process{} @@ -908,11 +941,25 @@ func ProcessesWithContext(ctx context.Context) ([]*Process, error) { return out, fmt.Errorf("could not get Processes %w", err) } + // Note: The PID enumeration and snapshot creation are separate calls + // and may not be perfectly consistent due to timing. + snapMap, err := buildSnapProcessMap() + if err != nil { + return out, fmt.Errorf("could not build process snapshot: %w", err) + } + for _, pid := range pids { p, err := NewProcessWithContext(ctx, pid) if err != nil { continue } + + if entry, ok := snapMap[uint32(pid)]; ok { + p.name = windows.UTF16ToString(entry.ExeFile[:]) + p.setPpid(int32(entry.ParentProcessID)) + p.numThreads = int32(entry.Threads) + } + out = append(out, p) } diff --git a/vendor/modules.txt b/vendor/modules.txt index 2e21ee50a4..439f5c9b9b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -567,7 +567,7 @@ github.com/seccomp/libseccomp-golang # github.com/secure-systems-lab/go-securesystemslib v0.11.0 ## explicit; go 1.25.0 github.com/secure-systems-lab/go-securesystemslib/encrypted -# github.com/shirou/gopsutil/v4 v4.26.4 +# github.com/shirou/gopsutil/v4 v4.26.5 ## explicit; go 1.24.0 github.com/shirou/gopsutil/v4/common github.com/shirou/gopsutil/v4/cpu