From afa7a0800da2bb44fd9daaea1180c046ea111db8 Mon Sep 17 00:00:00 2001 From: Ophestra Date: Wed, 24 Sep 2025 21:10:13 +0900 Subject: cmd/hsu: return hsurc id The uid format is stable, this value is what caller has to obtain through hsu. Closes #14. Signed-off-by: Ophestra --- internal/app/process.go | 2 +- internal/sys/hsu.go | 87 +++++++++++++++++++------------------------------ 2 files changed, 34 insertions(+), 55 deletions(-) (limited to 'internal') diff --git a/internal/app/process.go b/internal/app/process.go index a182fa6c..368b655f 100644 --- a/internal/app/process.go +++ b/internal/app/process.go @@ -255,7 +255,7 @@ func (seal *outcome) main() { // passed through to shim by hsu shimEnv + "=" + strconv.Itoa(fd), // interpreted by hsu - "HAKUREI_APP_ID=" + seal.user.identity.String(), + "HAKUREI_IDENTITY=" + seal.user.identity.String(), } } diff --git a/internal/sys/hsu.go b/internal/sys/hsu.go index 2be12d1e..39fb4f18 100644 --- a/internal/sys/hsu.go +++ b/internal/sys/hsu.go @@ -17,69 +17,48 @@ import ( // Hsu caches responses from cmd/hsu. type Hsu struct { - uidOnce sync.Once - uidCopy map[int]struct { - uid int - err error - } - uidMu sync.RWMutex + idOnce sync.Once + idErr error + id int } var ErrHsuAccess = errors.New("current user is not in the hsurc file") func (h *Hsu) Uid(identity int) (int, error) { - h.uidOnce.Do(func() { - h.uidCopy = make(map[int]struct { - uid int - err error - }) - }) - - { - h.uidMu.RLock() - u, ok := h.uidCopy[identity] - h.uidMu.RUnlock() - if ok { - return u.uid, u.err - } - } + h.idOnce.Do(func() { + h.id = -1 + hsuPath := internal.MustHsuPath() - h.uidMu.Lock() - defer h.uidMu.Unlock() + cmd := exec.Command(hsuPath) + cmd.Path = hsuPath + cmd.Stderr = os.Stderr // pass through fatal messages + cmd.Env = make([]string, 0) + cmd.Dir = container.FHSRoot + var ( + p []byte + exitError *exec.ExitError + ) - u := struct { - uid int - err error - }{} - defer func() { h.uidCopy[identity] = u }() - - u.uid = -1 - hsuPath := internal.MustHsuPath() - - cmd := exec.Command(hsuPath) - cmd.Path = hsuPath - cmd.Stderr = os.Stderr // pass through fatal messages - cmd.Env = []string{"HAKUREI_APP_ID=" + strconv.Itoa(identity)} - cmd.Dir = container.FHSRoot - var ( - p []byte - exitError *exec.ExitError - ) - - const step = "obtain uid from hsu" - if p, u.err = cmd.Output(); u.err == nil { - u.uid, u.err = strconv.Atoi(string(p)) - if u.err != nil { - u.err = &hst.AppError{Step: step, Err: u.err, Msg: "invalid uid string from hsu"} + const step = "obtain uid from hsu" + if p, h.idErr = cmd.Output(); h.idErr == nil { + h.id, h.idErr = strconv.Atoi(string(p)) + if h.idErr != nil { + h.idErr = &hst.AppError{Step: step, Err: h.idErr, Msg: "invalid uid string from hsu"} + } + } else if errors.As(h.idErr, &exitError) && exitError != nil && exitError.ExitCode() == 1 { + // hsu prints an error message in this case + h.idErr = &hst.AppError{Step: step, Err: ErrHsuAccess} + } else if os.IsNotExist(h.idErr) { + h.idErr = &hst.AppError{Step: step, Err: os.ErrNotExist, + Msg: fmt.Sprintf("the setuid helper is missing: %s", hsuPath)} } - } else if errors.As(u.err, &exitError) && exitError != nil && exitError.ExitCode() == 1 { - // hsu prints an error message in this case - u.err = &hst.AppError{Step: step, Err: ErrHsuAccess} - } else if os.IsNotExist(u.err) { - u.err = &hst.AppError{Step: step, Err: os.ErrNotExist, - Msg: fmt.Sprintf("the setuid helper is missing: %s", hsuPath)} + }) + + uid := -1 + if h.id >= 0 { + uid = 1000000 + h.id*10000 + identity } - return u.uid, u.err + return uid, h.idErr } // MustUid calls [State.Uid] and terminates on error. -- cgit v1.3.1