From e19130f378b0920c0764044e9603f0a809bd9e83 Mon Sep 17 00:00:00 2001 From: fuleyi Date: Fri, 4 Jul 2025 15:27:54 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20procfs=E5=A2=9E=E5=8A=A0TrustedExe?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit procfs增加TrustedExe方法:判断/proc/pid/ns/mnt 和 /proc/1/ns/mnt是否相同,如果不相同,则进程exe字段不可信。 Log: procfs增加TrustedExe方法 pms: TASK-369021 --- procfs/procfs.go | 43 +++++++++++++++++++++++++++++++++++++++++- users/passwd/passwd.go | 9 +++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/procfs/procfs.go b/procfs/procfs.go index 4c00480..7a437ce 100644 --- a/procfs/procfs.go +++ b/procfs/procfs.go @@ -5,13 +5,16 @@ package procfs import ( + "errors" "fmt" "io/ioutil" "os" "path/filepath" - "github.com/linuxdeepin/go-lib/encoding/kv" "strconv" "strings" + "sync" + + "github.com/linuxdeepin/go-lib/encoding/kv" ) type Process uint @@ -53,6 +56,20 @@ func (p Process) Exe() (string, error) { return exe, err } +func (p Process) TrustedExe() (string, error) { + exeFile := p.getFile("exe") + exe, err := filepath.EvalSymlinks(exeFile) + if err != nil { + return "", err + } + if os.Getuid() == 0 { + if !checkSenderNsMntValid(uint32(p)) { + return "", errors.New("due to the difference between the current process's ns mnt and the init process's ns mnt, the exe field is not reliable") + } + } + return exe, nil +} + type EnvVars []string func (p Process) Environ() (EnvVars, error) { @@ -145,3 +162,27 @@ func (st Status) PPid() (uint, error) { } return uint(v), nil } + +var _initProcNsMnt string +var _once sync.Once + +// 通过判断/proc/pid/ns/mnt 和 /proc/1/ns/mnt是否相同,如果不相同,则进程exe字段不可信 +func checkSenderNsMntValid(pid uint32) bool { + _once.Do(func() { + out, err := os.Readlink("/proc/1/ns/mnt") + if err != nil { + fmt.Println(err) + return + } + _initProcNsMnt = strings.TrimSpace(out) + }) + c, err := os.Readlink(fmt.Sprintf("/proc/%v/ns/mnt", pid)) + if err != nil { + fmt.Println(err) + return false + } + defer func() { + fmt.Printf("pid 1 mnt ns is %v,pid %v mnt ns is %v\n", _initProcNsMnt, pid, strings.TrimSpace(c)) + }() + return strings.TrimSpace(c) == _initProcNsMnt +} diff --git a/users/passwd/passwd.go b/users/passwd/passwd.go index 677b96e..91d4ff3 100644 --- a/users/passwd/passwd.go +++ b/users/passwd/passwd.go @@ -10,9 +10,12 @@ import "C" import ( "fmt" + "sync" "unsafe" ) +var mutex sync.Mutex + // Passwd wraps up `passwd` struct used in kernel type Passwd struct { Name string @@ -53,6 +56,8 @@ func (err *UserNotFoundError) Error() string { // GetPasswdByName wraps up `getpwnam` system call. // It retrieves records from the password file based on username. func GetPasswdByName(name string) (*Passwd, error) { + mutex.Lock() + defer mutex.Unlock() nameC := C.CString(name) defer C.free(unsafe.Pointer(nameC)) passwdC, err := C.getpwnam(nameC) @@ -70,6 +75,8 @@ func GetPasswdByName(name string) (*Passwd, error) { // GetPasswdByUid wraps up `getpwuid` system call. // It retrieves records from the password file based on uid. func GetPasswdByUid(uid uint32) (*Passwd, error) { + mutex.Lock() + defer mutex.Unlock() uidC := C.__uid_t(uid) passwdC, err := C.getpwuid(uidC) if passwdC == nil { @@ -86,6 +93,8 @@ func GetPasswdByUid(uid uint32) (*Passwd, error) { // GetPasswdEntry wraps up `getpwent` system call // It performs sequential scans of the records in the password file. func GetPasswdEntry() []*Passwd { + mutex.Lock() + defer mutex.Unlock() var passwds []*Passwd // Restart scanning from the begging of the password file.