Skip to content

Commit

Permalink
Improve metadata handling of profiles
Browse files Browse the repository at this point in the history
Also, improve OS profile handling
  • Loading branch information
dhaavi committed Nov 24, 2020
1 parent 4b694c5 commit 5a88fc2
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 122 deletions.
25 changes: 18 additions & 7 deletions network/connection.go
Expand Up @@ -165,15 +165,26 @@ type Reason struct {
Context interface{}
}

func getProcessContext(proc *process.Process) ProcessContext {
return ProcessContext{
func getProcessContext(ctx context.Context, proc *process.Process) ProcessContext {
// Gather process information.
pCtx := ProcessContext{
BinaryPath: proc.Path,
ProcessName: proc.Name,
ProfileName: proc.Profile().LocalProfile().Name,
PID: proc.Pid,
Profile: proc.Profile().LocalProfile().ID,
Source: string(proc.Profile().LocalProfile().Source),
}

// Get local profile.
localProfile := proc.Profile().LocalProfile()
if localProfile == nil {
log.Tracer(ctx).Warningf("network: process %s has no profile", proc)
return pCtx
}

// Add profile information and return.
pCtx.ProfileName = localProfile.Name
pCtx.Profile = localProfile.ID
pCtx.Source = string(localProfile.Source)
return pCtx
}

// NewConnectionFromDNSRequest returns a new connection based on the given dns request.
Expand Down Expand Up @@ -204,7 +215,7 @@ func NewConnectionFromDNSRequest(ctx context.Context, fqdn string, cnames []stri
CNAME: cnames,
},
process: proc,
ProcessContext: getProcessContext(proc),
ProcessContext: getProcessContext(ctx, proc),
Started: timestamp,
Ended: timestamp,
}
Expand Down Expand Up @@ -304,7 +315,7 @@ func NewConnectionFromFirstPacket(pkt packet.Packet) *Connection {
IPProtocol: pkt.Info().Protocol,
LocalIP: pkt.Info().LocalIP(),
LocalPort: pkt.Info().LocalPort(),
ProcessContext: getProcessContext(proc),
ProcessContext: getProcessContext(pkt.Ctx(), proc),
process: proc,
// remote endpoint
Entity: entity,
Expand Down
128 changes: 61 additions & 67 deletions process/process.go
Expand Up @@ -232,88 +232,82 @@ func loadProcess(ctx context.Context, pid int) (*Process, error) {
defer markRequestFinished()
}

// create new process
// Create new a process object.
new := &Process{
Pid: pid,
Virtual: true, // caller must decide to actually use the process - we need to save now.
FirstSeen: time.Now().Unix(),
}

switch {
case new.IsKernel():
new.UserName = "Kernel"
new.Name = "Operating System"
default:

pInfo, err := processInfo.NewProcess(int32(pid))
if err != nil {
return nil, err
}

// UID
// net yet implemented for windows
if runtime.GOOS == "linux" {
var uids []int32
uids, err = pInfo.Uids()
if err != nil {
return nil, fmt.Errorf("failed to get UID for p%d: %s", pid, err)
}
new.UserID = int(uids[0])
}
// Get process information from the system.
pInfo, err := processInfo.NewProcess(int32(pid))
if err != nil {
return nil, err
}

// Username
new.UserName, err = pInfo.Username()
// UID
// net yet implemented for windows
if runtime.GOOS == "linux" {
var uids []int32
uids, err = pInfo.Uids()
if err != nil {
return nil, fmt.Errorf("process: failed to get Username 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])
}

// TODO: User Home
// new.UserHome, err =
// Username
new.UserName, err = pInfo.Username()
if err != nil {
return nil, fmt.Errorf("process: failed to get Username for p%d: %s", pid, err)
}

// PPID
ppid, err := pInfo.Ppid()
if err != nil {
return nil, fmt.Errorf("failed to get PPID for p%d: %s", pid, err)
}
new.ParentPid = int(ppid)
// TODO: User Home
// new.UserHome, err =

// Path
new.Path, err = pInfo.Exe()
if err != nil {
return nil, fmt.Errorf("failed to get Path for p%d: %s", pid, err)
}
// remove linux " (deleted)" suffix for deleted files
if onLinux {
new.Path = strings.TrimSuffix(new.Path, " (deleted)")
}
// Executable Name
_, new.ExecName = filepath.Split(new.Path)

// Current working directory
// net yet implemented for windows
// new.Cwd, err = pInfo.Cwd()
// if err != nil {
// log.Warningf("process: failed to get Cwd: %s", err)
// }

// Command line arguments
new.CmdLine, err = pInfo.Cmdline()
if err != nil {
return nil, fmt.Errorf("failed to get Cmdline for p%d: %s", pid, err)
}
// PPID
ppid, err := pInfo.Ppid()
if err != nil {
return nil, fmt.Errorf("failed to get PPID for p%d: %s", pid, err)
}
new.ParentPid = int(ppid)

// Name
new.Name, err = pInfo.Name()
if err != nil {
return nil, fmt.Errorf("failed to get Name for p%d: %s", pid, err)
}
if new.Name == "" {
new.Name = new.ExecName
}
// Path
new.Path, err = pInfo.Exe()
if err != nil {
return nil, fmt.Errorf("failed to get Path for p%d: %s", pid, err)
}
// remove linux " (deleted)" suffix for deleted files
if onLinux {
new.Path = strings.TrimSuffix(new.Path, " (deleted)")
}
// Executable Name
_, new.ExecName = filepath.Split(new.Path)

// Current working directory
// net yet implemented for windows
// new.Cwd, err = pInfo.Cwd()
// if err != nil {
// log.Warningf("process: failed to get Cwd: %s", err)
// }

// Command line arguments
new.CmdLine, err = pInfo.Cmdline()
if err != nil {
return nil, fmt.Errorf("failed to get Cmdline for p%d: %s", pid, err)
}

// OS specifics
new.specialOSInit()
// Name
new.Name, err = pInfo.Name()
if err != nil {
return nil, fmt.Errorf("failed to get Name for p%d: %s", pid, err)
}
if new.Name == "" {
new.Name = new.ExecName
}

// OS specifics
new.specialOSInit()

new.Save()
return new, nil
Expand Down
6 changes: 2 additions & 4 deletions process/process_default.go
Expand Up @@ -2,10 +2,8 @@

package process

// IsKernel returns whether the process is the Kernel.
func (p *Process) IsKernel() bool {
return p.Pid == 0
}
// SystemProcessID is the PID of the System/Kernel itself.
const SystemProcessID = 0

// specialOSInit does special OS specific Process initialization.
func (p *Process) specialOSInit() {
Expand Down
6 changes: 2 additions & 4 deletions process/process_linux.go
@@ -1,9 +1,7 @@
package process

// IsKernel returns whether the process is the Kernel.
func (p *Process) IsKernel() bool {
return p.Pid == 0
}
// SystemProcessID is the PID of the System/Kernel itself.
const SystemProcessID = 0

// specialOSInit does special OS specific Process initialization.
func (p *Process) specialOSInit() {
Expand Down
6 changes: 2 additions & 4 deletions process/process_windows.go
Expand Up @@ -7,10 +7,8 @@ import (
"github.com/safing/portbase/utils/osdetail"
)

// IsKernel returns whether the process is the Kernel.
func (p *Process) IsKernel() bool {
return p.Pid == 4
}
// SystemProcessID is the PID of the System/Kernel itself.
const SystemProcessID = 4

// specialOSInit does special OS specific Process initialization.
func (p *Process) specialOSInit() {
Expand Down
18 changes: 8 additions & 10 deletions process/special.go
Expand Up @@ -9,11 +9,9 @@ import (
"golang.org/x/sync/singleflight"
)

// Special Process IDs
const (
UnidentifiedProcessID = -1
SystemProcessID = 0
)
// UnidentifiedProcessID is the PID used for anything that could not be
// attributed to a PID for any reason.
const UnidentifiedProcessID = -1

var (
// unidentifiedProcess is used when a process cannot be found.
Expand All @@ -39,18 +37,18 @@ var (

// GetUnidentifiedProcess returns the special process assigned to unidentified processes.
func GetUnidentifiedProcess(ctx context.Context) *Process {
return getSpecialProcess(ctx, UnidentifiedProcessID, unidentifiedProcess)
return getSpecialProcess(ctx, unidentifiedProcess)
}

// GetSystemProcess returns the special process used for the Kernel.
func GetSystemProcess(ctx context.Context) *Process {
return getSpecialProcess(ctx, SystemProcessID, systemProcess)
return getSpecialProcess(ctx, systemProcess)
}

func getSpecialProcess(ctx context.Context, pid int, template *Process) *Process {
p, _, _ := getSpecialProcessSingleInflight.Do(strconv.Itoa(pid), func() (interface{}, error) {
func getSpecialProcess(ctx context.Context, template *Process) *Process {
p, _, _ := getSpecialProcessSingleInflight.Do(strconv.Itoa(template.Pid), func() (interface{}, error) {
// Check if we have already loaded the special process.
process, ok := GetProcessFromStorage(pid)
process, ok := GetProcessFromStorage(template.Pid)
if ok {
return process, nil
}
Expand Down
4 changes: 4 additions & 0 deletions profile/profile-layered.go
Expand Up @@ -154,6 +154,10 @@ func (lp *LayeredProfile) UnlockForUsage() {

// LocalProfile returns the local profile associated with this layered profile.
func (lp *LayeredProfile) LocalProfile() *Profile {
if lp == nil {
return nil
}

lp.RLock()
defer lp.RUnlock()

Expand Down

0 comments on commit 5a88fc2

Please sign in to comment.