From f9aa658c6da8902c69822dd8789db83df9a831f7 Mon Sep 17 00:00:00 2001 From: Austin Vazquez Date: Thu, 23 Jul 2026 14:57:36 -0500 Subject: [PATCH] fix(sandbox/vm): shut down vm.Instance when localsandbox.Start fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit localsandbox.Start calls vmm.NewInstance — which allocates resources on behalf of the caller — but only assigns s.instance on success. Any failure after NewInstance (AddDisk, AddFS, AddNIC, SetCPUAndMemory, or vmi.Start) returns without calling Shutdown, leaving an orphaned vm.Instance. localsandbox.Stop returns ErrFailedPrecondition when s.instance is nil, so there is no subsequent path that reaches Shutdown to release those resources. Add a deferred Shutdown after a successful NewInstance call, guarded by a vmiStarted flag that is only set true once vmi.Start succeeds and s.instance is assigned. This covers all failure paths without changing the success path. The Shutdown error is discarded on the cleanup path; the original Start error is what callers need. Signed-off-by: Austin Vazquez --- internal/shim/sandbox/vm/vm.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/internal/shim/sandbox/vm/vm.go b/internal/shim/sandbox/vm/vm.go index 1d4fbd89..62f8178f 100644 --- a/internal/shim/sandbox/vm/vm.go +++ b/internal/shim/sandbox/vm/vm.go @@ -75,6 +75,12 @@ func (s *localsandbox) Start(ctx context.Context, opts ...sandbox.Opt) error { if err != nil { return err } + vmiStarted := false + defer func() { + if !vmiStarted { + _ = vmi.Shutdown(ctx) + } + }() for _, d := range o.Disks { var mountOpts []vm.MountOpt @@ -126,6 +132,7 @@ func (s *localsandbox) Start(ctx context.Context, opts ...sandbox.Opt) error { return err } + vmiStarted = true s.instance = vmi return nil }