diff --git a/process/process.go b/process/process.go index 619e832a..72b2c2b3 100644 --- a/process/process.go +++ b/process/process.go @@ -44,6 +44,10 @@ type Process struct { CmdLine string FirstArg string + // SpecialDetail holds special information, the meaning of which can change + // based on any of the previous attributes. + SpecialDetail string + LocalProfileKey string profile *profile.LayeredProfile @@ -65,6 +69,24 @@ func (p *Process) Profile() *profile.LayeredProfile { return p.profile } +// IsSystemResolver is a shortcut to check if the process is or belongs to the +// system resolver and needs special handling. +func (p *Process) IsSystemResolver() bool { + // Check if process exists. + if p == nil { + return false + } + + // Check if local profile exists. + localProfile := p.profile.LocalProfile() + if localProfile == nil { + return false + } + + // Check ID. + return localProfile.ID == profile.SystemResolverProfileID +} + // GetLastSeen returns the unix timestamp when the process was last seen. func (p *Process) GetLastSeen() int64 { p.Lock() diff --git a/process/process_windows.go b/process/process_windows.go index c202bcb9..c0f722c2 100644 --- a/process/process_windows.go +++ b/process/process_windows.go @@ -18,6 +18,7 @@ func (p *Process) specialOSInit() { 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: diff --git a/process/profile.go b/process/profile.go index 792c11f8..8639c39a 100644 --- a/process/profile.go +++ b/process/profile.go @@ -3,6 +3,7 @@ package process import ( "context" "os" + "runtime" "strings" "github.com/safing/portbase/log" @@ -54,6 +55,20 @@ func (p *Process) GetProfile(ctx context.Context) (changed bool, err error) { // sure that we won't kill any of our own things. } } + // Check if this is the system resolver. + switch runtime.GOOS { + case "windows": + if (p.Path == `C:\Windows\System32\svchost.exe` || p.Path == `C:\Windows\system32\svchost.exe`) && + (strings.Contains(p.SpecialDetail, "Dnscache") || strings.Contains(p.CmdLine, "-k NetworkService")) { + profileID = profile.SystemResolverProfileID + } + case "linux": + switch p.Path { + case "/lib/systemd/systemd-resolved", + "/usr/lib/systemd/systemd-resolved": + profileID = profile.SystemResolverProfileID + } + } } // Get the (linked) local profile. diff --git a/profile/special.go b/profile/special.go index 754cdc67..252cd1c4 100644 --- a/profile/special.go +++ b/profile/special.go @@ -11,6 +11,11 @@ const ( // SystemProfileName is the name used for the system/kernel. SystemProfileName = "Operating System" + // SystemResolverProfileID is the profile ID used for the system's DNS resolver. + SystemResolverProfileID = "_system-resolver" + // SystemResolverProfileName is the name used for the system's DNS resolver. + SystemResolverProfileName = "System DNS Client" + // PortmasterProfileID is the profile ID used for the Portmaster Core itself. PortmasterProfileID = "_portmaster" // PortmasterProfileName is the name used for the Portmaster Core itself. @@ -35,6 +40,8 @@ func updateSpecialProfileMetadata(profile *Profile, binaryPath string) (ok, chan newProfileName = UnidentifiedProfileName case SystemProfileID: newProfileName = SystemProfileName + case SystemResolverProfileID: + newProfileName = SystemResolverProfileName case PortmasterProfileID: newProfileName = PortmasterProfileName case PortmasterAppProfileID: @@ -68,6 +75,9 @@ func getSpecialProfile(profileID, linkedPath string) *Profile { case SystemProfileID: return New(SourceLocal, SystemProfileID, linkedPath, nil) + case SystemResolverProfileID: + return New(SourceLocal, SystemResolverProfileID, linkedPath, nil) + case PortmasterProfileID: profile := New(SourceLocal, PortmasterProfileID, linkedPath, nil) profile.Internal = true