mirror of
https://github.com/safing/portmaster
synced 2025-09-02 02:29:12 +00:00
* Move portbase into monorepo * Add new simple module mgr * [WIP] Switch to new simple module mgr * Add StateMgr and more worker variants * [WIP] Switch more modules * [WIP] Switch more modules * [WIP] swtich more modules * [WIP] switch all SPN modules * [WIP] switch all service modules * [WIP] Convert all workers to the new module system * [WIP] add new task system to module manager * [WIP] Add second take for scheduling workers * [WIP] Add FIXME for bugs in new scheduler * [WIP] Add minor improvements to scheduler * [WIP] Add new worker scheduler * [WIP] Fix more bug related to new module system * [WIP] Fix start handing of the new module system * [WIP] Improve startup process * [WIP] Fix minor issues * [WIP] Fix missing subsystem in settings * [WIP] Initialize managers in constructor * [WIP] Move module event initialization to constrictors * [WIP] Fix setting for enabling and disabling the SPN module * [WIP] Move API registeration into module construction * [WIP] Update states mgr for all modules * [WIP] Add CmdLine operation support * Add state helper methods to module group and instance * Add notification and module status handling to status package * Fix starting issues * Remove pilot widget and update security lock to new status data * Remove debug logs * Improve http server shutdown * Add workaround for cleanly shutting down firewall+netquery * Improve logging * Add syncing states with notifications for new module system * Improve starting, stopping, shutdown; resolve FIXMEs/TODOs * [WIP] Fix most unit tests * Review new module system and fix minor issues * Push shutdown and restart events again via API * Set sleep mode via interface * Update example/template module * [WIP] Fix spn/cabin unit test * Remove deprecated UI elements * Make log output more similar for the logging transition phase * Switch spn hub and observer cmds to new module system * Fix log sources * Make worker mgr less error prone * Fix tests and minor issues * Fix observation hub * Improve shutdown and restart handling * Split up big connection.go source file * Move varint and dsd packages to structures repo * Improve expansion test * Fix linter warnings * Fix interception module on windows * Fix linter errors --------- Co-authored-by: Vladimir Stoilov <vladimir@safing.io>
107 lines
2.7 KiB
Go
107 lines
2.7 KiB
Go
//go:build linux
|
|
|
|
package proc
|
|
|
|
import (
|
|
"errors"
|
|
"io/fs"
|
|
"os"
|
|
"strconv"
|
|
|
|
"github.com/safing/portmaster/base/log"
|
|
"github.com/safing/portmaster/service/network/socket"
|
|
)
|
|
|
|
// GetPID returns the already existing pid of the given socket info or searches for it.
|
|
// This also acts as a getter for socket.Info.PID, as locking for that occurs here.
|
|
func GetPID(socketInfo socket.Info) (pid int) {
|
|
// Get currently assigned PID to the socket info.
|
|
currentPid := socketInfo.GetPID()
|
|
|
|
// If the current PID already is valid (ie. not unidentified), return it immediately.
|
|
if currentPid != socket.UndefinedProcessID {
|
|
return currentPid
|
|
}
|
|
|
|
// Find PID for the given UID and inode.
|
|
pid = findPID(socketInfo.GetUIDandInode())
|
|
|
|
// Set the newly found PID on the socket info.
|
|
socketInfo.SetPID(pid)
|
|
|
|
// Return found PID.
|
|
return pid
|
|
}
|
|
|
|
// findPID returns the pid of the given uid and socket inode.
|
|
func findPID(uid, inode int) (pid int) {
|
|
socketName := "socket:[" + strconv.Itoa(inode) + "]"
|
|
|
|
// Always update pid table (it has a call limiter anyway)
|
|
updatePids()
|
|
|
|
// Get all pids for the given uid.
|
|
pids, ok := getPidsByUser(uid)
|
|
if !ok {
|
|
return socket.UndefinedProcessID
|
|
}
|
|
|
|
// Look through the PIDs in reverse order, because higher/newer PIDs will be more likely to
|
|
// be searched for.
|
|
for j := len(pids) - 1; j >= 0; j-- {
|
|
if pidHasSocket(pids[j], socketName) {
|
|
return pids[j]
|
|
}
|
|
}
|
|
|
|
return socket.UndefinedProcessID
|
|
}
|
|
|
|
func pidHasSocket(pid int, socketName string) bool {
|
|
socketBase := "/proc/" + strconv.Itoa(pid) + "/fd"
|
|
entries := readDirNames(socketBase)
|
|
if len(entries) == 0 {
|
|
return false
|
|
}
|
|
|
|
socketBase += "/"
|
|
// Look through the FDs in reverse order, because higher/newer FDs will be
|
|
// more likely to be searched for.
|
|
for i := len(entries) - 1; i >= 0; i-- {
|
|
link, err := os.Readlink(socketBase + entries[i])
|
|
if err != nil {
|
|
if !errors.Is(err, fs.ErrNotExist) {
|
|
log.Warningf("proc: failed to read link /proc/%d/fd/%s: %s", pid, entries[i], err)
|
|
}
|
|
continue
|
|
}
|
|
if link == socketName {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// readDirNames only reads the directory names. Using os.ReadDir() would call `lstat` on every
|
|
// resulting directory name, which we don't need. This function will be called a lot, so we should
|
|
// refrain from unnecessary work.
|
|
func readDirNames(dir string) (names []string) {
|
|
file, err := os.Open(dir)
|
|
if err != nil {
|
|
if !errors.Is(err, fs.ErrNotExist) {
|
|
log.Warningf("proc: could not open directory %s: %s", dir, err)
|
|
}
|
|
return
|
|
}
|
|
defer func() {
|
|
_ = file.Close()
|
|
}()
|
|
|
|
names, err = file.Readdirnames(0)
|
|
if err != nil {
|
|
log.Warningf("proc: could not get entries from directory %s: %s", dir, err)
|
|
return []string{}
|
|
}
|
|
return
|
|
}
|