From 4cf694d2b31c7aa5c66cbb83d7d54c1a6cb1b4aa Mon Sep 17 00:00:00 2001 From: Ophestra Date: Tue, 26 Aug 2025 02:15:00 +0900 Subject: hst: use hsu userid for share path suffix The privileged user is identifier to hakurei through its hsu userid. Using the kernel uid here makes little sense and is a leftover design choice from before hsu was implemented. Closes #7. Signed-off-by: Ophestra --- internal/sys/interface.go | 25 +++++++++++++++++-------- internal/sys/std.go | 20 ++++++++++++++------ 2 files changed, 31 insertions(+), 14 deletions(-) (limited to 'internal/sys') diff --git a/internal/sys/interface.go b/internal/sys/interface.go index 5dbe18e6..ed765ece 100644 --- a/internal/sys/interface.go +++ b/internal/sys/interface.go @@ -22,9 +22,9 @@ type State interface { LookupEnv(key string) (string, bool) // TempDir provides [os.TempDir]. TempDir() string - // LookPath provides [exec.LookPath]. + // LookPath provides exec.LookPath. LookPath(file string) (string, error) - // MustExecutable provides [proc.MustExecutable]. + // MustExecutable provides [container.MustExecutable]. MustExecutable() string // LookupGroup provides [user.LookupGroup]. LookupGroup(name string) (*user.Group, error) @@ -32,9 +32,9 @@ type State interface { ReadDir(name string) ([]fs.DirEntry, error) // Stat provides [os.Stat]. Stat(name string) (fs.FileInfo, error) - // Open provides [os.Open] + // Open provides [os.Open]. Open(name string) (fs.File, error) - // EvalSymlinks provides [filepath.EvalSymlinks] + // EvalSymlinks provides filepath.EvalSymlinks. EvalSymlinks(path string) (string, error) // Exit provides [os.Exit]. Exit(code int) @@ -45,19 +45,28 @@ type State interface { // Paths returns a populated [hst.Paths] struct. Paths() hst.Paths // Uid invokes hsu and returns target uid. - // Any errors returned by Uid is already wrapped [fmsg.BaseError]. - Uid(aid int) (int, error) + // Any errors returned by Uid is already wrapped [hlog.BaseError]. + Uid(identity int) (int, error) +} + +// GetUserID obtains user id from hsu by querying uid of identity 0. +func GetUserID(os State) (int, error) { + if uid, err := os.Uid(0); err != nil { + return -1, err + } else { + return (uid / 10000) - 100, nil + } } // CopyPaths is a generic implementation of [hst.Paths]. -func CopyPaths(os State, v *hst.Paths) { +func CopyPaths(os State, v *hst.Paths, userid int) { if tempDir, err := container.NewAbs(os.TempDir()); err != nil { log.Fatalf("invalid TMPDIR: %v", err) } else { v.TempDir = tempDir } - v.SharePath = v.TempDir.Append("hakurei." + strconv.Itoa(os.Getuid())) + v.SharePath = v.TempDir.Append("hakurei." + strconv.Itoa(userid)) hlog.Verbosef("process share directory at %q", v.SharePath) r, _ := os.LookupEnv(xdgRuntimeDir) diff --git a/internal/sys/std.go b/internal/sys/std.go index 89fdd289..828cbc45 100644 --- a/internal/sys/std.go +++ b/internal/sys/std.go @@ -49,11 +49,19 @@ func (s *Std) Printf(format string, v ...any) { hlog.Verbosef(form const xdgRuntimeDir = "XDG_RUNTIME_DIR" func (s *Std) Paths() hst.Paths { - s.pathsOnce.Do(func() { CopyPaths(s, &s.paths) }) + s.pathsOnce.Do(func() { + if userid, err := GetUserID(s); err != nil { + hlog.PrintBaseError(err, "cannot obtain user id from hsu:") + hlog.BeforeExit() + s.Exit(1) + } else { + CopyPaths(s, &s.paths, userid) + } + }) return s.paths } -func (s *Std) Uid(aid int) (int, error) { +func (s *Std) Uid(identity int) (int, error) { s.uidOnce.Do(func() { s.uidCopy = make(map[int]struct { uid int @@ -63,7 +71,7 @@ func (s *Std) Uid(aid int) (int, error) { { s.uidMu.RLock() - u, ok := s.uidCopy[aid] + u, ok := s.uidCopy[identity] s.uidMu.RUnlock() if ok { return u.uid, u.err @@ -77,7 +85,7 @@ func (s *Std) Uid(aid int) (int, error) { uid int err error }{} - defer func() { s.uidCopy[aid] = u }() + defer func() { s.uidCopy[identity] = u }() u.uid = -1 hsuPath := internal.MustHsuPath() @@ -85,7 +93,7 @@ func (s *Std) Uid(aid int) (int, error) { cmd := exec.Command(hsuPath) cmd.Path = hsuPath cmd.Stderr = os.Stderr // pass through fatal messages - cmd.Env = []string{"HAKUREI_APP_ID=" + strconv.Itoa(aid)} + cmd.Env = []string{"HAKUREI_APP_ID=" + strconv.Itoa(identity)} cmd.Dir = container.FHSRoot var ( p []byte @@ -95,7 +103,7 @@ func (s *Std) Uid(aid int) (int, error) { if p, u.err = cmd.Output(); u.err == nil { u.uid, u.err = strconv.Atoi(string(p)) if u.err != nil { - u.err = hlog.WrapErrSuffix(u.err, "cannot parse uid from hsu:") + u.err = hlog.WrapErr(u.err, "invalid uid string from hsu") } } else if errors.As(u.err, &exitError) && exitError != nil && exitError.ExitCode() == 1 { u.err = hlog.WrapErr(syscall.EACCES, "") // hsu prints to stderr in this case -- cgit v1.3.1