Rework Communication+Link to Connection
This commit is contained in:
@@ -23,7 +23,7 @@ var (
|
||||
dbController *database.Controller
|
||||
dbControllerFlag = abool.NewBool(false)
|
||||
|
||||
deleteProcessesThreshold = 15 * time.Minute
|
||||
deleteProcessesThreshold = 7 * time.Minute
|
||||
)
|
||||
|
||||
// GetProcessFromStorage returns a process from the internal storage.
|
||||
@@ -68,7 +68,7 @@ func (p *Process) Save() {
|
||||
processesLock.Unlock()
|
||||
}
|
||||
|
||||
if dbControllerFlag.IsSet() && p.Error == "" {
|
||||
if dbControllerFlag.IsSet() {
|
||||
go dbController.PushUpdate(p)
|
||||
}
|
||||
}
|
||||
@@ -93,90 +93,49 @@ func (p *Process) Delete() {
|
||||
}
|
||||
|
||||
// CleanProcessStorage cleans the storage from old processes.
|
||||
func CleanProcessStorage(activeComms map[string]struct{}) {
|
||||
activePIDs, err := getActivePIDs()
|
||||
func CleanProcessStorage(activePIDs map[int]struct{}) {
|
||||
// add system table of processes
|
||||
procs, err := processInfo.Processes()
|
||||
if err != nil {
|
||||
log.Warningf("process: failed to get list of active PIDs: %s", err)
|
||||
activePIDs = nil
|
||||
} else {
|
||||
for _, p := range procs {
|
||||
activePIDs[int(p.Pid)] = struct{}{}
|
||||
}
|
||||
}
|
||||
processesCopy := All()
|
||||
|
||||
processesCopy := All()
|
||||
threshold := time.Now().Add(-deleteProcessesThreshold).Unix()
|
||||
delete := false
|
||||
|
||||
// clean primary processes
|
||||
for _, p := range processesCopy {
|
||||
p.Lock()
|
||||
// check if internal
|
||||
if p.Pid <= 0 {
|
||||
p.Unlock()
|
||||
continue
|
||||
}
|
||||
|
||||
// has comms?
|
||||
_, hasComms := activeComms[p.DatabaseKey()]
|
||||
|
||||
// virtual / active
|
||||
virtual := p.Virtual
|
||||
active := false
|
||||
if activePIDs != nil {
|
||||
_, active = activePIDs[p.Pid]
|
||||
}
|
||||
p.Unlock()
|
||||
|
||||
if !virtual && !hasComms && !active && p.LastCommEstablished < threshold {
|
||||
go p.Delete()
|
||||
}
|
||||
}
|
||||
|
||||
// clean virtual/failed processes
|
||||
for _, p := range processesCopy {
|
||||
p.Lock()
|
||||
// check if internal
|
||||
if p.Pid <= 0 {
|
||||
p.Unlock()
|
||||
continue
|
||||
}
|
||||
|
||||
_, active := activePIDs[p.Pid]
|
||||
switch {
|
||||
case p.Error != "":
|
||||
if p.Meta().Created < threshold {
|
||||
delete = true
|
||||
}
|
||||
case p.Virtual:
|
||||
_, parentIsActive := processesCopy[p.ParentPid]
|
||||
active := true
|
||||
if activePIDs != nil {
|
||||
_, active = activePIDs[p.Pid]
|
||||
}
|
||||
if !parentIsActive || !active {
|
||||
delete = true
|
||||
case p.Pid <= 0:
|
||||
// internal
|
||||
case active:
|
||||
// process in system process table or recently seen on the network
|
||||
default:
|
||||
// delete now or soon
|
||||
switch {
|
||||
case p.LastSeen == 0:
|
||||
// add last
|
||||
p.LastSeen = time.Now().Unix()
|
||||
case p.LastSeen > threshold:
|
||||
// within keep period
|
||||
default:
|
||||
// delete now
|
||||
log.Tracef("process.clean: deleted %s", p.DatabaseKey())
|
||||
go p.Delete()
|
||||
}
|
||||
}
|
||||
|
||||
p.Unlock()
|
||||
|
||||
if delete {
|
||||
log.Tracef("process.clean: deleted %s", p.DatabaseKey())
|
||||
go p.Delete()
|
||||
delete = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getActivePIDs() (map[int]struct{}, error) {
|
||||
procs, err := processInfo.Processes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
activePIDs := make(map[int]struct{})
|
||||
for _, p := range procs {
|
||||
activePIDs[int(p.Pid)] = struct{}{}
|
||||
}
|
||||
|
||||
return activePIDs, nil
|
||||
}
|
||||
|
||||
// SetDBController sets the database controller and allows the package to push database updates on a save. It must be set by the package that registers the "network" database.
|
||||
func SetDBController(controller *database.Controller) {
|
||||
dbController = controller
|
||||
|
||||
@@ -46,11 +46,10 @@ type Process struct {
|
||||
Icon string
|
||||
// Icon is a path to the icon and is either prefixed "f:" for filepath, "d:" for database cache path or "c:"/"a:" for a the icon key to fetch it from a company / authoritative node and cache it in its own cache.
|
||||
|
||||
FirstCommEstablished int64
|
||||
LastCommEstablished int64
|
||||
FirstSeen int64
|
||||
LastSeen int64
|
||||
|
||||
Virtual bool // This process is either merged into another process or is not needed.
|
||||
Error string // If this is set, the process is invalid. This is used to cache failing or inexistent processes.
|
||||
Virtual bool // This process is either merged into another process or is not needed.
|
||||
}
|
||||
|
||||
// Profile returns the assigned layered profile.
|
||||
@@ -63,67 +62,15 @@ func (p *Process) Profile() *profile.LayeredProfile {
|
||||
|
||||
// Strings returns a string representation of process.
|
||||
func (p *Process) String() string {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
||||
if p == nil {
|
||||
return "?"
|
||||
}
|
||||
return fmt.Sprintf("%s:%s:%d", p.UserName, p.Path, p.Pid)
|
||||
}
|
||||
|
||||
// AddCommunication increases the connection counter and the last connection timestamp.
|
||||
func (p *Process) AddCommunication() {
|
||||
p.Lock()
|
||||
defer p.Unlock()
|
||||
|
||||
// check if we should save
|
||||
save := false
|
||||
if p.LastCommEstablished == 0 || p.LastCommEstablished < time.Now().Add(-3*time.Second).Unix() {
|
||||
save = true
|
||||
}
|
||||
|
||||
// update LastCommEstablished
|
||||
p.LastCommEstablished = time.Now().Unix()
|
||||
if p.FirstCommEstablished == 0 {
|
||||
p.FirstCommEstablished = p.LastCommEstablished
|
||||
}
|
||||
|
||||
if save {
|
||||
go p.Save()
|
||||
}
|
||||
return fmt.Sprintf("%s:%s:%d", p.UserName, p.Path, p.Pid)
|
||||
}
|
||||
|
||||
// var db = database.NewInterface(nil)
|
||||
|
||||
// CountConnections returns the count of connections of a process
|
||||
// func (p *Process) CountConnections() int {
|
||||
// q, err := query.New(fmt.Sprintf("%s/%d/", processDatabaseNamespace, p.Pid)).
|
||||
// Where(query.Where("Pid", query.Exists, nil)).
|
||||
// Check()
|
||||
// if err != nil {
|
||||
// log.Warningf("process: failed to build query to get connection count of process: %s", err)
|
||||
// return -1
|
||||
// }
|
||||
//
|
||||
// it, err := db.Query(q)
|
||||
// if err != nil {
|
||||
// log.Warningf("process: failed to query db to get connection count of process: %s", err)
|
||||
// return -1
|
||||
// }
|
||||
//
|
||||
// cnt := 0
|
||||
// for _ = range it.Next {
|
||||
// cnt++
|
||||
// }
|
||||
// if it.Err() != nil {
|
||||
// log.Warningf("process: failed to query db to get connection count of process: %s", err)
|
||||
// return -1
|
||||
// }
|
||||
//
|
||||
// return cnt
|
||||
// }
|
||||
|
||||
// GetOrFindPrimaryProcess returns the highest process in the tree that matches the given PID.
|
||||
func GetOrFindPrimaryProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
log.Tracer(ctx).Tracef("process: getting primary process for PID %d", pid)
|
||||
@@ -139,9 +86,6 @@ func GetOrFindPrimaryProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if process.Error != "" {
|
||||
return nil, fmt.Errorf("%s [cached error]", process.Error)
|
||||
}
|
||||
|
||||
for {
|
||||
if process.ParentPid == 0 {
|
||||
@@ -152,10 +96,6 @@ func GetOrFindPrimaryProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
log.Tracer(ctx).Tracef("process: could not get parent of %d: %d: %s", process.Pid, process.ParentPid, err)
|
||||
return process, nil
|
||||
}
|
||||
if parentProcess.Error != "" {
|
||||
log.Tracer(ctx).Tracef("process: could not get parent of %d: %d: %s [cached error]", process.Pid, process.ParentPid, parentProcess.Error)
|
||||
return process, nil
|
||||
}
|
||||
|
||||
// if parent process path does not match, we have reached the top of the tree of matching processes
|
||||
if process.Path != parentProcess.Path {
|
||||
@@ -192,9 +132,6 @@ func GetOrFindProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if p.Error != "" {
|
||||
return nil, fmt.Errorf("%s [cached error]", p.Error)
|
||||
}
|
||||
|
||||
// mark for use, save to storage
|
||||
p.Lock()
|
||||
@@ -275,8 +212,9 @@ func loadProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
|
||||
// create new process
|
||||
new := &Process{
|
||||
Pid: pid,
|
||||
Virtual: true, // caller must decide to actually use the process - we need to save now.
|
||||
Pid: pid,
|
||||
Virtual: true, // caller must decide to actually use the process - we need to save now.
|
||||
FirstSeen: time.Now().Unix(),
|
||||
}
|
||||
|
||||
switch {
|
||||
@@ -302,7 +240,7 @@ func loadProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
var uids []int32
|
||||
uids, err = pInfo.Uids()
|
||||
if err != nil {
|
||||
return failedToLoad(new, fmt.Errorf("failed to get UID for p%d: %s", pid, err))
|
||||
return nil, fmt.Errorf("failed to get UID for p%d: %s", pid, err)
|
||||
}
|
||||
new.UserID = int(uids[0])
|
||||
}
|
||||
@@ -310,7 +248,7 @@ func loadProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
// Username
|
||||
new.UserName, err = pInfo.Username()
|
||||
if err != nil {
|
||||
return failedToLoad(new, fmt.Errorf("process: failed to get Username for p%d: %s", pid, err))
|
||||
return nil, fmt.Errorf("process: failed to get Username for p%d: %s", pid, err)
|
||||
}
|
||||
|
||||
// TODO: User Home
|
||||
@@ -319,14 +257,14 @@ func loadProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
// PPID
|
||||
ppid, err := pInfo.Ppid()
|
||||
if err != nil {
|
||||
return failedToLoad(new, fmt.Errorf("failed to get PPID for p%d: %s", pid, err))
|
||||
return nil, fmt.Errorf("failed to get PPID for p%d: %s", pid, err)
|
||||
}
|
||||
new.ParentPid = int(ppid)
|
||||
|
||||
// Path
|
||||
new.Path, err = pInfo.Exe()
|
||||
if err != nil {
|
||||
return failedToLoad(new, fmt.Errorf("failed to get Path for p%d: %s", pid, err))
|
||||
return nil, fmt.Errorf("failed to get Path for p%d: %s", pid, err)
|
||||
}
|
||||
// Executable Name
|
||||
_, new.ExecName = filepath.Split(new.Path)
|
||||
@@ -341,13 +279,13 @@ func loadProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
// Command line arguments
|
||||
new.CmdLine, err = pInfo.Cmdline()
|
||||
if err != nil {
|
||||
return failedToLoad(new, fmt.Errorf("failed to get Cmdline for p%d: %s", pid, err))
|
||||
return nil, fmt.Errorf("failed to get Cmdline for p%d: %s", pid, err)
|
||||
}
|
||||
|
||||
// Name
|
||||
new.Name, err = pInfo.Name()
|
||||
if err != nil {
|
||||
return failedToLoad(new, fmt.Errorf("failed to get Name for p%d: %s", pid, err))
|
||||
return nil, fmt.Errorf("failed to get Name for p%d: %s", pid, err)
|
||||
}
|
||||
if new.Name == "" {
|
||||
new.Name = new.ExecName
|
||||
@@ -436,9 +374,3 @@ func loadProcess(ctx context.Context, pid int) (*Process, error) {
|
||||
new.Save()
|
||||
return new, nil
|
||||
}
|
||||
|
||||
func failedToLoad(p *Process, err error) (*Process, error) {
|
||||
p.Error = err.Error()
|
||||
p.Save()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user