Repository navigation
fix(vz): stop the VM even when CanRequestStop is false - #5436
Conversation
6a1847b to
6060594
Compare
| func (l *LimaVzDriver) Stop(ctx context.Context) error { | ||
| logrus.Info("Shutting down VZ") | ||
| canStop := l.machine.CanRequestStop() | ||
| defer l.removePIDFile() |
There was a problem hiding this comment.
Do we need this explicitly now ??
If requestStop is not supported anyway we have ssh shutdown this should cover almost all cases. Even that doesn't work stop will end in error (having pid in this case is better right ??).
Just my take please let me know what you think
There was a problem hiding this comment.
With vz the PID file holds the PID of the process that runs the VM in-process: vz.pid is written with os.Getpid() in vm_darwin.go. Stop() is only called on the way out startRoutinesAndWait() at hostagent.go:530, and for an external driver the driver process is stopped on the next line by server.Stop().
So once Stop() returns, with or without an error, that PID is dead and the file cannot mean "the VM is still running".
The cleanup is also not only about the error path: nothing ever removes vz.pid, not even after a successful stop. qemu removes it in killQEMU() and krunkit in the goroutine that waits for the process; vz is the only driver that doesn't. It goes unnoticed today because ReadPIDFile() drops the PID file of a dead process, so within one boot it self-heals. After a reboot the PID may have been reused, and that is the broken state reported in #5087.
There was a problem hiding this comment.
🟡 Changes recommended
A rejected RequestStop result incorrectly suppresses the SSH fallback.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Improves graceful VZ shutdown and PID-file cleanup.
Changes:
- Falls back to SSH shutdown when VZ cannot request a stop.
- Extracts stop waiting and PID cleanup helpers with tests.
File summaries
| File | Description |
|---|---|
pkg/driver/vz/vz_driver_darwin.go |
Updates shutdown and cleanup behavior. |
pkg/driver/vz/vz_driver_darwin_test.go |
Tests waiting and PID removal. |
Review details
- Files reviewed: 2/2 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
6060594 to
8a2a03c
Compare
`LimaVzDriver.Stop()` returned an error without stopping the VM when `CanRequestStop()` reported false, and it never removed the driver PID file. When launchd sends SIGTERM to the host agent of a LaunchDaemon instance, the host agent exits with `vz: CanRequestStop is not supported` and leaves `vz.pid` behind. Within the same boot this is harmless, because `ReadPIDFile` removes the PID file of a dead process, but after a reboot the recorded PID may have been reused by an unrelated process. The instance then shows up as `Broken` with "vz driver is running but host agent is not", and launchd with `KeepAlive` crash-loops `limactl start`. Ask the guest to shut down over SSH whenever the request could not be made through the Virtualization framework, not only for the macOS guests that ignore `RequestStop()`. The VM is never stopped forcibly with `VirtualMachine.Stop()`: that does not give the guest a chance to stop cleanly, and may corrupt the disk. Always remove the PID file when the driver stops, as the qemu and krunkit drivers already do. Related to lima-vm#5087 Signed-off-by: Eugene Kalinin <e.v.kalinin@gmail.com>
8a2a03c to
ce10d54
Compare
|
@balajiv113 Was your concern resolved? |
A host agent that dies without stopping the VM can leave an instance in one of two broken states, and `limactl start` then refuses to start it until they are cleared by hand. Recover from both instead: - the VM driver is running with no host agent attached, which is force-stopped; - nothing is listening on the host agent socket, whose files are removed without signaling any process, since the recorded PID may since belong to an unrelated one. Only the host agent's own ha.pid and ha.sock are removed. A driver that runs as its own process may still be alive, and deleting its PID file would hide it from the next inspection and allow a second driver to be started for the same instance; the exception is a driver that runs the VM inside the host agent process, such as vz, which records the same PID and so is removed with them. The two run in sequence rather than as alternatives, because clearing a departed host agent can reveal a driver that is still running and has to be stopped on its own. Doing that after ha.pid is gone also means the force stop cannot signal a reused PID. Two upstream changes have since narrowed how these states arise, without closing them. e529ce0 makes `ReadPIDFile` ignore PID files written during a previous boot, which covers PID reuse across a reboot. lima-vm#5436 removes `vz.pid` whenever the vz driver stops, which covers the launchd SIGTERM path for vz. What is left: - a driver that runs as its own process, such as qemu, outliving a host agent that died within the same boot. No reboot and no PID reuse are needed, and nothing stops that VM or clears its PID file; - PID reuse within a single boot; - instances whose directory carries no boot session marker, because they were started by an older version of Lima; - platforms that expose no boot session ID (`osutil.ErrBootSessionNotSupported`), where PID files are handled as they were before the marker. lima-vm#5436 fixed the first of the two bugs of lima-vm#5087; this is the rest of it. Fixes lima-vm#5087. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Signed-off-by: Robert Esker <resker@gmail.com>
`limactl info` listed VM types with their location only, so there was no way to
ask what a driver supports. Anything that needed to know had to hardcode a list
of VM types, e.g. the `qemu | krunkit` whitelist in the snapshot bats test.
Add DriverFeatures.CanSnapshot and report each driver's features per VM type
under vmTypesEx. Internal drivers are queried directly; external drivers are
started in a temporary directory, queried, and stopped again, so no instance
is touched. Features are omitted when a driver cannot be queried, so a driver
that fails to start does not break the command.
Signed-off-by: ChengyuZhu6 <hudson@cyzhu.com>
Merge pull request #5508 from olamilekan000/5312-structured-snapshots
driver: return structured snapshot metadata
driver: return structured snapshot metadata
Signed-off-by: olamilekan000 <odukoyaonline@gmail.com>
Merge pull request #5575 from lima-vm/dependabot/go_modules/github.com/foxcpp/go-mockdns-1.3.0
build(deps): bump github.com/foxcpp/go-mockdns from 1.2.0 to 1.3.0
Merge pull request #5576 from lima-vm/dependabot/go_modules/github.com/pb33f/ordered-map/v2-2.3.2
build(deps): bump github.com/pb33f/ordered-map/v2 from 2.3.1 to 2.3.2
Merge pull request #5577 from lima-vm/dependabot/go_modules/github.com/klauspost/compress-1.20.1
build(deps): bump github.com/klauspost/compress from 1.18.5 to 1.20.1
build(deps): bump github.com/klauspost/compress from 1.18.5 to 1.20.1
Bumps [github.com/klauspost/compress](https://github.com/klauspost/compress) from 1.18.5 to 1.20.1.
- [Release notes](https://github.com/klauspost/compress/releases)
- [Commits](https://github.com/klauspost/compress/compare/v1.18.5...v1.20.1)
---
updated-dependencies:
- dependency-name: github.com/klauspost/compress
dependency-version: 1.20.1
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
build(deps): bump github.com/pb33f/ordered-map/v2 from 2.3.1 to 2.3.2
Bumps [github.com/pb33f/ordered-map/v2](https://github.com/pb33f/ordered-map) from 2.3.1 to 2.3.2.
- [Changelog](https://github.com/pb33f/ordered-map/blob/master/CHANGELOG.md)
- [Commits](https://github.com/pb33f/ordered-map/compare/v2.3.1...v2.3.2)
---
updated-dependencies:
- dependency-name: github.com/pb33f/ordered-map/v2
dependency-version: 2.3.2
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
build(deps): bump github.com/foxcpp/go-mockdns from 1.2.0 to 1.3.0
Bumps [github.com/foxcpp/go-mockdns](https://github.com/foxcpp/go-mockdns) from 1.2.0 to 1.3.0.
- [Release notes](https://github.com/foxcpp/go-mockdns/releases)
- [Commits](https://github.com/foxcpp/go-mockdns/compare/v1.2.0...v1.3.0)
---
updated-dependencies:
- dependency-name: github.com/foxcpp/go-mockdns
dependency-version: 1.3.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Merge pull request #5559 from Sarthak-Shreshtha01/fix/issue-5552
templates/k8s: accept an https:// url when joining a node
Merge pull request #5460 from bcollard/fix/additional-disks-label-truncation
Do not identify additional disks by filesystem label
Do not identify additional disks by filesystem label
An `additionalDisks` entry whose name did not fit in the filesystem label
was reformatted on every boot, silently destroying its contents.
`mkfs.ext4` silently truncates the label to 16 bytes, so a name longer
than 11 characters produced a label that could never match the
`/dev/disk/by-label/lima-${DISK_NAME}` node the first-time-setup guard
tested for. The guard was true on every boot and `mkfs` ran again. The
disk still mounted, because the mount uses the device path, so nothing
appeared to be wrong. (`mkfs.xfs` instead rejects a label over 12 bytes,
so an xfs disk with a name over 7 characters was never formatted at all.)
Identify the disk by the presence of a filesystem on its partition
instead: the guard tests whether `blkid -o value -s TYPE` prints anything.
It tests the output rather than the exit status, because util-linux blkid
exits 0 for a bare GPT partition-table entry that has no filesystem yet,
and BusyBox blkid (Alpine) ignores -o and -s and always exits 0. This
removes the length limit and, because a disk formatted by an older Lima
version also carries a filesystem, such disks are recognised rather than
reformatted on upgrade. A partition left without a filesystem by an
interrupted boot or a failed mkfs is formatted on the next boot. The
guard fails closed: if blkid is missing or reports an error, the disk is
left alone, so a disk whose state cannot be determined is never
reformatted.
The labels are kept as a convenience and clamped to what each filesystem
accepts, so that `mkfs.xfs` no longer aborts the boot. A GPT partition
label, which holds 36 characters, now carries the name as well. For an
fsType not listed here, the limit (and even whether mkfs.$FORMAT_FSTYPE
accepts a label at all) is unknown, so no label is set rather than guess
and risk aborting boot. The label is passed without a bash array, since
on Alpine /bin/bash is BusyBox ash, which has none.
Over-long names are reported at info level rather than as an error: the
disk works correctly now that identification does not depend on the
label. The notice is limited to Linux guests and disks Lima formats, the
only case in which a label is written. The `additionalDisks` comment in
the default template now points at the partition label, which keeps
names of up to 31 characters whole.
The disk-mount test regression check used a plain substring match, which
the new long-named disk's mount point ("/mnt/lima-data-with-a-long-name")
also satisfies, silently defeating the original disk's assertion. Anchor
the pattern to end-of-line.
Fixes #5407
Assisted-by: Claude Code
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Baptiste Collard <9626829+bcollard@users.noreply.github.com>
Merge pull request #5514 from lima-vm/fix/5466
driver(hcs): drop dependency on `qemu-img` for VHDX image conversion
templates/k8s: accept an https:// url when joining a node
The documentation and the k3s template pass the control plane as a
URL ("https://<ADDRESS>:6443"), but the k8s template put the url
param into apiServerEndpoint unchanged, and kubeadm expects a bare
host:port there, so the documented command did not work.
Strip the https:// prefix in the template, so both forms work, and
make the template comment and the BATS test use the URL form.
Fixes #5552
Signed-off-by: Sarthak <sarthakshreshtha345@gmail.com>
driver(hcs): drop dependency on qemu-img
Signed-off-by: unsuman <anshumansahoo500@gmail.com>
Merge pull request #5480 from SABITHSAHEB/apfs-gpt-header-bounds
apfs: bound GPT partition entry size and count before use
Merge pull request #5560 from jandubois/wsl2-no-distributions
wsl2: handle a host with no WSL distributions
Merge pull request #5558 from aka-rider/portfwd-current-client
portfwd: dial through the current guest agent client, not the (poissibly stale one) captured at listen time
Merge pull request #5563 from kolyshkin/fix-rawhide-url
limactl-url-fedora-rawhide: don't rely on COMPOSE_ID
Merge pull request #5562 from AkihiroSuda/dev
templates: update
limactl-url-fedora-rawhide: don't rely on COMPOSE_ID
The rawhide/COMPOSE_ID file on dl.fedoraproject.org is sometimes out of
sync with the contents of the images directory. For example, currently
COMPOSE_ID says Fedora-Rawhide-20260929.n.0, while the only image
available is Fedora-Cloud-Base-Generic-Rawhide-20261002.n.0, so
starting an instance from experimental/fedora-rawhide fails with:
failed to download `https://dl.fedoraproject.org/pub/fedora/linux/development/rawhide/Cloud/x86_64/images/Fedora-Cloud-Base-Generic-Rawhide-20260929.n.0.x86_64.qcow2`: unexpected HTTP status Not Found
Instead, get the image file name from the CHECKSUM file in the images
directory, which describes the images actually present there. As a
bonus, this also gives us the image digest.
While at it, add --retry to curl invocations.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Merge pull request #5561 from AkihiroSuda/nerdctl
nerdctl: update from v2.4.0 to v2.4.1
templates: update
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Merge pull request #5405 from SABITHSAHEB/wsl2-ssh-address-validate
wsl2: validate guest-reported address in getSSHAddress
nerdctl: update from v2.4.0 to v2.4.1
https://github.com/containerd/nerdctl/releases/tag/v2.4.1
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
CI: drop the dummy WSL2 distro
CI imported an empty distro because the WSL2 driver failed when WSL had
no distributions. The driver handles that case now, so CI can test it by
running the WSL2 jobs with no distributions installed.
Signed-off-by: Jan Dubois <jan.dubois@suse.com>
Driver: WSL2: Better handle no distributions
This fixes the case where WSL is installed, but no distributions are
installed at all. In that case, newer versions of WSL no longer prints the
error code `Wsl/WSL_E_DEFAULT_DISTRO_NOT_FOUND` (or indeed, any error code
at all).
Instead of trying to parse error messages, use the WSL API to check if the
distribution exists. However, the API is very limited and does not allow
us to check the state of the distribution in the case it _does_ exist, so
we still need to parse the text for that.
If WSL is not installed, using the WSL API causes a command prompt window
to appear with a prompt to install WSL. To avoid showing that, try to
detect whether WSL is installed by opening its registry key.
Signed-off-by: Mark Yen <mark.yen@suse.com>
Signed-off-by: Jan Dubois <jan.dubois@suse.com>
Merge pull request #5342 from jandubois/ci-plain-windows-jobs
CI: factor Windows setup into composite actions; add plain-Windows jobs
Merge pull request #5198 from ekalinin/feat-4065-disk-mountpoint
additionalDisks: support custom mountPoint and optional mounting
Merge pull request #5556 from lima-vm/dependabot/go_modules/hack/tools/github.com/golangci/golangci-lint/v2-2.14.0
build(deps): bump github.com/golangci/golangci-lint/v2 from 2.13.2 to 2.14.0 in /hack/tools
additionalDisks: support custom mountPoint and optional mounting
Additional disks were always mounted at the hardcoded path
/mnt/lima-<name>, with no way to change that location or to attach a disk
without Lima mounting it. Issue #4065 asks for both: a custom mount point
and an attach-only mode so the guest can manage the disk itself (a
flexibility Colima can benefit from).
Add two optional, backwards-compatible fields to each additionalDisks
entry:
- mountPoint: absolute guest path to mount at (default /mnt/lima-<name>)
- mount: whether Lima auto-mounts the disk (default true; false attaches
the disk without mounting it)
A separate `mount` boolean is used rather than overloading an empty
mountPoint, per the discussion in #4065. nil for either field preserves
the current behavior. Values are passed to the guest via
LIMA_CIDATA_DISK_<i>_MOUNT / _MOUNTPOINT and honored by 05-lima-disks.sh
(non-swap disks only). mountPoint is validated to be an absolute guest
path (path.IsAbs, not the host-dependent filepath.IsAbs) and neither a
critical system path nor the reserved guest home directory.
Fixes #4065
Signed-off-by: Eugene Kalinin <e.v.kalinin@gmail.com>
portfwd: dial through the current guest agent client, not the one captured at listen time
processGuestAgentEvents built one dialer per event stream and the
listeners kept it for their whole lifetime. When the guest agent was
unreachable at the 10 s check, getOrCreateClient closed that client
and opened a new one, so every accepted host connection failed with
"grpc: the client connection is closing". Resolve the client per dial.
Signed-off-by: Iurii Krasnoshchok <github@iurii.net>
Assisted-by: Claude Code
build(deps): bump github.com/golangci/golangci-lint/v2 in /hack/tools
Bumps [github.com/golangci/golangci-lint/v2](https://github.com/golangci/golangci-lint) from 2.13.2 to 2.14.0.
- [Release notes](https://github.com/golangci/golangci-lint/releases)
- [Changelog](https://github.com/golangci/golangci-lint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/golangci/golangci-lint/compare/v2.13.2...v2.14.0)
---
updated-dependencies:
- dependency-name: github.com/golangci/golangci-lint/v2
dependency-version: 2.14.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
autostart: export AutoStartManager interface
golangci-lint v2.14.0 (revive v1.17.0) reports `unexported-return`
for Manager, ManagerWith, and DaemonManager returning the unexported
autoStartManager type.
Assisted-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Merge pull request #5399 from mvanhorn/fix/5389-disable-llmnr-login-delay
fix: Disable LLMNR to prevent Debian SSH login delay
Merge pull request #5546 from Sarthak-Shreshtha01/fix/issue-5545
guestagent: close the gRPC connection when a write fails
Merge pull request #5528 from trodemaster/feat/vz-guest-os-version-log
feat(vz): record the guest macOS version from the restore image
CI: factor Windows setup into composite actions; add plain-Windows jobs
Lima should run on a Windows host whose only ssh is the native OpenSSH
client, but the existing Windows jobs run with Git for Windows and MSYS2
installed, so a new dependency on their tools would go unnoticed. The
plain-Windows jobs remove both toolchains before testing.
The MSYS2 jobs got a Cygwin ssh from Git for Windows through
_LIMA_WINDOWS_EXTRA_PATH and now install MSYS2's openssh instead. That
was the experimental variable's last use in the repo, so remove it.
The MSYS2 jobs also install rsync, so the integration tests cover the
rsync copy backend on Windows. Because MSYS2 setup now runs before the
unit tests and make, the unit tests that skip without rsync run on
Windows too.
The WSL2 job's id changes from windows to windows-wsl2.
Signed-off-by: Jan Dubois <jan.dubois@suse.com>
copytool: expect converted paths in TestRsyncCommandPaths on Windows
On Windows, Command converts each local path for the rsync it runs,
because a Cygwin or MSYS rsync reads "C:" as a host. The test still
expected the paths as given, but no Windows CI job had rsync on
PATH when the unit tests ran, so it always skipped there.
Convert the expected paths the same way.
Signed-off-by: Jan Dubois <jan.dubois@suse.com>
Merge pull request #5554 from somaz94/krunkit-lock-for-instance
krunkit: auto-unlock disk locked to the same instance on startup
Merge pull request #5555 from lima-vm/fix/5551
CI: tolerate systemd-binfmt failure on wsl2
Merge pull request #5553 from lima-vm/dependabot/github_actions/codeql-action-9d88a12d2b
build(deps): bump the codeql-action group with 3 updates
Merge pull request #5299 from jandubois/copytool-native-windows-openssh
copytool: support native Windows OpenSSH
CI: tolerate systemd-binfmt failure on wsl2
WSL 3.0.1 mounts /proc/sys/fs/binfmt_misc read-only, so systemd-binfmt
cannot flush its rules and exits 1. That leaves the guest "degraded" and
fails the systemd check even though the instance is fully functional.
The behaviour is host-side and reproduces with any rootfs, so add the
unit to the set of failures lima does not control, scoped to vmType wsl2.
Fixes #5551
Signed-off-by: unsuman <anshumansahoo500@gmail.com>
guestagent: close the gRPC connection when a write fails
If the gRPC server fails to write, it stops sending but keeps reading.
The connection then stays half-open: requests reach the guest, but no
response ever comes back, and the host agent never reconnects.
Close the connection on the first write error, so that the read side
fails too and the host agent reconnects.
Fixes #5545
Signed-off-by: Sarthak <sarthakshreshtha345@gmail.com>
krunkit: auto-unlock disk locked to the same instance on startup
Signed-off-by: somaz <genius5711@gmail.com>
build(deps): bump the codeql-action group with 3 updates
Bumps the codeql-action group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).
Updates `github/codeql-action/init` from 4.38.1 to 4.38.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/1c5b675653bb5c22dbe9b12b556ec555138e09fd...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2)
Updates `github/codeql-action/analyze` from 4.38.1 to 4.38.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/1c5b675653bb5c22dbe9b12b556ec555138e09fd...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2)
Updates `github/codeql-action/upload-sarif` from 4.38.1 to 4.38.2
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/1c5b675653bb5c22dbe9b12b556ec555138e09fd...2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2)
---
updated-dependencies:
- dependency-name: github/codeql-action/init
dependency-version: 4.38.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: codeql-action
- dependency-name: github/codeql-action/analyze
dependency-version: 4.38.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: codeql-action
- dependency-name: github/codeql-action/upload-sarif
dependency-version: 4.38.2
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: codeql-action
...
Signed-off-by: dependabot[bot] <support@github.com>
Merge pull request #5548 from jandubois/lint-quick-exclude-deepwiki
CI: lint-quick: ignore deepwiki.com 429
CI: lint-quick: ignore deepwiki.com 429
deepwiki.com now answers non-browser clients with a Vercel bot
challenge that returns 429, so the README's DeepWiki badge has failed
every lint-quick run since 2026-09-28. GitHub's image proxy still
fetches the badge, so readers see it.
Signed-off-by: Jan Dubois <jan.dubois@suse.com>
Merge pull request #5088 from resker/feature/vz-shutdown-recovery
fix(start): recover from the broken states left by an unclean shutdown
Merge pull request #5117 from pirate/secure-vz-block-devices
Secure macOS VZ block-device attachment
Merge pull request #5538 from lima-vm/dependabot/github_actions/codeql-action-97c20ee9f3
build(deps): bump the codeql-action group across 1 directory with 3 updates
build(deps): bump the codeql-action group across 1 directory with 3 updates
Bumps the codeql-action group with 3 updates in the / directory: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).
Updates `github/codeql-action/init` from 4.38.0 to 4.38.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/b96794f015dfd88f77b49b1c93e0fa7110f94c63...1c5b675653bb5c22dbe9b12b556ec555138e09fd)
Updates `github/codeql-action/analyze` from 4.38.0 to 4.38.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/b96794f015dfd88f77b49b1c93e0fa7110f94c63...1c5b675653bb5c22dbe9b12b556ec555138e09fd)
Updates `github/codeql-action/upload-sarif` from 4.38.0 to 4.38.1
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/b96794f015dfd88f77b49b1c93e0fa7110f94c63...1c5b675653bb5c22dbe9b12b556ec555138e09fd)
---
updated-dependencies:
- dependency-name: github/codeql-action/analyze
dependency-version: 4.38.1
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: codeql-action
- dependency-name: github/codeql-action/init
dependency-version: 4.38.1
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: codeql-action
- dependency-name: github/codeql-action/upload-sarif
dependency-version: 4.38.1
dependency-type: direct:production
update-type: version-update:semver-patch
dependency-group: codeql-action
...
Signed-off-by: dependabot[bot] <support@github.com>
Merge pull request #5544 from unsuman/fix-5511
driver(qemu): disable the TPM PPI on HVF with QEMU >= 11.0
Merge pull request #5542 from unsuman/fix-lima-social-link
fix(docs): replace broken Twitter/X URL in README
driver(qemu): disable the TPM PPI on HVF with QEMU >= 11.0
Signed-off-by: Ansuman Sahoo <anshumansahoo500@gmail.com>
wsl2: validate guest-reported address in getSSHAddress
getSSHAddress reads the instance address from commands run inside the
guest; only the fallback probe checked that the output was an IP, the
first two returned it verbatim. The pipeline in the first probe exits 0
even when hostname does not support -I, so its usage text could become
inst.SSHAddress and end up on the ssh/scp/rsync command line instead of
falling through to the next probe.
Route all three probes through one helper that accepts only global
unicast addresses (private and ULA ranges included), so unspecified,
loopback, link-local and multicast values fall through the same way
127.0.1.1 already did in the fallback.
Signed-off-by: Sabith Saheb <shabi7204192361@gmail.com>
fix: disable LLMNR to prevent Debian SSH login delay
systemd-resolved's LLMNR probe adds a multi-second delay to SSH logins on
Debian. Debian 13's sshd passes an UNKNOWN peer address for vsock connections
to Linux audit, which resolves it via LLMNR; that lookup is the delay.
Set LLMNR=no, gated behind the internal_disableLLMNR param so only the
Debian 13 image template opts in, mirroring the Ubuntu 26.04 workaround
pattern. Other distros keep LLMNR untouched.
Compare the param against the literal "true" rather than testing it for
non-emptiness, so setting it to "false" does not still emit LLMNR=no.
template_test covers "", "false" and "true", so reverting the template
alone fails that subtest.
Record in the debian-13 template why the workaround exists, with the
upstream OpenSSH commit that removes the need for it and the Debian bug
report tracking it downstream.
Fixes #5389
Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
fix broken X link in README
Signed-off-by: Ansuman Sahoo <anshumansahoo500@gmail.com>
Merge pull request #5537 from lima-vm/dependabot/go_modules/hack/tools/google.golang.org/grpc-1.84.0
build(deps): bump google.golang.org/grpc from 1.83.2 to 1.84.0 in /hack/tools
build(deps): bump google.golang.org/grpc in /hack/tools
Bumps [google.golang.org/grpc](https://github.com/grpc/grpc-go) from 1.83.2 to 1.84.0.
- [Release notes](https://github.com/grpc/grpc-go/releases)
- [Commits](https://github.com/grpc/grpc-go/compare/v1.83.2...v1.84.0)
---
updated-dependencies:
- dependency-name: google.golang.org/grpc
dependency-version: 1.84.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Support secure host block-device attachment on macOS VZ
Attach explicitly allowed host disks through a dedicated root-owned helper,
passing validated file descriptors to unprivileged VZ over an authenticated
Unix socket. Scope sudoers grants to the invoking user and exact device paths,
reject unsafe helper paths and socket symlinks, authenticate both peers, and
validate the received device identity.
Retain descriptors per VM while preserving process-lifetime network wrappers
used by krunkit. Lock whole host disks across instances sharing LIMA_HOME,
including raw/block aliases and partitions. Reject duplicate configuration
entries and external VZ drivers at runtime.
Compose network and block-device sudoers fragments through pkg/sudoers, match
complete generated lines, and warn when regeneration removes existing grants.
Keep integration-test grants in temporary fragments and revoke them before
detaching the test RAM disk. Add security, lifecycle, and real-disk regression
coverage and document installation requirements and remaining grant limits.
Signed-off-by: Nick Sweeting <git@sweeting.me>
feat(vz): record the guest macOS version from the restore image
When creating a macOS guest, the vz driver loads the IPSW as a
VZMacOSRestoreImage and reads only the hardware model from it, then
removes the IPSW after installation. The image also carries the OS
version and build number, which are otherwise lost at that point.
Log both and persist them next to vz-hwmodel as vz-guest-os-version and
vz-guest-os-build-version, written once when the hardware model is
extracted. store.ReadGuestOSVersion reads them back (empty when unknown,
e.g. for instances created before this change), so that host-side steps
such as disk patching and cidata generation can select behavior by guest
macOS version. For macOS guests, cidata also exposes the values to
provisioning scripts as LIMA_CIDATA_GUEST_OS_VERSION and
LIMA_CIDATA_GUEST_OS_BUILD_VERSION, emitted empty when unknown like the
other optional LIMA_CIDATA_* variables.
The values describe the restore image, i.e. the guest at first boot;
they do not track later OS updates.
Signed-off-by: Blake Garner <blake@netjibbing.com>
docs(autostart): document unclean shutdown recovery
Describe the two broken states an instance can be left in when its host agent dies
without stopping the VM, when they are likely to occur, and what `limactl start`
does about each.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Robert Esker <resker@gmail.com>
fix(start): recover from the broken states left by an unclean shutdown
A host agent that dies without stopping the VM can leave an instance in one of two
broken states, and `limactl start` then refuses to start it until they are cleared
by hand. Recover from both instead:
- the VM driver is running with no host agent attached, which is force-stopped;
- nothing is listening on the host agent socket, whose files are removed without
signaling any process, since the recorded PID may since belong to an unrelated
one.
Only the host agent's own ha.pid and ha.sock are removed. A driver that runs as
its own process may still be alive, and deleting its PID file would hide it from
the next inspection and allow a second driver to be started for the same
instance; the exception is a driver that runs the VM inside the host agent
process, such as vz, which records the same PID and so is removed with them.
The two run in sequence rather than as alternatives, because clearing a departed
host agent can reveal a driver that is still running and has to be stopped on
its own. Doing that after ha.pid is gone also means the force stop cannot signal
a reused PID.
Two upstream changes have since narrowed how these states arise, without closing
them. e529ce08 makes `ReadPIDFile` ignore PID files written during a previous boot,
which covers PID reuse across a reboot. #5436 removes `vz.pid` whenever the vz
driver stops, which covers the launchd SIGTERM path for vz. What is left:
- a driver that runs as its own process, such as qemu, outliving a host agent that
died within the same boot. No reboot and no PID reuse are needed, and nothing
stops that VM or clears its PID file;
- PID reuse within a single boot;
- instances whose directory carries no boot session marker, because they were
started by an older version of Lima;
- platforms that expose no boot session ID (`osutil.ErrBootSessionNotSupported`),
where PID files are handled as they were before the marker.
#5436 fixed the first of the two bugs of #5087; this is the rest of it.
Fixes #5087.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Robert Esker <resker@gmail.com>
fix(store): name the recoverable broken states, and only when provable
An unclean shutdown can leave an instance in one of two broken states that
`limactl start` is able to recover from. Give each a sentinel error so callers
can match it with `errors.Is` rather than comparing message strings:
`ErrDriverRunningHostAgentStopped` when the VM driver outlives the host agent,
and `ErrHostAgentUnreachable` when nothing is listening on the host agent socket.
The second is reported only on ECONNREFUSED, which is the one outcome that
proves the host agent recorded in ha.pid is gone. A timeout, a protocol error,
or a socket that does not exist yet may all come from a live host agent --
including one that has written its PID file but not yet bound its socket -- and
must not be recoverable: a caller acting on the sentinel would remove that
agent's files and start a second host agent for the same instance. Such failures
are still recorded and still leave the instance Broken.
On Windows the sockets layer reports WSAECONNREFUSED, which `syscall.Errno.Is`
does not map to `syscall.ECONNREFUSED`, so the sentinel never fires there. The
state is reported without being recovered from automatically, which is the safe
direction; the recovery exists for launchd-managed instances on macOS.
The tests drive the real host agent client against a unix socket, so they cover
the error chain that Inspect actually sees rather than synthetic values.
Part of #5087.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: Robert Esker <resker@gmail.com>
Merge pull request #5527 from lima-vm/dependabot/go_modules/github.com/lima-vm/go-qcow2reader-0.8.0
build(deps): bump github.com/lima-vm/go-qcow2reader from 0.7.1 to 0.8.0
build(deps): bump github.com/lima-vm/go-qcow2reader from 0.7.1 to 0.8.0
Bumps [github.com/lima-vm/go-qcow2reader](https://github.com/lima-vm/go-qcow2reader) from 0.7.1 to 0.8.0.
- [Release notes](https://github.com/lima-vm/go-qcow2reader/releases)
- [Commits](https://github.com/lima-vm/go-qcow2reader/compare/v0.7.1...v0.8.0)
---
updated-dependencies:
- dependency-name: github.com/lima-vm/go-qcow2reader
dependency-version: 0.8.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Merge pull request #5523 from jandubois/fix-readpidfile
store/instance: Fix finding process by pid file
Merge pull request #5436 from ekalinin/fix/vz-clean-shutdown
fix(vz): stop the VM even when CanRequestStop is false
Merge pull request #5525 from lima-vm/dependabot/go_modules/hack/tools/github.com/AkihiroSuda/gosocialcheck-0.2.0
build(deps): bump github.com/AkihiroSuda/gosocialcheck from 0.1.3 to 0.2.0 in /hack/tools
Merge pull request #5524 from lima-vm/dependabot/go_modules/github.com/mattn/go-shellwords-1.0.15
build(deps): bump github.com/mattn/go-shellwords from 1.0.14 to 1.0.15
build(deps): bump github.com/AkihiroSuda/gosocialcheck in /hack/tools
Bumps [github.com/AkihiroSuda/gosocialcheck](https://github.com/AkihiroSuda/gosocialcheck) from 0.1.3 to 0.2.0.
- [Release notes](https://github.com/AkihiroSuda/gosocialcheck/releases)
- [Commits](https://github.com/AkihiroSuda/gosocialcheck/compare/v0.1.3...v0.2.0)
---
updated-dependencies:
- dependency-name: github.com/AkihiroSuda/gosocialcheck
dependency-version: 0.2.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
build(deps): bump github.com/mattn/go-shellwords from 1.0.14 to 1.0.15
Bumps [github.com/mattn/go-shellwords](https://github.com/mattn/go-shellwords) from 1.0.14 to 1.0.15.
- [Release notes](https://github.com/mattn/go-shellwords/releases)
- [Commits](https://github.com/mattn/go-shellwords/compare/v1.0.14...v1.0.15)
---
updated-dependencies:
- dependency-name: github.com/mattn/go-shellwords
dependency-version: 1.0.15
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
store/instance: Fix finding process by pid file
On Windows, `os.FindProcess()` returns an error if the pid given does not
correspond to a valid process; this is unlike *nix, where it succeeds, and
the caller must attempt to send a signal to the target process to know if
it is still alive. Catch that error on Windows and return no error to
match the other cases.
The underlying Win32 call `OpenProcess` returns ERROR_INVALID_PARAMETER on
either invalid pid (e.g. 0), as well as valid pids that do not exist. So
we can only catch that generic case and swallow the error.
Signed-off-by: Mark Yen <mark.yen@suse.com>
(cherry picked from commit 8a338c8cf5c1ca598cc8a0abe1f5300a2f5c4569)
Merge pull request #5509 from AkihiroSuda/nerdctl
nerdctl: update from v2.3.5 to v2.4.0
nerdctl: update from v2.3.5 to v2.4.0
https://github.com/containerd/nerdctl/releases/tag/v2.4.0
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
copytool: support native Windows OpenSSH
On Windows, `limactl copy` converted host paths to the Cygwin/MSYS form
no matter which tool would consume them, and it passed ControlMaster
options unconditionally. Native OpenSSH cannot use that path form and
has no multiplexing, so scp failed with "getsockname failed".
The two backends need different path forms. scp takes whatever its own
toolchain uses, while rsync on Windows is always Cygwin-based and reads
a drive letter as a hostspec. So every path now takes the form of the
binary that reads it, operands and ssh options alike, because scp hands
its options to the ssh beside itself while rsync hands them to the ssh
it names.
Both backends now skip multiplexing on Windows, so they stop building
a control socket path they never use.
Signed-off-by: Jan Dubois <jan.dubois@suse.com>
Merge pull request #5503 from AkihiroSuda/macos-27
templates: add macos-27 (Golden Gate)
Merge pull request #5337 from jandubois/copytool-parse-error
copytool: report a bad path instead of a missing tool
Merge pull request #5341 from jandubois/docs-plain-windows-wsl2
docs: document the Windows host SSH toolchain
docs: clarify that macOS guests need the host macOS to be newer
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
templates: add macos-27 (Golden Gate)
Add the `macos-27` template for macOS 27 "Golden Gate" (27.0, build 26A428),
and repoint the `macos` aliases (`templates/macos.yaml` and
`templates/_images/macos.yaml`) from `macos-26` to `macos-27`.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
hack: accept IPSW URLs without the "fullrestores" path component
Apple changed the IPSW path layout for macOS 27.0; the URL no longer
contains the `fullrestores` path component:
https://updates.cdn-apple.com/2026FallFCS/<uuid>/UniversalMac_27.0_26A428_Restore.ipsw
The regex in `hack/update-template-macos.sh` did not match this layout, and
`macos_url_spec_from_location` just returns non-zero on a mismatch, so the
script would silently skip such a template rather than fail. Relax the path
part of the regex to accept any depth.
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
docs: document $SSH and correct the Windows SSH notes
The $SSH environment variable replaces the ssh command Lima runs, and
the environment variables page had no entry for it. Describe it.
The QEMU page said nothing about the Windows host's ssh binaries, and
the WSL2 page claimed Windows ships no ssh.exe.
These pages describe the state after the copytool work lands, so merge
this commit after it.
Signed-off-by: Jan Dubois <jan.dubois@suse.com>
copytool: report a bad path instead of a missing tool
A path naming an instance that does not exist reached the user as
"neither rsync nor scp found on host", because the auto backend
discarded the parse error, skipped rsync, and reported whatever the scp
fallback said. Only a host without scp saw that message; everywhere else
the auto backend built the copy tool without complaint and the real
error surfaced later, from the copy command itself. The explicit rsync
backend reduced the same error to "rsync not available on guest(s)".
The fallback message no longer guesses which tool is missing, since
rsync may well have been found and rejected for another reason.
Signed-off-by: Jan Dubois <jan.dubois@suse.com>
Merge pull request #5512 from AkihiroSuda/fix-5510
hack/tools: go mod tidy
hack/tools: go mod tidy
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Merge pull request #5220 from afbjorklund/sbom
Add SBOM artifact using cyclonedx-gomod
Merge pull request #5484 from unsuman/net/pr2-lima-net-daemon
networks: add the `lima-privileged-net` daemon and tap device naming
networks: add the lima-privileged-net daemon and tap device naming
Generalize the daemon handling in pkg/networks, which so far assumed that
socket_vmnet is the only privileged helper, and describe the Linux helper
(lima-privileged-net) next to it:
- RequiredDaemons() returns the helpers needed on the current host, so the
callers no longer have to hardcode socket_vmnet.
- paths.limaPrivilegedNet holds the path of the Linux helper, mirroring
paths.socketVMNet.
- StartCmd() renders the lima-privileged-net command line, and TapCmd() the
command that attaches an instance to the bridge of a network.
- TapName() derives a tap device name that fits into IFNAMSIZ, and
TapNamePattern() renders the matching sudoers wildcard. IsTapName() and
IsManagedBridge(), which recognize the names TapName() and BridgeName()
generate, were added alongside the helper itself in the previous commit.
- DigestSpec() hashes a daemon binary so that the sudoers rules generated by
the next commit can pin it with a sudo `Digest_Spec`.
Signed-off-by: Ansuman Sahoo <anshumansahoo500@gmail.com>
Merge pull request #5375 from jandubois/apparmor-allow-lima-mount-points
cidata: allow apparmor mounts on every Lima mount point
Merge pull request #5501 from AkihiroSuda/fix-5500
copytool: make `copy -r` into an existing directory consistent across backends
copytool: make `copy -r` into an existing directory consistent across backends
For a recursive copy whose destination is an existing directory, the rsync
backend copied the *contents* of the source directory, while the scp backend
copied the directory itself, like `cp -r` and `scp -r` do. Since `--backend=auto`
prefers rsync and only falls back to scp when the guest has no rsync, the
outcome of the very same command depended on the guest image.
The rsync backend appended a trailing slash to every path of a recursive copy,
and a trailing slash on the source is what tells rsync to copy the contents.
Derive the form to pass to rsync from the destination instead, so that a
trailing slash spelled by the user is no longer significant:
- the destination is an existing directory: `SRC DST`, copying SRC into DST;
- the destination does not exist yet: `SRC/ DST`, making DST a copy of SRC.
A destination that can neither be confirmed nor ruled out to be a directory
fails the copy, instead of being assumed to be missing, which would put the
files in the wrong place again.
This also fixes two related defects of the previous code: `copy -r` of a
non-directory into a destination that does not exist made rsync fail on the
appended slash, and multiple sources were merged into the destination instead
of being copied by name.
Add the missing case to copy.bats (both backends, both directions), which only
covered a plain `SRC DST` copy into a destination that does not exist yet, plus
unit tests for the path rewriting, which needs no VM.
`limactl shell --sync` does want the form that copies the contents, so let it
spell its own paths with a trailing slash and stop setting Options.Recursive,
which for rsync only added a `-r` that `-a` already implies.
Fixes #5500
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Merge pull request #5506 from lima-vm/dependabot/github_actions/codeql-action-8213001b74
build(deps): bump the codeql-action group with 3 updates
Merge pull request #5505 from lima-vm/dependabot/go_modules/golang-x-7af35257a6
build(deps): bump the golang-x group across 1 directory with 3 updates
Merge pull request #5507 from lima-vm/dependabot/github_actions/zizmorcore/zizmor-action-0.6.4
build(deps): bump zizmorcore/zizmor-action from 0.6.3 to 0.6.4
build(deps): bump zizmorcore/zizmor-action from 0.6.3 to 0.6.4
Bumps [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) from 0.6.3 to 0.6.4.
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](https://github.com/zizmorcore/zizmor-action/compare/70fb788f84895a7701f5643d103d587e460b5c99...cc914d7f3750a2d13d75c7f184a1060aa0e9d482)
---
updated-dependencies:
- dependency-name: zizmorcore/zizmor-action
dependency-version: 0.6.4
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
build(deps): bump the codeql-action group with 3 updates
Bumps the codeql-action group with 3 updates: [github/codeql-action/init](https://github.com/github/codeql-action), [github/codeql-action/analyze](https://github.com/github/codeql-action) and [github/codeql-action/upload-sarif](https://github.com/github/codeql-action).
Updates `github/codeql-action/init` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...b96794f015dfd88f77b49b1c93e0fa7110f94c63)
Updates `github/codeql-action/analyze` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...b96794f015dfd88f77b49b1c93e0fa7110f94c63)
Updates `github/codeql-action/upload-sarif` from 4.37.9 to 4.38.0
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/cdf488f595d80d6e07e03d4674febd5ab45fa938...b96794f015dfd88f77b49b1c93e0fa7110f94c63)
---
updated-dependencies:
- dependency-name: github/codeql-action/init
dependency-version: 4.38.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: codeql-action
- dependency-name: github/codeql-action/analyze
dependency-version: 4.38.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: codeql-action
- dependency-name: github/codeql-action/upload-sarif
dependency-version: 4.38.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: codeql-action
...
Signed-off-by: dependabot[bot] <support@github.com>
build(deps): bump the golang-x group across 1 directory with 3 updates
Bumps the golang-x group with 2 updates in the / directory: [golang.org/x/image](https://github.com/golang/image) and [golang.org/x/net](https://github.com/golang/net).
Updates `golang.org/x/image` from 0.45.0 to 0.46.0
- [Commits](https://github.com/golang/image/compare/v0.45.0...v0.46.0)
Updates `golang.org/x/net` from 0.58.0 to 0.59.0
- [Commits](https://github.com/golang/net/compare/v0.58.0...v0.59.0)
Updates `golang.org/x/text` from 0.41.0 to 0.42.0
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.41.0...v0.42.0)
---
updated-dependencies:
- dependency-name: golang.org/x/image
dependency-version: 0.46.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: golang-x
- dependency-name: golang.org/x/net
dependency-version: 0.59.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: golang-x
- dependency-name: golang.org/x/text
dependency-version: 0.42.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: golang-x
...
Signed-off-by: dependabot[bot] <support@github.com>
Merge pull request #5443 from sharanrajt/nested-virt-qemu
qemu: support `nestedVirtualization` with HVF (QEMU 11.1 or later)
Merge pull request #5502 from lima-vm/dependabot/go_modules/github.com/modelcontextprotocol/go-sdk-1.8.0
build(deps): bump github.com/modelcontextprotocol/go-sdk from 1.7.0 to 1.8.0
qemu: support `nestedVirtualization`
Add support for `nestedVirtualization` in the QEMU driver:
- On macOS (aarch64, HVF): requires QEMU 11.1.0 or later and macOS 15 or
later (Apple M3 or later). QEMU 11.1 added nested virtualization support
to HVF for the aarch64 `virt` machine using `hv_vm_config_set_el2_enabled`
(https://wiki.qemu.org/ChangeLog/11.1). Enabled by appending
`virtualization=on` to the `-machine virt` option.
- On Linux (aarch64, KVM): requires QEMU 10.1.0 or later and a host kernel
(6.16 or later) booted with `kvm-arm.mode=nested`. Enabled by appending
`virtualization=on` to the `-machine virt` option.
- On Linux (x86_64, KVM): verifies that nested virtualization is enabled
in the host KVM module (`kvm_intel` or `kvm_amd` parameter `nested`) and
that CPU type `host` is used.
For unsupported architectures or accelerators, a warning is logged and
the field is ignored.
Tested on Apple M4 / macOS 26.5 with QEMU 11.1.0: the guest kernel
initializes KVM in nVHE mode and a nested KVM VM boots EDK2 to the
UEFI shell.
Fix #5419
Signed-off-by: Sharan Raj T <sharanrajtm@gmail.com>
build(deps): bump github.com/modelcontextprotocol/go-sdk
Bumps [github.com/modelcontextprotocol/go-sdk](https://github.com/modelcontextprotocol/go-sdk) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/modelcontextprotocol/go-sdk/releases)
- [Commits](https://github.com/modelcontextprotocol/go-sdk/compare/v1.7.0...v1.8.0)
---
updated-dependencies:
- dependency-name: github.com/modelcontextprotocol/go-sdk
dependency-version: 1.8.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
apfs: bound GPT partition entry size and count before use
findAPFSPartitionGPT trusted the entry size and count from the GPT
header. An entry size below 16 panics in the type-GUID copy and a large
value sizes a multi-GB allocation, while the count only bounds the scan
loop. Bound the entry size to [128, 4096], a sanity range rather than
the UEFI 128*2^n rule (which sets no maximum; 128 is the only size seen
in practice), and bound the count through the total table size, since
UEFI sets no maximum on it either. Cap nx_block_size at
NX_MAXIMUM_BLOCK_SIZE since it sizes every readBlock allocation.
Signed-off-by: Sabith Saheb <shabi7204192361@gmail.com>
Merge pull request #5418 from chrisanderton/fsync-drop
hostagent: don't fsync every log record
Merge pull request #5498 from lima-vm/dependabot/go_modules/hack/tools/mvdan.cc/sh/v3-3.14.1
build(deps): bump mvdan.cc/sh/v3 from 3.14.0 to 3.14.1 in /hack/tools
build(deps): bump mvdan.cc/sh/v3 from 3.14.0 to 3.14.1 in /hack/tools
Bumps [mvdan.cc/sh/v3](https://github.com/mvdan/sh) from 3.14.0 to 3.14.1.
- [Release notes](https://github.com/mvdan/sh/releases)
- [Changelog](https://github.com/mvdan/sh/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mvdan/sh/compare/v3.14.0...v3.14.1)
---
updated-dependencies:
- dependency-name: mvdan.cc/sh/v3
dependency-version: 3.14.1
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
fix(vz): stop the VM even when CanRequestStop is false
`LimaVzDriver.Stop()` returned an error without stopping the VM when
`CanRequestStop()` reported false, and it never removed the driver PID file.
When launchd sends SIGTERM to the host agent of a LaunchDaemon instance, the
host agent exits with `vz: CanRequestStop is not supported` and leaves `vz.pid`
behind. Within the same boot this is harmless, because `ReadPIDFile` removes
the PID file of a dead process, but after a reboot the recorded PID may have
been reused by an unrelated process. The instance then shows up as `Broken`
with "vz driver is running but host agent is not", and launchd with
`KeepAlive` crash-loops `limactl start`.
Ask the guest to shut down over SSH whenever the request could not be made
through the Virtualization framework, not only for the macOS guests that ignore
`RequestStop()`. The VM is never stopped forcibly with `VirtualMachine.Stop()`:
that does not give the guest a chance to stop cleanly, and may corrupt the disk.
Always remove the PID file when the driver stops, as the qemu and krunkit
drivers already do.
Related to #5087
Signed-off-by: Eugene Kalinin <e.v.kalinin@gmail.com>
cidata: allow apparmor mounts on every Lima mount point
Ubuntu 25.04 added an apparmor profile for fusermount3 that only permits
fuse mounts under home, /mnt, /tmp and /media. A Lima mount point mirrors
the host path, so it is /Users/USER from a macOS host and /c/Users/USER
from a Windows one. Reverse-sshfs mounts fail there with
"fusermount3: mount failed: Permission denied". The override added in
#4968 covered @{HOME} alone, which only ever helped a Linux host.
Derive the rules from the cidata mount points instead, and rewrite the
file on every boot. Writing it only when it is missing, as #4968 did,
would keep the home-only rule on instances that already have it, and
would miss later changes to an instance's mounts. The cost is that a
rule added to the file by hand is lost on the next boot.
The Windows QEMU job has skipped its mount-home check since the job was
added. The failure the skip cites predates the default template's move
to Ubuntu 25.04, but the skip hid this bug too. Re-enable it.
Signed-off-by: Jan Dubois <jan.dubois@suse.com>
Merge pull request #5489 from resker/fix/autostart-lima-home
fix(autostart): propagate LIMA_HOME into generated launchd/systemd units
Merge pull request #5376 from SABITHSAHEB/networks-varrun-whitespace
validate paths.varRun against an allowlist before findBaseDirectory trims it
Merge pull request #5192 from AkihiroSuda/fix-4389
Rewrite test-port-forwarding.pl in BATS
Merge pull request #5483 from unsuman/net/pr1-lima-net-helper
`lima-privileged-net`: add the privileged network helper for Linux hosts
Add SBOM artifact to the release notes
Signed-off-by: Anders F Björklund <anders.f.bjorklund@gmail.com>
Add SBOM artifact using cyclonedx-gomod
One for lima as a library, one for each cmd.
https://github.com/CycloneDX/cyclonedx-gomod
Add cyclonedx-gomod to hack/tools dir
Running cyclonedx-gomod vendor fails
Mention SBOM in README.md as required
Signed-off-by: Anders F Björklund <anders.f.bjorklund@gmail.com>
Merge pull request #5491 from AkihiroSuda/gomodjail
gomodjail: update to v2.0.1, enforce `gomodjail analyze` in CI
fix(autostart): propagate LIMA_HOME into generated launchd/systemd units
`limactl autostart enable` rendered a launchd plist or systemd unit that carried
no LIMA_HOME. Neither launchd nor systemd inherits the environment of the shell
that registered the instance, so the autostarted `limactl start <instance>`
resolved LIMA_HOME to its default ~/.lima and could not find an instance kept
anywhere else. Both conditions were affected, `--condition=login` as well as
`--condition=boot`.
Pass the LIMA_HOME in effect at registration time to the templates and emit it:
an EnvironmentVariables dict in the two plists, and an Environment= line in the
systemd unit.
The system LaunchDaemon is rendered by `daemonInstall` rather than by the shared
manager, so it needs the value supplied separately. Its rendering moves to
`renderDaemonPlist` to be testable: a key the template references but the map
omits renders as the literal "<no value>" instead of failing, which would then be
written into /Library/LaunchDaemons.
The render tests pin LIMA_HOME so the generated units do not vary with the host
running the test.
Fixes #5488
Signed-off-by: Robert Esker <resker@gmail.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Merge pull request #5494 from alexandear/docs/emeritus-alexandear
MAINTAINERS: move alexandear to emeritus section
MAINTAINERS: remove alexandear
Signed-off-by: Oleksandr Redko <oleksandr.red+github@gmail.com>
Merge pull request #5336 from trodemaster/upstream-pr/b1-fakecloudinit-clean
feat(vz): add osOpts.Darwin.suppressFirstLoginSetup
lima-privileged-net: add the privileged network helper for Linux hosts
Linux has no equivalent of socket_vmnet, so add lima-privileged-net, a small
helper that limactl runs via sudo to set up the "shared", "host" and "bridged"
networks. It is installed into libexec/lima/privileged/, a directory reserved
for helpers that run with elevated privileges, so that they are easy to tell
apart from the unprivileged helpers and easy to audit.
`lima-privileged-net start` creates (for "shared" and "host") the lima-<name>
bridge, assigns the gateway address, spawns dnsmasq for DHCP, and installs the
NAT/forwarding rules of the "shared" mode. `lima-privileged-net tap` creates the
tap device of a single instance, hands it to the calling user, and attaches it
to the bridge. Both take all parameters from the command line rather than
reading the user-writable networks.yaml, because the arguments are what the
sudoers file pins down.
The tap device is created with `ip tuntap`, falling back to the /dev/net/tun
ioctls that iproute2 itself uses, because busybox's `ip` applet does not
implement the tuntap subcommand.
The helper tears the network down again when the last instance leaves, and only
ever touches bridges and tap devices that follow the Lima naming scheme.
networks.IsManagedBridge() and networks.IsTapName() recognize the bridges and
tap devices that lima-privileged-net owns, so it never touches an interface it
did not create itself. Config.Validate() rejects a network name that would make
the derived bridge name exceed IFNAMSIZ-1. A daemon-side commit adds the
matching name generators and the command lines that start the helper and attach
an instance to its bridge.
Signed-off-by: Ansuman Sahoo <anshumansahoo500@gmail.com>
gomodjail: update to v2.0.1, enforce `gomodjail analyze` in CI
gomodjail v2 moves the focus to static analysis: `gomodjail analyze`
verifies that the modules annotated `gomodjail:confined` in go.mod cannot
reach a denied capability (filesystem, network, process execution, raw
syscalls, OS state modification, or cgo).
Add gomodjail to ./hack/tools, add a `gomodjail` lint target, and wire it
into `make lint` and the "Lints" job. Unlike the legacy dynamic mode, this
gate is blocking.
The verdicts are platform-dependent, so the gate is pinned to linux/amd64
and linux/arm64. These are the only platforms that can be analyzed from any
host: analyzing darwin needs a macOS host, as the "vz" driver requires cgo.
The linux verdicts are a superset of the darwin ones anyway. Windows is
deliberately left out, as it would unconfine 18 more modules (go-yaml,
containerd/log, go-runewidth, ...) and weaken the gate for the other
platforms.
`gomodjail fix` downgraded 36 modules to `gomodjail:unconfined` to make the
gate pass. 65 modules remain confined: 37 clean, 28 warning-only.
`make gomodjail-fix` is added for redoing this on dependency bumps, so that
the decision stays visible and reviewable in go.mod.
The macOS job that exercises the legacy dynamic mode (`gomodjail run`) is
kept as an experiment, with its checkout pinned to v2.0.1 instead of HEAD.
Assisted-by: Claude Code (Opus 5)
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Merge pull request #5493 from lima-vm/dependabot/go_modules/al.essio.dev/pkg/shellescape-1.6.1
build(deps): bump al.essio.dev/pkg/shellescape from 1.6.0 to 1.6.1
Merge pull request #5492 from lima-vm/dependabot/go_modules/golang-x-b740b0382b
build(deps): bump the golang-x group across 1 directory with 2 updates
Merge pull request #5454 from SABITHSAHEB/portfwd-event-strip-control-chars
reject guest agent events that report an invalid IP
build(deps): bump al.essio.dev/pkg/shellescape from 1.6.0 to 1.6.1
Bumps [al.essio.dev/pkg/shellescape](https://github.com/alessio/shellescape) from 1.6.0 to 1.6.1.
- [Release notes](https://github.com/alessio/shellescape/releases)
- [Commits](https://github.com/alessio/shellescape/compare/v1.6.0...v1.6.1)
---
updated-dependencies:
- dependency-name: al.essio.dev/pkg/shellescape
dependency-version: 1.6.1
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
build(deps): bump the golang-x group across 1 directory with 2 updates
Bumps the golang-x group with 2 updates in the / directory: [golang.org/x/sync](https://github.com/golang/sync) and [golang.org/x/sys](https://github.com/golang/sys).
Updates `golang.org/x/sync` from 0.22.0 to 0.23.0
- [Commits](https://github.com/golang/sync/compare/v0.22.0...v0.23.0)
Updates `golang.org/x/sys` from 0.47.0 to 0.48.0
- [Commits](https://github.com/golang/sys/compare/v0.47.0...v0.48.0)
---
updated-dependencies:
- dependency-name: golang.org/x/sync
dependency-version: 0.23.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: golang-x
- dependency-name: golang.org/x/sys
dependency-version: 0.48.0
dependency-type: direct:production
update-type: version-update:semver-minor
dependency-group: golang-x
...
Signed-off-by: dependabot[bot] <support@github.com>
reject guest agent events that report an invalid IP
IPPort.Ip arrives over the guest agent gRPC stream as an arbitrary
string under the guest's control and ends up in
PortForwardEvent.GuestAddr, which limactl start/watch print to the
operator terminal, so a bogus entry could inject ANSI/OSC escape
sequences. Fail the event stream with an error when an entry does not
parse as an IP, before the forwarders derive GuestAddr and log lines
from it.
Signed-off-by: Sabith Saheb <shabi7204192361@gmail.com>
validate paths.varRun before findBaseDirectory trims it
findBaseDirectory() cuts paths.varRun down to the deepest component that
already exists, and validatePath() only ever sees the trimmed value, so
the components that have not been created yet are never checked. The
untrimmed value is what MkdirCmd/PIDFile/Sock interpolate into the
sudoers file, where a newline in that tail becomes a directive of its
own and a comma ends the command list entry.
Check the whole value before it is trimmed, and require every component
to be an identifier rather than enumerating sudoers metacharacters, the
same rule the network name, mode, interface and group already use. Only
varRun is checked this way; the other paths keep the existing whitespace
check so layouts like /Users/foo/.local keep working.
The check is only reached on darwin, so its tests are built with
!windows and use filepath.IsAbs like the rest of the package.
Signed-off-by: Sabith Saheb <shabi7204192361@gmail.com>
Rewrite test-port-forwarding.pl in BATS
Add hack/bats/tests/port-forwarding.bats, covering the same portForwards
rule matrix as hack/test-port-forwarding.pl, with one @test per
forward/ignore scenario, and run it in CI on every host platform:
- Linux: the existing "bats" job
- macOS: the "qemu" job (QEMU driver) and the "vz" job (vz driver)
- Windows: the "windows" job (WSL2 driver) and the "windows-qemu" job
Instead of grepping hostagent log strings and sleeping for a fixed time
(issue 4388), the test records `limactl watch --json` events and waits
for the "forwarding"/"not-forwarding" event of each guest listener
before connecting.
The test honors LIMACTL_CREATE_ARGS (e.g. --vm-type), allows overriding
the base template via LIMA_BATS_PORT_FORWARDING_BASE_TEMPLATE (the WSL2
job uses template:experimental/wsl2), and installs socat in the guest
with whatever package manager the guest image provides.
Notable differences from the Perl script:
- Uses socat on both the host and the guest (the nc/socat choice is
dropped; CI was already running the socat mode).
- The tests for the `guestPortRange: [305, 309]` rule now actually use
ports 305-309; the Perl script tested ports 325-329 by mistake, which
are not covered by any rule.
- Test names are ASCII-only ("->" instead of a Unicode arrow): the MSYS2
bash mangles multibyte characters inconsistently between bats' test
registration and dispatch, making every such test fail with
"bats: unknown test name".
- Guest paths passed to `limactl shell` are embedded in an `sh -c`
command string instead of being passed as arguments, because MSYS2
path conversion would rewrite a bare /tmp/... argument to
C:/msys64/tmp/... before limactl.exe sees it.
hack/test-port-forwarding.pl is removed. The only piece of it that
test-templates.sh still needs is the `guestPort: 8888` rule for the
"CONTAINER_ENGINE run" test, which is now injected with `limactl yq`.
The injected rule replaces any portForwards rules from the template, as
the Perl script did: all instances share the host port namespace, so
e.g. test-misc.yaml's own rules would collide with a concurrently
running instance created from the same template. The modified template
is round-tripped through `limactl tmpl copy --embed` so that it still
passes the template-embedding check (`limactl yq` indents sequences
differently than the embed encoder).
The perl/nc/socat host requirements and the guest netcat/socat installs
are gone; the external host IP is now looked up with getent instead of
perl.
The test passed 56/56 (16 skipped as designed on a Linux host) against
the QEMU driver without KVM.
Fix #4389
Assisted-by: Claude Fable 5 <noreply@anthropic.com>
Assisted-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
Merge pull request #5462 from iamstarkov/vz-audio-microphone
vz: add audio.microphone to attach a capture stream
Merge pull request #5482 from lima-vm/dependabot/github_actions/zizmorcore/zizmor-action-0.6.3
build(deps): bump zizmorcore/zizmor-action from 0.6.2 to 0.6.3
build(deps): bump zizmorcore/zizmor-action from 0.6.2 to 0.6.3
Bumps [zizmorcore/zizmor-action](https://github.com/zizmorcore/zizmor-action) from 0.6.2 to 0.6.3.
- [Release notes](https://github.com/zizmorcore/zizmor-action/releases)
- [Commits](https://github.com/zizmorcore/zizmor-action/compare/3dc1ecc9bcb9e94e9b2c709687979e1298497054...70fb788f84895a7701f5643d103d587e460b5c99)
---
updated-dependencies:
- dependency-name: zizmorcore/zizmor-action
dependency-version: 0.6.3
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <support@github.com>
Merge pull request #5487 from unsuman/fix/zizmor
ci(zizmor): use self-repository syntax
ci(zizmor): use self-repository syntax
Signed-off-by: Ansuman Sahoo <anshumansahoo500@gmail.com>
Merge pull request #5481 from lima-vm/dependabot/go_modules/hack/tools/mvdan.cc/sh/v3-3.14.0
build(deps): bump mvdan.cc/sh/v3 from 3.13.1 to 3.14.0 in /hack/tools
Merge pull request #5307 from AkihiroSuda/docs
website: update hugo-extended, docsy
build(deps): bump mvdan.cc/sh/v3 from 3.13.1 to 3.14.0 in /hack/tools
Bumps [mvdan.cc/sh/v3](https://github.com/mvdan/sh) from 3.13.1 to 3.14.0.
- [Release notes](https://github.com/mvdan/sh/releases)
- [Changelog](https://github.com/mvdan/sh/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mvdan/sh/compare/v3.13.1...v3.14.0)
---
updated-dependencies:
- dependency-name: mvdan.cc/sh/v3
dependency-version: 3.14.0
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Merge pull request #5479 from AkihiroSuda/dev
go.mod: golang.org/x/crypto v0.56.0
vz: add audio.microphone to attach a capture stream
The vz driver only creates a host output stream, so a guest with
`audio.device: vz` gets a speaker and no microphone: `/dev/snd` has
`pcmC0D0p` but no capture device, and nothing in the guest can record.
Add an opt-in `audio.microphone` boolean, default false. When it is set,
the driver also creates a host input stream and passes both streams to
SetStreams. It is opt-in because an input stream…
Problem
LimaVzDriver.Stop()returnsvz: CanRequestStop is not supportedwithout stopping the VM whenCanRequestStop()is false, and it never removes the driver PID file. The qemu and krunkit drivers do remove theirs.On an instance registered as a LaunchDaemon (
limactl autostart enable --condition=boot), launchd sends SIGTERM to the host agent,Stop()fails, andvz.pidis left behind. Within the same boot that is harmless, becausestore.ReadPIDFile()removes the PID file of a dead process, but after a reboot the recorded PID may have been reused by an unrelated process. The instance is then reported asBrokenwithvz driver is running but host agent is not, and launchd withKeepAlivecrash-loopslimactl start.This is bug 1 of #5087. It overlaps with the vz part of the draft PR #5088.
Changes
RequestStop(). That is what stops the VM in the reported case, whereCanRequestStop()is false.vz.pidbehind.waitForStopped(), which also stops its ticker. The timeout is unchanged at 30 seconds.The VM is never stopped forcibly with
VirtualMachine.Stop(): as noted in review, that does not give the guest a chance to stop cleanly and may corrupt the disk. When the guest ignores every request to shut down,Stop()returns an error, as it does today.Not in this PR
The LaunchDaemon plist does not set
ExitTimeOut, so launchd sends SIGKILL 20 seconds after SIGTERM, which can cut the graceful shutdown short. That belongs to the autostart code, so it is left for a separate change.Testing
go test ./pkg/driver/vz/...covers the two extracted helpers, including that the PID file is removed and that removing a missing one is not an error.Stop()itself needs a real VM, so it is not unit tested.make golangci-lintis clean.Assisted-by: Claude Code