diff options
| author | Ophestra Umiker <cat@ophivana.moe> | 2024-11-16 21:19:45 +0900 |
|---|---|---|
| committer | Ophestra Umiker <cat@ophivana.moe> | 2024-11-16 21:19:45 +0900 |
| commit | df33123bd7f1e0cb4e98580b7e63818c82aa7206 (patch) | |
| tree | 8b21831634e6169eb875cbfd359fa4006d6c66b3 /internal/linux | |
| parent | 1a09b55bd4753c6d5cbecf96d1b56f23b0e44b95 (diff) | |
app: integrate fsu
This removes the dependency on external user switchers like sudo/machinectl and decouples fortify user ids from the passwd database.
Signed-off-by: Ophestra Umiker <cat@ophivana.moe>
Diffstat (limited to 'internal/linux')
| -rw-r--r-- | internal/linux/interface.go | 8 | ||||
| -rw-r--r-- | internal/linux/std.go | 85 |
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 |
