execute: ensure elevate adapter is running before elevated calls

Add ensureElevateAdapter() which probes the adapter socket and starts
elevate-adapter-start if unreachable. Runs in the execute server
process (outside the sandbox) so the adapter starts unsandboxed.
This commit is contained in:
ollie 2026-07-19 11:33:34 +02:00
parent 6f35059d83
commit 519869a003
1 changed files with 32 additions and 0 deletions

View File

@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"net"
"os"
"os/exec"
"path/filepath"
@ -404,6 +405,35 @@ func (e *Server) Close() {
}
}
// ensureElevateAdapter checks if the elevate adapter is reachable and starts
// it if not. Runs outside the sandbox so the adapter process is unsandboxed.
func ensureElevateAdapter() {
sock := os.Getenv("OLLIE_ELEVATE_SOCKET")
if sock == "" {
xdg := os.Getenv("XDG_RUNTIME_DIR")
if xdg == "" {
return
}
sock = filepath.Join(xdg, "ollie", "elevate.sock")
}
// Quick connect test
conn, err := net.DialTimeout("unix", sock, 500*time.Millisecond)
if err == nil {
conn.Close()
return
}
// Not running — start it
startScript := filepath.Join(PluginsPath(), "elevate-adapter-start")
if _, err := os.Stat(startScript); err != nil {
return
}
cmd := exec.Command(startScript) //nolint:gosec
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
_ = cmd.Run()
// Give it a moment to bind the socket
time.Sleep(300 * time.Millisecond)
}
// executeElevated runs cmd outside the sandbox via x/elevate.
// Returns (output, error); a non-zero exit code is treated as an error.
// If detach is true, the process is immediately backgrounded into the detach registry.
@ -413,6 +443,8 @@ func (e *Server) executeElevated(ctx context.Context, cmd, dir string, timeout i
return "", fmt.Errorf("elevation not available: x/elevate not found")
}
ensureElevateAdapter()
wantDetach := len(detach) > 0 && detach[0]
var cancel context.CancelFunc