8.9 KiB
8.9 KiB
ANCIENT-MOD: running on old kernels (target: 4.19)
Upstream requires kernel ≥ 5.10 (see README, "REQUIREMENTS") and dropped the fallback code for
older kernels. This branch restores or adds fallbacks so the system can at least boot on 4.19.
Code touched by this effort is marked with ANCIENT-MOD comments where practical.
Legend: revert = reverse-applied an upstream commit (possibly adjusted), new = new code because upstream code was refactored since the fallback was removed.
Boot-critical
| Area | Kernel feature | Change | Where |
|---|---|---|---|
Mount point checks (is_mount_point_at(), path_is_mount_point()), used by early mount_setup() for /proc, /sys, /dev with MNT_FATAL |
STATX_ATTR_MOUNT_ROOT (5.8) |
new: xstatx_full() emulates the attribute when it is required but missing: compares the mount id (from /proc/self/fdinfo) of the inode with its parent's (.. for directories, parent path for others); same inode as parent ⇒ root ⇒ mount point. Replaces upstream fallback removed in a98a6eb95c. |
src/basic/stat-util.c (xstatx_emulate()) |
chase() (used everywhere), path_get_mnt_id_at(), fds_inode_and_mount_same(), XSTATX_MNT_ID_BEST |
STATX_MNT_ID (5.8/5.10) |
new: same emulation fills stx_mnt_id from /proc/self/fdinfo/<fd> mnt_id: (available since 3.15). Replaces removals in 7ecfa87c56, e5a3127339. |
src/basic/stat-util.c |
| cgroup2 mount | memory_recursiveprot (5.7) |
revert (adjusted) of 80c5b63db5: option is probed again instead of always passed; if it cannot be probed because fsopen() is missing (< 5.2) it is not used. |
src/shared/mount-setup.c |
mount_option_supported() |
fsopen() (5.2) |
revert of part of c2198d0c3f: return -EAGAIN ("don't know") when the new mount API is unavailable. |
src/basic/mountpoint-util.c |
close_all_fds*() (every fork/exec, systemd-executor) |
close_range() (5.9) |
revert of c471cca093 and d58c826c54: fall back to iterating /proc/self/fd (or the frugal loop). |
src/basic/fd-util.c, src/basic/fd-util.h, src/test/test-fd-util.c |
pidref_set_pid() (every process PID1 tracks, safe_fork(), posix_spawn_wrapper()) |
pidfd_open() (5.3) |
revert (adjusted) of part of 6e14c46bac: ENOSYS ⇒ PidRef without fd (plain PID). |
src/basic/pidref.c |
pidref_wait_for_terminate_full() with timeout |
pidfd (5.3) | new: without pidfd poll waitid(P_PID, …, WNOHANG) every 10 ms instead of returning -ENOMEDIUM. |
src/basic/pidref.c |
pidfd_check_pidfs(), pidfd_info_mask_is_supported(), pidfd_get_inode_id_self_cached() |
pidfd (5.3) | revert/new: ENOSYS ⇒ "not supported" instead of hard error. | src/basic/pidfd-util.c |
sd-event child sources (sd_event_add_child(), used by udevd, logind, …) |
pidfd (5.3), waitid(P_PIDFD) (5.4) |
new (upstream removed the non-pidfd path in 6e14c46bac and later made the code pidfd-only): if pidfd_open() is unsupported the source works on the PID via waitid(P_PID) + SIGCHLD signalfd. SIGCHLD is blocked automatically in that case (upstream no longer requires callers to block it). send_child_signal() falls back to kill()/rt_sigqueueinfo(); set_child_pidfd_own() returns -EOPNOTSUPP without pidfd. |
src/libsystemd/sd-event/sd-event.c |
pam_systemd session creation |
pidfd (5.3) | revert of part of 6e14c46bac: fall back to CreateSession (PID based). |
src/login/pam_systemd.c |
Unit cgroup-empty tracking (unit_check_cgroup_events()) |
frozen key in cgroup.events (5.2) |
new: if the key is missing, read only populated. Without this every cgroup event read failed and stopped units were never noticed as empty. |
src/core/cgroup.c |
| Freeze/thaw | cgroup v2 freezer (5.2) | revert of 3c86a935ad: cg_freezer_supported() restored; freeze is -EOPNOTSUPP / no-op when cgroup.freeze is absent. |
src/basic/cgroup-util.[ch], src/core/cgroup.c, src/core/unit.c |
Credentials (LoadCredential=, SetCredential=, ImportCredential= — used by many stock units) |
new mount API fsopen/fsmount/move_mount (5.2) |
new: if the credentials fs cannot be created because the API is missing, use the existing "plain directory" fallback (previously only used on EPERM). | src/core/exec-credential.c |
ProtectProc= / ProcSubset= (used by logind, networkd, timesyncd, hostnamed, …) |
per-instance procfs, textual hidepid=, subset= (5.8) |
new: on kernels < 5.8 the options are ignored (they would either fail with EINVAL or, worse, change the host's shared /proc superblock). /proc/sys & friends are then still protected by the normal ProtectKernel* mounts. Upstream removed the old fallback in 0cba5bdcf1. |
src/core/namespace.c |
RootDirectory= |
open_tree() (5.2) |
new: tolerate ENOSYS when cloning the root directory mount and use the classic bind mount path. | src/core/namespace.c |
futimens_opath(), access_fd() |
AT_EMPTY_PATH for utimensat()/faccessat() (5.8) |
revert of 52bf232e82 (manually): fall back to /proc/self/fd/<fd>. |
src/basic/fs-util.c |
Networking
| Area | Kernel feature | Change | Where |
|---|---|---|---|
socket_bind_to_ifindex() (DHCP client, resolved, networkd, …) |
SO_BINDTOIFINDEX (5.1) |
revert of ddbbc98bd5 (manually): fall back to SO_BINDTODEVICE. |
src/basic/socket-util.c |
rtnl_resolve_ifname_full() (alternative names) |
IFLA_ALT_IFNAME lookup (5.5) |
revert of 42b09813f4: treat EINVAL like ENODEV. |
src/libsystemd/sd-netlink/netlink-util.c |
| networkd startup enumeration | nexthop (5.3) | revert of 034b69d8b8 (manually): ignore -EOPNOTSUPP from nexthop enumeration, otherwise networkd refuses to start. |
src/network/networkd-manager.c |
| networkd permanent MAC address | IFLA_PERM_ADDRESS (5.6) |
revert of 04f05d9bd7: fall back to ethtool. |
src/network/networkd-link.c |
| IPv6 DNAT (nspawn port forwarding / firewall-util) | nft concatenation fix (5.8) | revert of 58fb46ecd5 (manually): -EOVERFLOW ⇒ -EOPNOTSUPP. |
src/shared/firewall-util.c |
Other
| Area | Kernel feature | Change | Where |
|---|---|---|---|
SurviveFinalKillSignal= |
user.* xattrs on cgroupfs (5.7) |
revert of 8292b859f3: fall back to trusted.survive_final_kill_signal. |
src/core/cgroup.c, src/shared/killall.c |
Loop devices via LOOP_SET_STATUS64 fallback |
buffer cache invalidation bug (fixed in 5.0) | revert of 5e3887e6c1: issue BLKFLSBUF when offset/size is set. |
src/shared/loop-util.c |
Known remaining gaps (not addressed)
- cgroup v1 is gone upstream: the kernel must boot with a cgroup v2 hierarchy. 4.19's cgroup v2
lacks the
cpuset(5.0) andfreezer(5.2) controllers,cgroup.kill(5.14, already graceful). - PSI (4.20):
systemd-oomddoes not work; memory-pressure event sources are already optional. - BPF: features needing BPF links / BPF LSM / bounded loops (5.3–5.7) —
RestrictFileSystems=,RestrictNetworkInterfaces=,SocketBind*=,BindNetworkInterface=, … — report "not supported" (upstream probing,ef12eadfc8). - New mount API without fallback (5.2/5.12):
PrivateBPF=,ExtensionImages=/ExtensionDirectories=(overlay viafsopen),MountImages=, runtimesystemctl bind/mount-image, idmapped mounts, mountfsd, nsresourced, sysext/confext, homed (also needs fscrypt v2 / 5.4), coredump's mount of the crashed process' root. MS_NOSYMFOLLOW(5.10) is passed as a legacymount(2)flag; older kernels silently ignore unknown flags, so the mount just lacksnosymfollow.- Credentials use a plain directory instead of a dedicated (noswap) tmpfs, i.e. less isolation.
- Per-device IO weight (
IODeviceWeight=, BFQ per-device weight, 5.4): upstream dropped the EINVAL workaround (00c4851af0), expect warnings when used. - udev net_id for IP-over-InfiniBand (
dev_port, 4.20):d3d375a686not reverted; multi-port IPoIB devices may get colliding names. test-event'stest_pidfdinherently requires pidfds and fails without them.- Anything else newer than 5.10 listed in
READMEas "recommended baseline" is expected to fall back gracefully upstream, but that has not been verified on a real old kernel.
Testing done
- Full native test suite (
meson test -C build) on a 7.x kernel. - Selected tests (
test-stat-util,test-mountpoint-util,test-chase,test-fs-util,test-fd-util,test-pidref,test-process-util,test-socket-util,test-mount-util,test-udev-spawn,test-async,test-eventexcepttest_pidfd) andsystemd --test --system(with the built generators) under anLD_PRELOADshim that simulates an old kernel: stripsSTATX_MNT_ID*/STATX_ATTR_MOUNT_ROOTfromstatx()results and makespidfd_open,pidfd_send_signal,pidfd_spawn,close_rangeand the new mount API return ENOSYS. - Not booted on a real 4.19 kernel yet.