From: Daan De Meyer Date: Fri, 10 Apr 2026 10:23:22 +0000 (+0000) Subject: libc: Add kexec_file_load() syscall wrapper X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4d91b0366afd215b68d0eae741da6a3aab5e3989;p=thirdparty%2Fsystemd.git libc: Add kexec_file_load() syscall wrapper Allow tabs in UAPI headers in .gitattributes since they are copied verbatim from the kernel. --- diff --git a/.gitattributes b/.gitattributes index dae59aa844a..6c6c4a8beaa 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,5 @@ *.[ch] whitespace=tab-in-indent,trailing-space +src/include/uapi/**/*.[ch] whitespace=trailing-space *.gpg binary generated *.bmp binary *.base64 generated diff --git a/README b/README index 359db5c3f43..ccb6f86bfe8 100644 --- a/README +++ b/README @@ -30,7 +30,7 @@ LICENSE: REQUIREMENTS: Linux kernel ≥ 3.15 for timerfd_create() CLOCK_BOOTTIME support - ≥ 3.17 for memfd_create() and getrandom() + ≥ 3.17 for memfd_create(), getrandom(), and kexec_file_load() (x86-64) ≥ 4.3 for ambient capabilities ≥ 4.5 for pids controller in cgroup v2 ≥ 4.6 for cgroup namespaces diff --git a/meson.build b/meson.build index 1c296073c29..e0e7102a39f 100644 --- a/meson.build +++ b/meson.build @@ -605,6 +605,7 @@ foreach ident : [ ['fchmodat2', '''#include '''], # no known header declares fchmodat2 ['bpf', '''#include '''], # no known header declares bpf ['kcmp', '''#include '''], # no known header declares kcmp + ['kexec_file_load', '''#include '''], # no known header declares kexec_file_load ['keyctl', '''#include '''], # no known header declares keyctl ['add_key', '''#include '''], # no known header declares add_key ['request_key', '''#include '''], # no known header declares request_key diff --git a/src/include/override/sys/kexec.h b/src/include/override/sys/kexec.h new file mode 100644 index 00000000000..4e256bdb6ad --- /dev/null +++ b/src/include/override/sys/kexec.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include /* IWYU pragma: export */ +#include + +/* Supported since kernel v3.17 (cb1052581e2bddd6096544f3f944f4e7fdad4c4f). + * Not available on all architectures. */ +#if HAVE_KEXEC_FILE_LOAD || defined __NR_kexec_file_load +# if !HAVE_KEXEC_FILE_LOAD +int missing_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline, unsigned long flags); +# define kexec_file_load missing_kexec_file_load +# endif +# define HAVE_KEXEC_FILE_LOAD_SYSCALL 1 +#else +# define HAVE_KEXEC_FILE_LOAD_SYSCALL 0 +#endif diff --git a/src/include/uapi/linux/kexec.h b/src/include/uapi/linux/kexec.h new file mode 100644 index 00000000000..e26e2110ce5 --- /dev/null +++ b/src/include/uapi/linux/kexec.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef LINUX_KEXEC_H +#define LINUX_KEXEC_H + +/* kexec system call - It loads the new kernel to boot into. + * kexec does not sync, or unmount filesystems so if you need + * that to happen you need to do that yourself. + */ + +#include + +/* kexec flags for different usage scenarios */ +#define KEXEC_ON_CRASH 0x00000001 +#define KEXEC_PRESERVE_CONTEXT 0x00000002 +#define KEXEC_UPDATE_ELFCOREHDR 0x00000004 +#define KEXEC_CRASH_HOTPLUG_SUPPORT 0x00000008 +#define KEXEC_ARCH_MASK 0xffff0000 + +/* + * Kexec file load interface flags. + * KEXEC_FILE_UNLOAD : Unload already loaded kexec/kdump image. + * KEXEC_FILE_ON_CRASH : Load/unload operation belongs to kdump image. + * KEXEC_FILE_NO_INITRAMFS : No initramfs is being loaded. Ignore the initrd + * fd field. + * KEXEC_FILE_FORCE_DTB : Force carrying over the current boot's DTB to the new + * kernel on x86. This is already the default behavior on + * some other architectures, like ARM64 and PowerPC. + */ +#define KEXEC_FILE_UNLOAD 0x00000001 +#define KEXEC_FILE_ON_CRASH 0x00000002 +#define KEXEC_FILE_NO_INITRAMFS 0x00000004 +#define KEXEC_FILE_DEBUG 0x00000008 +#define KEXEC_FILE_NO_CMA 0x00000010 +#define KEXEC_FILE_FORCE_DTB 0x00000020 + +/* These values match the ELF architecture values. + * Unless there is a good reason that should continue to be the case. + */ +#define KEXEC_ARCH_DEFAULT ( 0 << 16) +#define KEXEC_ARCH_386 ( 3 << 16) +#define KEXEC_ARCH_68K ( 4 << 16) +#define KEXEC_ARCH_PARISC (15 << 16) +#define KEXEC_ARCH_X86_64 (62 << 16) +#define KEXEC_ARCH_PPC (20 << 16) +#define KEXEC_ARCH_PPC64 (21 << 16) +#define KEXEC_ARCH_IA_64 (50 << 16) +#define KEXEC_ARCH_ARM (40 << 16) +#define KEXEC_ARCH_S390 (22 << 16) +#define KEXEC_ARCH_SH (42 << 16) +#define KEXEC_ARCH_MIPS_LE (10 << 16) +#define KEXEC_ARCH_MIPS ( 8 << 16) +#define KEXEC_ARCH_AARCH64 (183 << 16) +#define KEXEC_ARCH_RISCV (243 << 16) +#define KEXEC_ARCH_LOONGARCH (258 << 16) + +/* The artificial cap on the number of segments passed to kexec_load. */ +#define KEXEC_SEGMENT_MAX 16 + +/* + * This structure is used to hold the arguments that are used when + * loading kernel binaries. + */ +struct kexec_segment { + const void *buf; + __kernel_size_t bufsz; + const void *mem; + __kernel_size_t memsz; +}; + + +#endif /* LINUX_KEXEC_H */ diff --git a/src/libc/kexec.c b/src/libc/kexec.c new file mode 100644 index 00000000000..122acff956c --- /dev/null +++ b/src/libc/kexec.c @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +#include +#include +#include + +#if !HAVE_KEXEC_FILE_LOAD && defined __NR_kexec_file_load +int missing_kexec_file_load(int kernel_fd, int initrd_fd, unsigned long cmdline_len, const char *cmdline, unsigned long flags) { + return syscall(__NR_kexec_file_load, kernel_fd, initrd_fd, cmdline_len, cmdline, flags); +} +#endif diff --git a/src/libc/meson.build b/src/libc/meson.build index 306512ffd70..3b7b96d07f2 100644 --- a/src/libc/meson.build +++ b/src/libc/meson.build @@ -4,6 +4,7 @@ libc_wrapper_sources = files( 'bpf.c', 'ioprio.c', 'kcmp.c', + 'kexec.c', 'keyctl.c', 'mempolicy.c', 'mount.c',