Add first tag handlers for svchost, app image, net

This commit is contained in:
Daniel 2022-10-03 22:12:04 +02:00
parent d60329e130
commit fd0ce5732d
8 changed files with 259 additions and 35 deletions

View file

@ -14,6 +14,7 @@ import (
"github.com/safing/portmaster/network/netutils"
"github.com/safing/portmaster/network/packet"
"github.com/safing/portmaster/process"
_ "github.com/safing/portmaster/process/tags"
"github.com/safing/portmaster/resolver"
"github.com/safing/spn/navigator"
)

View file

@ -69,13 +69,18 @@ func GetNetworkHost(ctx context.Context, remoteIP net.IP) (process *Process, err
UserID: NetworkHostProcessID,
Pid: NetworkHostProcessID,
ParentPid: NetworkHostProcessID,
Path: fmt.Sprintf("net:%s", remoteIP),
Tags: []profile.Tag{
{
Key: "net",
Value: remoteIP.String(),
},
},
FirstSeen: now,
LastSeen: now,
}
// Get the (linked) local profile.
networkHostProfile, err := profile.GetProfile(profile.SourceNetwork, remoteIP.String(), "", false)
networkHostProfile, err := profile.GetLocalProfile("", networkHost.MatchingData(), networkHost.CreateProfileCallback)
if err != nil {
return nil, err
}

View file

@ -1,11 +1,7 @@
//+build !windows,!linux
//go:build !windows && !linux
// +build !windows,!linux
package process
// SystemProcessID is the PID of the System/Kernel itself.
const SystemProcessID = 0
// specialOSInit does special OS specific Process initialization.
func (p *Process) specialOSInit() {
}

View file

@ -2,6 +2,3 @@ package process
// SystemProcessID is the PID of the System/Kernel itself.
const SystemProcessID = 0
// specialOSInit does special OS specific Process initialization.
func (p *Process) specialOSInit() {}

View file

@ -1,28 +1,4 @@
package process
import (
"fmt"
"github.com/safing/portbase/log"
"github.com/safing/portbase/utils/osdetail"
)
// SystemProcessID is the PID of the System/Kernel itself.
const SystemProcessID = 4
// specialOSInit does special OS specific Process initialization.
func (p *Process) specialOSInit() {
// add svchost.exe service names to Name
if p.ExecName == "svchost.exe" {
svcNames, err := osdetail.GetServiceNames(int32(p.Pid))
switch err {
case nil:
p.Name += fmt.Sprintf(" (%s)", svcNames)
p.SpecialDetail = svcNames
case osdetail.ErrServiceNotFound:
log.Tracef("process: failed to get service name for svchost.exe (pid %d): %s", p.Pid, err)
default:
log.Warningf("process: failed to get service name for svchost.exe (pid %d): %s", p.Pid, err)
}
}
}

View file

@ -0,0 +1,87 @@
package tags
import (
"strings"
"github.com/safing/portmaster/process"
"github.com/safing/portmaster/profile"
)
func init() {
err := process.RegisterTagHandler(new(AppImageHandler))
if err != nil {
panic(err)
}
}
const (
appImageName = "AppImage"
appImagePathTagKey = "app-image-path"
)
// AppImageHandler handles AppImage processes on Unix systems.
type AppImageHandler struct{}
// Name returns the tag handler name.
func (h *AppImageHandler) Name() string {
return appImageName
}
// TagDescriptions returns a list of all possible tags and their description
// of this handler.
func (h *AppImageHandler) TagDescriptions() []process.TagDescription {
return []process.TagDescription{
{
ID: appImagePathTagKey,
Name: "App Image Path",
Description: "Path to the app image file itself.",
},
}
}
// AddTags adds tags to the given process.
func (h *AppImageHandler) AddTags(p *process.Process) {
// Get and verify AppImage location.
appImageLocation, ok := p.Env["APPIMAGE"]
if !ok {
return
}
appImageMountDir, ok := p.Env["APPDIR"]
if !ok {
return
}
// Check if the process path is in the mount dir.
if !strings.HasPrefix(p.Path, appImageMountDir) {
return
}
// Add matching path for regular profile matching.
p.MatchingPath = appImageLocation
// Add app image tags.
p.Tags = append(p.Tags, profile.Tag{
Key: appImagePathTagKey,
Value: appImageLocation,
})
}
// CreateProfile creates a profile based on the tags of the process.
// Returns nil to skip.
func (h *AppImageHandler) CreateProfile(p *process.Process) *profile.Profile {
for _, tag := range p.Tags {
if tag.Key == appImagePathTagKey {
return profile.New(&profile.Profile{
Source: profile.SourceLocal,
PresentationPath: p.Path,
Fingerprints: []profile.Fingerprint{
{
Type: profile.FingerprintTypePathID,
Operation: profile.FingerprintOperationEqualsID,
Value: tag.Value, // Value of appImagePathTagKey.
},
},
})
}
}
return nil
}

