diff --git a/pkg/proctree/datasource.go b/pkg/proctree/datasource.go index d708803dd699..c42a43319998 100644 --- a/pkg/proctree/datasource.go +++ b/pkg/proctree/datasource.go @@ -103,7 +103,7 @@ func (ptds *DataSource) exportProcessInfo( } childInfo := child.GetInfo() if childInfo.IsAliveAt(queryTime) { - aliveChildren[childInfo.GetPid()] = childHash + aliveChildren[int(childInfo.GetPid())] = childHash // TODO: change types pkg to reduce mem footprint } } @@ -116,7 +116,7 @@ func (ptds *DataSource) exportProcessInfo( } threadInfo := thread.GetInfo() if threadInfo.IsAliveAt(queryTime) { - aliveThreads[threadInfo.GetTid()] = threadHash + aliveThreads[int(threadInfo.GetTid())] = threadHash // TODO: change types pkg to reduce mem footprint } } @@ -126,10 +126,11 @@ func (ptds *DataSource) exportProcessInfo( // Export the information as the expected datasource process structure. return datasource.TimeRelevantInfo[datasource.ProcessInfo]{ Info: datasource.ProcessInfo{ - EntityId: process.GetHash(), - Pid: infoFeed.Pid, - NsPid: infoFeed.NsPid, - Ppid: infoFeed.PPid, + EntityId: process.GetHash(), + // TODO: change types pkg to reduce mem footprint (Pid, NsPid, Ppid, ThreadsIds, ChildProcessesIds) + Pid: int(infoFeed.Pid), + NsPid: int(infoFeed.NsPid), + Ppid: int(infoFeed.PPid), ContainerId: "", // TODO: Add Cmd: []string{}, // TODO: Add ExecutionBinary: exportFileInfo(executable, queryTime), @@ -156,12 +157,13 @@ func (ptds *DataSource) exportThreadInfo( // Export the information as the expected datasource thread structure. return datasource.TimeRelevantInfo[datasource.ThreadInfo]{ Info: datasource.ThreadInfo{ - EntityId: thread.GetHash(), - Tid: infoFeed.Tid, - NsTid: infoFeed.NsTid, - Pid: infoFeed.Pid, - UserId: infoFeed.Uid, - GroupId: infoFeed.Gid, + EntityId: thread.GetHash(), + // TODO: change types pkg to reduce mem footprint (Tid, NsTid, Pid, UserId, GroupId) + Tid: int(infoFeed.Tid), + NsTid: int(infoFeed.NsTid), + Pid: int(infoFeed.Pid), + UserId: int(infoFeed.Uid), + GroupId: int(infoFeed.Gid), StartTime: info.GetStartTime(), ExitTime: info.GetExitTime(), Name: infoFeed.Name, @@ -217,11 +219,12 @@ func exportFileInfo(fileInfo *FileInfo, queryTime time.Time) datasource.FileInfo // Export the information as the expected datasource file structure. return datasource.FileInfo{ - Path: fileInfoFeed.Path, - Hash: "", // TODO: Add - Inode: fileInfoFeed.Inode, - Device: fileInfoFeed.Dev, + Path: fileInfoFeed.Path, + Hash: "", // TODO: Add + // TODO: change types pkg to reduce mem footprint (Inode, Device, Mode) + Inode: int(fileInfoFeed.Inode), + Device: int(fileInfoFeed.Dev), Ctime: time.Unix(0, int64(fileInfoFeed.Ctime)), - Mode: fileInfoFeed.InodeMode, + Mode: int(fileInfoFeed.InodeMode), } } diff --git a/pkg/proctree/fileinfo.go b/pkg/proctree/fileinfo.go index 5a2c6a0bd6bd..c2250b1dfcc2 100644 --- a/pkg/proctree/fileinfo.go +++ b/pkg/proctree/fileinfo.go @@ -1,6 +1,7 @@ package proctree import ( + "math" "strings" "sync" "time" @@ -12,10 +13,10 @@ import ( type FileInfoFeed struct { // Name string Path string // mutable (file path) - Dev int // mutable (device number) - Ctime int // mutable (creation time) - Inode int // mutable (inode number) - InodeMode int // mutable (inode mode) + Dev uint32 // mutable (device number) + Ctime uint64 // mutable (creation time) + Inode uint64 // mutable (inode number) + InodeMode uint16 // mutable (inode mode) } // @@ -88,16 +89,16 @@ func (fi *FileInfo) setFeedAt(feed *FileInfoFeed, targetTime time.Time) { } atFeed.Path = filePath } - if feed.Dev >= 0 { + if feed.Dev != math.MaxUint32 { atFeed.Dev = feed.Dev } - if feed.Ctime >= 0 { + if feed.Ctime != math.MaxUint64 { atFeed.Ctime = feed.Ctime } - if feed.Inode >= 0 { + if feed.Inode != math.MaxUint64 { atFeed.Inode = feed.Inode } - if feed.InodeMode >= 0 { + if feed.InodeMode != math.MaxUint16 { atFeed.InodeMode = feed.InodeMode } @@ -145,7 +146,7 @@ func (fi *FileInfo) GetPathAt(targetTime time.Time) string { } // GetDev returns the device number of the file. -func (fi *FileInfo) GetDev() int { +func (fi *FileInfo) GetDev() uint32 { fi.mutex.RLock() defer fi.mutex.RUnlock() @@ -153,7 +154,7 @@ func (fi *FileInfo) GetDev() int { } // GetDevAt returns the device number of the file at the given time. -func (fi *FileInfo) GetDevAt(targetTime time.Time) int { +func (fi *FileInfo) GetDevAt(targetTime time.Time) uint32 { fi.mutex.RLock() defer fi.mutex.RUnlock() @@ -161,7 +162,7 @@ func (fi *FileInfo) GetDevAt(targetTime time.Time) int { } // GetCtime returns the creation time of the file. -func (fi *FileInfo) GetCtime() int { +func (fi *FileInfo) GetCtime() uint64 { fi.mutex.RLock() defer fi.mutex.RUnlock() @@ -169,7 +170,7 @@ func (fi *FileInfo) GetCtime() int { } // GetCtimeAt returns the creation time of the file at the given time. -func (fi *FileInfo) GetCtimeAt(targetTime time.Time) int { +func (fi *FileInfo) GetCtimeAt(targetTime time.Time) uint64 { fi.mutex.RLock() defer fi.mutex.RUnlock() @@ -177,7 +178,7 @@ func (fi *FileInfo) GetCtimeAt(targetTime time.Time) int { } // GetInode returns the inode number of the file. -func (fi *FileInfo) GetInode() int { +func (fi *FileInfo) GetInode() uint64 { fi.mutex.RLock() defer fi.mutex.RUnlock() @@ -185,7 +186,7 @@ func (fi *FileInfo) GetInode() int { } // GetInodeAt returns the inode number of the file at the given time. -func (fi *FileInfo) GetInodeAt(targetTime time.Time) int { +func (fi *FileInfo) GetInodeAt(targetTime time.Time) uint64 { fi.mutex.RLock() defer fi.mutex.RUnlock() @@ -193,7 +194,7 @@ func (fi *FileInfo) GetInodeAt(targetTime time.Time) int { } // GetInodeMode returns the inode mode of the file. -func (fi *FileInfo) GetInodeMode() int { +func (fi *FileInfo) GetInodeMode() uint16 { fi.mutex.RLock() defer fi.mutex.RUnlock() @@ -201,7 +202,7 @@ func (fi *FileInfo) GetInodeMode() int { } // GetInodeModeAt returns the inode mode of the file at the given time. -func (fi *FileInfo) GetInodeModeAt(targetTime time.Time) int { +func (fi *FileInfo) GetInodeModeAt(targetTime time.Time) uint16 { fi.mutex.RLock() defer fi.mutex.RUnlock() diff --git a/pkg/proctree/proctree.go b/pkg/proctree/proctree.go index 9ed389c10344..1c46973bf7b0 100644 --- a/pkg/proctree/proctree.go +++ b/pkg/proctree/proctree.go @@ -74,7 +74,7 @@ type ProcTreeConfig struct { type ProcessTree struct { processes *lru.Cache[uint32, *Process] // hash -> process threads *lru.Cache[uint32, *Thread] // hash -> threads - procfsChan chan int // channel of pids to read from procfs + procfsChan chan int32 // channel of pids to read from procfs procfsOnce *sync.Once // busy loop debug message throttling ctx context.Context // context for the process tree procfsQuery bool diff --git a/pkg/proctree/proctree_feed.go b/pkg/proctree/proctree_feed.go index 603e675c688a..300009f8fe94 100644 --- a/pkg/proctree/proctree_feed.go +++ b/pkg/proctree/proctree_feed.go @@ -1,6 +1,7 @@ package proctree import ( + "math" "path/filepath" "time" @@ -44,15 +45,15 @@ func (pt *ProcessTree) setParentFeed( taskInfoFeed := pt.GetTaskInfoFeedFromPool() taskInfoFeed.Name = "" // do not change the parent name - taskInfoFeed.Tid = int(forkFeed.ParentTid) - taskInfoFeed.Pid = int(forkFeed.ParentPid) - taskInfoFeed.NsTid = int(forkFeed.ParentNsTid) - taskInfoFeed.NsPid = int(forkFeed.ParentNsPid) + taskInfoFeed.Tid = forkFeed.ParentTid + taskInfoFeed.Pid = forkFeed.ParentPid + taskInfoFeed.NsTid = forkFeed.ParentNsTid + taskInfoFeed.NsPid = forkFeed.ParentNsPid taskInfoFeed.StartTimeNS = forkFeed.ParentStartTime - taskInfoFeed.PPid = -1 // do not change the parent ppid - taskInfoFeed.NsPPid = -1 // do not change the parent nsppid - taskInfoFeed.Uid = -1 // do not change the parent uid - taskInfoFeed.Gid = -1 // do not change the parent gid + taskInfoFeed.PPid = -1 // do not change the parent ppid + taskInfoFeed.NsPPid = -1 // do not change the parent nsppid + taskInfoFeed.Uid = math.MaxUint32 // do not change the parent uid + taskInfoFeed.Gid = math.MaxUint32 // do not change the parent gid taskInfoFeed.ExitTimeNS = 0 parent.GetInfo().SetFeedAt(taskInfoFeed, feedTimeStamp) @@ -61,7 +62,7 @@ func (pt *ProcessTree) setParentFeed( pt.PutTaskInfoFeedInPool(taskInfoFeed) if pt.procfsQuery { - pt.FeedFromProcFSAsync(int(forkFeed.ParentPid)) // try to enrich ppid and name from procfs + pt.FeedFromProcFSAsync(forkFeed.ParentPid) // try to enrich ppid and name from procfs } } @@ -74,15 +75,15 @@ func (pt *ProcessTree) setLeaderFeed( taskInfoFeed := pt.GetTaskInfoFeedFromPool() taskInfoFeed.Name = parent.GetInfo().GetName() - taskInfoFeed.Tid = int(forkFeed.LeaderTid) - taskInfoFeed.Pid = int(forkFeed.LeaderPid) - taskInfoFeed.NsTid = int(forkFeed.LeaderNsTid) - taskInfoFeed.NsPid = int(forkFeed.LeaderNsPid) + taskInfoFeed.Tid = forkFeed.LeaderTid + taskInfoFeed.Pid = forkFeed.LeaderPid + taskInfoFeed.NsTid = forkFeed.LeaderNsTid + taskInfoFeed.NsPid = forkFeed.LeaderNsPid taskInfoFeed.StartTimeNS = forkFeed.LeaderStartTime - taskInfoFeed.PPid = int(forkFeed.ParentPid) - taskInfoFeed.NsPPid = int(forkFeed.ParentNsPid) - taskInfoFeed.Uid = -1 // do not change the leader uid - taskInfoFeed.Gid = -1 // do not change the leader gid + taskInfoFeed.PPid = forkFeed.ParentPid + taskInfoFeed.NsPPid = forkFeed.ParentNsPid + taskInfoFeed.Uid = math.MaxUint32 // do not change the leader uid + taskInfoFeed.Gid = math.MaxUint32 // do not change the leader gid taskInfoFeed.ExitTimeNS = 0 leader.GetInfo().SetFeedAt(taskInfoFeed, feedTimeStamp) @@ -91,7 +92,7 @@ func (pt *ProcessTree) setLeaderFeed( pt.PutTaskInfoFeedInPool(taskInfoFeed) if pt.procfsQuery { - pt.FeedFromProcFSAsync(int(forkFeed.LeaderPid)) // try to enrich name from procfs if needed + pt.FeedFromProcFSAsync(forkFeed.LeaderPid) // try to enrich name from procfs if needed } } @@ -105,15 +106,15 @@ func (pt *ProcessTree) setThreadFeed( taskInfoFeed := pt.GetTaskInfoFeedFromPool() taskInfoFeed.Name = leader.GetInfo().GetName() - taskInfoFeed.Tid = int(forkFeed.ChildTid) - taskInfoFeed.Pid = int(forkFeed.ChildPid) - taskInfoFeed.NsTid = int(forkFeed.ChildNsTid) - taskInfoFeed.NsPid = int(forkFeed.ChildNsPid) + taskInfoFeed.Tid = forkFeed.ChildTid + taskInfoFeed.Pid = forkFeed.ChildPid + taskInfoFeed.NsTid = forkFeed.ChildNsTid + taskInfoFeed.NsPid = forkFeed.ChildNsPid taskInfoFeed.StartTimeNS = forkFeed.ChildStartTime - taskInfoFeed.PPid = int(forkFeed.ParentPid) - taskInfoFeed.NsPPid = int(forkFeed.ParentNsPid) - taskInfoFeed.Uid = -1 // do not change the thread uid - taskInfoFeed.Gid = -1 // do not change the thread gid + taskInfoFeed.PPid = forkFeed.ParentPid + taskInfoFeed.NsPPid = forkFeed.ParentNsPid + taskInfoFeed.Uid = math.MaxUint32 // do not change the thread uid + taskInfoFeed.Gid = math.MaxUint32 // do not change the thread gid taskInfoFeed.ExitTimeNS = 0 thread.GetInfo().SetFeedAt(taskInfoFeed, feedTimeStamp) @@ -148,7 +149,7 @@ func (pt *ProcessTree) FeedFromFork(feed *ForkFeed) error { // might have been created by execve() events, and those need to be updated (they're missing // ppid, for example). - if !found || parent.GetInfo().GetPid() != int(feed.ParentPid) { + if !found || parent.GetInfo().GetPid() != feed.ParentPid { pt.setParentFeed(parent, feed, feedTimeStamp) } @@ -163,7 +164,7 @@ func (pt *ProcessTree) FeedFromFork(feed *ForkFeed) error { // Same case here (for events out of order created by execve first) - if !found || leader.GetInfo().GetPPid() != int(feed.ParentPid) { + if !found || leader.GetInfo().GetPPid() != feed.ParentPid { pt.setLeaderFeed(leader, parent, feed, feedTimeStamp) } @@ -189,7 +190,7 @@ func (pt *ProcessTree) FeedFromFork(feed *ForkFeed) error { // Same case here (for events out of order created by execve first) - if !found || thread.GetInfo().GetPPid() != int(feed.ParentPid) { + if !found || thread.GetInfo().GetPPid() != feed.ParentPid { pt.setThreadFeed(thread, leader, feed, feedTimeStamp) } @@ -263,10 +264,10 @@ func (pt *ProcessTree) FeedFromExec(feed *ExecFeed) error { fileInfoFeed := pt.GetFileInfoFeedFromPool() fileInfoFeed.Path = feed.PathName - fileInfoFeed.Dev = int(feed.Dev) - fileInfoFeed.Ctime = int(feed.Ctime) - fileInfoFeed.Inode = int(feed.Inode) - fileInfoFeed.InodeMode = int(feed.InodeMode) + fileInfoFeed.Dev = feed.Dev + fileInfoFeed.Ctime = feed.Ctime + fileInfoFeed.Inode = feed.Inode + fileInfoFeed.InodeMode = feed.InodeMode process.GetExecutable().SetFeedAt(fileInfoFeed, execTimestamp) diff --git a/pkg/proctree/proctree_output.go b/pkg/proctree/proctree_output.go index 2e3476084abb..70f32c2d7618 100644 --- a/pkg/proctree/proctree_output.go +++ b/pkg/proctree/proctree_output.go @@ -124,9 +124,9 @@ func (pt *ProcessTree) String() string { } hashStr := fmt.Sprintf("%v", process.GetHash()) startTime := fmt.Sprintf("%v", process.GetInfo().GetStartTimeNS()) - tid := stringify(processFeed.Tid) - pid := stringify(processFeed.Pid) - ppid := stringify(processFeed.PPid) + tid := stringify(int(processFeed.Tid)) + pid := stringify(int(processFeed.Pid)) + ppid := stringify(int(processFeed.PPid)) date := process.GetInfo().GetStartTime().Format("2006-01-02 15:04:05") // add the row to the table diff --git a/pkg/proctree/proctree_procfs.go b/pkg/proctree/proctree_procfs.go index 814c7b346194..9f1f4dffb46c 100644 --- a/pkg/proctree/proctree_procfs.go +++ b/pkg/proctree/proctree_procfs.go @@ -2,8 +2,8 @@ package proctree import ( "fmt" + "math" "os" - "strconv" "sync" "time" @@ -40,10 +40,10 @@ func (pt *ProcessTree) feedFromProcFSLoop() { } // FeedFromProcFSAsync feeds the process tree with data from procfs asynchronously. -func (pt *ProcessTree) FeedFromProcFSAsync(givenPid int) { +func (pt *ProcessTree) FeedFromProcFSAsync(givenPid int32) { if pt.procfsChan == nil { logger.Debugw("starting procfs proctree loop") // will tell if called more than once - pt.procfsChan = make(chan int, 1000) + pt.procfsChan = make(chan int32, 1000) pt.feedFromProcFSLoop() } @@ -59,7 +59,7 @@ func (pt *ProcessTree) FeedFromProcFSAsync(givenPid int) { } // FeedFromProcFS feeds the process tree with data from procfs. -func (pt *ProcessTree) FeedFromProcFS(givenPid int) error { +func (pt *ProcessTree) FeedFromProcFS(givenPid int32) error { procDir := "/proc" // If a PID is given, only deal with that process @@ -77,7 +77,7 @@ func (pt *ProcessTree) FeedFromProcFS(givenPid int) error { if !dir.IsDir() { continue } - pid, err := strconv.Atoi(dir.Name()) + pid, err := proc.ParseInt32(dir.Name()) if err != nil { continue } @@ -93,7 +93,7 @@ func (pt *ProcessTree) FeedFromProcFS(givenPid int) error { // // getProcessByPID returns a process by its PID. -func getProcessByPID(pt *ProcessTree, givenPid int) (*Process, error) { +func getProcessByPID(pt *ProcessTree, givenPid int32) (*Process, error) { if givenPid <= 0 { return nil, errfmt.Errorf("invalid PID") } @@ -120,7 +120,7 @@ func getProcessByPID(pt *ProcessTree, givenPid int) (*Process, error) { } // dealWithProc deals with a process from procfs. -func dealWithProc(pt *ProcessTree, givenPid int) error { +func dealWithProc(pt *ProcessTree, givenPid int32) error { if givenPid <= 0 { return errfmt.Errorf("invalid PID") } @@ -181,15 +181,15 @@ func dealWithProc(pt *ProcessTree, givenPid int) error { // NOTE: override all the fields of the taskInfoFeed, to avoid any previous data. taskInfoFeed := pt.GetTaskInfoFeedFromPool() - taskInfoFeed.Name = name // command name (add "procfs+" to debug if needed) - taskInfoFeed.Tid = pid // status: pid == tid - taskInfoFeed.Pid = tgid // status: tgid == pid - taskInfoFeed.PPid = ppid // status: ppid == ppid - taskInfoFeed.NsTid = nspid // status: nspid == nspid - taskInfoFeed.NsPid = nstgid // status: nstgid == nspid - taskInfoFeed.NsPPid = nsppid // status: nsppid == nsppid - taskInfoFeed.Uid = -1 // do not change the parent uid - taskInfoFeed.Gid = -1 // do not change the parent gid + taskInfoFeed.Name = name // command name (add "procfs+" to debug if needed) + taskInfoFeed.Tid = pid // status: pid == tid + taskInfoFeed.Pid = tgid // status: tgid == pid + taskInfoFeed.PPid = ppid // status: ppid == ppid + taskInfoFeed.NsTid = nspid // status: nspid == nspid + taskInfoFeed.NsPid = nstgid // status: nstgid == nspid + taskInfoFeed.NsPPid = nsppid // status: nsppid == nsppid + taskInfoFeed.Uid = math.MaxUint32 // do not change the parent uid + taskInfoFeed.Gid = math.MaxUint32 // do not change the parent gid taskInfoFeed.StartTimeNS = procfsTimeStamp taskInfoFeed.ExitTimeNS = 0 @@ -214,7 +214,7 @@ func dealWithProc(pt *ProcessTree, givenPid int) error { } // dealWithThread deals with a thread from procfs. -func dealWithThread(pt *ProcessTree, givenPid int, givenTid int) error { +func dealWithThread(pt *ProcessTree, givenPid, givenTid int32) error { if givenPid <= 0 { return errfmt.Errorf("invalid PID") } @@ -264,15 +264,15 @@ func dealWithThread(pt *ProcessTree, givenPid int, givenTid int) error { // NOTE: override all the fields of the taskInfoFeed, to avoid any previous data. taskInfoFeed := pt.GetTaskInfoFeedFromPool() - taskInfoFeed.Name = name // command name (add "procfs+" to debug if needed) - taskInfoFeed.Tid = pid // status: pid == tid - taskInfoFeed.Pid = tgid // status: tgid == pid - taskInfoFeed.PPid = ppid // status: ppid == ppid - taskInfoFeed.NsTid = nspid // status: nspid == nspid - taskInfoFeed.NsPid = nstgid // status: nstgid == nspid - taskInfoFeed.NsPPid = nsppid // status: nsppid == nsppid - taskInfoFeed.Uid = -1 // do not change the parent uid - taskInfoFeed.Gid = -1 // do not change the parent gid + taskInfoFeed.Name = name // command name (add "procfs+" to debug if needed) + taskInfoFeed.Tid = pid // status: pid == tid + taskInfoFeed.Pid = tgid // status: tgid == pid + taskInfoFeed.PPid = ppid // status: ppid == ppid + taskInfoFeed.NsTid = nspid // status: nspid == nspid + taskInfoFeed.NsPid = nstgid // status: nstgid == nspid + taskInfoFeed.NsPPid = nsppid // status: nsppid == nsppid + taskInfoFeed.Uid = math.MaxUint32 // do not change the parent uid + taskInfoFeed.Gid = math.MaxUint32 // do not change the parent gid taskInfoFeed.StartTimeNS = procfsTimeStamp taskInfoFeed.ExitTimeNS = 0 @@ -304,7 +304,7 @@ func dealWithThread(pt *ProcessTree, givenPid int, givenTid int) error { } // dealWithProcFsEntry deals with a process from procfs. -func dealWithProcFsEntry(pt *ProcessTree, givenPid int) error { +func dealWithProcFsEntry(pt *ProcessTree, givenPid int32) error { _, err := os.Stat(fmt.Sprintf("/proc/%v", givenPid)) if os.IsNotExist(err) { return errfmt.Errorf("could not find process %v", givenPid) @@ -327,7 +327,7 @@ func dealWithProcFsEntry(pt *ProcessTree, givenPid int) error { if !taskDir.IsDir() { continue } - tid, err := strconv.Atoi(taskDir.Name()) + tid, err := proc.ParseInt32(taskDir.Name()) if err != nil { continue } diff --git a/pkg/proctree/taskinfo.go b/pkg/proctree/taskinfo.go index 8a9cd07c4c14..44dc4ca816d6 100644 --- a/pkg/proctree/taskinfo.go +++ b/pkg/proctree/taskinfo.go @@ -1,6 +1,7 @@ package proctree import ( + "math" "sync" "time" @@ -11,14 +12,14 @@ import ( // TaskInfoFeed allows external packages to set/get multiple values of a task at once. type TaskInfoFeed struct { Name string // mutable (process name can be changed) - Tid int // immutable - Pid int // immutable - PPid int // mutable (process can be reparented) - NsTid int // immutable - NsPid int // immutable - NsPPid int // mutable (process can be reparented) - Uid int // mutable (process uid can be changed) - Gid int // mutable (process gid can be changed) + Tid int32 // immutable + Pid int32 // immutable + PPid int32 // mutable (process can be reparented) + NsTid int32 // immutable + NsPid int32 // immutable + NsPPid int32 // mutable (process can be reparented) + Uid uint32 // mutable (process uid can be changed) + Gid uint32 // mutable (process gid can be changed) StartTimeNS uint64 // immutable (this is a duration, in ns, since boot) ExitTimeNS uint64 // immutable (this is a duration, in ns, since boot) } @@ -91,10 +92,10 @@ func (ti *TaskInfo) SetFeedAt(feed *TaskInfoFeed, targetTime time.Time) { if feed.NsPid >= 0 { atFeed.NsPPid = feed.NsPPid } - if feed.Uid >= 0 { + if feed.Uid != math.MaxUint32 { atFeed.Uid = feed.Uid } - if feed.Gid >= 0 { + if feed.Gid != math.MaxUint32 { atFeed.Gid = feed.Gid } if feed.StartTimeNS != 0 { @@ -184,7 +185,7 @@ func (ti *TaskInfo) GetNameAt(targetTime time.Time) string { } // GetTid returns the tid of the task. -func (ti *TaskInfo) GetTid() int { +func (ti *TaskInfo) GetTid() int32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -192,7 +193,7 @@ func (ti *TaskInfo) GetTid() int { } // GetPid returns the pid of the task. -func (ti *TaskInfo) GetPid() int { +func (ti *TaskInfo) GetPid() int32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -200,7 +201,7 @@ func (ti *TaskInfo) GetPid() int { } // GetNsTid returns the nsTid of the task. -func (ti *TaskInfo) GetNsTid() int { +func (ti *TaskInfo) GetNsTid() int32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -208,7 +209,7 @@ func (ti *TaskInfo) GetNsTid() int { } // GetNsPid returns the nsPid of the task. -func (ti *TaskInfo) GetNsPid() int { +func (ti *TaskInfo) GetNsPid() int32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -216,7 +217,7 @@ func (ti *TaskInfo) GetNsPid() int { } // GetPPid returns the ppid of the task. -func (ti *TaskInfo) GetPPid() int { +func (ti *TaskInfo) GetPPid() int32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -224,7 +225,7 @@ func (ti *TaskInfo) GetPPid() int { } // GetPPidAt returns the ppid of the task at the given time. -func (ti *TaskInfo) GetPPidAt(targetTime time.Time) int { +func (ti *TaskInfo) GetPPidAt(targetTime time.Time) int32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -232,7 +233,7 @@ func (ti *TaskInfo) GetPPidAt(targetTime time.Time) int { } // GetNsPPid returns the nsPPid of the task. -func (ti *TaskInfo) GetNsPPid() int { +func (ti *TaskInfo) GetNsPPid() int32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -240,7 +241,7 @@ func (ti *TaskInfo) GetNsPPid() int { } // GetNsPPidAt returns the nsPPid of the task at the given time. -func (ti *TaskInfo) GetNsPPidAt(targetTime time.Time) int { +func (ti *TaskInfo) GetNsPPidAt(targetTime time.Time) int32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -248,7 +249,7 @@ func (ti *TaskInfo) GetNsPPidAt(targetTime time.Time) int { } // GetUid returns the uid of the task. -func (ti *TaskInfo) GetUid() int { +func (ti *TaskInfo) GetUid() uint32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -256,7 +257,7 @@ func (ti *TaskInfo) GetUid() int { } // GetUidAt returns the uid of the task at the given time. -func (ti *TaskInfo) GetUidAt(targetTime time.Time) int { +func (ti *TaskInfo) GetUidAt(targetTime time.Time) uint32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -264,7 +265,7 @@ func (ti *TaskInfo) GetUidAt(targetTime time.Time) int { } // GetGid returns the gid of the task. -func (ti *TaskInfo) GetGid() int { +func (ti *TaskInfo) GetGid() uint32 { ti.mutex.RLock() defer ti.mutex.RUnlock() @@ -272,7 +273,7 @@ func (ti *TaskInfo) GetGid() int { } // GetGidAt returns the gid of the task at the given time. -func (ti *TaskInfo) GetGidAt(targetTime time.Time) int { +func (ti *TaskInfo) GetGidAt(targetTime time.Time) uint32 { ti.mutex.RLock() defer ti.mutex.RUnlock() diff --git a/pkg/utils/proc/exe.go b/pkg/utils/proc/exe.go index 2c9dce293ded..7eab1cab913d 100644 --- a/pkg/utils/proc/exe.go +++ b/pkg/utils/proc/exe.go @@ -2,7 +2,6 @@ package proc import ( "os" - "strconv" "github.com/aquasecurity/tracee/pkg/errfmt" "github.com/aquasecurity/tracee/pkg/logger" @@ -10,18 +9,19 @@ import ( // GetProcNS returns the namespace ID of a given namespace and process. // To do so, it requires access to the /proc file system of the host, and CAP_SYS_PTRACE capability. -func GetProcBinary(pid int) (string, error) { +func GetProcBinary(pid int32) (string, error) { exePath := GetProcExePath(pid) binPath, err := os.Readlink(exePath) if err != nil { return "", errfmt.Errorf("could not read exe file: %v", err) } + return binPath, nil } // GetProcNS returns the namespace ID of a given namespace and process. // To do so, it requires access to the /proc file system of the host, and CAP_SYS_PTRACE capability. -func GetAllBinaryProcs() (map[string][]uint32, error) { +func GetAllBinaryProcs() (map[string][]int32, error) { // map[binpath]pids procDir, err := os.Open("/proc") if err != nil { return nil, errfmt.Errorf("could not open procfs dir: %v", err) @@ -31,18 +31,23 @@ func GetAllBinaryProcs() (map[string][]uint32, error) { logger.Errorw("Closing file", "error", err) } }() + procs, err := procDir.Readdirnames(-1) if err != nil { return nil, errfmt.Errorf("could not open procfs dir: %v", err) } - binProcs := map[string][]uint32{} + + binProcs := map[string][]int32{} for _, proc := range procs { - procInt, _ := strconv.ParseInt(proc, 10, 32) - bin, _ := GetProcBinary(int(procInt)) + pid, err := ParseInt32(proc) + if err != nil { + continue + } + bin, _ := GetProcBinary(pid) if _, ok := binProcs[bin]; !ok { - binProcs[bin] = []uint32{} + binProcs[bin] = []int32{} } - binProcs[bin] = append(binProcs[bin], uint32(procInt)) + binProcs[bin] = append(binProcs[bin], pid) } return binProcs, nil diff --git a/pkg/utils/proc/formatters.go b/pkg/utils/proc/formatters.go index bf64ef43d3d0..62820e28f047 100644 --- a/pkg/utils/proc/formatters.go +++ b/pkg/utils/proc/formatters.go @@ -4,28 +4,28 @@ import "strconv" // GetTaskPath returns the path to the task directory of a process given its PID. // The path is in the form /proc//task. -func GetTaskPath(pid int) string { +func GetTaskPath(pid int32) string { pidStr := strconv.FormatInt(int64(pid), 10) return "/proc/" + pidStr + "/task" } // GetStatPath returns the path to the stat file of a process given its PID. // The path is in the form /proc//stat. -func GetStatPath(pid int) string { +func GetStatPath(pid int32) string { pidStr := strconv.FormatInt(int64(pid), 10) return "/proc/" + pidStr + "/stat" } // GetStatusPath returns the path to the status file of a process given its PID. // The path is in the form /proc//status. -func GetStatusPath(pid int) string { +func GetStatusPath(pid int32) string { pidStr := strconv.FormatInt(int64(pid), 10) return "/proc/" + pidStr + "/status" } // GetTaskStatPath returns the path to the stat file of a thread given its PID and TID. // The path is in the form /proc//task//stat. -func GetTaskStatPath(pid, tid int) string { +func GetTaskStatPath(pid, tid int32) string { pidStr := strconv.FormatInt(int64(pid), 10) tidStr := strconv.FormatInt(int64(tid), 10) return "/proc/" + pidStr + "/task/" + tidStr + "/stat" @@ -33,7 +33,7 @@ func GetTaskStatPath(pid, tid int) string { // GetTaskStatusPath returns the path to the status file of a thread given its PID and TID. // The path is in the form /proc//task//status. -func GetTaskStatusPath(pid, tid int) string { +func GetTaskStatusPath(pid, tid int32) string { pidStr := strconv.FormatInt(int64(pid), 10) tidStr := strconv.FormatInt(int64(tid), 10) return "/proc/" + pidStr + "/task/" + tidStr + "/status" @@ -41,20 +41,20 @@ func GetTaskStatusPath(pid, tid int) string { // GetProcExePath returns the path to the executable of a process given its PID. // The path is in the form /proc//exe. -func GetProcExePath(pid int) string { +func GetProcExePath(pid int32) string { pidStr := strconv.FormatInt(int64(pid), 10) return "/proc/" + pidStr + "/exe" } // GetProcNSDirPath returns the path to the directory containing the namespaces of a process given its PID. // The path is in the form /proc//ns. -func GetProcNSDirPath(pid int) string { +func GetProcNSDirPath(pid int32) string { pidStr := strconv.FormatInt(int64(pid), 10) return "/proc/" + pidStr + "/ns" } // GetProcNSPath returns the path to a specific namespace of a process given its PID and the namespace name. // The path is in the form /proc//ns/. -func GetProcNSPath(pid int, nsName string) string { +func GetProcNSPath(pid int32, nsName string) string { return GetProcNSDirPath(pid) + "/" + nsName } diff --git a/pkg/utils/proc/ns.go b/pkg/utils/proc/ns.go index 0a681d25d8a4..5082e46456ef 100644 --- a/pkg/utils/proc/ns.go +++ b/pkg/utils/proc/ns.go @@ -35,17 +35,18 @@ func GetMountNSFirstProcesses() (map[int]int, error) { mountNSTimeMap := make(map[int]pidTimestamp) // Iterate over each pid for _, entry := range entries { - pid, err := strconv.ParseUint(entry, 10, 32) + pid, err := ParseInt32(entry) if err != nil { continue } - procNS, err := GetAllProcNS(uint(pid)) + + procNS, err := GetAllProcNS(pid) if err != nil { logger.Debugw("Failed in fetching process mount namespace", "pid", pid, "error", err.Error()) continue } - processStartTime, err := GetProcessStartTime(uint(pid)) + processStartTime, err := GetProcessStartTime(pid) if err != nil { logger.Debugw("Failed in fetching process start time", "pid", pid, "error", err.Error()) continue @@ -69,8 +70,8 @@ func GetMountNSFirstProcesses() (map[int]int, error) { } // GetProcessStartTime return the start time of the process using the procfs -func GetProcessStartTime(pid uint) (int, error) { - statPath := GetStatPath(int(pid)) +func GetProcessStartTime(pid int32) (int, error) { + statPath := GetStatPath(pid) stat, err := os.ReadFile(statPath) if err != nil { return 0, errfmt.WrapError(err) @@ -111,8 +112,8 @@ type ProcNS struct { // GetAllProcNS return all the namespaces of a given process. // To do so, it requires access to the /proc file system of the host, and CAP_SYS_PTRACE capability. -func GetAllProcNS(pid uint) (*ProcNS, error) { - nsDirPath := GetProcNSDirPath(int(pid)) +func GetAllProcNS(pid int32) (*ProcNS, error) { + nsDirPath := GetProcNSDirPath(pid) nsDir, err := os.Open(nsDirPath) if err != nil { return nil, errfmt.Errorf("could not open ns dir: %v", err) @@ -169,8 +170,8 @@ func GetAllProcNS(pid uint) (*ProcNS, error) { // GetProcNS returns the namespace ID of a given namespace and process. // To do so, it requires access to the /proc file system of the host, and CAP_SYS_PTRACE capability. -func GetProcNS(pid uint, nsName string) (int, error) { - nsPath := GetProcNSPath(int(pid), nsName) +func GetProcNS(pid int32, nsName string) (int, error) { + nsPath := GetProcNSPath(pid, nsName) nsLink, err := os.Readlink(nsPath) if err != nil { return 0, errfmt.Errorf("could not read ns file: %v", err) diff --git a/pkg/utils/proc/parsers.go b/pkg/utils/proc/parsers.go index 2705f65b1ae9..23ba28f4ded7 100644 --- a/pkg/utils/proc/parsers.go +++ b/pkg/utils/proc/parsers.go @@ -7,11 +7,13 @@ import ( // // proc status/stat fields type parsers +// TODO: move to a more appropriate package (e.g. pkg/utils/parsers.go) +// TODO: consider using them in argument parsing // -func parseInt(value string) int { - val, _ := strconv.Atoi(value) - return val +func ParseInt32(value string) (int32, error) { + val, err := strconv.ParseInt(value, 10, 32) + return int32(val), err } func ParseInt64(value string) (int64, error) { diff --git a/pkg/utils/proc/stat.go b/pkg/utils/proc/stat.go index fbe8d07cd161..85c46946f522 100644 --- a/pkg/utils/proc/stat.go +++ b/pkg/utils/proc/stat.go @@ -103,13 +103,13 @@ var procStatValueParserArray = [StatMaxNumFields]procStatValueParser{ } // NewThreadProcStat reads the /proc//task//stat file and parses it into a ProcStat struct. -func NewThreadProcStat(pid, tid int) (*ProcStat, error) { +func NewThreadProcStat(pid, tid int32) (*ProcStat, error) { taskStatPath := GetTaskStatPath(pid, tid) return newProcStat(taskStatPath) } // NewProcStat reads the /proc//stat file and parses it into a ProcStat struct. -func NewProcStat(pid int) (*ProcStat, error) { +func NewProcStat(pid int32) (*ProcStat, error) { statPath := GetStatPath(pid) return newProcStat(statPath) } diff --git a/pkg/utils/proc/status.go b/pkg/utils/proc/status.go index b8f2728ea1cf..0fa483c905c0 100644 --- a/pkg/utils/proc/status.go +++ b/pkg/utils/proc/status.go @@ -47,12 +47,12 @@ import ( // ProcStatus represents the minimal required fields of the /proc status file. type ProcStatus struct { name string // up to 64 chars: https://elixir.bootlin.com/linux/v6.11.4/source/fs/proc/array.c#L99 - tgid int - pid int - pPid int - nstgid int - nspid int - nspgid int + tgid int32 + pid int32 + pPid int32 + nstgid int32 + nspid int32 + nspgid int32 } type procStatusValueParser func(value string, s *ProcStatus) @@ -70,13 +70,13 @@ var procStatusValueParserMap = map[string]procStatusValueParser{ // key: status } // NewThreadProcStatus reads the /proc//task//status file and parses it into a ProcStatus struct. -func NewThreadProcStatus(pid, tid int) (*ProcStatus, error) { +func NewThreadProcStatus(pid, tid int32) (*ProcStatus, error) { taskStatusPath := GetTaskStatusPath(pid, tid) return newProcStatus(taskStatusPath) } // NewProcStatus reads the /proc//status file and parses it into a ProcStatus struct. -func NewProcStatus(pid int) (*ProcStatus, error) { +func NewProcStatus(pid int32) (*ProcStatus, error) { statusPath := GetStatusPath(pid) return newProcStatus(statusPath) } @@ -130,27 +130,27 @@ func parseName(value string, s *ProcStatus) { } func parseTgid(value string, s *ProcStatus) { - s.tgid = parseInt(value) + s.tgid, _ = ParseInt32(value) } func parsePid(value string, s *ProcStatus) { - s.pid = parseInt(value) + s.pid, _ = ParseInt32(value) } func parsePPid(value string, s *ProcStatus) { - s.pPid = parseInt(value) + s.pPid, _ = ParseInt32(value) } func parseNsTgid(value string, s *ProcStatus) { - s.nstgid = parseInt(value) + s.nstgid, _ = ParseInt32(value) } func parseNsPid(value string, s *ProcStatus) { - s.nspid = parseInt(value) + s.nspid, _ = ParseInt32(value) } func parseNsPgid(value string, s *ProcStatus) { - s.nspgid = parseInt(value) + s.nspgid, _ = ParseInt32(value) } // @@ -163,31 +163,31 @@ func (s *ProcStatus) GetName() string { } // GetPid returns the process ID. -func (s *ProcStatus) GetPid() int { +func (s *ProcStatus) GetPid() int32 { return s.pid } // GetTgid returns the thread group ID. -func (s *ProcStatus) GetTgid() int { +func (s *ProcStatus) GetTgid() int32 { return s.tgid } // GetPPid returns the parent process ID. -func (s *ProcStatus) GetPPid() int { +func (s *ProcStatus) GetPPid() int32 { return s.pPid } // GetNsPid returns process ID in the namespace of the process. -func (s *ProcStatus) GetNsPid() int { +func (s *ProcStatus) GetNsPid() int32 { return s.nspid } // GetNsTgid returns thread group ID in the namespace of the process. -func (s *ProcStatus) GetNsTgid() int { +func (s *ProcStatus) GetNsTgid() int32 { return s.nstgid } // GetNsPPid returns process group ID in the namespace of the process. -func (s *ProcStatus) GetNsPPid() int { +func (s *ProcStatus) GetNsPPid() int32 { return s.nspgid } diff --git a/pkg/utils/proc/status_test.go b/pkg/utils/proc/status_test.go index ed9f823a53ba..25cfb993f603 100644 --- a/pkg/utils/proc/status_test.go +++ b/pkg/utils/proc/status_test.go @@ -1,16 +1,19 @@ package proc import ( + "os" "testing" "unsafe" "github.com/google/go-cmp/cmp" + + "github.com/aquasecurity/tracee/pkg/utils/tests" ) const ( // ensure that the test will fail if the ProcStatus struct size changes maxProcStatusNameLength = 64 // https://elixir.bootlin.com/linux/v6.11.4/source/fs/proc/array.c#L99 - maxProcStatusLength = 128 + maxProcStatusLength = 104 ) func TestProcStatusSize(t *testing.T) { @@ -24,12 +27,12 @@ func TestProcStatusSize(t *testing.T) { { name: "Empty string", input: ProcStatus{name: ""}, - expectedSize: 64, // 64 bytes struct = 48 bytes (6 * int) + 16 bytes (string = 8 bytes pointer + 8 bytes length) + expectedSize: 40, // 40 bytes struct = [24 bytes (6 * int32)] + [16 bytes (string = 8 bytes pointer + 8 bytes length)] }, { name: "String with 64 characters (max length)", input: ProcStatus{name: string(make([]byte, maxProcStatusNameLength))}, - expectedSize: maxProcStatusLength, // 128 bytes struct = 48 bytes (6 * int) + 16 bytes (string = 8 bytes pointer + 8 bytes length) + 64 bytes (string content) + expectedSize: maxProcStatusLength, // 104 bytes struct = [24 bytes (6 * int32)] + [16 bytes (string = 8 bytes pointer + 8 bytes length)] + [64 bytes (string content)] }, } @@ -46,6 +49,13 @@ func TestProcStatusSize(t *testing.T) { } } +// TestProcStatus_PrintSizes prints the sizes of the structs used in the ProcStatus type. +// Run it as DEBUG test to see the output. +func TestProcStatus_PrintSizes(t *testing.T) { + procStatus := ProcStatus{} + tests.PrintStructSizes(t, os.Stdout, procStatus) +} + func TestProcStatusParsing(t *testing.T) { t.Parallel() diff --git a/tests/integration/tracee.go b/tests/integration/tracee.go index 17728d499f34..78c3539e2a57 100644 --- a/tests/integration/tracee.go +++ b/tests/integration/tracee.go @@ -244,11 +244,12 @@ func assureIsRoot(t *testing.T) { } func getProcNS(nsName string) string { - pid := syscall.Getpid() - nsID, err := uproc.GetProcNS(uint(pid), nsName) + pidInt := syscall.Getpid() + pid := int32(pidInt) + nsID, err := uproc.GetProcNS(pid, nsName) if err != nil { panic(err) } - return strconv.Itoa(nsID) + return strconv.FormatUint(uint64(nsID), 10) }