aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/linux
diff options
context:
space:
mode:
Diffstat (limited to 'internal/linux')
-rw-r--r--internal/linux/interface.go8
-rw-r--r--internal/linux/std.go85
2 files changed, 64 insertions, 29 deletions
diff --git a/internal/linux/interface.go b/internal/linux/interface.go
index 36f61b1a..a920492f 100644
--- a/internal/linux/interface.go
+++ b/internal/linux/interface.go
@@ -22,8 +22,8 @@ type System interface {
LookPath(file string) (string, error)
// Executable provides [os.Executable].
Executable() (string, error)
- // Lookup provides [user.Lookup].
- Lookup(username string) (*user.User, error)
+ // LookupGroup provides [user.LookupGroup].
+ LookupGroup(name string) (*user.Group, error)
// ReadDir provides [os.ReadDir].
ReadDir(name string) ([]fs.DirEntry, error)
// Stat provides [os.Stat].
@@ -35,10 +35,10 @@ type System interface {
// Stdout provides [os.Stdout].
Stdout() io.Writer
- // FshimPath returns an absolute path to the fshim binary.
- FshimPath() string
// Paths returns a populated [Paths] struct.
Paths() Paths
+ // Uid invokes fsu and returns target uid.
+ Uid(aid int) (int, error)
// SdBooted implements https://www.freedesktop.org/software/systemd/man/sd_booted.html
SdBooted() bool
}
diff --git a/internal/linux/std.go b/internal/linux/std.go
index e0a0994c..4ea5b903 100644
--- a/internal/linux/std.go
+++ b/internal/linux/std.go
@@ -7,6 +7,7 @@ import (
"os"
"os/exec"
"os/user"
+ "strconv"
"sync"
"git.ophivana.moe/security/fortify/internal"
@@ -21,41 +22,75 @@ type Std struct {
sdBooted bool
sdBootedOnce sync.Once
- fshim string
- fshimOnce sync.Once
+ uidOnce sync.Once
+ uidCopy map[int]struct {
+ uid int
+ err error
+ }
+ uidMu sync.RWMutex
}
-func (s *Std) Geteuid() int { return os.Geteuid() }
-func (s *Std) LookupEnv(key string) (string, bool) { return os.LookupEnv(key) }
-func (s *Std) TempDir() string { return os.TempDir() }
-func (s *Std) LookPath(file string) (string, error) { return exec.LookPath(file) }
-func (s *Std) Executable() (string, error) { return os.Executable() }
-func (s *Std) Lookup(username string) (*user.User, error) { return user.Lookup(username) }
-func (s *Std) ReadDir(name string) ([]os.DirEntry, error) { return os.ReadDir(name) }
-func (s *Std) Stat(name string) (fs.FileInfo, error) { return os.Stat(name) }
-func (s *Std) Open(name string) (fs.File, error) { return os.Open(name) }
-func (s *Std) Exit(code int) { fmsg.Exit(code) }
-func (s *Std) Stdout() io.Writer { return os.Stdout }
+func (s *Std) Geteuid() int { return os.Geteuid() }
+func (s *Std) LookupEnv(key string) (string, bool) { return os.LookupEnv(key) }
+func (s *Std) TempDir() string { return os.TempDir() }
+func (s *Std) LookPath(file string) (string, error) { return exec.LookPath(file) }
+func (s *Std) Executable() (string, error) { return os.Executable() }
+func (s *Std) LookupGroup(name string) (*user.Group, error) { return user.LookupGroup(name) }
+func (s *Std) ReadDir(name string) ([]os.DirEntry, error) { return os.ReadDir(name) }
+func (s *Std) Stat(name string) (fs.FileInfo, error) { return os.Stat(name) }
+func (s *Std) Open(name string) (fs.File, error) { return os.Open(name) }
+func (s *Std) Exit(code int) { fmsg.Exit(code) }
+func (s *Std) Stdout() io.Writer { return os.Stdout }
const xdgRuntimeDir = "XDG_RUNTIME_DIR"
-func (s *Std) FshimPath() string {
- s.fshimOnce.Do(func() {
- p, ok := internal.Path(internal.Fshim)
- if !ok {
- fmsg.Fatal("invalid fshim path, this copy of fortify is not compiled correctly")
- }
- s.fshim = p
- })
-
- return s.fshim
-}
-
func (s *Std) Paths() Paths {
s.pathsOnce.Do(func() { CopyPaths(s, &s.paths) })
return s.paths
}
+func (s *Std) Uid(aid int) (int, error) {
+ s.uidOnce.Do(func() {
+ s.uidCopy = make(map[int]struct {
+ uid int
+ err error
+ })
+ })
+
+ s.uidMu.RLock()
+ if u, ok := s.uidCopy[aid]; ok {
+ s.uidMu.RUnlock()
+ return u.uid, u.err
+ }
+
+ s.uidMu.RUnlock()
+ s.uidMu.Lock()
+ defer s.uidMu.Unlock()
+
+ u := struct {
+ uid int
+ err error
+ }{}
+ defer func() { s.uidCopy[aid] = u }()
+
+ u.uid = -1
+ if fsu, ok := internal.Check(internal.Fsu); !ok {
+ fmsg.Fatal("invalid fsu path, this copy of fshim is not compiled correctly")
+ panic("unreachable")
+ } else {
+ cmd := exec.Command(fsu)
+ cmd.Path = fsu
+ cmd.Stderr = os.Stderr // pass through fatal messages
+ cmd.Env = []string{"FORTIFY_APP_ID=" + strconv.Itoa(aid)}
+ cmd.Dir = "/"
+ var p []byte
+ if p, u.err = cmd.Output(); u.err == nil {
+ u.uid, u.err = strconv.Atoi(string(p))
+ }
+ return u.uid, u.err
+ }
+}
+
func (s *Std) SdBooted() bool {
s.sdBootedOnce.Do(func() { s.sdBooted = copySdBooted() })
return s.sdBooted