65
process/tags/net.go Normal file
View file

@ -0,0 +1,65 @@
package tags
import (
"github.com/safing/portmaster/process"
"github.com/safing/portmaster/profile"
)
func init() {
err := process.RegisterTagHandler(new(NetworkHandler))
if err != nil {
panic(err)
}
}
const (
netName = "Network"
netTagKey = "net"
)
// NetworkHandler handles AppImage processes on Unix systems.
type NetworkHandler struct{}
// Name returns the tag handler name.
func (h *NetworkHandler) Name() string {
return netName
}
// TagDescriptions returns a list of all possible tags and their description
// of this handler.
func (h *NetworkHandler) TagDescriptions() []process.TagDescription {
return []process.TagDescription{
{
ID: netTagKey,
Name: "Things on the Network",
Description: "Other (virtual) devices that make requests to Portmaster, if enabled in Portmaster.",
},
}
}
// AddTags adds tags to the given process.
func (h *NetworkHandler) AddTags(p *process.Process) {
// The "net" tag is added directly when creating the virtual process.
}
// CreateProfile creates a profile based on the tags of the process.
// Returns nil to skip.
func (h *NetworkHandler) CreateProfile(p *process.Process) *profile.Profile {
for _, tag := range p.Tags {
if tag.Key == netTagKey {
return profile.New(&profile.Profile{
Source: profile.SourceLocal,
Name: p.Name,
Fingerprints: []profile.Fingerprint{
{
Type: profile.FingerprintTypeTagID,
Key: tag.Key,
Operation: profile.FingerprintOperationEqualsID,
Value: tag.Value,
},
},
})
}
}
return nil
}

View file

@ -0,0 +1,97 @@
package tags
import (
"fmt"
"strings"
"github.com/safing/portbase/log"
"github.com/safing/portmaster/process"
"github.com/safing/portmaster/profile"
)
func init() {
err := process.RegisterTagHandler(new(SVCHostTagHandler))
if err != nil {
panic(err)
}
}
const (
svchostName = "SvcHost"
svchostTagKey = "svchost"
)
// SVCHostTagHandler handles svchost processes on Windows.
type SVCHostTagHandler struct{}
// Name returns the tag handler name.
func (h *SVCHostTagHandler) Name() string {
return svcHostName
}
// TagDescriptions returns a list of all possible tags and their description
// of this handler.
func (h *SVCHostTagHandler) TagDescriptions() []process.TagDescription {
return []process.TagDescription{
process.TagDescription{
ID: svcHostTagKey,
Name: "SvcHost Service Name",
Description: "Name of a service running in svchost.exe as reported by Windows.",
},
}
}
// TagKeys returns a list of all possible tag keys of this handler.
func (h *SVCHostTagHandler) TagKeys() []string {
return []string{svcHostTagKey}
}
// AddTags adds tags to the given process.
func (h *SVCHostTagHandler) AddTags(p *process.Process) {
// Check for svchost.exe.
if p.ExecName != "svchost.exe" {
return
}
// Get services of svchost instance.
svcNames, err := osdetail.GetServiceNames(int32(p.Pid))
switch err {
case nil:
// Append service names to process name.
p.Name += fmt.Sprintf(" (%s)", strings.Join(svcNames, ", "))
// Add services as tags.
for _, svcName := range svcNames {
p.Tag = append(p.Tag, profile.Tag{
Key: svchostTagKey,
Value: svcName,
})
}
case osdetail.ErrServiceNotFound:
log.Tracef("process/tags: failed to get service name for svchost.exe (pid %d): %s", p.Pid, err)
default:
log.Warningf("process/tags: failed to get service name for svchost.exe (pid %d): %s", p.Pid, err)
}
}
// CreateProfile creates a profile based on the tags of the process.
// Returns nil to skip.
func (h *SVCHostTagHandler) CreateProfile(p *process.Process) *profile.Profile {
for _, tag := range p.Tags {
if tag.Key == svchostTagKey {
return profile.New(
profile.SourceLocal,
"",
"Windows Service: "+tag.Value,
p.Path,
[]profile.Fingerprint{profile.Fingerprint{
Type: profile.FingerprintTypeTagID,
Key: tag.Key,
Operation: profile.FingerprintOperationEqualsID,
Value: tag.Value,
}},
nil,
)
}
}
return nil
}