Skip to content

Commit 3a2b8b8

Browse files
fix(virtio-linux): add CONFIG_PROC_CHILDREN and fix broken kconfigs
1 parent 88a1113 commit 3a2b8b8

1 file changed

Lines changed: 185 additions & 67 deletions

File tree

packages/virtio-linux/build.sh

Lines changed: 185 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -44,106 +44,224 @@ fi
4444

4545
CFG="scripts/config --file .config"
4646

47+
# --- no loadable modules -----------------------------------------------------
48+
# We ship a single vmlinuz and never run `make modules_install`, so a module is
49+
# unreachable by construction. Turning MODULES off makes that invariant
50+
# structural rather than a convention: nothing can sit at =m and silently
51+
# vanish from the shipped kernel, and the module loader stops being attack
52+
# surface in a guest that has no use for it. olddefconfig promotes the handful
53+
# of defconfig tristates that were =m up to =y.
54+
$CFG --disable MODULES
55+
56+
# `scripts/config --enable FOO` is a silent no-op in two cases: FOO isn't a real
57+
# symbol (typo, or upstream renamed it), or FOO's dependencies aren't satisfied
58+
# — either way `make olddefconfig` drops the line without complaint. So route
59+
# the must-haves through want() and assert on the resulting .config below,
60+
# instead of finding the hole from inside a guest.
61+
REQUIRED=()
62+
want() {
63+
local sym
64+
for sym in "$@"; do
65+
$CFG --enable "$sym"
66+
REQUIRED+=("$sym")
67+
done
68+
}
69+
4770
# --- virtio guest drivers ----------------------------------------------------
4871
# Pin the core virtio transports and every guest-side device driver we'd
4972
# plausibly want from a microVM hypervisor, plus the modern transports
5073
# (MMIO for firecracker-style, PCI for cloud-hypervisor/qemu).
51-
$CFG --enable VIRTIO
52-
$CFG --enable VIRTIO_PCI
74+
want VIRTIO VIRTIO_PCI VIRTIO_MMIO VIRTIO_MMIO_CMDLINE_DEVICES
75+
want VIRTIO_BLK VIRTIO_NET VIRTIO_CONSOLE VIRTIO_BALLOON VIRTIO_INPUT
76+
want VIRTIO_IOMMU VIRTIO_DMA_SHARED_BUFFER
77+
want HW_RANDOM HW_RANDOM_VIRTIO
5378
$CFG --enable VIRTIO_PCI_LEGACY
54-
$CFG --enable VIRTIO_MMIO
55-
$CFG --enable VIRTIO_MMIO_CMDLINE_DEVICES
56-
$CFG --enable VIRTIO_BLK
57-
$CFG --enable VIRTIO_NET
58-
$CFG --enable VIRTIO_CONSOLE
59-
$CFG --enable VIRTIO_BALLOON
60-
$CFG --enable VIRTIO_INPUT
61-
$CFG --enable VIRTIO_SCSI
62-
$CFG --enable VIRTIO_GPU
63-
$CFG --enable VIRTIO_PMEM
64-
$CFG --enable VIRTIO_IOMMU
65-
$CFG --enable VIRTIO_MEM
66-
$CFG --enable VIRTIO_NET_FAILOVER
67-
$CFG --enable VIRTIO_DMA_SHARED_BUFFER
68-
$CFG --enable HW_RANDOM
69-
$CFG --enable HW_RANDOM_VIRTIO
70-
# vsock + virtio-vsock for host<->guest sockets
71-
$CFG --enable VSOCKETS
72-
$CFG --enable VIRTIO_VSOCKETS
73-
# virtiofs (needs FUSE)
74-
$CFG --enable FUSE_FS
75-
$CFG --enable VIRTIO_FS
79+
80+
# The SCSI and GPU guest drivers are not called VIRTIO_SCSI / VIRTIO_GPU (no
81+
# such symbols), and the failover netdev is NET_FAILOVER, which VIRTIO_NET
82+
# selects for us anyway. Asking by the wrong name was invisible on x86 — where
83+
# kvm_guest.config happens to set the real symbols — and a missing driver on
84+
# arm64, where we don't merge that fragment.
85+
want SCSI_VIRTIO DRM_VIRTIO_GPU NET_FAILOVER
86+
87+
# virtio-mem is gated on the memory hotplug/hotremove machinery; without it the
88+
# driver silently drops out of the config.
89+
want MEMORY_HOTPLUG MEMORY_HOTREMOVE VIRTIO_MEM
90+
91+
# virtio-pmem likewise needs libnvdimm, and DAX is what makes a pmem device (or
92+
# virtiofs, below) mappable without going through the guest page cache.
93+
want ZONE_DEVICE LIBNVDIMM VIRTIO_PMEM DAX FS_DAX
94+
95+
# vsock + virtio-vsock for host<->guest sockets. The loopback transport lets
96+
# guest-local services speak vsock without a host peer, which is what most
97+
# vsock-based agents test against.
98+
want VSOCKETS VSOCKETS_LOOPBACK VIRTIO_VSOCKETS
99+
100+
# virtiofs (needs FUSE). DAX mapping and passthrough are what make it fast
101+
# enough to use as a real rootfs/workspace share.
102+
want FUSE_FS VIRTIO_FS FUSE_DAX FUSE_PASSTHROUGH
103+
104+
# 9p-over-virtio: the older host share, and something x86 gets for free from
105+
# kvm_guest.config — pin it so arm64 has it too.
106+
want NET_9P NET_9P_VIRTIO 9P_FS
107+
108+
# ip=/DHCP autoconfiguration from the kernel cmdline (also x86-only via the
109+
# fragment otherwise).
110+
want IP_PNP IP_PNP_DHCP
76111

