Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion procfs/procfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
}
9 changes: 9 additions & 0 deletions users/passwd/passwd.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand All @@ -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.
Expand Down