Library / SDK
libkrun/libkrun avatar
libkrun/libkrun

libkrun: a deliberately tiny VMM you link into your own process

A dynamic library providing Virtualization-based process isolation capabilities

2,718 stars271 forksRustApache-2.0

At a glance

What is it?
A Rust dynamic library that gives a process KVM or HVF isolation behind a small C API, with an explicit list of what it refuses to become, and a warning that main is a 2.0 rewrite you should not deploy yet.
Who is it for?
libkrun is a component rather than a hypervisor, and reading it that way is the only way its feature list makes sense. It ships the virtio devices a process isolation boundary needs and stops, which is why crun, krunkit and muvm can each embed it rather than reimplementing VM bring-up.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 18 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A library that brings up a VM, not a hypervisor you administer

libkrun is a dynamic library that lets a program run processes in a partially isolated environment using KVM virtualization on Linux and HVF on macOS on ARM64. The design claim is in the same sentence: it integrates a VMM, the userspace side of a hypervisor, with the minimum emulated devices required for its purpose, abstracts most of the complexity of virtual machine management, and offers a simple C API.

The non-goals list is what makes this project readable, because it is short and blunt. It is explicitly not trying to become a generic VMM, and it is explicitly not trying to be compatible with all kinds of workloads. The goals it does claim are enabling other projects to easily gain KVM-based process isolation, being self-sufficient with no need to call an external VMM, being as small as possible, having the smallest possible footprint across RAM, CPU and boot time, and being compatible with a reasonable amount of workloads.

That footprint goal is the interesting one, because it is measurable and unusual to see stated. A VMM with no hardware emulation of anything beyond virtio, no graphical console, and no management plane can plausibly boot faster and cost less than a general-purpose one.

The repository metadata shows a Rust project under Apache-2.0 with 2,718 stars, 271 forks, 97 open issues, no archive flag, and a last push of 2026-09-21. There are no GitHub topics and no homepage configured, so the README and the consumer list are the whole discovery surface.

The main branch is a 2.0 rewrite, and the README says so in bold

The most important line in the README is a note near the top, and it changes how you should evaluate everything else:

text
The `main` branch is now **libkrun 2.0**, which will not be backwards
compatible with the 1.x API/ABI. The 2.0 API is also still under active
development and may change further before the first stable release.

The instruction that follows is to use the newest `stable-*` release branch instead if you are building from source for production.

This is not a hypothetical warning, and you can verify it against the repository. The build files on main carry version 2.0.0 with ABI version 2, while the most recent GitHub releases are all in the 1.19 line:

text
ABI_VERSION=2
FULL_VERSION=2.0.0

KRUN_INIT_ABI_VERSION=0
KRUN_INIT_FULL_VERSION=0.1.0

So both facts are true at once. Main is 2.0 and incompatible, and the release tags you see are cut from the stable branches. Reading `main` to learn what the current API looks like will teach you an API that does not exist in any release.

The recent release notes also illustrate the sort of work this project does, which is almost entirely in the virtio and platform layers. v1.19.4, published 2026-07-03, is a single fix requiring the virtio-fs macOS security context to succeed with mode 0444. v1.19.3, published 2026-06-26, implements `krun_add_virtiofs4`, supports disabling attribute caching and disabling allow_idmap, adds different permission semantics on macOS, and reverts an earlier change that mapped host process UID and GID to root in the guest. v1.19.2, published 2026-06-24, is a single revert of a virtio-console fix for transmit data loss on shutdown. Two of three releases being a revert or a one-line permissions fix is normal for something at this layer.

Eight virtio devices, and balloon means free-page reporting only

The device list is the entire hardware surface, and it is deliberately short:

text
virtio-console
virtio-block
virtio-fs
virtio-gpu (venus and native-context)
virtio-net
virtio-vsock (for TSI and socket redirection)
virtio-balloon (only free-page reporting)
virtio-rng