77112
# --- namespaces + cgroups (containers / sandboxing) --------------------------
78-
$CFG --enable NAMESPACES
79-
$CFG --enable UTS_NS
80-
$CFG --enable IPC_NS
81-
$CFG --enable PID_NS
82-
$CFG --enable NET_NS
83-
$CFG --enable USER_NS
84-
$CFG --enable TIME_NS
85-
$CFG --enable CGROUPS
86-
$CFG --enable MEMCG
87-
$CFG --enable CPUSETS
88-
$CFG --enable CGROUP_PIDS
89-
$CFG --enable CGROUP_FREEZER
90-
$CFG --enable CGROUP_DEVICE
91-
$CFG --enable CGROUP_CPUACCT
92-
$CFG --enable CGROUP_SCHED
93-
$CFG --enable BLK_CGROUP
113+
want NAMESPACES UTS_NS IPC_NS PID_NS NET_NS USER_NS TIME_NS
114+
want CGROUPS MEMCG CPUSETS CGROUP_PIDS CGROUP_FREEZER CGROUP_DEVICE
115+
want CGROUP_CPUACCT CGROUP_SCHED BLK_CGROUP CGROUP_HUGETLB CGROUP_MISC
116+
want CGROUP_PERF CGROUP_BPF CGROUP_NET_PRIO CGROUP_NET_CLASSID NET_CLS_CGROUP
117+
# Pressure-stall + delay accounting: what memory/CPU-aware schedulers,
118+
# systemd-oomd and cgroup `*.pressure` readers need.
119+
want PSI TASKSTATS TASK_DELAY_ACCT TASK_IO_ACCOUNTING
120+
# Note: cgroup v1's memory and cpuset controllers (MEMCG_V1 / CPUSETS_V1) stay
121+
# off — v2-only, same as modern distros.
122+
123+
# --- /proc + process introspection userspace expects -------------------------
124+
# PROC_CHILDREN backs /proc/<pid>/task/<tid>/children, which process
125+
# supervisors use to walk a tree without scanning all of /proc.
126+
# CHECKPOINT_RESTORE brings /proc/<pid>/map_files plus the rest of the CRIU
127+
# surface, and USERFAULTFD is how CRIU (and lazy restore / live migration)
128+
# faults pages back in. PROC_PAGE_MONITOR is /proc/<pid>/pagemap + smaps,
129+
# which every memory profiler reads.
130+
want PROC_CHILDREN PROC_PAGE_MONITOR PROC_KCORE CHECKPOINT_RESTORE USERFAULTFD
131+
132+
# --- core syscall surface container runtimes assume --------------------------
133+
# seccomp is how every runtime filters syscalls; runc's default spec mounts
134+
# /dev/mqueue (POSIX_MQUEUE) and needs ptys for `exec -t`.
135+
want SECCOMP SECCOMP_FILTER
136+
want SYSVIPC SYSVIPC_SYSCTL POSIX_MQUEUE POSIX_MQUEUE_SYSCTL UNIX98_PTYS
137+
want EPOLL SIGNALFD TIMERFD EVENTFD AIO IO_URING FUTEX
138+
want BINFMT_ELF BINFMT_SCRIPT BINFMT_MISC
139+
want HUGETLBFS TRANSPARENT_HUGEPAGE
140+
141+
# --- BPF ---------------------------------------------------------------------
142+
# systemd's device access control, container runtimes and the whole
143+
# observability stack are BPF-first now; CGROUP_BPF is the cgroup-v2 attach
144+
# point. KPROBES/PERF_EVENTS are what BPF_EVENTS — and therefore BPF_LSM —
145+
# are gated on.
146+
# Not enabled: DEBUG_INFO_BTF. CO-RE tooling (bpftrace, libbpf skeletons)
147+
# wants it, but it needs pahole (dwarves) as a build dep and a DWARF-enabled
148+
# build, so it's a deliberate follow-up rather than a free win.
149+
want BPF_SYSCALL BPF_JIT CGROUP_BPF PERF_EVENTS KPROBES
150+
# BPF_EVENTS is what gates BPF_LSM (and attaching BPF to kprobes/uprobes/
151+
# tracepoints at all), and it needs KPROBE_EVENTS || UPROBE_EVENTS — both of
152+
# which live inside `if FTRACE` in kernel/trace/Kconfig. FTRACE is
153+
# `default y if DEBUG_KERNEL`, which x86_64_defconfig satisfies, but arm64's
154+
# defconfig explicitly carries `# CONFIG_FTRACE is not set` — so on arm64 the
155+
# probe-event symbols were unreachable and BPF_EVENTS silently fell to n,
156+
# taking BPF_LSM with it. Turn the menu on and pin both probe backends.
157+
want FTRACE KPROBE_EVENTS UPROBE_EVENTS BPF_EVENTS
94158

