fix infinite recursion in session/{sid}/agent directory

pathType() only recognized 'proc' as a subdirectory under sessions.
The 'agent' hierarchy (agent/, agent/{aid}/, agent/{aid}/proc/) was
falling through to 'return "file"', causing walk() to succeed with
QTFile at any depth. 9p ls then printed the basename 'agent' forever.

Fix: increase SplitN limit to 5, add directory cases for the full
agent path hierarchy, and verify the session exists before allowing
descent into any sub-path.
This commit is contained in:
Levi Neely 2026-07-30 00:10:54 +02:00
parent fee8d1bf36
commit ac494b50b4
1 changed files with 35 additions and 5 deletions

View File

@ -527,19 +527,28 @@ func (s *Server) pathType(path string) string {
if isSessionFile(path) {
return "file"
}
// Verify session exists.
if session.Lookup(s.sessionTree, name) == nil {
return ""
}
return "dir"
}
parts := strings.SplitN(name, "/", 5)
// Verify session exists before descending.
sess := session.Lookup(s.sessionTree, parts[0])
if sess == nil {
return ""
}
// /session/{id}/proc — directory
parts := strings.SplitN(name, "/", 3)
if len(parts) == 2 && parts[1] == "proc" {
return "dir"
}
// /session/{id}/agent — directory
if len(parts) == 2 && parts[1] == "agent" {
return "dir"
}
// /session/{id}/proc/{pid} — verify PID exists in detached list
if len(parts) == 3 && parts[1] == "proc" {
sess := session.Lookup(s.sessionTree, parts[0])
if sess == nil {
return ""
}
for _, p := range sess.Core.Agent().ListDetached() {
if fmt.Sprintf("%d", p.PID) == parts[2] {
return "file"
@ -547,6 +556,27 @@ func (s *Server) pathType(path string) string {
}
return ""
}
// /session/{id}/agent/{aid} — directory
if len(parts) == 3 && parts[1] == "agent" {
return "dir"
}
// /session/{id}/agent/{aid}/proc — directory
if len(parts) == 4 && parts[1] == "agent" && parts[3] == "proc" {
return "dir"
}
// /session/{id}/agent/{aid}/proc/{pid} — verify exists
if len(parts) == 5 && parts[1] == "agent" && parts[3] == "proc" {
for _, p := range sess.Core.Agent().ListDetached() {
if fmt.Sprintf("%d", p.PID) == parts[4] {
return "file"
}
}
return ""
}
// /session/{id}/agent/{aid}/{file} — file
if len(parts) >= 4 && parts[1] == "agent" {
return "file"
}
// /session/{id}/{file} — file
return "file"
}