Two entries carry qualifications that matter. virtio-gpu is documented as venus and native-context, which is what makes the krunkit and muvm use cases possible on macOS and Asahi Linux respectively, since neither has a conventional GPU passthrough story. And virtio-balloon is explicitly limited to free-page reporting, meaning you get memory reclamation signalling but not the full balloon device with deflate-style page compression.

The absence of other devices is a design statement rather than an omission. No USB, no SCSI, no audio, no input devices at the virtio level, no TPM. If your workload needs any of those, this is the wrong library and the README's non-goals are telling you so before you discover it at boot.

The tree backs up the platform breadth in an interesting way. `Cargo.toml` defines a workspace whose members include `src/libkrun` plus architecture and platform modules named `src/arch`, `src/arch_gen`, `src/hvf`, `src/whp`, `src/aws_nitro`, `src/cpuid`, `src/smbios`, `src/polly`, `src/kernel`, `src/devices`, `src/input`, `src/display` and `src/utils`. The presence of a module for whp, which is the Windows Hypervisor Platform, goes beyond the two platforms the README's opening sentence names, and there is an AWS Nitro module plus a matching `launch-tee.c` example, which is the confidential-computing path rather than ordinary isolation.

Two mutually exclusive networking strategies, one of them unusual

Networking is offered two ways that cannot be combined: virtio-vsock with TSI, and virtio-net with a userspace proxy such as passt or gvproxy. You add a virtio-net interface with `krun_add_net_unixstream` and `krun_add_net_unixdgram` when you want the conventional path.

The interesting one is TSI, Transparent Socket Impersonation. The README calls it a novel technique that gives the VM network connectivity with no virtual interface at all, supporting both outgoing and incoming connections, so a userspace application inside the VM can connect outward and the outside can reach ports listening inside. That is a meaningfully different trust and performance profile from a tap device, and it removes the network interface from the guest entirely.

Enabling it is mostly implicit. TSI for AF_INET and AF_INET6 is switched on automatically when no network interface has been added. TSI for AF_UNIX additionally requires the root filesystem to be configured with `/` as the shared directory.

The limitations are listed and they are not small. TSI requires a custom kernel, the one bundled with libkrunfw. It covers only SOCK_DGRAM and SOCK_STREAM over AF_INET, AF_INET6 and AF_UNIX, so raw sockets do not work. Listening on SOCK_DGRAM sockets from the guest is unsupported. And when AF_UNIX impersonation is enabled, only absolute paths are accepted as addresses.

For an investigator, the honest summary is that TSI removes a device but adds a kernel dependency and several socket restrictions, so it suits a workload that wants ordinary TCP and UDP proxying through the VMM and not one that needs raw sockets or datagram listeners.

The security model says the VMM and the guest are one entity

This is the section worth reading twice, because it defines what libkrun does not do for you. The model starts from the position that the guest and the VMM belong to the same security context, and that for many operations the VMM acts as a proxy for the guest inside the host, so host resources reachable by the VMM can potentially be reached by the guest through it.

The practical instruction is to think of guest and VMM as a single entity when designing the security posture. To stop the guest reaching host resources, you use the host operating system's own isolation to run the VMM in a confined context, and on Linux the primary mechanism is namespaces. Single-user systems may relax that and simply run the VMM under a particular UID and GID.

That is an honest division of labour. libkrun is not a sandbox boundary on its own; it is the thing you put inside a boundary. If you were expecting VM isolation to substitute for container isolation, this paragraph is the correction.

Two devices get specific warnings. virtio-fs, when configured through the `krun_add_virtiofs*` functions, provides no protection against a guest reaching other directories in the same filesystem or even other filesystems on the host, so a host-side mount point isolation mechanism has to be combined with it. The same section notes a guest may exhaust filesystem resources such as inode limits and disk capacity, which needs host-side controls.

For TSI the same logic applies to networking: the VMM proxies AF_INET, AF_INET6 and AF_UNIX sockets in both directions, so the two should be treated as sharing a network context and whatever restrictions you want on the guest should be applied to the VMM.