95159
# --- container networking ----------------------------------------------------
96-
$CFG --enable VETH
97-
$CFG --enable TUN
98-
$CFG --enable WIREGUARD
160+
want VETH TUN WIREGUARD MACVLAN IPVLAN DUMMY BRIDGE BRIDGE_NETFILTER
161+
want VLAN_8021Q IPV6
162+
# Port publishing and egress NAT: docker, podman and CNI plugins program either
163+
# nftables or iptables, and their rules lean on the addrtype/conntrack/multiport
164+
# matches. defconfig sets NETFILTER_ADVANCED=n, which hides most of this and
165+
# defaults the rest to =m — invisible to us, since we ship no modules.
166+
want NETFILTER NETFILTER_ADVANCED NETFILTER_XTABLES
167+
want NF_CONNTRACK NF_NAT NF_NAT_MASQUERADE
168+
want NF_TABLES NF_TABLES_INET NF_TABLES_IPV4 NF_TABLES_IPV6
169+
want NFT_CT NFT_NAT NFT_MASQ NFT_COMPAT NFT_LIMIT NFT_LOG
170+
want NFT_REJECT NFT_REJECT_IPV4 NFT_REJECT_IPV6 NFT_FIB_IPV4 NFT_FIB_IPV6
171+
want IP_NF_IPTABLES IP_NF_IPTABLES_LEGACY IP_NF_FILTER IP_NF_NAT IP_NF_MANGLE
172+
want IP_NF_TARGET_MASQUERADE IP_NF_TARGET_REJECT IP_NF_TARGET_REDIRECT
173+
want IP6_NF_IPTABLES IP6_NF_IPTABLES_LEGACY IP6_NF_FILTER IP6_NF_NAT
174+
want IP6_NF_MANGLE IP6_NF_TARGET_MASQUERADE IP6_NF_TARGET_REJECT
175+
want NETFILTER_XT_NAT NETFILTER_XT_MARK NETFILTER_XT_MATCH_ADDRTYPE
176+
want NETFILTER_XT_MATCH_CONNTRACK NETFILTER_XT_MATCH_MULTIPORT
177+
want NETFILTER_XT_MATCH_COMMENT NETFILTER_XT_MATCH_STATE
178+
want NETFILTER_XT_TARGET_MASQUERADE NETFILTER_XT_TARGET_REDIRECT
179+
# The log backends default to =m, which for us means `nft ... log` and
180+
# `iptables -j LOG` rules would load but never emit anything.
181+
want NETFILTER_XT_TARGET_LOG NF_LOG_SYSLOG NF_LOG_IPV4 NF_LOG_IPV6 NF_LOG_ARP
182+
# `ss` and anything else that enumerates sockets goes through sock_diag.
183+
want INET_DIAG INET_TCP_DIAG INET_UDP_DIAG UNIX_DIAG NETLINK_DIAG PACKET_DIAG
184+
# tc classifiers/qdiscs, including the eBPF datapath hooks. NET_ACT_MIRRED is
185+
# both how `tc` redirects/mirrors traffic and IFB's hard dependency — without
186+
# it the ifb driver drops out of the config.
187+
want NET_SCH_INGRESS NET_SCH_FQ_CODEL NET_CLS_BPF NET_ACT_BPF
188+
want NET_ACT_MIRRED IFB
189+
190+
# --- block devices + filesystems ---------------------------------------------
191+
# Loop devices and device-mapper are how disk images get mounted and how the
192+
# thin/crypt/verity storage stacks work; dm-verity is what a signed read-only
193+
# rootfs is built on.
194+
want BLK_DEV_LOOP BLK_DEV_DM DM_SNAPSHOT DM_THIN_PROVISIONING DM_CRYPT DM_VERITY
195+
# initramfs, and the decompressors a packed initrd might use.
196+
want BLK_DEV_INITRD RD_GZIP RD_XZ RD_ZSTD
197+
want EXT4_FS EXT4_FS_POSIX_ACL EXT4_FS_SECURITY
198+
# Read-only image formats: squashfs and erofs both show up as container/rootfs
199+
# images; ISO9660 + vfat are what cloud-init style config drives use.
200+
want SQUASHFS SQUASHFS_XZ SQUASHFS_ZSTD EROFS_FS EROFS_FS_ZIP
201+
want ISO9660_FS VFAT_FS NLS_CODEPAGE_437 NLS_ISO8859_1 NLS_UTF8 NLS_ASCII
202+
# systemd mounts /proc/sys/fs/binfmt_misc and friends through autofs.
203+
want AUTOFS_FS
99204

