mirror of
https://github.com/safing/portmaster
synced 2025-09-01 10:09:11 +00:00
116 lines
3.3 KiB
Go
116 lines
3.3 KiB
Go
package process
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/safing/portbase/log"
|
|
"github.com/safing/portmaster/profile"
|
|
)
|
|
|
|
var (
|
|
ownPID = os.Getpid()
|
|
)
|
|
|
|
// GetProfile finds and assigns a profile set to the process.
|
|
func (p *Process) GetProfile(ctx context.Context) (changed bool, err error) {
|
|
// Update profile metadata outside of *Process lock.
|
|
defer p.UpdateProfileMetadata()
|
|
|
|
p.Lock()
|
|
defer p.Unlock()
|
|
|
|
// Check if profile is already loaded.
|
|
if p.profile != nil {
|
|
log.Tracer(ctx).Trace("process: profile already loaded")
|
|
return
|
|
}
|
|
|
|
// If not, continue with loading the profile.
|
|
log.Tracer(ctx).Trace("process: loading profile")
|
|
|
|
// Check if we need a special profile.
|
|
profileID := ""
|
|
switch p.Pid {
|
|
case UnidentifiedProcessID:
|
|
profileID = profile.UnidentifiedProfileID
|
|
case SystemProcessID:
|
|
profileID = profile.SystemProfileID
|
|
case ownPID:
|
|
profileID = profile.PortmasterProfileID
|
|
default:
|
|
// Check if this is another Portmaster component.
|
|
if updatesPath != "" && strings.HasPrefix(p.Path, updatesPath) {
|
|
switch {
|
|
case strings.Contains(p.Path, "portmaster-app"):
|
|
profileID = profile.PortmasterAppProfileID
|
|
case strings.Contains(p.Path, "portmaster-notifier"):
|
|
profileID = profile.PortmasterNotifierProfileID
|
|
default:
|
|
// Unexpected binary from within the Portmaster updates directpry.
|
|
log.Warningf("process: unexpected binary in the updates directory: %s", p.Path)
|
|
// TODO: Assign a fully restricted profile in the future when we are
|
|
// sure that we won't kill any of our own things.
|
|
}
|
|
}
|
|
// Check if this is the system resolver.
|
|
switch runtime.GOOS {
|
|
case "windows":
|
|
// Depending on the OS version System32 may be capitalized or not.
|
|
if (p.Path == `C:\Windows\System32\svchost.exe` ||
|
|
p.Path == `C:\Windows\system32\svchost.exe`) &&
|
|
// This comes from the windows tasklist command and should be pretty consistent.
|
|
(strings.Contains(p.SpecialDetail, "Dnscache") ||
|
|
// As an alternative in case of failure, we try to match the svchost.exe service parameter.
|
|
strings.Contains(p.CmdLine, "-s Dnscache")) {
|
|
profileID = profile.SystemResolverProfileID
|
|
}
|
|
case "linux":
|
|
switch p.Path {
|
|
case "/lib/systemd/systemd-resolved",
|
|
"/usr/lib/systemd/systemd-resolved",
|
|
"/lib64/systemd/systemd-resolved",
|
|
"/usr/lib64/systemd/systemd-resolved":
|
|
profileID = profile.SystemResolverProfileID
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get the (linked) local profile.
|
|
localProfile, err := profile.GetProfile(profile.SourceLocal, profileID, p.Path)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
// Assign profile to process.
|
|
p.LocalProfileKey = localProfile.Key()
|
|
p.profile = localProfile.LayeredProfile()
|
|
|
|
return true, nil
|
|
}
|
|
|
|
// UpdateProfileMetadata updates the metadata of the local profile
|
|
// as required.
|
|
func (p *Process) UpdateProfileMetadata() {
|
|
// Check if there is a profile to work with.
|
|
localProfile := p.Profile().LocalProfile()
|
|
if localProfile == nil {
|
|
return
|
|
}
|
|
|
|
// Update metadata of profile.
|
|
metadataUpdated := localProfile.UpdateMetadata(p.Path)
|
|
|
|
// Mark profile as used.
|
|
profileChanged := localProfile.MarkUsed()
|
|
|
|
// Save the profile if we changed something.
|
|
if metadataUpdated || profileChanged {
|
|
err := localProfile.Save()
|
|
if err != nil {
|
|
log.Warningf("process: failed to save profile %s: %s", localProfile.ScopedID(), err)
|
|
}
|
|
}
|
|
}
|