@@ -840,22 +840,30 @@ func servicesListHandler(data []byte, resp RPCResponse) {
840840 }
841841
842842 serviceInfo , err := service .ListServices (servicesReq .Hostname )
843- /*
844- Errors from listing the services are not fatal. The client can
845- display a message to the user about the issue
846- We still want other errors like timeouts to be handled in the
847- normal way.
848- */
849- servicesResp := & sliverpb.Services {
850- Details : serviceInfo ,
851- Error : err .Error (),
852- Response : & commonpb.Response {},
853- }
843+ servicesResp := buildServicesResp (serviceInfo , err )
854844
855845 data , err = proto .Marshal (servicesResp )
856846 resp (data , err )
857847}
858848
849+ // buildServicesResp packages the result of service.ListServices into a
850+ // sliverpb.Services response. Errors from listing services are not fatal
851+ // (partial results may still be useful to the operator), so a non-nil error
852+ // is reported via the Error string field rather than failing the RPC.
853+ // The nil-check is load-bearing: callers previously called err.Error()
854+ // unconditionally, crashing the implant when ListServices succeeded cleanly.
855+ func buildServicesResp (details []* sliverpb.ServiceDetails , err error ) * sliverpb.Services {
856+ errStr := ""
857+ if err != nil {
858+ errStr = err .Error ()
859+ }
860+ return & sliverpb.Services {
861+ Details : details ,
862+ Error : errStr ,
863+ Response : & commonpb.Response {},
864+ }
865+ }
866+
859867func serviceDetailHandler (data []byte , resp RPCResponse ) {
860868 serviceDetailReq := & sliverpb.ServiceDetailReq {}
861869 err := proto .Unmarshal (data , serviceDetailReq )
0 commit comments