Merge pull request #240 from safing/fix/pid-lock

Check binary path of PID lock
This commit is contained in:
Patrick Pacher 2021-01-29 14:36:59 +01:00 committed by GitHub
commit 16c0eafd1f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 6 deletions

View file

@ -1,6 +1,7 @@
package main
import (
"errors"
"fmt"
"io/ioutil"
"log"
@ -32,16 +33,50 @@ func checkAndCreateInstanceLock(name string) (pid int32, err error) {
return 0, createInstanceLock(lockFilePath)
}
// check if process exists
// Check if process exists.
p, err := processInfo.NewProcess(int32(parsedPid))
if err == nil {
return p.Pid, nil
switch {
case err == nil:
// Process exists, continue.
case errors.Is(err, processInfo.ErrorProcessNotRunning):
// A process with the locked PID does not exist.
// This is expected, so we can continue normally.
return 0, createInstanceLock(lockFilePath)
default:
// There was an internal error getting the process.
return 0, err
}
// else create new lock
// Get the process paths and evaluate and clean them.
executingBinaryPath, err := p.Exe()
if err != nil {
return 0, fmt.Errorf("failed to get path of existing process: %w", err)
}
cleanedExecutingBinaryPath, err := filepath.EvalSymlinks(executingBinaryPath)
if err != nil {
return 0, fmt.Errorf("failed to evaluate path of existing process: %w", err)
}
ownBinaryPath, err := os.Executable()
if err != nil {
return 0, fmt.Errorf("failed to get path of own process: %w", err)
}
cleanedOwnBinaryPath, err := filepath.EvalSymlinks(ownBinaryPath)
if err != nil {
return 0, fmt.Errorf("failed to evaluate path of own process: %w", err)
}
// Check if the binary path matches.
if cleanedExecutingBinaryPath != cleanedOwnBinaryPath {
// The process with the locked PID belongs to another binary.
// As the Portmaster usually starts very early, it will have a low PID,
// which could be assigned to another process on next boot.
return 0, createInstanceLock(lockFilePath)
}
// Return PID of already running instance.
return p.Pid, nil
}
func createInstanceLock(lockFilePath string) error {
// check data root dir
err := dataRoot.Ensure()

View file

@ -130,7 +130,10 @@ func run(opts *Options, cmdArgs []string) (err error) {
// check for duplicate instances
if opts.ShortIdentifier == "core" || opts.ShortIdentifier == "hub" {
pid, _ := checkAndCreateInstanceLock(opts.ShortIdentifier)
pid, err := checkAndCreateInstanceLock(opts.ShortIdentifier)
if err != nil {
return fmt.Errorf("failed to exec lock: %w", err)
}
if pid != 0 {
return fmt.Errorf("another instance of %s is already running: PID %d", opts.Name, pid)
}