100205
# --- bind mounts / pivot_root substrate --------------------------------------
101206
# Bind mounts are part of core VFS, but pivot_root + the filesystems people
102207
# commonly use to assemble container roots are configurable. Make sure the
103-
# usual suspects are present.
104-
$CFG --enable TMPFS
105-
$CFG --enable TMPFS_POSIX_ACL
106-
$CFG --enable TMPFS_XATTR
107-
$CFG --enable PROC_FS
108-
$CFG --enable SYSFS
109-
$CFG --enable DEVTMPFS
110-
$CFG --enable DEVTMPFS_MOUNT
208+
# usual suspects are present. TMPFS_INODE64 avoids inode-number reuse on
209+
# long-lived tmpfs trees.
210+
want TMPFS TMPFS_POSIX_ACL TMPFS_XATTR TMPFS_INODE64
211+
want PROC_FS SYSFS DEVTMPFS DEVTMPFS_MOUNT
111212

112213
# --- overlayfs ---------------------------------------------------------------
113-
$CFG --enable OVERLAY_FS
114-
$CFG --enable OVERLAY_FS_REDIRECT_DIR
115-
$CFG --enable OVERLAY_FS_INDEX
116-
$CFG --enable OVERLAY_FS_XINO_AUTO
117-
$CFG --enable OVERLAY_FS_METACOPY
214+
want OVERLAY_FS OVERLAY_FS_REDIRECT_DIR OVERLAY_FS_INDEX
215+
want OVERLAY_FS_XINO_AUTO OVERLAY_FS_METACOPY
118216

