v1.15.0
* IDState cleaned up. Should work on all *NIXes now. * Can now get IDState of arbitrary PID. * Shuffled some env stuff around.
This commit is contained in:
158
funcs_nix.go
Normal file
158
funcs_nix.go
Normal file
@@ -0,0 +1,158 @@
|
||||
//go:build !(windows || plan9 || wasip1 || js || ios)
|
||||
|
||||
package sysutils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
`math`
|
||||
"os"
|
||||
|
||||
`github.com/shirou/gopsutil/v3/process`
|
||||
"golang.org/x/sys/unix"
|
||||
"r00t2.io/sysutils/envs"
|
||||
`r00t2.io/sysutils/errs`
|
||||
`r00t2.io/sysutils/internal`
|
||||
)
|
||||
|
||||
// GetIDState returns current ID/elevation information. An IDState should *not* be explicitly created/defined.
|
||||
func GetIDState() (ids IDState) {
|
||||
|
||||
var err error
|
||||
|
||||
ids.RUID, ids.EUID, ids.SUID = unix.Getresuid()
|
||||
ids.uidsChecked = true
|
||||
ids.RGID, ids.EGID, ids.SGID = unix.Getresgid()
|
||||
ids.gidsChecked = true
|
||||
|
||||
ids.SudoEnvCmd = envs.HasEnv(envSudoCmd)
|
||||
ids.SudoEnvHome = envs.HasEnv(envSudoHome)
|
||||
ids.SudoEnvGroup = envs.HasEnv(envSudoGrp)
|
||||
ids.SudoEnvUser = envs.HasEnv(envSudoUid) || envs.HasEnv(envSudoUname)
|
||||
if ids.SudoEnvCmd || ids.SudoEnvHome || ids.SudoEnvGroup || ids.SudoEnvUser {
|
||||
ids.SudoEnvVars = true
|
||||
}
|
||||
ids.sudoChecked = true
|
||||
|
||||
// PID 1 will *always* be root, so that can return a false positive for sudo.
|
||||
if os.Getppid() != 1 {
|
||||
ids.stat = new(unix.Stat_t)
|
||||
if err = unix.Stat(
|
||||
fmt.Sprintf("/proc/%d/stat", os.Getppid()),
|
||||
ids.stat,
|
||||
); err != nil {
|
||||
err = nil
|
||||
} else {
|
||||
ids.PPIDUidMatch = ids.RUID == int(ids.stat.Uid)
|
||||
ids.ppidUidChecked = true
|
||||
ids.PPIDGidMatch = ids.RGID == int(ids.stat.Gid)
|
||||
ids.ppidGidChecked = true
|
||||
}
|
||||
} else {
|
||||
ids.ppidUidChecked = true
|
||||
ids.ppidGidChecked = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetIDStateProc is like GetIDState but for an arbitrary PID.
|
||||
func GetIDStateProc(pid uint32) (ids IDState, err error) {
|
||||
|
||||
var i32 int32
|
||||
var ints []int32
|
||||
var sudoUid bool
|
||||
var sudoUname bool
|
||||
var proc *process.Process
|
||||
var envMap map[string]string
|
||||
|
||||
if pid > math.MaxInt32 {
|
||||
err = errs.ErrHighPid
|
||||
return
|
||||
}
|
||||
|
||||
ids = IDState{
|
||||
RUID: -1,
|
||||
EUID: -1,
|
||||
SUID: -1,
|
||||
RGID: -1,
|
||||
EGID: -1,
|
||||
SGID: -1,
|
||||
}
|
||||
|
||||
if proc, err = process.NewProcess(int32(pid)); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// UIDs
|
||||
if ints, err = proc.Uids(); err != nil {
|
||||
return
|
||||
}
|
||||
if ints != nil && len(ints) > 0 {
|
||||
if len(ints) >= 3 {
|
||||
ids.SUID = int(ints[2])
|
||||
}
|
||||
if len(ints) >= 2 {
|
||||
ids.EUID = int(ints[1])
|
||||
}
|
||||
if len(ints) >= 1 {
|
||||
ids.RUID = int(ints[0])
|
||||
}
|
||||
}
|
||||
ids.uidsChecked = true
|
||||
|
||||
// GIDs
|
||||
if ints, err = proc.Gids(); err != nil {
|
||||
return
|
||||
}
|
||||
if ints != nil && len(ints) > 0 {
|
||||
if len(ints) >= 3 {
|
||||
ids.SGID = int(ints[2])
|
||||
}
|
||||
if len(ints) >= 2 {
|
||||
ids.EGID = int(ints[1])
|
||||
}
|
||||
if len(ints) >= 1 {
|
||||
ids.SGID = int(ints[0])
|
||||
}
|
||||
}
|
||||
ids.gidsChecked = true
|
||||
|
||||
// Sudo (env check)
|
||||
if envMap, err = internal.GetPidEnvMap(uint32(pid)); err != nil {
|
||||
return
|
||||
}
|
||||
_, ids.SudoEnvCmd = envMap[envSudoCmd]
|
||||
_, ids.SudoEnvHome = envMap[envSudoHome]
|
||||
_, ids.SudoEnvGroup = envMap[envSudoGrp]
|
||||
_, sudoUid = envMap[envSudoUid]
|
||||
_, sudoUname = envMap[envSudoUname]
|
||||
ids.SudoEnvUser = sudoUid || sudoUname
|
||||
if ids.SudoEnvCmd || ids.SudoEnvHome || ids.SudoEnvGroup || ids.SudoEnvUser {
|
||||
ids.SudoEnvVars = true
|
||||
}
|
||||
ids.sudoChecked = true
|
||||
|
||||
// Sudo (PPID check)
|
||||
if i32, err = proc.Ppid(); err != nil {
|
||||
return
|
||||
}
|
||||
if i32 != 1 {
|
||||
ids.stat = new(unix.Stat_t)
|
||||
if err = unix.Stat(
|
||||
fmt.Sprintf("/proc/%d/stat", i32),
|
||||
ids.stat,
|
||||
); err != nil {
|
||||
err = nil
|
||||
} else {
|
||||
ids.PPIDUidMatch = ids.RUID == int(ids.stat.Uid)
|
||||
ids.ppidUidChecked = true
|
||||
ids.PPIDGidMatch = ids.SGID == int(ids.stat.Gid)
|
||||
ids.ppidGidChecked = true
|
||||
}
|
||||
} else {
|
||||
ids.ppidUidChecked = true
|
||||
ids.ppidGidChecked = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user