From ac494b50b4a0f52ae39badb6c13882600dbcbca3 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Thu, 30 Jul 2026 00:10:54 +0200 Subject: [PATCH] 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. --- server/server.go | 40 +++++++++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 5 deletions(-) diff --git a/server/server.go b/server/server.go index a3dd7d5..64d762e 100644 --- a/server/server.go +++ b/server/server.go @@ -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" }