hst: use hsu userid for share path suffix
All checks were successful
Test / Create distribution (push) Successful in 34s
Test / Sandbox (push) Successful in 2m8s
Test / Hakurei (push) Successful in 3m11s
Test / Hpkg (push) Successful in 4m8s
Test / Sandbox (race detector) (push) Successful in 4m31s
Test / Hakurei (race detector) (push) Successful in 5m8s
Test / Flake checks (push) Successful in 1m25s

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 <cat@gensokyo.uk>
This commit is contained in:
2025-08-26 02:15:00 +09:00
parent c9facb746b
commit 4cf694d2b3
12 changed files with 53 additions and 34 deletions

View File

@@ -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)

View File

@@ -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