119217
# --- fanotify (privileged FS event monitoring + access control) -------------
120-
$CFG --enable FANOTIFY
121-
$CFG --enable FANOTIFY_ACCESS_PERMISSIONS
218+
want FANOTIFY FANOTIFY_ACCESS_PERMISSIONS
122219

123-
# --- landlock (unprivileged sandboxing LSM) ----------------------------------
124-
$CFG --enable SECURITY
125-
$CFG --enable SECURITY_LANDLOCK
126-
# Landlock is a stackable LSM; make sure it's actually in the active list.
127-
$CFG --set-str LSM "landlock,lockdown,yama,integrity,apparmor,bpf"
220+
# --- LSMs --------------------------------------------------------------------
221+
# landlock for unprivileged sandboxing, yama for ptrace scoping, bpf-lsm for
222+
# programmable policy.
223+
want SECURITY SECURITY_NETWORK SECURITY_LANDLOCK SECURITY_YAMA BPF_LSM
224+
# Deliberately not enabling SECURITY_LOCKDOWN_LSM: it does
225+
# `select MODULE_SIG if MODULES`, and MODULE_SIG with the default
226+
# CONFIG_MODULE_SIG_KEY="certs/signing_key.pem" makes the build generate a
227+
# fresh RSA keypair and embed the cert in the image — a different vmlinuz on
228+
# every build. Lockdown buys us nothing here anyway (we ship no modules and
229+
# there's no secure-boot chain in a microVM guest).
230+
# Stackable LSMs only run if they're in this list, and only names that are
231+
# actually compiled in mean anything — so keep the list and the config in sync.
232+
# (The list previously named lockdown, apparmor and integrity, none of which
233+
# was built.)
234+
$CFG --set-str LSM "landlock,yama,bpf"
128235

129236
# --- nested KVM (let this guest itself host VMs) -----------------------------
130237
# CONFIG_KVM is host-side virtualization; enabling it inside the guest is
131238
# what makes nesting work from the guest's point of view. Whether nesting
132239
# is *actually* available depends on the outer hypervisor exposing
133240
# vmx/svm/EL2-virt to us, but the kernel side has to be built either way.
134241
# KVM_INTEL/KVM_AMD only exist on x86; on arm64 the equivalent is folded
135-
# into CONFIG_KVM. scripts/config silently no-ops on unknown symbols and
136-
# olddefconfig drops them, so listing both arches' symbols here is safe.
242+
# into CONFIG_KVM. These stay outside want() precisely because they're
243+
# arch-conditional, so olddefconfig is free to drop the ones that don't apply.
137244
$CFG --enable VIRTUALIZATION
138245
$CFG --enable KVM
139246
$CFG --enable KVM_INTEL
140247
$CFG --enable KVM_AMD
141-
$CFG --enable KVM_XFER_TO_GUEST_WORK
142-
$CFG --enable KVM_GENERIC_DIRTYLOG_READ_PROTECT
143248

144249
# Resolve any new dependencies / silently drop options renamed upstream.
145250
make olddefconfig
146251

252+
# --- assert the config we asked for is the config we got ---------------------
253+
missing=()
254+
for sym in "${REQUIRED[@]}"; do
255+
grep -qx "CONFIG_${sym}=y" .config || missing+=("CONFIG_${sym}")
256+
done
257+
if [ "${#missing[@]}" -gt 0 ]; then
258+
echo "error: required kernel options absent from .config after olddefconfig:" >&2
259+
printf ' %s\n' "${missing[@]}" >&2
260+
echo "cause is one of: symbol renamed/removed upstream, unmet dependency," >&2
261+
echo "or left as =m (no modules are shipped by this package)." >&2
262+
exit 1
263+
fi
264+
147265
make -j"$JOBS" "$KERNEL_TARGET"
148266

149267
OUT=$OUTPUT_DIR/usr/share/virtio-linux

0 commit comments

Comments
 (0)