diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-09-24 21:10:13 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-09-24 21:10:13 +0900 |
| commit | afa7a0800da2bb44fd9daaea1180c046ea111db8 (patch) | |
| tree | 16625a815e17c3d587513f54554a965860db4a47 | |
| parent | 773253fdf5388dd77d817be98024cc975d207104 (diff) | |
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 <cat@gensokyo.uk>
| -rw-r--r-- | cmd/hsu/main.go | 37 | ||||
| -rw-r--r-- | internal/app/process.go | 2 | ||||
| -rw-r--r-- | internal/sys/hsu.go | 87 |
3 files changed, 55 insertions, 71 deletions
diff --git a/cmd/hsu/main.go b/cmd/hsu/main.go index 28571b9b..cb82c204 100644 --- a/cmd/hsu/main.go +++ b/cmd/hsu/main.go @@ -15,7 +15,7 @@ import ( const ( hsuConfFile = "/etc/hsurc" envShim = "HAKUREI_SHIM" - envAID = "HAKUREI_APP_ID" + envIdentity = "HAKUREI_IDENTITY" envGroups = "HAKUREI_GROUPS" PR_SET_NO_NEW_PRIVS = 0x26 @@ -48,8 +48,8 @@ func main() { } // uid = 1000000 + - // fid * 10000 + - // aid + // id * 10000 + + // identity uid := 1000000 // refuse to run if hsurc is not protected correctly @@ -62,29 +62,25 @@ func main() { } // authenticate before accepting user input + var id int if f, err := os.Open(hsuConfFile); err != nil { log.Fatal(err) - } else if fid, ok := mustParseConfig(f, puid); !ok { + } else if v, ok := mustParseConfig(f, puid); !ok { log.Fatalf("uid %d is not in the hsurc file", puid) } else { - uid += fid * 10000 - } + id = v + if err = f.Close(); err != nil { + log.Fatal(err) + } - // allowed aid range 0 to 9999 - if as, ok := os.LookupEnv(envAID); !ok { - log.Fatal("HAKUREI_APP_ID not set") - } else if aid, err := parseUint32Fast(as); err != nil || aid < 0 || aid > 9999 { - log.Fatal("invalid aid") - } else { - uid += aid + uid += id * 10000 } // pass through setup fd to shim var shimSetupFd string if s, ok := os.LookupEnv(envShim); !ok { - // hakurei requests target uid - // print resolved uid and exit - fmt.Print(uid) + // hakurei requests hsurc user id + fmt.Print(id) os.Exit(0) } else if len(s) != 1 || s[0] > '9' || s[0] < '3' { log.Fatal("HAKUREI_SHIM holds an invalid value") @@ -92,6 +88,15 @@ func main() { shimSetupFd = s } + // allowed identity range 0 to 9999 + if as, ok := os.LookupEnv(envIdentity); !ok { + log.Fatal("HAKUREI_IDENTITY not set") + } else if identity, err := parseUint32Fast(as); err != nil || identity < 0 || identity > 9999 { + log.Fatal("invalid identity") + } else { + uid += identity + } + // supplementary groups var suppGroups, suppCurrent []int 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. |
