feat(os): give both guest kernels the tc and checkpoint/restore capabilities Incus needs - #1182
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
🟢 Approval recommended
The changes are limited to kernel config fragments/parity/docs, are consistent across both backends, and align with the stated Incus/LXC requirements and existing capability-matrix conventions.
Pull request overview
This PR closes two kernel capability gaps that prevent Incus system containers from working correctly inside a CVM, by enabling required traffic-control (tc) primitives and checkpoint/restore support on both guest OS backends (mkosi + Yocto) and documenting the new guarantees.
Changes:
- Enable HTB/ingress/u32/police tc features (
NET_SCH_HTB,NET_SCH_INGRESS,NET_CLS_U32,NET_ACT_POLICE) built-in for Incus per-instance bandwidth limits. - Enable
CONFIG_CHECKPOINT_RESTORE=yto support LXC’sPR_SET_MM_MAPusage needed by Incus seccomp notification handling. - Extend mkosi parity assertions and document these non-netfilter kernel capabilities in the guest capability matrix.
File summaries
| File | Description |
|---|---|
| os/yocto/layers/meta-dstack/recipes-kernel/linux/files/dstack-docker.cfg | Adds built-in tc + checkpoint/restore kernel symbols for the Yocto guest kernel fragment. |
| os/mkosi/parity.json | Asserts the new kernel config requirements for mkosi parity gating. |
| os/mkosi/components/kernel/kernel.config | Adds the same built-in tc + checkpoint/restore kernel symbols for the mkosi guest kernel fragment. |
| docs/guest-netfilter-capabilities.md | Documents tc and checkpoint/restore capabilities alongside the existing nested-manager capability guidance. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
kvinwang
force-pushed
the
feat/guest-kernel-tc-and-checkpoint-restore
branch
from
September 6, 2026 09:21
177cee9 to
b32c21e
Compare
kvinwang
force-pushed
the
feat/guest-kernel-tc-and-checkpoint-restore
branch
from
September 6, 2026 09:50
b32c21e to
fed2b4d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Two guest-kernel capability gaps that Incus system containers inside a CVM run into, reported against the 0.5.9 guest (
6.9.0-dstack):Per-instance bandwidth limits (#1176). Incus implements
limits.max/limits.ingress/limits.egresson a bridged NIC as an HTB root qdisc and class on the host-side veth for egress, and an ingress qdisc with a u32 filter and a police action for ingress. That needsNET_SCH_HTB,NET_SCH_INGRESS,NET_CLS_U32andNET_ACT_POLICE.NET_SCHEDalone provides none of them — each is its own tristate — so the manager accepts the setting and then fails to start the instance:Both current backends lack all four: the locally built Yocto 6.18
kernel-confighas them (andNET_CLS_ACT) asnot set, andx86_64_defconfigplusos/mkosi/components/kernel/kernel.configproduces the same.Seccomp notification handling (#1180). LXC retitles its monitor process to
[lxc monitor] <path> <name>withprctl(PR_SET_MM, PR_SET_MM_MAP, ...), and Incus's seccomp handler resolves a monitor PID to its instance by that title. The kernel only implementsPR_SET_MM_MAPunderCONFIG_CHECKPOINT_RESTORE; without it the prctl returnsEINVAL, the monitor keeps itsincusd forkstartcommand line,incusdlogsFailed to find container for monitor <pid>, and withseccomp_listener_continueevery intercepted syscall (security.syscalls.intercept.*) is resumed unhandled instead of getting the container-aware answer. Here the two backends differ: the Yocto 6.18 build already has the symbol, through thecfg/lxc.sccandcfg/criu.sccthat meta-virtualization adds toKERNEL_FEATURES(the 0.5.9 kernel did not), whilex86_64_defconfigleaves it at its Kconfig default ofn, so the mkosi kernel is missing it and nothing asserted it on either side.No gate would have caught either. Neither Incus nor anyone else ships a kernel-config checker for Incus; the closest thing is LXC's own
lxc-checkconfig, which Incus's requirements page implicitly defers to ("any kernel feature required by the LXC version in use"). Run against the mkosi kernel it reports seven symbols missing —CHECKPOINT_RESTORE,MACVLAN,NETFILTER_XT_MATCH_COMMENTand the four socket-diag interfaces — all of which the Yocto kernel has. It does not know about traffic control, so it would not have caught #1176.Fix
b215bdb):NET_SCHED,NET_CLS_ACT,NET_SCH_HTB,NET_SCH_INGRESS,NET_CLS_U32,NET_ACT_POLICE, all=y, in both fragments. Built in rather than=mfor the same reason asCONFIG_TLS: nokernel-module-*package to forget in the Yocto rootfs (a missing one fails at runtime, not at build time), and no reliance on module autoload from inside the manager's own namespaces. ~100 KB of text in total.CHECKPOINT_RESTORE=y(9be802d) in both fragments — new on mkosi, an assertion on Yocto so neither backend can lose it.lxc-checkconfigasks for (ecae1f8):MACVLAN=y(Incusnictype=macvlan),NETFILTER_XT_MATCH_COMMENT=m(-m commenton the xtables frontends; the Yocto rootfs already shipskernel-module-xt-comment, mkosi installs every module it builds),UNIX_DIAG/INET_DIAG/PACKET_DIAG/NETLINK_DIAG=y(ss, CRIU). Values match what the Yocto tree already had.lxc-checkconfig(bb3acfc): vendored verbatim atos/common/scripts/lxc-checkconfig(lxc/lxc969a3c5, LGPL-2.1-or-later, license text added underLICENSES/), driven bycheck-lxc-kernel-config.sh, which runs it withCONFIG=<built .config>, fails on anymissing/requiredline, ignores the script's host-state probes (cgroup mounts,/proc/self/ns/cgroup) and refuses to pass if fewer than 20 symbols came backenabled. The only exemptions areIP_NF_TARGET_MASQUERADE/IP6_NF_TARGET_MASQUERADE, backwards-compat aliases that justselect NETFILTER_XT_TARGET_MASQUERADE(which both kernels build); the IPv6 one is unreachable on mkosi anyway (needs legacy ip6tables). Called right aftercheck-kernel-config.shinkernel-build.sh(mkosi) andexport-artifacts.sh(Yocto);acceptance.shchecks the mkosi wiring.All new fragment lines live in one block that is byte-identical between the two backends, following the bridge-filtering block.
parity.jsonasserts the new symbols on the installed mkosi kernel config.Security assessment of
CHECKPOINT_RESTORE(asked for in #1180). On x86 the symbol gates:PR_SET_MM(needsCAP_CHECKPOINT_RESTOREorCAP_SYS_ADMINin the caller's user namespace), thekernel.ns_last_pidsysctl and the IPC*_next_idsysctls (same check),PTRACE_O_SUSPEND_SECCOMP(init-namespaceCAP_SYS_ADMIN),PTRACE_SECCOMP_GET_FILTER/GET_METADATAon a ptraced task (CAP_SYS_ADMIN),MSG_COPYonmsgrcv(non-destructive read of a queue the caller can already read) and theARCH_MAP_VDSO_*arch_prctl. It also selectsPROC_CHILDRENandKCMP(KCMPwas alreadyyon both backends). Every path is capability- or ptrace-gated guest-userspace surface; none of it faces the host, so it does not change what a malicious host can reach, and it is what every general-purpose distro kernel ships (Debian, Ubuntu, Fedora all set it;docker checkpoint/ CRIU need it). The CVM is single-tenant, so intra-guest process introspection is not a boundary dstack defends — and the Yocto image has been shipping it since it moved to 6.18.docs/guest-netfilter-capabilities.mdrecords all of the above next to the netfilter matrix (and corrects that table's "Since" column: the netfilter work is inv0.6.0-rc0, so it ships in 0.6.0, not 0.6.1).Verification
kernel-build.shlocally onlinux-6.18.40(both dstack patches applied):x86_64_defconfig→merge_config.shwith the final fragment →olddefconfig;check-kernel-config.shandcheck-lxc-kernel-config.shboth pass. Resulting.confighas every requested symbol at the requested value, plusKCMP=y,PROC_CHILDREN=y,NET_XGRESS=y.dstack-docker.cfginto the deployedkernel-configof a locallinux-yocto6.18.39 build withmerge_config.sh+olddefconfigagainst the bitbake kernel source; both gates pass. The diff against the previous config shows exactly the requested symbols flipping (plusNETFILTER_SKIP_EGRESS=y, adef_boolthat followsNET_XGRESS).next's mkosi config it reports the seven symbols above and exits 1; against an empty file it exits 1 withreported only 2 enabled symbols; refusing to proceed. On the new configs it counts 30 enabled symbols.os/mkosi/tests/acceptance.shpasses,shellcheckis clean on the wrapper,reuse lintlistsLGPL-2.1-or-lateras used with no unused licenses.limits.max/ traffic-measurement andsysinfointerception gates on a disposable CVM once a candidate image exists; that is the right place for the end-to-end check.Closes #1176
Closes #1180