Build requirements, three consumers, and a header set that names the API surface

The README lists Linux build requirements as libkrunfw, a working Rust toolchain, and C library static libraries, because the init binary is statically linked. The README's own build section is cut off partway through that list, so the remaining requirements are not spelled out there, and the Makefile in the repository is likewise cut short partway through its conditional block.

What is visible is still informative. Variant selection is done through Makefile variables, with `SEV=1` selecting a `-sev` variant and the `amd-sev` Cargo feature, and `TDX=1` selecting a `-tdx` variant and the `tdx` feature. A separate `VIRGL_RESOURCE_MAP2` switch adds its matching feature, and test targets auto-enable the block device and network features unless explicitly set. That is a conventional feature-gated build rather than a universal one.

The header list defines the public API in four parts:

text
LIBRARY_HEADER = include/libkrun.h
LIBRARY_HEADER_DISPLAY = include/libkrun_display.h
LIBRARY_HEADER_INPUT = include/libkrun_input.h
LIBRARY_HEADER_INIT = include/libkrun_init.h

So display and input are separate headers rather than part of the core API, which is consistent with a project whose goal is process isolation rather than presenting a desktop. The Makefile also produces `.pc` files, `libkrun.pc.in` and `libkrun_init.pc.in`, so the library integrates with pkg-config rather than requiring hand-written link flags.

The three named consumers are the best available evidence of what this thing is actually for. crun uses it to add virtualization-based isolation to container and confidential workloads, which is the most likely place you will encounter it. krunkit runs GPU-enabled lightweight VMs on macOS through venus. muvm, from the Asahi Linux project, launches a microVM with GPU acceleration through native context for running games that need 4k pages. Two of the three are about giving a graphical workload a VM, which tells you how much device emulation is actually necessary.

Editorial conclusion

libkrun is a component rather than a hypervisor, and reading it that way is the only way its feature list makes sense. It ships the virtio devices a process isolation boundary needs and stops, which is why crun, krunkit and muvm can each embed it rather than reimplementing VM bring-up. The two things to weigh before depending on it are both stated plainly in the README: the VMM and the guest share a security context, so host namespaces do the isolation work, and the main branch is an incompatible 2.0 rewrite with no stable release. Pin a `stable-*` branch for anything in production, read the TSI limitations if you plan to use Transparent Socket Impersonation, and check the device list against your workload before you assume a needed device is emulated.

Frequently asked questions

What is libkrun and what platforms does it support?

libkrun is a dynamic library that lets a program run processes in a partially isolated environment using KVM virtualization on Linux and HVF on macOS on ARM64. It bundles a VMM with the minimum emulated devices needed and exposes it through a simple C API, rather than being a general-purpose hypervisor you administer.

Why does the README warn against using the main branch for production?

Because main is libkrun 2.0, which is not backwards compatible with the 1.x API or ABI and is still under active development before its first stable release. The build files on main report version 2.0.0 with ABI 2, while the published releases are in the 1.19 line, so for production builds the README directs you to the newest stable release branch.

What are the SEV and TDX variants of libkrun?

libkrun-sev adds AMD SEV support covering SEV, SEV-ES and SEV-SNP memory encryption plus remote attestation, and requires an SEV-capable CPU. libkrun-tdx adds Intel TDX memory encryption and requires a TDX-capable CPU. Each variant produces a dynamic library with its own name and soname, so both can be installed side by side.

Does libkrun isolate the guest from the host by itself?

No. The security model treats the guest and the VMM as belonging to the same security context, since the VMM often proxies guest operations against host resources. Isolation comes from the host operating system, with namespaces on Linux as the primary mechanism, so libkrun is something you place inside a boundary rather than a boundary itself.

Official sources

  1. Issues
  2. libkrun/libkrun on GitHub
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/libkrun-libkrun.svg)](https://hysenlabs.com/projects/libkrun-libkrun)