go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/processes/linuxproc.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package processes 5 6 import ( 7 "path/filepath" 8 "strconv" 9 10 "github.com/cockroachdb/errors" 11 "github.com/rs/zerolog/log" 12 "github.com/spf13/afero" 13 "go.mondoo.com/cnquery/providers/os/connection/shared" 14 "go.mondoo.com/cnquery/providers/os/resources/procfs" 15 ) 16 17 type LinuxProcManager struct { 18 conn shared.Connection 19 } 20 21 func (lpm *LinuxProcManager) Name() string { 22 return "Linux Process Manager" 23 } 24 25 func (lpm *LinuxProcManager) List() ([]*OSProcess, error) { 26 // get all subdirectories of /proc, filter by numbers 27 f, err := lpm.conn.FileSystem().Open("/proc") 28 if err != nil { 29 return nil, errors.WithMessage(err, "failed to access /proc") 30 } 31 32 dirs, err := f.Readdirnames(-1) 33 if err != nil { 34 return nil, err 35 } 36 37 res := []*OSProcess{} 38 for i := range dirs { 39 // we only parse directories that are numbers 40 pid, err := strconv.ParseInt(dirs[i], 10, 64) 41 if err != nil { 42 continue 43 } 44 45 // collect process info 46 proc, err := lpm.Process(pid) 47 if err != nil { 48 log.Warn().Err(err).Int64("pid", pid).Msg("mql[processes]> could not retrieve process information") 49 continue 50 } 51 52 res = append(res, proc) 53 } 54 return res, nil 55 } 56 57 // check that the pid directory exists 58 func (lpm *LinuxProcManager) Exists(pid int64) (bool, error) { 59 pidPath := filepath.Join("/proc", strconv.FormatInt(pid, 10)) 60 afutil := afero.Afero{Fs: lpm.conn.FileSystem()} 61 return afutil.Exists(pidPath) 62 } 63 64 func (lpm *LinuxProcManager) Process(pid int64) (*OSProcess, error) { 65 pidPath := filepath.Join("/proc", strconv.FormatInt(pid, 10)) 66 67 exists, err := lpm.Exists(pid) 68 if err != nil { 69 return nil, err 70 } 71 if !exists { 72 return nil, errors.New("process " + strconv.FormatInt(pid, 10) + " does not exist: " + pidPath) 73 } 74 75 // parse the cmdline 76 cmdlinef, err := lpm.conn.FileSystem().Open(filepath.Join(pidPath, "cmdline")) 77 if err != nil { 78 return nil, err 79 } 80 defer cmdlinef.Close() 81 82 cmdline, err := procfs.ParseProcessCmdline(cmdlinef) 83 if err != nil { 84 return nil, err 85 } 86 87 statusf, err := lpm.conn.FileSystem().Open(filepath.Join(pidPath, "status")) 88 if err != nil { 89 return nil, err 90 } 91 defer statusf.Close() 92 93 status, err := procfs.ParseProcessStatus(statusf) 94 if err != nil { 95 return nil, err 96 } 97 98 socketInodes, socketInodesErr := lpm.procSocketInods(pid, pidPath) 99 100 process := &OSProcess{ 101 Pid: pid, 102 Executable: status.Executable, 103 State: status.State, 104 Command: cmdline, 105 SocketInodes: socketInodes, 106 SocketInodesError: socketInodesErr, 107 } 108 109 return process, nil 110 }