From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2192424BBF4 for ; Mon, 19 Jan 2026 03:25:32 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793134; cv=none; b=kS5p6yjJxKKXR2JC2I9XYu8RZq5TCwcI9MhWvJu8dyWGxA52nzm+QLKml7h2ntfZCB61OPmnBS2PmMhSxV1LycNmLyPB99xd6xtX4+HnmFlpORLjtqw4nG5Bv8RjSRMlOtNthU2smDr2rm/kyjJybfhvy4JJr94eyO7qGHNqQoI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793134; c=relaxed/simple; bh=w61Zjy29wRsJz3cZu9F5CjXrYJPKyO7BCVnsWG/w14k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Ua7d9Qz8MIuT1zPTFoXPnVnN8rnXngyWK34CKM9SEtuYXX24ZP2U1w3MCkXBCbzo8frqtNlYLtya7Flgs3F6Da2h/WzpYlCKqUFuR4dXI4LIJU81B7VjcawgNmqtMfvLLFEmSHHOlW4h5lSpK746r8iXoaDSHIEa2DMZ3hz1MrM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=XgAAuE6V; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="XgAAuE6V" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793132; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=o5aAmHphuaCuElIjD1nSE+54sJuhoN+zFArjQztPTzw=; b=XgAAuE6V0IO1NYIXjeoTUsYsddk3+zDU+YHlQD37kdAcq2bqwzLXhgGCM+or3MoxYS5U3t n9+/yL9ZlUDHLFZ5gn2D1bv5c/cT31e07vkqQbBRKZSEiFW98e3CA6aPZg74o4g9tGt+m0 mSFZepnqNnJng50sbnBe6scluyxG/Ks= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-103-BmTL6VVUNSi1MjAC_BE4Zg-1; Sun, 18 Jan 2026 22:25:29 -0500 X-MC-Unique: BmTL6VVUNSi1MjAC_BE4Zg-1 X-Mimecast-MFC-AGG-ID: BmTL6VVUNSi1MjAC_BE4Zg_1768793127 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CE54C1954B0B; Mon, 19 Jan 2026 03:25:25 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 896FD195419F; Mon, 19 Jan 2026 03:25:12 +0000 (UTC) From: Pingfan Liu To: bpf@vger.kernel.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , kexec@lists.infradead.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, KP Singh , Stanislav Fomichev , Hao Luo , Jiri Olsa Subject: [PATCHv6 01/13] bpf: Introduce kfuncs to parser buffer content Date: Mon, 19 Jan 2026 11:24:12 +0800 Message-ID: <20260119032424.10781-2-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" In the security kexec_file_load case, the buffer holding the kernel image should not be accessible from userspace. Typically, BPF data flow occurs between user space and kernel space in either direction. However, the above case presents a unique scenario where the kernel, instead of a user task, reads data from a file, passes it to a BPF program for parsing, and finally stores the parsed result. This requires a mechanism to channel the intermediate data from the BPF program directly to the kernel. BPF buffer parser kfuncs are introduced to serve this purpose: BTF_ID_FLAGS(func, bpf_get_parser_context, KF_ACQUIRE | KF_RET_NULL) BTF_ID_FLAGS(func, bpf_put_parser_context, KF_RELEASE) BTF_ID_FLAGS(func, bpf_buffer_parser, KF_TRUSTED_ARGS | KF_SLEEPABLE) where bpf_get_parser_context() and bpf_put_parser_context() manage the trusted argument, and bpf_buffer_parser() forwards data to a callback that processes the structured buffer constructed by the BPF program. Signed-off-by: Pingfan Liu Cc: Alexei Starovoitov Cc: Daniel Borkmann Cc: David S. Miller Cc: John Fastabend Cc: Andrii Nakryiko Cc: Martin KaFai Lau Cc: Eduard Zingerman Cc: Song Liu Cc: Yonghong Song Cc: KP Singh Cc: Stanislav Fomichev Cc: Hao Luo Cc: Jiri Olsa To: bpf@vger.kernel.org --- include/linux/bpf.h | 19 ++++ kernel/bpf/Makefile | 3 + kernel/bpf/bpf_buffer_parser.c | 170 +++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 kernel/bpf/bpf_buffer_parser.c diff --git a/include/linux/bpf.h b/include/linux/bpf.h index e5be698256d15..25bc1b6b8a600 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -3843,4 +3843,23 @@ static inline int bpf_map_check_op_flags(struct bpf_= map *map, u64 flags, u64 all return 0; } =20 +struct bpf_parser_buf { + char *buf; + int size; +}; + +struct bpf_parser_context; +typedef int (*bpf_parser_handler_t)(struct bpf_parser_context *ctx); + +struct bpf_parser_context { + struct kref ref; + struct hlist_node hash_node; + bpf_parser_handler_t func; + struct bpf_parser_buf *buf; + void *data; +}; + +struct bpf_parser_context *alloc_bpf_parser_context(bpf_parser_handler_t f= unc, + void *data); +void put_bpf_parser_context(struct bpf_parser_context *ctx); #endif /* _LINUX_BPF_H */ diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile index 232cbc97434db..309b905a81736 100644 --- a/kernel/bpf/Makefile +++ b/kernel/bpf/Makefile @@ -56,6 +56,9 @@ obj-$(CONFIG_BPF_SYSCALL) +=3D kmem_cache_iter.o ifeq ($(CONFIG_DMA_SHARED_BUFFER),y) obj-$(CONFIG_BPF_SYSCALL) +=3D dmabuf_iter.o endif +ifeq ($(CONFIG_KEXEC_BPF),y) +obj-$(CONFIG_BPF_SYSCALL) +=3D bpf_buffer_parser.o +endif =20 CFLAGS_REMOVE_percpu_freelist.o =3D $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_bpf_lru_list.o =3D $(CC_FLAGS_FTRACE) diff --git a/kernel/bpf/bpf_buffer_parser.c b/kernel/bpf/bpf_buffer_parser.c new file mode 100644 index 0000000000000..6acb4b5da71b3 --- /dev/null +++ b/kernel/bpf/bpf_buffer_parser.c @@ -0,0 +1,170 @@ +// SPDX-License-Identifier: GPL-2.0 +#include +#include +#include +#include +#include +#include + +#define BPF_CONTEXT_HASH_BITS 10 + +static DEFINE_SPINLOCK(bpf_parser_context_lock); +static DEFINE_HASHTABLE(bpf_parser_context_map, BPF_CONTEXT_HASH_BITS); + +/* Generate a simple hash key from pointer address */ +static inline unsigned int bpf_parser_context_hash_key(struct bpf_parser_c= ontext *ctx) +{ + return hash_ptr(ctx, BPF_CONTEXT_HASH_BITS); +} + +static void release_bpf_parser_context(struct kref *kref) +{ + struct bpf_parser_context *ctx =3D container_of(kref, struct bpf_parser_c= ontext, ref); + + if (!!ctx->buf) { + vfree(ctx->buf->buf); + kfree(ctx->buf); + } + spin_lock(&bpf_parser_context_lock); + hash_del(&ctx->hash_node); + spin_unlock(&bpf_parser_context_lock); + kfree(ctx); +} + +struct bpf_parser_context *alloc_bpf_parser_context(bpf_parser_handler_t f= unc, + void *data) +{ + struct bpf_parser_context *ctx; + unsigned int key; + + ctx =3D kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return NULL; + ctx->func =3D func; + ctx->data =3D data; + kref_init(&ctx->ref); + key =3D bpf_parser_context_hash_key(ctx); + spin_lock(&bpf_parser_context_lock); + hash_add(bpf_parser_context_map, &ctx->hash_node, key); + spin_unlock(&bpf_parser_context_lock); + + return ctx; +} + +void put_bpf_parser_context(struct bpf_parser_context *ctx) +{ + if (!ctx) + return; + kref_put(&ctx->ref, release_bpf_parser_context); +} + +static struct bpf_parser_context *find_bpf_parser_context(unsigned long id) +{ + struct bpf_parser_context *ctx; + unsigned int key; + int cnt; + + key =3D bpf_parser_context_hash_key((struct bpf_parser_context *)id); + spin_lock(&bpf_parser_context_lock); + hash_for_each_possible(bpf_parser_context_map, ctx, hash_node, key) { + if (ctx =3D=3D (struct bpf_parser_context *)id) { + cnt =3D kref_get_unless_zero(&ctx->ref); + if (!cnt) + ctx =3D NULL; + spin_unlock(&bpf_parser_context_lock); + return ctx; + } + } + spin_unlock(&bpf_parser_context_lock); + + return NULL; +} + +__bpf_kfunc_start_defs() + +__bpf_kfunc struct bpf_parser_context *bpf_get_parser_context(unsigned lon= g id) +{ + struct bpf_parser_context *ctx; + + ctx =3D find_bpf_parser_context(id); + + return ctx; +} + +__bpf_kfunc void bpf_put_parser_context(struct bpf_parser_context *ctx) +{ + put_bpf_parser_context(ctx); +} + +__bpf_kfunc void bpf_parser_context_release_dtor(void *ctx) +{ + put_bpf_parser_context(ctx); +} +CFI_NOSEAL(bpf_parser_context_release_dtor); + +__bpf_kfunc int bpf_buffer_parser(char *buf, int buf_sz, + struct bpf_parser_context *context) +{ + struct bpf_parser_buf *parser_buf; + int ret; + char *b; + + if (unlikely(context->func =3D=3D NULL)) + return -EINVAL; + + b =3D __vmalloc(buf_sz, GFP_KERNEL_ACCOUNT | __GFP_ZERO); + if (!b) + return -ENOMEM; + ret =3D copy_from_kernel_nofault(b, buf, buf_sz); + if (!!ret) { + vfree(b); + return ret; + } + + parser_buf =3D kmalloc(sizeof(struct bpf_parser_buf), GFP_KERNEL); + if (!parser_buf) { + vfree(b); + return -ENOMEM; + } + parser_buf->buf =3D b; + parser_buf->size =3D buf_sz; + context->buf =3D parser_buf; + ret =3D context->func(context); + + return ret; +} +__bpf_kfunc_end_defs(); + +BTF_KFUNCS_START(buffer_parser_ids) +BTF_ID_FLAGS(func, bpf_get_parser_context, KF_ACQUIRE | KF_RET_NULL) +BTF_ID_FLAGS(func, bpf_put_parser_context, KF_RELEASE) +BTF_ID_FLAGS(func, bpf_buffer_parser, KF_TRUSTED_ARGS | KF_SLEEPABLE) +BTF_KFUNCS_END(buffer_parser_ids) + +static const struct btf_kfunc_id_set buffer_parser_kfunc_set =3D { + .owner =3D THIS_MODULE, + .set =3D &buffer_parser_ids, +}; + + +BTF_ID_LIST(buffer_parser_dtor_ids) +BTF_ID(struct, bpf_parser_context) +BTF_ID(func, bpf_parser_context_release_dtor) + +static int __init buffer_parser_kfunc_init(void) +{ + int ret; + const struct btf_id_dtor_kfunc buffer_parser_dtors[] =3D { + { + .btf_id =3D buffer_parser_dtor_ids[0], + .kfunc_btf_id =3D buffer_parser_dtor_ids[1] + }, + }; + + ret =3D register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, &buffer_parser_k= func_set); + return ret ?: register_btf_id_dtor_kfuncs(buffer_parser_dtors, + ARRAY_SIZE(buffer_parser_dtors), + THIS_MODULE); +} + +late_initcall(buffer_parser_kfunc_init); --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B613A1F03D7 for ; Mon, 19 Jan 2026 03:25:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793149; cv=none; b=cqGIBkNWDGiULt/W+ppa1T2P4AG0wR434igTlilEZ6XgwZEqb4Vo2+rpeQ7SdtDTyqNYf7e9AeRVIbBpKsDfoggDkr4rGYrhThYDX+YVVAh3Ecmq2fpij2qE64itth88MfqPZom9hIQ63dw7ASRIDSroL51DO8cspZ6F/4/hQzk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793149; c=relaxed/simple; bh=xZIJ/PR6dsy+v+Zq7zr3kiP1+mSLugxSEkpHG58PHlM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZrRQvdFoe0TwonngM9vZAI9kIU9ziuy0rZGiK/ouTeRxX13ltzZJiLIo6n7aEyb1hl/LUNSPoipSe3DsNP14N5lLFVqzxw3zWz6+q8ueB/XQrU40njJedyP0Egq7bzTRp5c/LLbpSqX23EQaFFyP7/LgVuvERVMD29SaE9g9Z/Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=i33r6dhu; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="i33r6dhu" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793146; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=uUfcEW/wlh3C/HM93w8YTTa2lylF3eZQ+D1pvi16zc0=; b=i33r6dhuWEQ/hsfY+2teZ4uXdifa1xkF9ditdK4nqZmByLdiCq7xdCA9MSf+rcKgvxRvjQ XZpd7Q1p2WCwsj6pJMskZoDokCPxGTnHPBTkAcDepZoCnwFw1ZkxfK5uQ/QTciwOW5Ly83 5wdxyK3SF8mop9mrIPmV8/X4WerFpv0= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-582-WBnPK6nxPgym9yRbPGjS6w-1; Sun, 18 Jan 2026 22:25:41 -0500 X-MC-Unique: WBnPK6nxPgym9yRbPGjS6w-1 X-Mimecast-MFC-AGG-ID: WBnPK6nxPgym9yRbPGjS6w_1768793139 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id D70F01800447; Mon, 19 Jan 2026 03:25:38 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id EBD0C195419F; Mon, 19 Jan 2026 03:25:26 +0000 (UTC) From: Pingfan Liu To: kexec@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 02/13] kexec_file: Move signature validation ahead Date: Mon, 19 Jan 2026 11:24:13 +0800 Message-ID: <20260119032424.10781-3-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Move the signature validation at the head of the function, so the image can be unfold and handled later. Signed-off-by: Pingfan Liu Cc: Baoquan He Cc: Dave Young Cc: Andrew Morton Cc: Philipp Rudo To: kexec@lists.infradead.org --- kernel/kexec_file.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index eb62a97942428..0222d17072d40 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -231,18 +231,19 @@ kimage_file_prepare_segments(struct kimage *image, in= t kernel_fd, int initrd_fd, kexec_dprintk("kernel: %p kernel_size: %#lx\n", image->kernel_buf, image->kernel_buf_len); =20 - /* Call arch image probe handlers */ - ret =3D arch_kexec_kernel_image_probe(image, image->kernel_buf, - image->kernel_buf_len); - if (ret) - goto out; - #ifdef CONFIG_KEXEC_SIG ret =3D kimage_validate_signature(image); =20 if (ret) goto out; #endif + + /* Call arch image probe handlers */ + ret =3D arch_kexec_kernel_image_probe(image, image->kernel_buf, + image->kernel_buf_len); + if (ret) + goto out; + /* It is possible that there no initramfs is being loaded */ if (!(flags & KEXEC_FILE_NO_INITRAMFS)) { ret =3D kernel_read_file_from_fd(initrd_fd, 0, &image->initrd_buf, --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 424A61DC9B3 for ; Mon, 19 Jan 2026 03:25:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793159; cv=none; b=eDjU98q6HNAEucl9M2A5AgAHeAuZYg9W5ztM3cHvjaj2hreH6D3aqNnF9F+DEWlYattlGW4E9EEh8l3ANbTIv/Xjz1sJNcieekfZqiqyYfdnSDnm65hLYtDDHFwAcyaClakhWGH/yhvaWA37S+kf1/mCIQmYG/1Th5N4OGNm3FY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793159; c=relaxed/simple; bh=+ecQ5gK8JeAjJGmk6QHcpXOGTwCDwRZN/RM0zrGbals=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KFXfBh79cVIRq7UU5MQBJds8q577JRyEtLVLhLe4QN0/AMS19DSINkCxxIDnRnjCvoDF0XtX7+zQ+WxO5sd8xqIKqrRxsO4tyL/v4Ns67arj9XW+5gMCyfv065XjRv5KE3scR2bq0YWYMTSEiaXY7j5VYoogAJMzKpQHSLbqtts= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Sr/WbDdh; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Sr/WbDdh" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793157; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=PWLya1dhQNEc2PDrSyTdG72OD3leiyaAynZDfpPJDd8=; b=Sr/WbDdh2I1uXlSQU3IFGZv1TUjRho8lhPqy53DJv8aodXfiKoNR8Qmz6HPF9y3OxDWgT4 vQWWCaEw/lszjUBOCgOARqj/P143HdNihdfPmsBLHFYlJN9zdBT0Lu+pzJbeSJVcMCDr3Y S5yF7fr+omOI4mCzZK7kTKQrtCZQROI= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-618-utvPLdATNoeFcSBB5BRvfw-1; Sun, 18 Jan 2026 22:25:54 -0500 X-MC-Unique: utvPLdATNoeFcSBB5BRvfw-1 X-Mimecast-MFC-AGG-ID: utvPLdATNoeFcSBB5BRvfw_1768793151 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EFC471956096; Mon, 19 Jan 2026 03:25:50 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 906531955F22; Mon, 19 Jan 2026 03:25:39 +0000 (UTC) From: Pingfan Liu To: kexec@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 03/13] kexec_file: Introduce routines to parse PE file Date: Mon, 19 Jan 2026 11:24:14 +0800 Message-ID: <20260119032424.10781-4-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" The incoming patches need to handle UEFI format image, which is in PE format. Hence introducing some routines here. Signed-off-by: Pingfan Liu Cc: Baoquan He Cc: Dave Young Cc: Andrew Morton Cc: Philipp Rudo To: kexec@lists.infradead.org --- kernel/Makefile | 1 + kernel/kexec_internal.h | 3 ++ kernel/kexec_uefi_app.c | 81 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 kernel/kexec_uefi_app.c diff --git a/kernel/Makefile b/kernel/Makefile index e83669841b8cc..f9e85c4a0622b 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -83,6 +83,7 @@ obj-$(CONFIG_CRASH_DUMP_KUNIT_TEST) +=3D crash_core_test.o obj-$(CONFIG_KEXEC) +=3D kexec.o obj-$(CONFIG_KEXEC_FILE) +=3D kexec_file.o obj-$(CONFIG_KEXEC_ELF) +=3D kexec_elf.o +obj-$(CONFIG_KEXEC_BPF) +=3D kexec_uefi_app.o obj-$(CONFIG_BACKTRACE_SELF_TEST) +=3D backtracetest.o obj-$(CONFIG_COMPAT) +=3D compat.o obj-$(CONFIG_CGROUPS) +=3D cgroup/ diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h index 228bb88c018bc..8e5e5c1237732 100644 --- a/kernel/kexec_internal.h +++ b/kernel/kexec_internal.h @@ -36,6 +36,9 @@ static inline void kexec_unlock(void) void kimage_file_post_load_cleanup(struct kimage *image); extern char kexec_purgatory[]; extern size_t kexec_purgatory_size; +extern bool pe_has_bpf_section(const char *file_buf, unsigned long pe_sz); +extern int pe_get_section(const char *file_buf, const char *sect_name, + char **sect_start, unsigned long *sect_sz); #else /* CONFIG_KEXEC_FILE */ static inline void kimage_file_post_load_cleanup(struct kimage *image) { } #endif /* CONFIG_KEXEC_FILE */ diff --git a/kernel/kexec_uefi_app.c b/kernel/kexec_uefi_app.c new file mode 100644 index 0000000000000..dbe6d76d47ffa --- /dev/null +++ b/kernel/kexec_uefi_app.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * UEFI appilication file helpers + * + * Copyright (C) 2025, 2026 Red Hat, Inc + */ + +#include +#include +#include +#include +#include +#include +#include "kexec_internal.h" + +/* + * The UEFI Terse Executable (TE) image has MZ header. + */ +static bool is_valid_pe(const char *kernel_buf, unsigned long kernel_len) +{ + struct mz_hdr *mz; + struct pe_hdr *pe; + + if (!kernel_buf) + return false; + mz =3D (struct mz_hdr *)kernel_buf; + if (mz->magic !=3D IMAGE_DOS_SIGNATURE) + return false; + pe =3D (struct pe_hdr *)(kernel_buf + mz->peaddr); + if (pe->magic !=3D IMAGE_NT_SIGNATURE) + return false; + if (pe->opt_hdr_size =3D=3D 0) { + pr_err("optional header is missing\n"); + return false; + } + return true; +} + +bool pe_has_bpf_section(const char *file_buf, unsigned long pe_sz) +{ + char *sect_start =3D NULL; + unsigned long sect_sz =3D 0; + int ret; + + if (!is_valid_pe(file_buf, pe_sz)) + return false; + ret =3D pe_get_section(file_buf, ".bpf", §_start, §_sz); + if (ret < 0) + return false; + return true; +} + +int pe_get_section(const char *file_buf, const char *sect_name, + char **sect_start, unsigned long *sect_sz) +{ + struct pe_hdr *pe_hdr; + struct pe32plus_opt_hdr *opt_hdr; + struct section_header *sect_hdr; + int section_nr, i; + struct mz_hdr *mz =3D (struct mz_hdr *)file_buf; + + *sect_start =3D NULL; + *sect_sz =3D 0; + pe_hdr =3D (struct pe_hdr *)(file_buf + mz->peaddr); + section_nr =3D pe_hdr->sections; + opt_hdr =3D (struct pe32plus_opt_hdr *)(file_buf + mz->peaddr + + sizeof(struct pe_hdr)); + sect_hdr =3D (struct section_header *)((char *)opt_hdr + + pe_hdr->opt_hdr_size); + + for (i =3D 0; i < section_nr; i++) { + if (strcmp(sect_hdr->name, sect_name) =3D=3D 0) { + *sect_start =3D (char *)file_buf + sect_hdr->data_addr; + *sect_sz =3D sect_hdr->raw_data_size; + return 0; + } + sect_hdr++; + } + + return -1; +} --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 07BF326B777 for ; Mon, 19 Jan 2026 03:26:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793171; cv=none; b=EYHNQiwMHHHHA2tIrIHcEcVm/AvKmUQSdofX6/EmIh2x7yppgzT9+LtfFW/qOi34RskLdRWzb8oGGmeRic2EGzS9ew24Nmqoz+R7mupYQuUHxHgQ2bbekFP//z8yV5UHgVqo8IXoePwfSQyqIjIX1AtogM2vPoP9sL64e0c3Eks= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793171; c=relaxed/simple; bh=fIvLL1De30RcxQb7+CKWRCpyMoJ4pOMT3KIG1pxkQV0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=g+7IFh4UDRrVhtCyifb1x+xm5p0oD/DRysEhY7ZRn3HLqDAair0TaN8Kr8CZxWigtli8o1h1aXCC16gWfQ1kuTqnU7JRBLr3Vcg/eOKVjlijXF0k3syxM0OS8yuAVBjuGej7NXinXYvJp50Yubrw3OAE+T2R8MxlE2dqDDGmNaM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=H5JaDAAV; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="H5JaDAAV" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793169; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=pv0T+x9AR2PJROBQmbxh+6k2mKN+f/nip4Zou9Zi7Ow=; b=H5JaDAAVTWkVLZxEbVqpu20XkPwn2+Jl3dIG1T80b83j6u/l2r7y0XxIHgbBFdHQqD++Qb 5wdDQedoQ84qkIkNcHGiCBWbyRfFBd/KkUSjK9JMWpl6seRR1oVwIpheqMK6dIdWL9lIme vPifG35y+uErohE/dn/JN7GbWyZbzYE= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-606-KVDeXZCXNESpvZ0icQjNMg-1; Sun, 18 Jan 2026 22:26:05 -0500 X-MC-Unique: KVDeXZCXNESpvZ0icQjNMg-1 X-Mimecast-MFC-AGG-ID: KVDeXZCXNESpvZ0icQjNMg_1768793163 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9E4E6180044D; Mon, 19 Jan 2026 03:26:02 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id A6F521955F22; Mon, 19 Jan 2026 03:25:51 +0000 (UTC) From: Pingfan Liu To: kexec@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 04/13] kexec_file: Use bpf-prog to decompose image Date: Mon, 19 Jan 2026 11:24:15 +0800 Message-ID: <20260119032424.10781-5-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" As UEFI becomes popular, a few architectures support to boot a PE format kernel image directly. But the internal of PE format varies, which means each parser for each format. This patch (with the rest in this series) introduces a common skeleton to all parsers, and leave the format parsing in bpf-prog, so the kernel code can keep relative stable. History, the syscall SYSCALL_DEFINE5(kexec_file_load, int, kernel_fd, int, initrd_fd, unsigned long, cmdline_len, const char __user *, cmdline_pt= r, unsigned long, flags) complies with the kernel protocol: bootable kernel, initramfs, cmdline. But the occurrence of UKI images challenges the traditional model. The image itself contains the kernel, initrd, and cmdline. To be compatible with both the old and new models, kexec_file_load can be reorganized into two stages. In the first stage, "decompose_kexec_image()" breaks down the passed-in image into the components required by the kernel boot protocol. In the second stage, the traditional image loader "arch_kexec_kernel_image_load()" prepares the switch to the next kernel. During the decomposition stage, the decomposition process can be nested. In each sub-process, BPF bytecode is extracted from the '.bpf' section to parse the current PE file. If the data section in the PE file contains another PE file, the sub-process is repeated. This is designed to handle the zboot format embedded in UKI format on the arm64 platform. There are some placeholder functions in this patch. (They will take effect after the introduction of kexec BPF light skeleton and BPF helpers.) Signed-off-by: Pingfan Liu Cc: Baoquan He Cc: Dave Young Cc: Andrew Morton Cc: Philipp Rudo To: kexec@lists.infradead.org --- kernel/Kconfig.kexec | 8 ++ kernel/Makefile | 2 +- kernel/kexec_bpf_loader.c | 161 ++++++++++++++++++++++++++++++++++++++ kernel/kexec_file.c | 9 ++- kernel/kexec_internal.h | 1 + 5 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 kernel/kexec_bpf_loader.c diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec index 15632358bcf71..0c5d619820bcd 100644 --- a/kernel/Kconfig.kexec +++ b/kernel/Kconfig.kexec @@ -46,6 +46,14 @@ config KEXEC_FILE for kernel and initramfs as opposed to list of segments as accepted by kexec system call. =20 +config KEXEC_BPF + bool "Enable bpf-prog to parse the kexec image" + depends on KEXEC_FILE + depends on DEBUG_INFO_BTF && BPF_SYSCALL + help + This is a feature to run bpf section inside a kexec image file, which + parses the image properly and help kernel set up kexec boot protocol + config KEXEC_SIG bool "Verify kernel signature during kexec_file_load() syscall" depends on ARCH_SUPPORTS_KEXEC_SIG diff --git a/kernel/Makefile b/kernel/Makefile index f9e85c4a0622b..05177a867690d 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -83,7 +83,7 @@ obj-$(CONFIG_CRASH_DUMP_KUNIT_TEST) +=3D crash_core_test.o obj-$(CONFIG_KEXEC) +=3D kexec.o obj-$(CONFIG_KEXEC_FILE) +=3D kexec_file.o obj-$(CONFIG_KEXEC_ELF) +=3D kexec_elf.o -obj-$(CONFIG_KEXEC_BPF) +=3D kexec_uefi_app.o +obj-$(CONFIG_KEXEC_BPF) +=3D kexec_bpf_loader.o kexec_uefi_app.o obj-$(CONFIG_BACKTRACE_SELF_TEST) +=3D backtracetest.o obj-$(CONFIG_COMPAT) +=3D compat.o obj-$(CONFIG_CGROUPS) +=3D cgroup/ diff --git a/kernel/kexec_bpf_loader.c b/kernel/kexec_bpf_loader.c new file mode 100644 index 0000000000000..dc59e1389da94 --- /dev/null +++ b/kernel/kexec_bpf_loader.c @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Kexec image bpf section helpers + * + * Copyright (C) 2025, 2026 Red Hat, Inc + */ + +#define pr_fmt(fmt) "kexec_file(Image): " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kexec_internal.h" + +/* Load a ELF */ +static int arm_bpf_prog(char *bpf_elf, unsigned long sz) +{ + return 0; +} + +static void disarm_bpf_prog(void) +{ +} + +struct kexec_context { + bool kdump; + char *kernel; + int kernel_sz; + char *initrd; + int initrd_sz; + char *cmdline; + int cmdline_sz; +}; + +void kexec_image_parser_anchor(struct kexec_context *context, + unsigned long parser_id); + +/* + * optimize("O0") prevents inline, compiler constant propagation + * + * Let bpf be the program context pointer so that it will not be spilled i= nto + * stack. + */ +__attribute__((used, optimize("O0"))) void kexec_image_parser_anchor( + struct kexec_context *context, + unsigned long parser_id) +{ + /* + * To prevent linker from Identical Code Folding (ICF) with kexec_image_p= arser_anchor, + * making them have different code. + */ + volatile int dummy =3D 0; + + dummy +=3D 1; +} + + +BTF_KFUNCS_START(kexec_modify_return_ids) +BTF_ID_FLAGS(func, kexec_image_parser_anchor, KF_SLEEPABLE) +BTF_KFUNCS_END(kexec_modify_return_ids) + +static const struct btf_kfunc_id_set kexec_modify_return_set =3D { + .owner =3D THIS_MODULE, + .set =3D &kexec_modify_return_ids, +}; + +static int __init kexec_bpf_prog_run_init(void) +{ + return register_btf_fmodret_id_set(&kexec_modify_return_set); +} +late_initcall(kexec_bpf_prog_run_init); + +static int kexec_buff_parser(struct bpf_parser_context *parser) +{ + return 0; +} + +/* At present, only PE format file with .bpf section is supported */ +#define file_has_bpf_section pe_has_bpf_section +#define file_get_section pe_get_section + +int decompose_kexec_image(struct kimage *image, int extended_fd) +{ + struct kexec_context context =3D { 0 }; + struct bpf_parser_context *bpf; + unsigned long kernel_sz, bpf_sz; + char *kernel_start, *bpf_start; + int ret =3D 0; + + if (image->type !=3D KEXEC_TYPE_CRASH) + context.kdump =3D false; + else + context.kdump =3D true; + + kernel_start =3D image->kernel_buf; + kernel_sz =3D image->kernel_buf_len; + + while (file_has_bpf_section(kernel_start, kernel_sz)) { + + bpf =3D alloc_bpf_parser_context(kexec_buff_parser, &context); + if (!bpf) + return -ENOMEM; + file_get_section((const char *)kernel_start, ".bpf", &bpf_start, &bpf_sz= ); + if (!!bpf_sz) { + /* load and attach bpf-prog */ + ret =3D arm_bpf_prog(bpf_start, bpf_sz); + if (ret) { + put_bpf_parser_context(bpf); + pr_err("Fail to load .bpf section\n"); + goto err; + } + } + context.kernel =3D kernel_start; + context.kernel_sz =3D kernel_sz; + /* bpf-prog fentry, which handle above buffers. */ + kexec_image_parser_anchor(&context, (unsigned long)bpf); + + /* + * Container may be nested and should be unfold one by one. + * The former bpf-prog should prepare 'kernel', 'initrd', + * 'cmdline' for the next phase by calling kexec_buff_parser() + */ + kernel_start =3D context.kernel; + kernel_sz =3D context.kernel_sz; + + /* + * detach the current bpf-prog from their attachment points. + */ + disarm_bpf_prog(); + put_bpf_parser_context(bpf); + } + + /* + * image's kernel_buf, initrd_buf, cmdline_buf are set. Now they should + * be updated to the new content. + */ + image->kernel_buf =3D context.kernel; + image->kernel_buf_len =3D context.kernel_sz; + image->initrd_buf =3D context.initrd; + image->initrd_buf_len =3D context.initrd_sz; + image->cmdline_buf =3D context.cmdline; + image->cmdline_buf_len =3D context.cmdline_sz; + + return 0; +err: + vfree(context.kernel); + vfree(context.initrd); + vfree(context.cmdline); + return ret; +} + diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 0222d17072d40..f9674bb5bd8db 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -238,7 +238,14 @@ kimage_file_prepare_segments(struct kimage *image, int= kernel_fd, int initrd_fd, goto out; #endif =20 - /* Call arch image probe handlers */ + if (IS_ENABLED(CONFIG_KEXEC_BPF)) + decompose_kexec_image(image, initrd_fd); + + /* + * From this point, the kexec subsystem handle the kernel boot protocol. + * + * Call arch image probe handlers + */ ret =3D arch_kexec_kernel_image_probe(image, image->kernel_buf, image->kernel_buf_len); if (ret) diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h index 8e5e5c1237732..ee01d0c8bb377 100644 --- a/kernel/kexec_internal.h +++ b/kernel/kexec_internal.h @@ -39,6 +39,7 @@ extern size_t kexec_purgatory_size; extern bool pe_has_bpf_section(const char *file_buf, unsigned long pe_sz); extern int pe_get_section(const char *file_buf, const char *sect_name, char **sect_start, unsigned long *sect_sz); +extern int decompose_kexec_image(struct kimage *image, int extended_fd); #else /* CONFIG_KEXEC_FILE */ static inline void kimage_file_post_load_cleanup(struct kimage *image) { } #endif /* CONFIG_KEXEC_FILE */ --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A53620A5C4 for ; Mon, 19 Jan 2026 03:26:22 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793184; cv=none; b=OeLWrYTorvcxvdm9xhj2siGyrhefYeTo8bBsfQdUVfGFn84NNNEmnSutJ9Fyw6DzM1RflM3RCi+4X+wvUx4dpJR845fR8+tUflk8Cj5/EfcjS3jC6JNCnNThqW8BipO8yGfQ84jG/W5xF7bFT7oOwtsKslx4cnubIpHfVZAn61I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793184; c=relaxed/simple; bh=KoOqMVsxXxT2B0pOv168WB7cXJrbry5wUPqp5jH0FWM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=q6KR3RiJ9BjpqjsLteW8mYfusxckOXaVrGZs4lvbChzBz9QMEuFQXZ99w3OkKzerM/kykKOu6/wSy6ggSVXSX/JVHQ2PSt95FpTrMP6e6Adii3xHkGUX1qp8qyBnMNzrwIE5gACVTfgwVKEbUBE6JhN3DC2/+sMzcJAloUMwYoE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=LirMqcu9; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="LirMqcu9" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793182; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Hg0gvqRYQBne5zWb7lRZ/WuuQgWnEek/Cp/61K7aU80=; b=LirMqcu9FVnMpWuRUCfDPIiJULmWtujMmeI88wl+HJIQlVwHateXkJkmmskX84vubAYA8g MRGk3Ywa6HOjQn2z65G9Sjl0fl4AYbuLLesOsncBz+hzMuPl6aWm3WbpIhzXe64Ngu0fjl WyDWxbUQMAAmO7pr6lF6hwEzYiB8a54= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-399-_4h3uHm2MPKI8q34RT6_Cg-1; Sun, 18 Jan 2026 22:26:17 -0500 X-MC-Unique: _4h3uHm2MPKI8q34RT6_Cg-1 X-Mimecast-MFC-AGG-ID: _4h3uHm2MPKI8q34RT6_Cg_1768793174 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 5D216180044D; Mon, 19 Jan 2026 03:26:14 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 58BF21955F22; Mon, 19 Jan 2026 03:26:03 +0000 (UTC) From: Pingfan Liu To: linux-kernel@vger.kernel.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , kexec@lists.infradead.org, bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org Subject: [PATCHv6 05/13] lib/decompress: Keep decompressor when CONFIG_KEEP_DECOMPRESSOR Date: Mon, 19 Jan 2026 11:24:16 +0800 Message-ID: <20260119032424.10781-6-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" The KEXE PE format parser needs the kernel built-in decompressor to decompress the kernel image. So moving the decompressor out of __init sections. Signed-off-by: Pingfan Liu Cc: Andrew Morton To: linux-kernel@vger.kernel.org --- include/linux/decompress/mm.h | 8 ++++++++ lib/Kconfig | 6 ++++++ lib/decompress.c | 6 +++--- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/include/linux/decompress/mm.h b/include/linux/decompress/mm.h index ac862422df158..39df02bcbc661 100644 --- a/include/linux/decompress/mm.h +++ b/include/linux/decompress/mm.h @@ -81,6 +81,7 @@ MALLOC_VISIBLE void free(void *where) #include #include #include +#include =20 /* Use defines rather than static inline in order to avoid spurious * warnings when not needed (indeed large_malloc / large_free are not @@ -92,7 +93,14 @@ MALLOC_VISIBLE void free(void *where) #define large_malloc(a) vmalloc(a) #define large_free(a) vfree(a) =20 +#ifdef CONFIG_KEEP_DECOMPRESSOR +#define INIT +#define INITCONST +#else #define INIT __init +#define INITCONST __initconst +#endif + #define STATIC =20 #include diff --git a/lib/Kconfig b/lib/Kconfig index 2923924bea78c..4424ae14dcf12 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -165,6 +165,12 @@ config RANDOM32_SELFTEST # # compression support is select'ed if needed # +config KEEP_DECOMPRESSOR + bool "keeps the decompress routines after kernel initialization" + default n + help + This option keeps the decompress routines after kernel initialization + config 842_COMPRESS select CRC32 tristate diff --git a/lib/decompress.c b/lib/decompress.c index 7785471586c62..29d4c749f1fc4 100644 --- a/lib/decompress.c +++ b/lib/decompress.c @@ -6,7 +6,7 @@ */ =20 #include - +#include #include #include #include @@ -48,7 +48,7 @@ struct compress_format { decompress_fn decompressor; }; =20 -static const struct compress_format compressed_formats[] __initconst =3D { +static const struct compress_format compressed_formats[] INITCONST =3D { { .magic =3D {0x1f, 0x8b}, .name =3D "gzip", .decompressor =3D gunzip }, { .magic =3D {0x1f, 0x9e}, .name =3D "gzip", .decompressor =3D gunzip }, { .magic =3D {0x42, 0x5a}, .name =3D "bzip2", .decompressor =3D bunzip2 }, @@ -60,7 +60,7 @@ static const struct compress_format compressed_formats[] = __initconst =3D { { /* sentinel */ } }; =20 -decompress_fn __init decompress_method(const unsigned char *inbuf, long le= n, +decompress_fn INIT decompress_method(const unsigned char *inbuf, long len, const char **name) { const struct compress_format *cf; --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1614E26ED3A for ; Mon, 19 Jan 2026 03:26:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793196; cv=none; b=HLW+V8eM4TMfb11JJ9zdRrWkxdXNnTsZjrBIsliSMJUbaVgC1qE8Runm3BiN5mF8lI3Hld4HddvsNsOErpmwKp+XD2P5KDHEneQFol7qWY+sRpV0gtW9sx7YlHhZ/KfwLubsuxta19uHydUCl1hp+0mp9oFlYrPJEjtw4TrNOGs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793196; c=relaxed/simple; bh=oDGl3auAeZXO4XYXRZ0gANgpXVRHzHt7SXKT39Am37Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=of4IO6kzFcD9QrwfARjhMbC/zOyk9EhYmchqgO5VowTTaln8vF2WyhQAa2wu2eCzoEMlT2hsqFoz0jpECTZWg1Z57BFwFmdw0dZRI1FegpIFQ7mERk0ybcqAQntZGw7DO8RyOwpE97sIIv8WJoQpuXVUHPGQ/UKmuc0nHg9R6G8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=HQRqDBzE; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="HQRqDBzE" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793193; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ugTOtriRaWK2mGaURO2PPvf5ie8qlQnqTxshN8BJKDc=; b=HQRqDBzEGwk912iKcECyz10VikuTPYYjOj7tCghuXexXuNPUXeMLMYdpJo9JUmeYTrOYp0 75HMoGoXJn4YpbFyBLf0vRkOpEXsqrVws1I3ac8qhSwygcLczqWx691t+cHS5OUo18xFL4 ilpbt2ctSvl+JF7xQStDO0BKLO3z+2Q= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-610-nvbzhAXAPeSDtbFAM1V6uA-1; Sun, 18 Jan 2026 22:26:29 -0500 X-MC-Unique: nvbzhAXAPeSDtbFAM1V6uA-1 X-Mimecast-MFC-AGG-ID: nvbzhAXAPeSDtbFAM1V6uA_1768793187 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8A6C71800342; Mon, 19 Jan 2026 03:26:26 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 16FB71955F22; Mon, 19 Jan 2026 03:26:14 +0000 (UTC) From: Pingfan Liu To: kexec@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 06/13] kexec_file: Implement decompress method for parser Date: Mon, 19 Jan 2026 11:24:17 +0800 Message-ID: <20260119032424.10781-7-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" On arm64, there is no boot-time decompression for the kernel image. Therefore, when a compressed kernel image is loaded, it must be decompressed. It is impractical to implement the complex decompression methods in BPF bytecode. However, decompression routines exist in the kernel. This patch bridges the compressed data with the kernel's decompression methods. Signed-off-by: Pingfan Liu Cc: Baoquan He Cc: Dave Young Cc: Andrew Morton Cc: Philipp Rudo To: kexec@lists.infradead.org --- kernel/Kconfig.kexec | 2 +- kernel/kexec_bpf_loader.c | 203 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 204 insertions(+), 1 deletion(-) diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec index 0c5d619820bcd..dbfdf34a78aa0 100644 --- a/kernel/Kconfig.kexec +++ b/kernel/Kconfig.kexec @@ -49,7 +49,7 @@ config KEXEC_FILE config KEXEC_BPF bool "Enable bpf-prog to parse the kexec image" depends on KEXEC_FILE - depends on DEBUG_INFO_BTF && BPF_SYSCALL + depends on DEBUG_INFO_BTF && BPF_SYSCALL && KEEP_DECOMPRESSOR help This is a feature to run bpf section inside a kexec image file, which parses the image properly and help kernel set up kexec boot protocol diff --git a/kernel/kexec_bpf_loader.c b/kernel/kexec_bpf_loader.c index dc59e1389da94..bd6a47fc53ed3 100644 --- a/kernel/kexec_bpf_loader.c +++ b/kernel/kexec_bpf_loader.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "kexec_internal.h" =20 /* Load a ELF */ @@ -80,8 +81,210 @@ static int __init kexec_bpf_prog_run_init(void) } late_initcall(kexec_bpf_prog_run_init); =20 +#define KEXEC_BPF_CMD_DECOMPRESS 0x1 + +#define KEXEC_BPF_SUBCMD_KERNEL 0x1 +#define KEXEC_BPF_SUBCMD_INITRD 0x2 +#define KEXEC_BPF_SUBCMD_CMDLINE 0x3 + +struct cmd_hdr { + uint16_t cmd; + uint16_t subcmd; + uint32_t payload_len; +} __packed; + + +/* Max decompressed size is capped at 512M */ +#define MAX_UNCOMPRESSED_BUF_SIZE (1 << 29) +#define CHUNK_SIZE (1 << 23) + +struct decompress_mem_allocator { + void *chunk_start; + unsigned int chunk_size; + void *chunk_cur; + unsigned int next_idx; + char **chunk_base_addr; +}; + +/* + * This global allocator for decompression is protected by kexec lock. + */ +static struct decompress_mem_allocator dcmpr_allocator; + +/* + * Set up an active chunk to hold partial decompressed data. + */ +static char *allocate_chunk_memory(void) +{ + struct decompress_mem_allocator *a =3D &dcmpr_allocator; + char *p; + + if (unlikely((a->next_idx * a->chunk_size >=3D MAX_UNCOMPRESSED_BUF_SIZE)= )) + return NULL; + + p =3D __vmalloc(a->chunk_size, GFP_KERNEL | __GFP_ACCOUNT); + if (!p) + return NULL; + a->chunk_base_addr[a->next_idx++] =3D p; + a->chunk_start =3D a->chunk_cur =3D p; + + return p; +} + +static int merge_decompressed_data(struct decompress_mem_allocator *a, + char **out, unsigned int *size) +{ + unsigned int last_chunk_sz =3D a->chunk_cur - a->chunk_start; + unsigned long total_sz; + char *dst, *cur_dst; + int i; + + total_sz =3D (a->next_idx - 1) * a->chunk_size + last_chunk_sz; + cur_dst =3D dst =3D __vmalloc(total_sz, GFP_KERNEL | __GFP_ACCOUNT); + if (!dst) + return -ENOMEM; + + for (i =3D 0; i < a->next_idx - 1; i++) { + memcpy(cur_dst, a->chunk_base_addr[i], a->chunk_size); + cur_dst +=3D a->chunk_size; + vfree(a->chunk_base_addr[i]); + } + + memcpy(cur_dst, a->chunk_base_addr[i], last_chunk_sz); + vfree(a->chunk_base_addr[i]); + *out =3D dst; + *size =3D total_sz; + + return 0; +} + +static int decompress_mem_allocator_init( + struct decompress_mem_allocator *a, + unsigned int chunk_size) +{ + unsigned long sz =3D (MAX_UNCOMPRESSED_BUF_SIZE / chunk_size) * sizeof(vo= id *); + char *buf; + + a->chunk_base_addr =3D __vmalloc(sz, GFP_KERNEL | __GFP_ACCOUNT); + if (!a->chunk_base_addr) + return -ENOMEM; + + /* Pre-allocate the memory for the first chunk */ + buf =3D __vmalloc(chunk_size, GFP_KERNEL | __GFP_ACCOUNT); + if (!buf) { + vfree(a->chunk_base_addr); + return -ENOMEM; + } + a->chunk_base_addr[0] =3D buf; + a->chunk_start =3D a->chunk_cur =3D buf; + a->chunk_size =3D chunk_size; + a->next_idx =3D 1; + return 0; +} + +static void decompress_mem_allocator_fini(struct decompress_mem_allocator = *a) +{ + vfree(a->chunk_base_addr); +} + +/* + * This is a callback for decompress_fn. + * + * It copies the partial decompressed content in [buf, buf + len) to dst. = If the + * active chunk is not large enough, retire it and activate a new chunk to= hold + * the remaining data. + */ +static long flush(void *buf, unsigned long len) +{ + struct decompress_mem_allocator *a =3D &dcmpr_allocator; + long free, copied =3D 0; + + if (unlikely(len > a->chunk_size)) { + pr_info("Chunk size is too small to hold decompressed data\n"); + return -1; + } + free =3D a->chunk_start + a->chunk_size - a->chunk_cur; + BUG_ON(free < 0); + if (free < len) { + memcpy(a->chunk_cur, buf, free); + copied +=3D free; + a->chunk_cur +=3D free; + buf +=3D free; + len -=3D free; + a->chunk_start =3D a->chunk_cur =3D allocate_chunk_memory(); + if (unlikely(!a->chunk_start)) { + pr_info("Decompression runs out of memory\n"); + return -1; + } + } + memcpy(a->chunk_cur, buf, len); + copied +=3D len; + a->chunk_cur +=3D len; + return copied; +} + +static int parser_cmd_decompress(char *compressed_data, int image_gz_sz, + char **out_buf, int *out_sz, struct kexec_context *ctx) +{ + struct decompress_mem_allocator *a =3D &dcmpr_allocator; + decompress_fn decompressor; + const char *name; + int ret; + + decompress_mem_allocator_init(a, CHUNK_SIZE); + decompressor =3D decompress_method(compressed_data, image_gz_sz, &name); + if (!decompressor) { + pr_err("Can not find decompress method\n"); + return -1; + } + pr_debug("Find decompressing method: %s, compressed sz:0x%x\n", + name, image_gz_sz); + ret =3D decompressor(compressed_data, image_gz_sz, NULL, flush, + NULL, NULL, NULL); + if (!!ret) + goto err; + ret =3D merge_decompressed_data(a, out_buf, out_sz); + +err: + decompress_mem_allocator_fini(a); + + return ret; +} + static int kexec_buff_parser(struct bpf_parser_context *parser) { + struct bpf_parser_buf *pbuf =3D parser->buf; + struct kexec_context *ctx =3D (struct kexec_context *)parser->data; + struct cmd_hdr *cmd =3D (struct cmd_hdr *)pbuf->buf; + char *decompressed_buf, *buf, *p; + int decompressed_sz, ret; + + buf =3D pbuf->buf + sizeof(struct cmd_hdr); + if (cmd->payload_len + sizeof(struct cmd_hdr) > pbuf->size) { + pr_info("Invalid payload size:0x%x, while buffer size:0x%x\n", + cmd->payload_len, pbuf->size); + return -EINVAL; + } + switch (cmd->cmd) { + case KEXEC_BPF_CMD_DECOMPRESS: + ret =3D parser_cmd_decompress(buf, cmd->payload_len, &decompressed_buf, + &decompressed_sz, ctx); + if (!ret) { + switch (cmd->subcmd) { + case KEXEC_BPF_SUBCMD_KERNEL: + vfree(ctx->kernel); + ctx->kernel =3D decompressed_buf; + ctx->kernel_sz =3D decompressed_sz; + break; + default: + break; + } + } + break; + default: + break; + } + return 0; } =20 --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC39B27586C for ; Mon, 19 Jan 2026 03:26:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793207; cv=none; b=JeR51tVEFcSi5KBjEd0gFVvSvSfPKUZeuJvnL0FGJYAosYXsHAahoATLcvpYtS0SuVO+Ey16OtIcmnVVz3jxi+kEIhyRsQMxDNT7PPzIbxg6Vs0/hkv/vEzk5ZrBGXaPni2SPyM2yGjLeKmaGu4q5F9cE41B6aO0xyFr5vJ1GWQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793207; c=relaxed/simple; bh=aEw1imkLf5wrWkotMxEW4yfr8s+cq8tJZ3ShfO4l2Ts=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=q/5KTIm7Mv6+31l6YlxfTNsw3jLoXNJjeXnkf1LRIUZk9eu07J5LC7T4GGx3S8CBVfvLPZ9Ur6rYlOi1K3FqQTA98bTrJcoYfCzWxltalw/GdcAuH2ug/9pK48KZMrhOb+JiYeaMpA3xh6fRuZv+xOzvMCCJ6IVm3k3ov8MIRLU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=esOhLfAw; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="esOhLfAw" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793203; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Yw3aB1Il7lON1+TKtraAyWydt+eFZrLxkMUyC2AOIMc=; b=esOhLfAwfj6xKGipkVoorIMkn1Za+Yo48DAN/tuU62/appbPKhoeaXgn39WLSFz/LWoILu o34K1Is9WuNYOgRABo7LhNnsVd690s3/d5hIIeZwxGYRV/7nDB8N9erz+BqYMBZzCAsSEU XrDxqIQTLP4G2rBBayDMTFscCGM0QIA= Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-256-oldMCqooNXCBv0xnVXj0ww-1; Sun, 18 Jan 2026 22:26:40 -0500 X-MC-Unique: oldMCqooNXCBv0xnVXj0ww-1 X-Mimecast-MFC-AGG-ID: oldMCqooNXCBv0xnVXj0ww_1768793198 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id E08771956046; Mon, 19 Jan 2026 03:26:37 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 5642F1955F22; Mon, 19 Jan 2026 03:26:26 +0000 (UTC) From: Pingfan Liu To: kexec@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 07/13] kexec_file: Implement copy method for parser Date: Mon, 19 Jan 2026 11:24:18 +0800 Message-ID: <20260119032424.10781-8-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Copying the bpf code parsing result to the proper place: image->kernel_buf, initrd_buf, cmdline_buf. Signed-off-by: Pingfan Liu Cc: Baoquan He Cc: Dave Young Cc: Andrew Morton Cc: Philipp Rudo To: kexec@lists.infradead.org --- kernel/kexec_bpf_loader.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/kernel/kexec_bpf_loader.c b/kernel/kexec_bpf_loader.c index bd6a47fc53ed3..5ad67672dead1 100644 --- a/kernel/kexec_bpf_loader.c +++ b/kernel/kexec_bpf_loader.c @@ -82,6 +82,7 @@ static int __init kexec_bpf_prog_run_init(void) late_initcall(kexec_bpf_prog_run_init); =20 #define KEXEC_BPF_CMD_DECOMPRESS 0x1 +#define KEXEC_BPF_CMD_COPY 0x2 =20 #define KEXEC_BPF_SUBCMD_KERNEL 0x1 #define KEXEC_BPF_SUBCMD_INITRD 0x2 @@ -281,6 +282,32 @@ static int kexec_buff_parser(struct bpf_parser_context= *parser) } } break; + case KEXEC_BPF_CMD_COPY: + p =3D __vmalloc(cmd->payload_len, GFP_KERNEL | __GFP_ACCOUNT); + if (!p) + return -ENOMEM; + memcpy(p, buf, cmd->payload_len); + switch (cmd->subcmd) { + case KEXEC_BPF_SUBCMD_KERNEL: + vfree(ctx->kernel); + ctx->kernel =3D p; + ctx->kernel_sz =3D cmd->payload_len; + break; + case KEXEC_BPF_SUBCMD_INITRD: + vfree(ctx->initrd); + ctx->initrd =3D p; + ctx->initrd_sz =3D cmd->payload_len; + break; + case KEXEC_BPF_SUBCMD_CMDLINE: + vfree(ctx->cmdline); + ctx->cmdline =3D p; + ctx->cmdline_sz =3D cmd->payload_len; + break; + default: + vfree(p); + break; + } + break; default: break; } --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 272FD78F2B for ; Mon, 19 Jan 2026 03:26:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793217; cv=none; b=oUmRv1r1qoeinzPyYpjRtZ2GgdTLU1iYbFaUAlqG295Zr0LnrRonyxiMtC1fSoeM5HVt61Ovbs+DoV9n33pVZ/GWjYELZFZbtaLV08FJZ0DNwYYSrTIdtyAgqP96/CLXWY4VTGFIIrx+Yn9TYEkzgWpyFnwjNpr03qsS8vVOeTI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793217; c=relaxed/simple; bh=3/Qlr9L7k0tcagEBAbUvz0VouVI3Sa9U76WDviaimMk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=fhv9BoXeq+CKQ5VIsBLSyHqZNp2wgqr6vCm2Jqara3+aRcZETuxd5Q0cYC1qw8Xp5jUQhDFCFtKmt8nX5iTgCYkYM0dlsSGE9LuKPDaOZpdQ6hcEP7Yr2NJmKC9xRzrjFs73XuddosglrUWjK8BWZ8UqM7Zelvn3je9qNCNPBoc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Z2ak50ak; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Z2ak50ak" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793214; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RnvK8l1NqmawWFSFXm69VvHCytbxPLgXNePZ3QGgOmc=; b=Z2ak50ak4ddOLVNhiU5Pfjyeb9sDVu0F1Sw7UdoLhrGAlgdmtY4n1SdaAye/MOFmP+3Iec DyFArXUuxwWY9N9gZhBfqpiwdtXedtLT0LIfMjzuroQa31Zz04mY/1VE5OZmBl0+6QCqeS qxWieJ+5E03EvWOmQnCqCIHzE1cuL9o= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-248-7S5UM6nvP2y4Edswv6xLmw-1; Sun, 18 Jan 2026 22:26:52 -0500 X-MC-Unique: 7S5UM6nvP2y4Edswv6xLmw-1 X-Mimecast-MFC-AGG-ID: 7S5UM6nvP2y4Edswv6xLmw_1768793210 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0743F19560A2; Mon, 19 Jan 2026 03:26:50 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AEA401955F22; Mon, 19 Jan 2026 03:26:38 +0000 (UTC) From: Pingfan Liu To: kexec@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 08/13] kexec_file: Introduce a bpf-prog lskel to parse PE file Date: Mon, 19 Jan 2026 11:24:19 +0800 Message-ID: <20260119032424.10781-9-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Analague to kernel/bpf/preload/iterators/Makefile, this Makefile is not invoked by the Kbuild system. It needs to be invoked manually when kexec_pe_parser_bpf.c is changed so that kexec_pe_parser_bpf.lskel.h can be re-generated by the command "bpftool gen skeleton -L kexec_pe_parser_bpf.o". kexec_pe_parser_bpf.lskel.h is used directly by the kernel kexec code in later patch. For this patch, there are bpf bytecode contained in opts_data[] and opts_insn[] in kexec_pe_parser_bpf.lskel.h, but in the following patch, they will be removed and only the function API in kexec_pe_parser_bpf.lskel.h left. As exposed in kexec_pe_parser_bpf.lskel.h, the interface between bpf-prog and the kernel are constituted by: four maps: struct bpf_map_desc ringbuf_1; struct bpf_map_desc ringbuf_2; struct bpf_map_desc ringbuf_3; struct bpf_map_desc ringbuf_4; four sections: struct bpf_map_desc rodata; struct bpf_map_desc data; struct bpf_map_desc rodata_str1_1; struct bpf_map_desc bss; one prog: SEC("fentry.s/kexec_image_parser_anchor") The interface of maps and sections are extracted in template.c, which should be included by any bpf-prog to interact with kexec_bpf component Signed-off-by: Pingfan Liu Cc: Alexei Starovoitov Cc: Baoquan He Cc: Dave Young Cc: Andrew Morton Cc: Philipp Rudo Cc: bpf@vger.kernel.org To: kexec@lists.infradead.org --- kernel/kexec_bpf/Makefile | 62 ++++ kernel/kexec_bpf/kexec_pe_parser_bpf.c | 12 + kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h | 372 +++++++++++++++++++ kernel/kexec_bpf/template.c | 68 ++++ 4 files changed, 514 insertions(+) create mode 100644 kernel/kexec_bpf/Makefile create mode 100644 kernel/kexec_bpf/kexec_pe_parser_bpf.c create mode 100644 kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h create mode 100644 kernel/kexec_bpf/template.c diff --git a/kernel/kexec_bpf/Makefile b/kernel/kexec_bpf/Makefile new file mode 100644 index 0000000000000..45d45cc0855a3 --- /dev/null +++ b/kernel/kexec_bpf/Makefile @@ -0,0 +1,62 @@ +# SPDX-License-Identifier: GPL-2.0 +OUTPUT :=3D .output +CLANG ?=3D clang +LLC ?=3D llc +LLVM_STRIP ?=3D llvm-strip +DEFAULT_BPFTOOL :=3D $(OUTPUT)/sbin/bpftool +BPFTOOL ?=3D $(DEFAULT_BPFTOOL) +LIBBPF_SRC :=3D $(abspath ../../tools/lib/bpf) +BPFOBJ :=3D $(OUTPUT)/libbpf.a +BPF_INCLUDE :=3D $(OUTPUT) +INCLUDES :=3D -I$(OUTPUT) -I$(BPF_INCLUDE) -I$(abspath ../../tools/lib) = \ + -I$(abspath ../../tools/include/uapi) +CFLAGS :=3D -g -Wall + +srctree :=3D $(patsubst %/kernel/kexec_bpf,%,$(CURDIR)) +VMLINUX =3D $(srctree)/vmlinux + +abs_out :=3D $(abspath $(OUTPUT)) +ifeq ($(V),1) +Q =3D +msg =3D +else +Q =3D @ +msg =3D @printf ' %-8s %s%s\n' "$(1)" "$(notdir $(2))" "$(if $(3), $(3))"; +MAKEFLAGS +=3D --no-print-directory +submake_extras :=3D feature_display=3D0 +endif + +.DELETE_ON_ERROR: + +.PHONY: all clean + +all: $(OUTPUT) kexec_pe_parser_bpf.lskel.h + +clean: + $(call msg,CLEAN) + $(Q)rm -rf $(OUTPUT) kexec_pe_parser_bpf.lskel.h + +kexec_pe_parser_bpf.lskel.h: $(OUTPUT)/kexec_pe_parser_bpf.o | $(BPFTOOL) + $(call msg,GEN-SKEL,$@) + $(Q)$(BPFTOOL) gen skeleton -L $< > $@ + +$(OUTPUT)/vmlinux.h: $(VMLINUX) $(DEFAULT_BPFTOOL) $(BPFOBJ) | $(OUTPUT) + @$(BPFTOOL) btf dump file $(VMLINUX) format c > $(OUTPUT)/vmlinux.h + +$(OUTPUT)/kexec_pe_parser_bpf.o: kexec_pe_parser_bpf.c $(OUTPUT)/vmlinux.h= $(BPFOBJ) | $(OUTPUT) + $(call msg,BPF,$@) + $(Q)$(CLANG) -g -O2 -target bpf $(INCLUDES) \ + -c $(filter %.c,$^) -o $@ && \ + $(LLVM_STRIP) -g $@ + +$(OUTPUT): + $(call msg,MKDIR,$@) + $(Q)mkdir -p $(OUTPUT) + +$(BPFOBJ): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(OUT= PUT) + $(Q)$(MAKE) $(submake_extras) -C $(LIBBPF_SRC) \ + OUTPUT=3D$(abspath $(dir $@))/ $(abspath $@) + +$(DEFAULT_BPFTOOL): + $(Q)$(MAKE) $(submake_extras) -C ../../tools/bpf/bpftool \ + prefix=3D OUTPUT=3D$(abs_out)/ DESTDIR=3D$(abs_out) install diff --git a/kernel/kexec_bpf/kexec_pe_parser_bpf.c b/kernel/kexec_bpf/kexe= c_pe_parser_bpf.c new file mode 100644 index 0000000000000..e4a2419240673 --- /dev/null +++ b/kernel/kexec_bpf/kexec_pe_parser_bpf.c @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2025, 2026 Red Hat, Inc + +#include "template.c" + +SEC("fentry.s/kexec_image_parser_anchor") +__attribute__((used)) int BPF_PROG(parse_pe, struct kexec_context *context, + unsigned long parser_id) +{ + return 0; +} diff --git a/kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h b/kernel/kexec_bp= f/kexec_pe_parser_bpf.lskel.h new file mode 100644 index 0000000000000..d1e863fd0ff4f --- /dev/null +++ b/kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h @@ -0,0 +1,372 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +/* THIS FILE IS AUTOGENERATED BY BPFTOOL! */ +#ifndef __KEXEC_PE_PARSER_BPF_SKEL_H__ +#define __KEXEC_PE_PARSER_BPF_SKEL_H__ + +#include + +struct kexec_pe_parser_bpf { + struct bpf_loader_ctx ctx; + struct { + struct bpf_map_desc ringbuf_1; + struct bpf_map_desc ringbuf_2; + struct bpf_map_desc ringbuf_3; + struct bpf_map_desc ringbuf_4; + struct bpf_map_desc rodata; + struct bpf_map_desc data; + struct bpf_map_desc bss; + struct bpf_map_desc rodata_str1_1; + } maps; + struct { + struct bpf_prog_desc parse_pe; + } progs; + struct { + int parse_pe_fd; + } links; +}; + +static inline int +kexec_pe_parser_bpf__parse_pe__attach(struct kexec_pe_parser_bpf *skel) +{ + int prog_fd =3D skel->progs.parse_pe.prog_fd; + int fd =3D skel_raw_tracepoint_open(NULL, prog_fd); + + if (fd > 0) + skel->links.parse_pe_fd =3D fd; + return fd; +} + +static inline int +kexec_pe_parser_bpf__attach(struct kexec_pe_parser_bpf *skel) +{ + int ret =3D 0; + + ret =3D ret < 0 ? ret : kexec_pe_parser_bpf__parse_pe__attach(skel); + return ret < 0 ? ret : 0; +} + +static inline void +kexec_pe_parser_bpf__detach(struct kexec_pe_parser_bpf *skel) +{ + skel_closenz(skel->links.parse_pe_fd); +} +static void +kexec_pe_parser_bpf__destroy(struct kexec_pe_parser_bpf *skel) +{ + if (!skel) + return; + kexec_pe_parser_bpf__detach(skel); + skel_closenz(skel->progs.parse_pe.prog_fd); + skel_closenz(skel->maps.ringbuf_1.map_fd); + skel_closenz(skel->maps.ringbuf_2.map_fd); + skel_closenz(skel->maps.ringbuf_3.map_fd); + skel_closenz(skel->maps.ringbuf_4.map_fd); + skel_closenz(skel->maps.rodata.map_fd); + skel_closenz(skel->maps.data.map_fd); + skel_closenz(skel->maps.bss.map_fd); + skel_closenz(skel->maps.rodata_str1_1.map_fd); + skel_free(skel); +} +static inline struct kexec_pe_parser_bpf * +kexec_pe_parser_bpf__open(void) +{ + struct kexec_pe_parser_bpf *skel; + + skel =3D skel_alloc(sizeof(*skel)); + if (!skel) + goto cleanup; + skel->ctx.sz =3D (void *)&skel->links - (void *)skel; + return skel; +cleanup: + kexec_pe_parser_bpf__destroy(skel); + return NULL; +} + +static inline int +kexec_pe_parser_bpf__load(struct kexec_pe_parser_bpf *skel) +{ + struct bpf_load_and_run_opts opts =3D {}; + int err; + static const char opts_data[] __attribute__((__aligned__(8))) =3D "\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x9f\xeb\x= 01\0\ +\x18\0\0\0\0\0\0\0\xdc\x02\0\0\xdc\x02\0\0\x85\x01\0\0\0\0\0\0\0\0\0\x02\x= 03\0\ +\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x= 02\0\ +\0\0\x04\0\0\0\x1b\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0= \0\0\ +\x02\x06\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x04\0\0\0\0\0= \0\0\ +\x02\0\0\x04\x10\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40= \0\0\ +\0\x2a\0\0\0\0\0\0\x0e\x07\0\0\0\x01\0\0\0\0\0\0\0\x02\0\0\x04\x10\0\0\0\x= 19\0\ +\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0\x34\0\0\0\0\0\0\x0e\x= 09\0\ +\0\0\x01\0\0\0\0\0\0\0\x02\0\0\x04\x10\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x= 1e\0\ +\0\0\x05\0\0\0\x40\0\0\0\x3e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\0\0\0\0\0\x= 02\0\ +\0\x04\x10\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0= \x48\ +\0\0\0\0\0\0\x0e\x0d\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x10\0\0\0\x52\0\0\0= \0\0\ +\0\x01\x08\0\0\0\x40\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\x65\0\0\0\x0f\0\0= \0\ +\x69\0\0\0\x01\0\0\x0c\x11\0\0\0\x14\x01\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x= 01\0\ +\0\0\0\0\0\0\x03\0\0\0\0\x13\0\0\0\x04\0\0\0\x04\0\0\0\x19\x01\0\0\0\0\0\x= 0e\ +\x14\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x0a\x13\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0= \x16\ +\0\0\0\x04\0\0\0\x10\0\0\0\x21\x01\0\0\0\0\0\x0e\x17\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\x03\0\0\0\0\x13\0\0\0\x04\0\0\0\x10\0\0\0\x2e\x01\0\0\0\0\0\x0e\x19\0\0= \0\0\ +\0\0\0\x39\x01\0\0\0\0\0\x0e\x19\0\0\0\0\0\0\0\x43\x01\0\0\0\0\0\x0e\x19\0= \0\0\ +\0\0\0\0\x55\x01\0\0\x01\0\0\x0f\x10\0\0\0\x1b\0\0\0\0\0\0\0\x10\0\0\0\x5a= \x01\ +\0\0\x01\0\0\x0f\x10\0\0\0\x1a\0\0\0\0\0\0\0\x10\0\0\0\x60\x01\0\0\x04\0\0= \x0f\ +\x40\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\x0a\0\0\0\x10\0\0\0\x10\0\0\0\x0c\0= \0\0\ +\x20\0\0\0\x10\0\0\0\x0e\0\0\0\x30\0\0\0\x10\0\0\0\x66\x01\0\0\x01\0\0\x0f= \x10\ +\0\0\0\x18\0\0\0\0\0\0\0\x10\0\0\0\x6e\x01\0\0\x01\0\0\x0f\x10\0\0\0\x1c\0= \0\0\ +\0\0\0\0\x10\0\0\0\x7d\x01\0\0\x01\0\0\x0f\x04\0\0\0\x15\0\0\0\0\0\0\0\x04= \0\0\ +\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54= \x59\ +\x50\x45\x5f\x5f\0\x74\x79\x70\x65\0\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x= 65\ +\x73\0\x72\x69\x6e\x67\x62\x75\x66\x5f\x31\0\x72\x69\x6e\x67\x62\x75\x66\x= 5f\ +\x32\0\x72\x69\x6e\x67\x62\x75\x66\x5f\x33\0\x72\x69\x6e\x67\x62\x75\x66\x= 5f\ +\x34\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e= \x67\ +\0\x63\x74\x78\0\x70\x61\x72\x73\x65\x5f\x70\x65\0\x66\x65\x6e\x74\x72\x79= \x2e\ +\x73\x2f\x6b\x65\x78\x65\x63\x5f\x69\x6d\x61\x67\x65\x5f\x70\x61\x72\x73\x= 65\ +\x72\x5f\x61\x6e\x63\x68\x6f\x72\0\x2f\x68\x6f\x6d\x65\x2f\x6c\x69\x6e\x75= \x78\ +\x2f\x6b\x65\x72\x6e\x65\x6c\x2f\x6b\x65\x78\x65\x63\x5f\x62\x70\x66\x2f\x= 6b\ +\x65\x78\x65\x63\x5f\x70\x65\x5f\x70\x61\x72\x73\x65\x72\x5f\x62\x70\x66\x= 2e\ +\x63\0\x5f\x5f\x61\x74\x74\x72\x69\x62\x75\x74\x65\x5f\x5f\x28\x28\x75\x73= \x65\ +\x64\x29\x29\x20\x69\x6e\x74\x20\x42\x50\x46\x5f\x50\x52\x4f\x47\x28\x70\x= 61\ +\x72\x73\x65\x5f\x70\x65\x2c\x20\x73\x74\x72\x75\x63\x74\x20\x6b\x65\x78\x= 65\ +\x63\x5f\x63\x6f\x6e\x74\x65\x78\x74\x20\x2a\x63\x6f\x6e\x74\x65\x78\x74\x= 2c\0\ +\x63\x68\x61\x72\0\x4c\x49\x43\x45\x4e\x53\x45\0\x64\x75\x6d\x6d\x79\x5f\x= 72\ +\x6f\x64\x61\x74\x61\0\x64\x75\x6d\x6d\x79\x5f\x64\x61\x74\x61\0\x64\x75\x= 6d\ +\x6d\x79\x5f\x62\x73\x73\0\x64\x75\x6d\x6d\x79\x5f\x72\x6f\x64\x61\x74\x61= \x5f\ +\x73\x74\x72\x31\0\x2e\x62\x73\x73\0\x2e\x64\x61\x74\x61\0\x2e\x6d\x61\x70= \x73\ +\0\x2e\x72\x6f\x64\x61\x74\x61\0\x2e\x72\x6f\x64\x61\x74\x61\x2e\x73\x74\x= 72\ +\x31\x2e\x31\0\x6c\x69\x63\x65\x6e\x73\x65\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\x79\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1b\0\0\0\0\0\0\0\0\0\0\0= \0\ +\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x72\x69\x6e\x67\x62\x75\x66\x5f\x31\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1b\0\0\0\0\0= \0\0\ +\0\0\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x72\x69\x6e\x67\x62\x75\x66\x5f= \x32\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1b= \0\0\ +\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x72\x69\x6e\x67\x62\x= 75\ +\x66\x5f\x33\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\x1b\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x72\x69\x= 6e\ +\x67\x62\x75\x66\x5f\x34\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x10\0\0\0\x01\0\0\0\x80\0\0\0\0\0\0\0= \0\0\ +\0\0\x6b\x65\x78\x65\x63\x5f\x70\x65\x2e\x72\x6f\x64\x61\x74\x61\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x72\x6f\x64\x61\x74\x61\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x10\0\0\0\x01\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\x6b\x65\x78\x65\x63\x5f\x70\x65\x2e\x64\x61\x74\x61\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\x1e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x64\x61\x74\x61\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x10\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\x6b\x65\x78\x65\x63\x5f\x70\x65\x2e\x62\x73\x73\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\x1d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \x02\ +\0\0\0\x04\0\0\0\x10\0\0\0\x01\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\0\x2e\x72\x6f= \x64\ +\x61\x74\x61\x2e\x73\x74\x72\x31\x2e\x31\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x21\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \x47\ +\x50\x4c\0\0\0\0\0\xb4\0\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\0\0\0\0\x12\0\0\0\0= \0\0\ +\0\x95\0\0\0\xc8\0\0\0\x1b\xf4\0\0\x1a\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\x70\x61\x72\x73= \x65\ +\x5f\x70\x65\0\0\0\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0= \0\0\ +\0\x01\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0= \0\0\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x6b\x65\x78\x65\x63\x5f\x69= \x6d\ +\x61\x67\x65\x5f\x70\x61\x72\x73\x65\x72\x5f\x61\x6e\x63\x68\x6f\x72\0\0\0= \0\0\ +\0\0"; + static const char opts_insn[] __attribute__((__aligned__(8))) =3D "\ +\xbf\x16\0\0\0\0\0\0\xbf\xa1\0\0\0\0\0\0\x07\x01\0\0\x78\xff\xff\xff\xb7\x= 02\0\ +\0\x88\0\0\0\xb7\x03\0\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x05\0\x3b\0\0\0\0\0\x= 61\ +\xa1\x78\xff\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x7c= \xff\ +\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x80\xff\0\0\0\0= \xd5\ +\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \x61\ +\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0= \0\0\ +\x18\x60\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0= \0\0\ +\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x08= \0\0\ +\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0= \xa8\ +\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x0c\0\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x= 02\0\ +\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0= \0\ +\x10\0\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x= 85\0\ +\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x14\0\0\0\x61\x01\0\0\0\0\0\0\x= d5\ +\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0= \0\0\ +\0\0\0\0\x18\0\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0= \0\0\ +\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x61\x01\0\0\0= \0\0\ +\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\xbf\x70\0= \0\0\ +\0\0\0\x95\0\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0= \x98\ +\x09\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0= \0\0\ +\x94\x09\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0= \0\0\ +\0\0\x88\x09\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\x05\0\0= \x18\ +\x61\0\0\0\0\0\0\0\0\0\0\x80\x09\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\0\0\x12\0= \0\0\ +\x18\x62\0\0\0\0\0\0\0\0\0\0\x80\x09\0\0\xb7\x03\0\0\x1c\0\0\0\x85\0\0\0\x= a6\0\ +\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xad\xff\0\0\0\0\x63\x7a\x78\xff\0\0\0\0\x= 61\ +\x60\x1c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xac\x09= \0\0\ +\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xa0\x= 09\0\ +\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x= a0\ +\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\x71\0\0\0\0\0\0\x61\x= 60\ +\x2c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xf4\x09\0\0= \x63\ +\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xe8\x09\0= \0\ +\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x91= \xff\ +\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\x63\x71\0\0\0\0\0\0\x61\x60= \x3c\ +\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x3c\x0a\0\0\x63= \x01\ +\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x30\x0a\0\0\x= b7\ +\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x82\xff= \0\0\ +\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\x63\x71\0\0\0\0\0\0\x61\x60\x4c= \0\0\ +\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x84\x0a\0\0\x63\x01= \0\0\ +\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x78\x0a\0\0\xb7\x= 03\0\ +\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x73\xff\0\0\0= \0\ +\x18\x61\0\0\0\0\0\0\0\0\0\0\x0c\0\0\0\x63\x71\0\0\0\0\0\0\x61\xa0\x78\xff= \0\0\ +\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xf0\x0a\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x= 5c\0\ +\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xcc\x0a\0\0\x63\x= 01\0\ +\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xc0\x0a\0\0\xb7= \x03\ +\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x60\xff\0\0= \0\0\ +\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\x63\x71\0\0\0\0\0\0\x79\x63\x60\0\0= \0\0\ +\0\x15\x03\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x08\x0b\0\0\xb7\x02\0= \0\ +\x10\0\0\0\x61\x60\x04\0\0\0\0\0\x45\0\x02\0\x01\0\0\0\x85\0\0\0\x94\0\0\0= \x05\ +\0\x01\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x10\0\0\0= \x61\ +\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x20\x0b\0\0\x63\x01\0\0\0\0\0= \0\ +\x18\x60\0\0\0\0\0\0\0\0\0\0\x18\x0b\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x28\x= 0b\0\ +\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x08\x0b\0\0\x18\x61\0\0= \0\0\ +\0\0\0\0\0\0\x30\x0b\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\0\0\x02\0\0\0\x18\x62= \0\0\ +\0\0\0\0\0\0\0\0\x20\x0b\0\0\xb7\x03\0\0\x20\0\0\0\x85\0\0\0\xa6\0\0\0\xbf= \x07\ +\0\0\0\0\0\0\xc5\x07\x3c\xff\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x10\0\0\0= \x61\ +\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x40\x0b\0\0\x63\x01\0\0\0\0\0= \0\ +\xb7\x01\0\0\x16\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x40\x0b\0\0\xb7\x03\0\0= \x04\ +\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x2f\xff\0\0\0\0\x61= \xa0\ +\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x78\x0b\0\0\x63\x01\0\0\0\0\0= \0\ +\x61\x60\x6c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x54= \x0b\ +\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x= 48\ +\x0b\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5= \x07\ +\x1f\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x14\0\0\0\x63\x71\0\0\0\0\0\0= \x79\ +\x63\x70\0\0\0\0\0\x15\x03\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\x= 0b\0\ +\0\xb7\x02\0\0\x10\0\0\0\x61\x60\x04\0\0\0\0\0\x45\0\x02\0\x01\0\0\0\x85\0= \0\0\ +\x94\0\0\0\x05\0\x01\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x18\x62\0\0\0\0\0\0\0\0= \0\0\ +\x14\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xa8\x0b\0\0\x63= \x01\ +\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xa0\x0b\0\0\x18\x61\0\0\0\0\0\0\0= \0\0\ +\0\xb0\x0b\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x90\x0b\0\0= \x18\ +\x61\0\0\0\0\0\0\0\0\0\0\xb8\x0b\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\0\0\x02\0= \0\0\ +\x18\x62\0\0\0\0\0\0\0\0\0\0\xa8\x0b\0\0\xb7\x03\0\0\x20\0\0\0\x85\0\0\0\x= a6\0\ +\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xfb\xfe\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x= 18\ +\x61\0\0\0\0\0\0\0\0\0\0\xf8\x0b\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x7c\0\0\0= \0\0\ +\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xd4\x0b\0\0\x63\x01\0\0\0= \0\0\ +\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xc8\x0b\0\0\xb7\x03\0\0= \x48\ +\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xeb\xfe\0\0\0\0\x18= \x61\ +\0\0\0\0\0\0\0\0\0\0\x18\0\0\0\x63\x71\0\0\0\0\0\0\x79\x63\x80\0\0\0\0\0\x= 15\ +\x03\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\x0c\0\0\xb7\x02\0\0\x10= \0\0\ +\0\x61\x60\x04\0\0\0\0\0\x45\0\x02\0\x01\0\0\0\x85\0\0\0\x94\0\0\0\x05\0\x= 01\0\ +\0\0\0\0\x85\0\0\0\x71\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x18\0\0\0\x61\x20= \0\0\ +\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x28\x0c\0\0\x63\x01\0\0\0\0\0\0\x18\x= 60\0\ +\0\0\0\0\0\0\0\0\0\x20\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x30\x0c\0\0\x7b= \x01\ +\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x10\x0c\0\0\x18\x61\0\0\0\0\0\0\0= \0\0\ +\0\x38\x0c\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\0\0\x02\0\0\0\x18\x62\0\0\0\0\0= \0\0\ +\0\0\0\x28\x0c\0\0\xb7\x03\0\0\x20\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0= \0\0\ +\0\xc5\x07\xc7\xfe\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0= \0\0\ +\x78\x0c\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x8c\0\0\0\0\0\x15\0\x03\0\0\0\0\0= \x18\ +\x61\0\0\0\0\0\0\0\0\0\0\x54\x0c\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0= \0\ +\x18\x62\0\0\0\0\0\0\0\0\0\0\x48\x0c\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\x= a6\0\ +\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xb7\xfe\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0= \0\ +\x1c\0\0\0\x63\x71\0\0\0\0\0\0\x79\x63\x90\0\0\0\0\0\x15\x03\x08\0\0\0\0\0= \x18\ +\x61\0\0\0\0\0\0\0\0\0\0\x90\x0c\0\0\xb7\x02\0\0\x10\0\0\0\x61\x60\x04\0\0= \0\0\ +\0\x45\0\x02\0\x01\0\0\0\x85\0\0\0\x94\0\0\0\x05\0\x01\0\0\0\0\0\x85\0\0\0= \x71\ +\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0= \0\0\ +\0\0\0\0\0\0\0\xa8\x0c\0\0\x63\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0= \xa0\ +\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xb0\x0c\0\0\x7b\x01\0\0\0\0\0\0\x18\x= 60\0\ +\0\0\0\0\0\0\0\0\0\x90\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xb8\x0c\0\0\x7b= \x01\ +\0\0\0\0\0\0\xb7\x01\0\0\x02\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xa8\x0c\0\0= \xb7\ +\x03\0\0\x20\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x93\xfe= \0\0\ +\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0\0= \0\0\ +\0\0\0\0\0\0\xc8\x0c\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\x16\0\0\0\x18\x62= \0\0\ +\0\0\0\0\0\0\0\0\xc8\x0c\0\0\xb7\x03\0\0\x04\0\0\0\x85\0\0\0\xa6\0\0\0\xbf= \x07\ +\0\0\0\0\0\0\xc5\x07\x86\xfe\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xd0\x0c\0= \0\ +\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\x0d\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0= \0\0\ +\0\0\0\0\0\xd8\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x08\x0d\0\0\x7b\x01\0\0= \0\0\ +\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xe8\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x= 50\ +\x0d\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xf0\x0c\0\0\x18\x= 61\0\ +\0\0\0\0\0\0\0\0\0\x60\x0d\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0= \0\0\ +\0\x0d\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x80\x0d\0\0\x7b\x01\0\0\0\0\0\0\x18= \x60\ +\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x78\x0d\0\0\x7b\x= 01\0\ +\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x18\x0d\0\0\x= 63\ +\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x1c\x0d= \0\0\ +\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x20= \x0d\ +\0\0\x7b\x01\0\0\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0= \0\ +\x48\x0d\0\0\x63\x01\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\x0d\0\0\x= b7\ +\x02\0\0\x1a\0\0\0\xb7\x03\0\0\x0c\0\0\0\xb7\x04\0\0\0\0\0\0\x85\0\0\0\xa7= \0\0\ +\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x50\xfe\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0= \0\ +\x0d\0\0\x63\x70\x6c\0\0\0\0\0\x77\x07\0\0\x20\0\0\0\x63\x70\x70\0\0\0\0\0= \xb7\ +\x01\0\0\x05\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\0\x0d\0\0\xb7\x03\0\0\x8c\0= \0\0\ +\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x70\x= 0d\0\ +\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0= \xa8\ +\0\0\0\xc5\x07\x3e\xfe\0\0\0\0\x63\x7a\x80\xff\0\0\0\0\x61\xa1\x78\xff\0\0= \0\0\ +\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa0\x80= \xff\ +\0\0\0\0\x63\x06\x98\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x10= \0\0\ +\0\0\0\0\x63\x06\x18\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\x61\x= 10\0\ +\0\0\0\0\0\x63\x06\x28\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\x61= \x10\ +\0\0\0\0\0\0\x63\x06\x38\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x0c\0\0\0\x= 61\ +\x10\0\0\0\0\0\0\x63\x06\x48\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\0\0= \0\ +\x61\x10\0\0\0\0\0\0\x63\x06\x58\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x14= \0\0\ +\0\x61\x10\0\0\0\0\0\0\x63\x06\x68\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x= 18\0\ +\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x78\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0= \x1c\ +\0\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x88\0\0\0\0\0\xb7\0\0\0\0\0\0\0\x95\0\0= \0\0\ +\0\0\0"; + opts.ctx =3D (struct bpf_loader_ctx *)skel; + opts.data_sz =3D sizeof(opts_data) - 1; + opts.data =3D (void *)opts_data; + opts.insns_sz =3D sizeof(opts_insn) - 1; + opts.insns =3D (void *)opts_insn; + + err =3D bpf_load_and_run(&opts); + if (err < 0) + return err; + return 0; +} + +static inline struct kexec_pe_parser_bpf * +kexec_pe_parser_bpf__open_and_load(void) +{ + struct kexec_pe_parser_bpf *skel; + + skel =3D kexec_pe_parser_bpf__open(); + if (!skel) + return NULL; + if (kexec_pe_parser_bpf__load(skel)) { + kexec_pe_parser_bpf__destroy(skel); + return NULL; + } + return skel; +} + +__attribute__((unused)) static void +kexec_pe_parser_bpf__assert(struct kexec_pe_parser_bpf *s __attribute__((u= nused))) +{ +#ifdef __cplusplus +#define _Static_assert static_assert +#endif +#ifdef __cplusplus +#undef _Static_assert +#endif +} + +#endif /* __KEXEC_PE_PARSER_BPF_SKEL_H__ */ diff --git a/kernel/kexec_bpf/template.c b/kernel/kexec_bpf/template.c new file mode 100644 index 0000000000000..9f17a4952ecd4 --- /dev/null +++ b/kernel/kexec_bpf/template.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2026 Red Hat, Inc +// +// Original file: kernel/kexec_bpf/template.c +// +#include "vmlinux.h" +#include +#include +#include +#include + +/* Command to kernel kexec bpf loader, which is defined on the stream */ +#define KEXEC_BPF_CMD_DECOMPRESS 0x1 +#define KEXEC_BPF_CMD_COPY 0x2 + +#define KEXEC_BPF_SUBCMD_KERNEL 0x1 +#define KEXEC_BPF_SUBCMD_INITRD 0x2 +#define KEXEC_BPF_SUBCMD_CMDLINE 0x3 + +/* + * The ringbufs can have different capacity. But only four ringbuf are pro= vided. + */ +#ifndef RINGBUF1_SIZE +#define RINGBUF1_SIZE 4 +#endif +#ifndef RINGBUF2_SIZE +#define RINGBUF2_SIZE 4 +#endif +#ifndef RINGBUF3_SIZE +#define RINGBUF3_SIZE 4 +#endif +#ifndef RINGBUF4_SIZE +#define RINGBUF4_SIZE 4 +#endif + +/* ringbuf is safe since the user space has no write access to them */ +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, RINGBUF1_SIZE); +} ringbuf_1 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, RINGBUF2_SIZE); +} ringbuf_2 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, RINGBUF3_SIZE); +} ringbuf_3 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, RINGBUF4_SIZE); +} ringbuf_4 SEC(".maps"); + +char LICENSE[] SEC("license") =3D "GPL"; + +/* + * This function ensures that the sections .rodata, .data, .rodata.str1.1 = and .bss + * are created for a bpf prog. + */ +static const char dummy_rodata[16] __attribute__((used)) =3D "rodata"; +static char dummy_data[16] __attribute__((used)) =3D "data"; +static char *dummy_mergeable_str __attribute__((used)) =3D ".rodata.str1.= 1"; +static char dummy_bss[16] __attribute__((used)); + --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 98B522737EB for ; Mon, 19 Jan 2026 03:27:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793230; cv=none; b=DZWZTTjOCLL8IhL2bFHLy7JOuVc7evI0OdCk0U8MsJRklBQZNDO6InErfVkKWvc98Qq1NitFuHfunDi/HNnbVXEj0wZWLntSRl1ReUCuMgDnVGL/Y8JNYfApVgZl94no6Z+6TeYS3vIdeoc0AOsd+eg4+hqCEy+d9HqiwZ6xaSQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793230; c=relaxed/simple; bh=uW+F2QtSidWZpv+WLcnvnCho2KgCi3lEi0l2DCvw9Sg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UxI/uuOxXnyNskfeEM9icrA2u89r89rBZKWIzi289GjQnJ6AuvybTv/EuujLVOYYLoEErux208hnLmJVlp/YVhI3OBGWvDi9T7qUecLJU2sf1nnlujE7tGruNuvBJdmQDFaz05+/bJj2F/rJks2gbi+v5DNHwQB/Pgm0ZTibEiw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=JyS3oYVC; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="JyS3oYVC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793227; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=d/X41VcnHuOXqT84jMlB3N9HZaOq9CdFFA8bWA8RbTY=; b=JyS3oYVCe+QBU2skYWQ5DrS/euVnq3vtAvnBY7E4Dq+2Gcx7MyydVd4DojVS9/HjP+gqmd ivhEaZ+aSQtiseq9RZyGx4cqItN6g8j/AxzcID762L/U11wdoR/q3NXQWi3y76U9JayNmb +DJLvxu9s/7EQAKWJBmvyJ2R1TVUMts= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-434-c3b4zj0LNDC0uhWE-SElyQ-1; Sun, 18 Jan 2026 22:27:03 -0500 X-MC-Unique: c3b4zj0LNDC0uhWE-SElyQ-1 X-Mimecast-MFC-AGG-ID: c3b4zj0LNDC0uhWE-SElyQ_1768793221 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 6197B1955F34; Mon, 19 Jan 2026 03:27:01 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id C90D11955F22; Mon, 19 Jan 2026 03:26:50 +0000 (UTC) From: Pingfan Liu To: kexec@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 09/13] kexec_file: Factor out routine to find a symbol in ELF Date: Mon, 19 Jan 2026 11:24:20 +0800 Message-ID: <20260119032424.10781-10-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" The routine to search a symbol in ELF can be shared, so split it out. Signed-off-by: Pingfan Liu Cc: Baoquan He Cc: Dave Young Cc: Andrew Morton Cc: Philipp Rudo To: kexec@lists.infradead.org --- kernel/kexec_file.c | 86 ++++++++++++++++++++++------------------- kernel/kexec_internal.h | 1 + 2 files changed, 47 insertions(+), 40 deletions(-) diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index f9674bb5bd8db..9731019ba2a1a 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -889,6 +889,51 @@ static int kexec_calculate_store_digests(struct kimage= *image) return ret; } =20 +#if defined(CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY) || defined(CONFIG_KEXEC_= BPF) +const Elf_Sym *elf_find_symbol(const Elf_Ehdr *ehdr, const char *name) +{ + const Elf_Shdr *sechdrs; + const Elf_Sym *syms; + const char *strtab; + int i, k; + + sechdrs =3D (void *)ehdr + ehdr->e_shoff; + + for (i =3D 0; i < ehdr->e_shnum; i++) { + if (sechdrs[i].sh_type !=3D SHT_SYMTAB) + continue; + + if (sechdrs[i].sh_link >=3D ehdr->e_shnum) + /* Invalid strtab section number */ + continue; + strtab =3D (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset; + syms =3D (void *)ehdr + sechdrs[i].sh_offset; + + /* Go through symbols for a match */ + for (k =3D 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) { + if (ELF_ST_BIND(syms[k].st_info) !=3D STB_GLOBAL) + continue; + + if (strcmp(strtab + syms[k].st_name, name) !=3D 0) + continue; + + if (syms[k].st_shndx =3D=3D SHN_UNDEF || + syms[k].st_shndx >=3D ehdr->e_shnum) { + pr_debug("Symbol: %s has bad section index %d.\n", + name, syms[k].st_shndx); + return NULL; + } + + /* Found the symbol we are looking for */ + return &syms[k]; + } + } + + return NULL; +} + +#endif + #ifdef CONFIG_ARCH_SUPPORTS_KEXEC_PURGATORY /* * kexec_purgatory_setup_kbuf - prepare buffer to load purgatory. @@ -1146,49 +1191,10 @@ int kexec_load_purgatory(struct kimage *image, stru= ct kexec_buf *kbuf) static const Elf_Sym *kexec_purgatory_find_symbol(struct purgatory_info *p= i, const char *name) { - const Elf_Shdr *sechdrs; - const Elf_Ehdr *ehdr; - const Elf_Sym *syms; - const char *strtab; - int i, k; - if (!pi->ehdr) return NULL; =20 - ehdr =3D pi->ehdr; - sechdrs =3D (void *)ehdr + ehdr->e_shoff; - - for (i =3D 0; i < ehdr->e_shnum; i++) { - if (sechdrs[i].sh_type !=3D SHT_SYMTAB) - continue; - - if (sechdrs[i].sh_link >=3D ehdr->e_shnum) - /* Invalid strtab section number */ - continue; - strtab =3D (void *)ehdr + sechdrs[sechdrs[i].sh_link].sh_offset; - syms =3D (void *)ehdr + sechdrs[i].sh_offset; - - /* Go through symbols for a match */ - for (k =3D 0; k < sechdrs[i].sh_size/sizeof(Elf_Sym); k++) { - if (ELF_ST_BIND(syms[k].st_info) !=3D STB_GLOBAL) - continue; - - if (strcmp(strtab + syms[k].st_name, name) !=3D 0) - continue; - - if (syms[k].st_shndx =3D=3D SHN_UNDEF || - syms[k].st_shndx >=3D ehdr->e_shnum) { - pr_debug("Symbol: %s has bad section index %d.\n", - name, syms[k].st_shndx); - return NULL; - } - - /* Found the symbol we are looking for */ - return &syms[k]; - } - } - - return NULL; + return elf_find_symbol(pi->ehdr, name); } =20 void *kexec_purgatory_get_symbol_addr(struct kimage *image, const char *na= me) diff --git a/kernel/kexec_internal.h b/kernel/kexec_internal.h index ee01d0c8bb377..2e8e0fedbe2a9 100644 --- a/kernel/kexec_internal.h +++ b/kernel/kexec_internal.h @@ -40,6 +40,7 @@ extern bool pe_has_bpf_section(const char *file_buf, unsi= gned long pe_sz); extern int pe_get_section(const char *file_buf, const char *sect_name, char **sect_start, unsigned long *sect_sz); extern int decompose_kexec_image(struct kimage *image, int extended_fd); +extern const Elf_Sym *elf_find_symbol(const Elf_Ehdr *ehdr, const char *na= me); #else /* CONFIG_KEXEC_FILE */ static inline void kimage_file_post_load_cleanup(struct kimage *image) { } #endif /* CONFIG_KEXEC_FILE */ --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2A61827586C for ; Mon, 19 Jan 2026 03:27:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793245; cv=none; b=ojhk0+CRkYUZx+J8KV7LuraBdVgnaog+2Nf8nIloOYWZD02d0ypzUNVQ3nBAfyrfksC3DUI9VC+WyRc9w38fxrmmdW4lfD0mCa2AcDBG1rlQb0/6FNMJ8oTKwZYmpsYR7HEAPzC7sYIa12ecN3X7mKoHRrCEFqwqKWXlUxlt3D4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793245; c=relaxed/simple; bh=t94TOy4M2d+HXboWxxlVyeu8E/Q3F75Xq/jctCSEkJE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jpCZiMOKWgfR5HUz+XbrVCvajLsEMQM9Uenzt+p/PiJqFBwzxyaRcFPv05Fao4ziAmqOgdcDFyUOfrLbxWeSL7d8B/p6n6MY/ytrS1WUQ78YQOOCkkHcGvZ6/MMzPsEZ/URdTvwbM+hCZmgay+xBOTqz2nbuiQyZo6+4Iv07bjo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=RvmOtfQF; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="RvmOtfQF" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793239; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=rVIO4pSwV1cOF3+JyTmxSKBMwoxbZ/66btH1QHe2vHM=; b=RvmOtfQFCb04fPhHl+9yg6ptHQNnOzDvs549cPo+9eJ8agxD2gZzQECHNUIUcAkrXESseH Ww8rempcKEh/1pfIz2qk/3diXGcjdlUirj0JTAQqIGIQmS7s0WkOPSO8KvMp8cl/dGY0yI diEK5N5Dv8Dbe7bI+TYuIS+1tuP6LFw= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-481-aEQIrnxOMUCU1GNYEi39OA-1; Sun, 18 Jan 2026 22:27:15 -0500 X-MC-Unique: aEQIrnxOMUCU1GNYEi39OA-1 X-Mimecast-MFC-AGG-ID: aEQIrnxOMUCU1GNYEi39OA_1768793233 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 00F4819560B2; Mon, 19 Jan 2026 03:27:13 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 1F7E71955F22; Mon, 19 Jan 2026 03:27:01 +0000 (UTC) From: Pingfan Liu To: kexec@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 10/13] kexec_file: Integrate bpf light skeleton to load image with bpf-prog Date: Mon, 19 Jan 2026 11:24:21 +0800 Message-ID: <20260119032424.10781-11-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" All kexec PE bpf prog should align with the interface exposed by the light skeleton four maps: struct bpf_map_desc ringbuf_1; struct bpf_map_desc ringbuf_2; struct bpf_map_desc ringbuf_3; struct bpf_map_desc ringbuf_4; four sections: struct bpf_map_desc rodata; struct bpf_map_desc data; struct bpf_map_desc rodata_str1_1; struct bpf_map_desc bss; one prog: SEC("fentry.s/kexec_image_parser_anchor") With the above presumption, the integration consists of two parts: -1. Call API exposed by light skeleton from kexec -2. The opts_insn[] and opts_data[] are bpf-prog dependent and can be extracted and passed in from the user space. In the kexec_file_load design, a PE file has a .bpf section, which data content is a ELF, and the ELF contains opts_insn[] opts_data[]. As a bonus, BPF bytecode can be placed under the protection of the entire PE signature. (Note, since opts_insn[] contains the information of the ringbuf size, the bpf-prog writer can change its proper size according to the kernel image size without modifying the kernel code) Signed-off-by: Pingfan Liu Cc: Alexei Starovoitov Cc: Baoquan He Cc: Dave Young Cc: Andrew Morton Cc: Philipp Rudo Cc: bpf@vger.kernel.org To: kexec@lists.infradead.org --- kernel/Makefile | 1 + kernel/kexec_bpf/Makefile | 8 + kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h | 254 +------------------ kernel/kexec_bpf_loader.c | 48 ++++ 4 files changed, 63 insertions(+), 248 deletions(-) diff --git a/kernel/Makefile b/kernel/Makefile index 05177a867690d..a1c5f5fb02770 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -143,6 +143,7 @@ obj-$(CONFIG_SYSCTL_KUNIT_TEST) +=3D sysctl-test.o =20 CFLAGS_kstack_erase.o +=3D $(DISABLE_KSTACK_ERASE) CFLAGS_kstack_erase.o +=3D $(call cc-option,-mgeneral-regs-only) +CFLAGS_kexec_bpf_loader.o +=3D -I$(srctree)/tools/lib obj-$(CONFIG_KSTACK_ERASE) +=3D kstack_erase.o KASAN_SANITIZE_kstack_erase.o :=3D n KCSAN_SANITIZE_kstack_erase.o :=3D n diff --git a/kernel/kexec_bpf/Makefile b/kernel/kexec_bpf/Makefile index 45d45cc0855a3..88e92eb910f64 100644 --- a/kernel/kexec_bpf/Makefile +++ b/kernel/kexec_bpf/Makefile @@ -39,6 +39,14 @@ clean: kexec_pe_parser_bpf.lskel.h: $(OUTPUT)/kexec_pe_parser_bpf.o | $(BPFTOOL) $(call msg,GEN-SKEL,$@) $(Q)$(BPFTOOL) gen skeleton -L $< > $@ + @# The following sed commands make opts_data[] and opts_insn[] visible in= a file instead of only in a function. + @# And it removes the bytecode + $(Q) sed -i '/static const char opts_data\[\].*=3D/,/";$$/d' $@ + $(Q) sed -i '/static const char opts_insn\[\].*=3D/,/";$$/d' $@ + $(Q) sed -i \ + -e 's/opts\.data_sz =3D sizeof(opts_data) - 1;/opts.data_sz =3D opts_dat= a_sz;/' \ + -e 's/opts\.insns_sz =3D sizeof(opts_insn) - 1;/opts.insns_sz =3D opts_i= nsn_sz;/' $@ + $(Q) sed -i '7i static char *opts_data, *opts_insn;\nstatic unsigned int = opts_data_sz, opts_insn_sz;' $@ =20 $(OUTPUT)/vmlinux.h: $(VMLINUX) $(DEFAULT_BPFTOOL) $(BPFOBJ) | $(OUTPUT) @$(BPFTOOL) btf dump file $(VMLINUX) format c > $(OUTPUT)/vmlinux.h diff --git a/kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h b/kernel/kexec_bp= f/kexec_pe_parser_bpf.lskel.h index d1e863fd0ff4f..db71b2150789d 100644 --- a/kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h +++ b/kernel/kexec_bpf/kexec_pe_parser_bpf.lskel.h @@ -4,6 +4,8 @@ #define __KEXEC_PE_PARSER_BPF_SKEL_H__ =20 #include +static char *opts_data, *opts_insn; +static unsigned int opts_data_sz, opts_insn_sz; =20 struct kexec_pe_parser_bpf { struct bpf_loader_ctx ctx; @@ -14,8 +16,8 @@ struct kexec_pe_parser_bpf { struct bpf_map_desc ringbuf_4; struct bpf_map_desc rodata; struct bpf_map_desc data; - struct bpf_map_desc bss; struct bpf_map_desc rodata_str1_1; + struct bpf_map_desc bss; } maps; struct { struct bpf_prog_desc parse_pe; @@ -63,8 +65,8 @@ kexec_pe_parser_bpf__destroy(struct kexec_pe_parser_bpf *= skel) skel_closenz(skel->maps.ringbuf_4.map_fd); skel_closenz(skel->maps.rodata.map_fd); skel_closenz(skel->maps.data.map_fd); - skel_closenz(skel->maps.bss.map_fd); skel_closenz(skel->maps.rodata_str1_1.map_fd); + skel_closenz(skel->maps.bss.map_fd); skel_free(skel); } static inline struct kexec_pe_parser_bpf * @@ -87,254 +89,10 @@ kexec_pe_parser_bpf__load(struct kexec_pe_parser_bpf *= skel) { struct bpf_load_and_run_opts opts =3D {}; int err; - static const char opts_data[] __attribute__((__aligned__(8))) =3D "\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x9f\xeb\x= 01\0\ -\x18\0\0\0\0\0\0\0\xdc\x02\0\0\xdc\x02\0\0\x85\x01\0\0\0\0\0\0\0\0\0\x02\x= 03\0\ -\0\0\x01\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\x01\0\0\0\0\0\0\0\x03\0\0\0\0\x= 02\0\ -\0\0\x04\0\0\0\x1b\0\0\0\x05\0\0\0\0\0\0\x01\x04\0\0\0\x20\0\0\0\0\0\0\0\0= \0\0\ -\x02\x06\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0\x02\0\0\0\x04\0\0\0\x04\0\0\0\0\0= \0\0\ -\x02\0\0\x04\x10\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40= \0\0\ -\0\x2a\0\0\0\0\0\0\x0e\x07\0\0\0\x01\0\0\0\0\0\0\0\x02\0\0\x04\x10\0\0\0\x= 19\0\ -\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0\x34\0\0\0\0\0\0\x0e\x= 09\0\ -\0\0\x01\0\0\0\0\0\0\0\x02\0\0\x04\x10\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x= 1e\0\ -\0\0\x05\0\0\0\x40\0\0\0\x3e\0\0\0\0\0\0\x0e\x0b\0\0\0\x01\0\0\0\0\0\0\0\x= 02\0\ -\0\x04\x10\0\0\0\x19\0\0\0\x01\0\0\0\0\0\0\0\x1e\0\0\0\x05\0\0\0\x40\0\0\0= \x48\ -\0\0\0\0\0\0\x0e\x0d\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x02\x10\0\0\0\x52\0\0\0= \0\0\ -\0\x01\x08\0\0\0\x40\0\0\0\0\0\0\0\x01\0\0\x0d\x02\0\0\0\x65\0\0\0\x0f\0\0= \0\ -\x69\0\0\0\x01\0\0\x0c\x11\0\0\0\x14\x01\0\0\0\0\0\x01\x01\0\0\0\x08\0\0\x= 01\0\ -\0\0\0\0\0\0\x03\0\0\0\0\x13\0\0\0\x04\0\0\0\x04\0\0\0\x19\x01\0\0\0\0\0\x= 0e\ -\x14\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\x0a\x13\0\0\0\0\0\0\0\0\0\0\x03\0\0\0\0= \x16\ -\0\0\0\x04\0\0\0\x10\0\0\0\x21\x01\0\0\0\0\0\x0e\x17\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\x03\0\0\0\0\x13\0\0\0\x04\0\0\0\x10\0\0\0\x2e\x01\0\0\0\0\0\x0e\x19\0\0= \0\0\ -\0\0\0\x39\x01\0\0\0\0\0\x0e\x19\0\0\0\0\0\0\0\x43\x01\0\0\0\0\0\x0e\x19\0= \0\0\ -\0\0\0\0\x55\x01\0\0\x01\0\0\x0f\x10\0\0\0\x1b\0\0\0\0\0\0\0\x10\0\0\0\x5a= \x01\ -\0\0\x01\0\0\x0f\x10\0\0\0\x1a\0\0\0\0\0\0\0\x10\0\0\0\x60\x01\0\0\x04\0\0= \x0f\ -\x40\0\0\0\x08\0\0\0\0\0\0\0\x10\0\0\0\x0a\0\0\0\x10\0\0\0\x10\0\0\0\x0c\0= \0\0\ -\x20\0\0\0\x10\0\0\0\x0e\0\0\0\x30\0\0\0\x10\0\0\0\x66\x01\0\0\x01\0\0\x0f= \x10\ -\0\0\0\x18\0\0\0\0\0\0\0\x10\0\0\0\x6e\x01\0\0\x01\0\0\x0f\x10\0\0\0\x1c\0= \0\0\ -\0\0\0\0\x10\0\0\0\x7d\x01\0\0\x01\0\0\x0f\x04\0\0\0\x15\0\0\0\0\0\0\0\x04= \0\0\ -\0\0\x69\x6e\x74\0\x5f\x5f\x41\x52\x52\x41\x59\x5f\x53\x49\x5a\x45\x5f\x54= \x59\ -\x50\x45\x5f\x5f\0\x74\x79\x70\x65\0\x6d\x61\x78\x5f\x65\x6e\x74\x72\x69\x= 65\ -\x73\0\x72\x69\x6e\x67\x62\x75\x66\x5f\x31\0\x72\x69\x6e\x67\x62\x75\x66\x= 5f\ -\x32\0\x72\x69\x6e\x67\x62\x75\x66\x5f\x33\0\x72\x69\x6e\x67\x62\x75\x66\x= 5f\ -\x34\0\x75\x6e\x73\x69\x67\x6e\x65\x64\x20\x6c\x6f\x6e\x67\x20\x6c\x6f\x6e= \x67\ -\0\x63\x74\x78\0\x70\x61\x72\x73\x65\x5f\x70\x65\0\x66\x65\x6e\x74\x72\x79= \x2e\ -\x73\x2f\x6b\x65\x78\x65\x63\x5f\x69\x6d\x61\x67\x65\x5f\x70\x61\x72\x73\x= 65\ -\x72\x5f\x61\x6e\x63\x68\x6f\x72\0\x2f\x68\x6f\x6d\x65\x2f\x6c\x69\x6e\x75= \x78\ -\x2f\x6b\x65\x72\x6e\x65\x6c\x2f\x6b\x65\x78\x65\x63\x5f\x62\x70\x66\x2f\x= 6b\ -\x65\x78\x65\x63\x5f\x70\x65\x5f\x70\x61\x72\x73\x65\x72\x5f\x62\x70\x66\x= 2e\ -\x63\0\x5f\x5f\x61\x74\x74\x72\x69\x62\x75\x74\x65\x5f\x5f\x28\x28\x75\x73= \x65\ -\x64\x29\x29\x20\x69\x6e\x74\x20\x42\x50\x46\x5f\x50\x52\x4f\x47\x28\x70\x= 61\ -\x72\x73\x65\x5f\x70\x65\x2c\x20\x73\x74\x72\x75\x63\x74\x20\x6b\x65\x78\x= 65\ -\x63\x5f\x63\x6f\x6e\x74\x65\x78\x74\x20\x2a\x63\x6f\x6e\x74\x65\x78\x74\x= 2c\0\ -\x63\x68\x61\x72\0\x4c\x49\x43\x45\x4e\x53\x45\0\x64\x75\x6d\x6d\x79\x5f\x= 72\ -\x6f\x64\x61\x74\x61\0\x64\x75\x6d\x6d\x79\x5f\x64\x61\x74\x61\0\x64\x75\x= 6d\ -\x6d\x79\x5f\x62\x73\x73\0\x64\x75\x6d\x6d\x79\x5f\x72\x6f\x64\x61\x74\x61= \x5f\ -\x73\x74\x72\x31\0\x2e\x62\x73\x73\0\x2e\x64\x61\x74\x61\0\x2e\x6d\x61\x70= \x73\ -\0\x2e\x72\x6f\x64\x61\x74\x61\0\x2e\x72\x6f\x64\x61\x74\x61\x2e\x73\x74\x= 72\ -\x31\x2e\x31\0\x6c\x69\x63\x65\x6e\x73\x65\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\x79\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1b\0\0\0\0\0\0\0\0\0\0\0= \0\ -\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x72\x69\x6e\x67\x62\x75\x66\x5f\x31\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1b\0\0\0\0\0= \0\0\ -\0\0\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x72\x69\x6e\x67\x62\x75\x66\x5f= \x32\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x1b= \0\0\ -\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x72\x69\x6e\x67\x62\x= 75\ -\x66\x5f\x33\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\x1b\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x72\x69\x= 6e\ -\x67\x62\x75\x66\x5f\x34\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x10\0\0\0\x01\0\0\0\x80\0\0\0\0\0\0\0= \0\0\ -\0\0\x6b\x65\x78\x65\x63\x5f\x70\x65\x2e\x72\x6f\x64\x61\x74\x61\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\x20\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x72\x6f\x64\x61\x74\x61\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x10\0\0\0\x01\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\x6b\x65\x78\x65\x63\x5f\x70\x65\x2e\x64\x61\x74\x61\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\x1e\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x64\x61\x74\x61\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\x02\0\0\0\x04\0\0\0\x10\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\x6b\x65\x78\x65\x63\x5f\x70\x65\x2e\x62\x73\x73\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\x1d\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \x02\ -\0\0\0\x04\0\0\0\x10\0\0\0\x01\0\0\0\x80\0\0\0\0\0\0\0\0\0\0\0\x2e\x72\x6f= \x64\ -\x61\x74\x61\x2e\x73\x74\x72\x31\x2e\x31\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x21\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \x47\ -\x50\x4c\0\0\0\0\0\xb4\0\0\0\0\0\0\0\x95\0\0\0\0\0\0\0\0\0\0\0\x12\0\0\0\0= \0\0\ -\0\x95\0\0\0\xc8\0\0\0\x1b\xf4\0\0\x1a\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\x70\x61\x72\x73= \x65\ -\x5f\x70\x65\0\0\0\0\0\0\0\0\0\0\0\0\x18\0\0\0\0\0\0\0\x08\0\0\0\0\0\0\0\0= \0\0\ -\0\x01\0\0\0\x10\0\0\0\0\0\0\0\0\0\0\0\x01\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0= \0\0\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\0\0\0\0\x6b\x65\x78\x65\x63\x5f\x69= \x6d\ -\x61\x67\x65\x5f\x70\x61\x72\x73\x65\x72\x5f\x61\x6e\x63\x68\x6f\x72\0\0\0= \0\0\ -\0\0"; - static const char opts_insn[] __attribute__((__aligned__(8))) =3D "\ -\xbf\x16\0\0\0\0\0\0\xbf\xa1\0\0\0\0\0\0\x07\x01\0\0\x78\xff\xff\xff\xb7\x= 02\0\ -\0\x88\0\0\0\xb7\x03\0\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x05\0\x3b\0\0\0\0\0\x= 61\ -\xa1\x78\xff\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x7c= \xff\ -\0\0\0\0\xd5\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa1\x80\xff\0\0\0\0= \xd5\ -\x01\x01\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0= \x61\ -\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0= \0\0\ -\x18\x60\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0= \0\0\ -\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x08= \0\0\ -\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0= \xa8\ -\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x0c\0\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x= 02\0\ -\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0= \0\ -\x10\0\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x= 85\0\ -\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x14\0\0\0\x61\x01\0\0\0\0\0\0\x= d5\ -\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0= \0\0\ -\0\0\0\0\x18\0\0\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0= \0\0\ -\0\x85\0\0\0\xa8\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x61\x01\0\0\0= \0\0\ -\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\xbf\x70\0= \0\0\ -\0\0\0\x95\0\0\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0= \x98\ -\x09\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0= \0\0\ -\x94\x09\0\0\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0= \0\0\ -\0\0\x88\x09\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\0\x05\0\0= \x18\ -\x61\0\0\0\0\0\0\0\0\0\0\x80\x09\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\0\0\x12\0= \0\0\ -\x18\x62\0\0\0\0\0\0\0\0\0\0\x80\x09\0\0\xb7\x03\0\0\x1c\0\0\0\x85\0\0\0\x= a6\0\ -\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xad\xff\0\0\0\0\x63\x7a\x78\xff\0\0\0\0\x= 61\ -\x60\x1c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xac\x09= \0\0\ -\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xa0\x= 09\0\ -\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x= a0\ -\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x63\x71\0\0\0\0\0\0\x61\x= 60\ -\x2c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xf4\x09\0\0= \x63\ -\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xe8\x09\0= \0\ -\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x91= \xff\ -\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\x63\x71\0\0\0\0\0\0\x61\x60= \x3c\ -\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x3c\x0a\0\0\x63= \x01\ -\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x30\x0a\0\0\x= b7\ -\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x82\xff= \0\0\ -\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\x63\x71\0\0\0\0\0\0\x61\x60\x4c= \0\0\ -\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x84\x0a\0\0\x63\x01= \0\0\ -\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x78\x0a\0\0\xb7\x= 03\0\ -\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x73\xff\0\0\0= \0\ -\x18\x61\0\0\0\0\0\0\0\0\0\0\x0c\0\0\0\x63\x71\0\0\0\0\0\0\x61\xa0\x78\xff= \0\0\ -\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xf0\x0a\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x= 5c\0\ -\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xcc\x0a\0\0\x63\x= 01\0\ -\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xc0\x0a\0\0\xb7= \x03\ -\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x60\xff\0\0= \0\0\ -\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\0\0\0\x63\x71\0\0\0\0\0\0\x79\x63\x60\0\0= \0\0\ -\0\x15\x03\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x08\x0b\0\0\xb7\x02\0= \0\ -\x10\0\0\0\x61\x60\x04\0\0\0\0\0\x45\0\x02\0\x01\0\0\0\x85\0\0\0\x94\0\0\0= \x05\ -\0\x01\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x10\0\0\0= \x61\ -\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x20\x0b\0\0\x63\x01\0\0\0\0\0= \0\ -\x18\x60\0\0\0\0\0\0\0\0\0\0\x18\x0b\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x28\x= 0b\0\ -\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x08\x0b\0\0\x18\x61\0\0= \0\0\ -\0\0\0\0\0\0\x30\x0b\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\0\0\x02\0\0\0\x18\x62= \0\0\ -\0\0\0\0\0\0\0\0\x20\x0b\0\0\xb7\x03\0\0\x20\0\0\0\x85\0\0\0\xa6\0\0\0\xbf= \x07\ -\0\0\0\0\0\0\xc5\x07\x3c\xff\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x10\0\0\0= \x61\ -\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x40\x0b\0\0\x63\x01\0\0\0\0\0= \0\ -\xb7\x01\0\0\x16\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x40\x0b\0\0\xb7\x03\0\0= \x04\ -\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x2f\xff\0\0\0\0\x61= \xa0\ -\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x78\x0b\0\0\x63\x01\0\0\0\0\0= \0\ -\x61\x60\x6c\0\0\0\0\0\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x54= \x0b\ -\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x= 48\ -\x0b\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5= \x07\ -\x1f\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x14\0\0\0\x63\x71\0\0\0\0\0\0= \x79\ -\x63\x70\0\0\0\0\0\x15\x03\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\x= 0b\0\ -\0\xb7\x02\0\0\x10\0\0\0\x61\x60\x04\0\0\0\0\0\x45\0\x02\0\x01\0\0\0\x85\0= \0\0\ -\x94\0\0\0\x05\0\x01\0\0\0\0\0\x85\0\0\0\x71\0\0\0\x18\x62\0\0\0\0\0\0\0\0= \0\0\ -\x14\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xa8\x0b\0\0\x63= \x01\ -\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xa0\x0b\0\0\x18\x61\0\0\0\0\0\0\0= \0\0\ -\0\xb0\x0b\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x90\x0b\0\0= \x18\ -\x61\0\0\0\0\0\0\0\0\0\0\xb8\x0b\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\0\0\x02\0= \0\0\ -\x18\x62\0\0\0\0\0\0\0\0\0\0\xa8\x0b\0\0\xb7\x03\0\0\x20\0\0\0\x85\0\0\0\x= a6\0\ -\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xfb\xfe\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x= 18\ -\x61\0\0\0\0\0\0\0\0\0\0\xf8\x0b\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x7c\0\0\0= \0\0\ -\x15\0\x03\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xd4\x0b\0\0\x63\x01\0\0\0= \0\0\ -\0\xb7\x01\0\0\0\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xc8\x0b\0\0\xb7\x03\0\0= \x48\ -\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xeb\xfe\0\0\0\0\x18= \x61\ -\0\0\0\0\0\0\0\0\0\0\x18\0\0\0\x63\x71\0\0\0\0\0\0\x79\x63\x80\0\0\0\0\0\x= 15\ -\x03\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\x0c\0\0\xb7\x02\0\0\x10= \0\0\ -\0\x61\x60\x04\0\0\0\0\0\x45\0\x02\0\x01\0\0\0\x85\0\0\0\x94\0\0\0\x05\0\x= 01\0\ -\0\0\0\0\x85\0\0\0\x71\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x18\0\0\0\x61\x20= \0\0\ -\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x28\x0c\0\0\x63\x01\0\0\0\0\0\0\x18\x= 60\0\ -\0\0\0\0\0\0\0\0\0\x20\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x30\x0c\0\0\x7b= \x01\ -\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x10\x0c\0\0\x18\x61\0\0\0\0\0\0\0= \0\0\ -\0\x38\x0c\0\0\x7b\x01\0\0\0\0\0\0\xb7\x01\0\0\x02\0\0\0\x18\x62\0\0\0\0\0= \0\0\ -\0\0\0\x28\x0c\0\0\xb7\x03\0\0\x20\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0= \0\0\ -\0\xc5\x07\xc7\xfe\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0= \0\0\ -\x78\x0c\0\0\x63\x01\0\0\0\0\0\0\x61\x60\x8c\0\0\0\0\0\x15\0\x03\0\0\0\0\0= \x18\ -\x61\0\0\0\0\0\0\0\0\0\0\x54\x0c\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\0\0\0= \0\ -\x18\x62\0\0\0\0\0\0\0\0\0\0\x48\x0c\0\0\xb7\x03\0\0\x48\0\0\0\x85\0\0\0\x= a6\0\ -\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\xb7\xfe\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0= \0\ -\x1c\0\0\0\x63\x71\0\0\0\0\0\0\x79\x63\x90\0\0\0\0\0\x15\x03\x08\0\0\0\0\0= \x18\ -\x61\0\0\0\0\0\0\0\0\0\0\x90\x0c\0\0\xb7\x02\0\0\x10\0\0\0\x61\x60\x04\0\0= \0\0\ -\0\x45\0\x02\0\x01\0\0\0\x85\0\0\0\x94\0\0\0\x05\0\x01\0\0\0\0\0\x85\0\0\0= \x71\ -\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0= \0\0\ -\0\0\0\0\0\0\0\xa8\x0c\0\0\x63\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0= \xa0\ -\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xb0\x0c\0\0\x7b\x01\0\0\0\0\0\0\x18\x= 60\0\ -\0\0\0\0\0\0\0\0\0\x90\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\xb8\x0c\0\0\x7b= \x01\ -\0\0\0\0\0\0\xb7\x01\0\0\x02\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\xa8\x0c\0\0= \xb7\ -\x03\0\0\x20\0\0\0\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x93\xfe= \0\0\ -\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\x1c\0\0\0\x61\x20\0\0\0\0\0\0\x18\x61\0\0= \0\0\ -\0\0\0\0\0\0\xc8\x0c\0\0\x63\x01\0\0\0\0\0\0\xb7\x01\0\0\x16\0\0\0\x18\x62= \0\0\ -\0\0\0\0\0\0\0\0\xc8\x0c\0\0\xb7\x03\0\0\x04\0\0\0\x85\0\0\0\xa6\0\0\0\xbf= \x07\ -\0\0\0\0\0\0\xc5\x07\x86\xfe\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xd0\x0c\0= \0\ -\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\x0d\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0= \0\0\ -\0\0\0\0\0\xd8\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x08\x0d\0\0\x7b\x01\0\0= \0\0\ -\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xe8\x0c\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x= 50\ -\x0d\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\xf0\x0c\0\0\x18\x= 61\0\ -\0\0\0\0\0\0\0\0\0\x60\x0d\0\0\x7b\x01\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0= \0\0\ -\0\x0d\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x80\x0d\0\0\x7b\x01\0\0\0\0\0\0\x18= \x60\ -\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x78\x0d\0\0\x7b\x= 01\0\ -\0\0\0\0\0\x61\x60\x08\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x18\x0d\0\0\x= 63\ -\x01\0\0\0\0\0\0\x61\x60\x0c\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x1c\x0d= \0\0\ -\x63\x01\0\0\0\0\0\0\x79\x60\x10\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x20= \x0d\ -\0\0\x7b\x01\0\0\0\0\0\0\x61\xa0\x78\xff\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0= \0\ -\x48\x0d\0\0\x63\x01\0\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x90\x0d\0\0\x= b7\ -\x02\0\0\x1a\0\0\0\xb7\x03\0\0\x0c\0\0\0\xb7\x04\0\0\0\0\0\0\x85\0\0\0\xa7= \0\0\ -\0\xbf\x07\0\0\0\0\0\0\xc5\x07\x50\xfe\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0= \0\ -\x0d\0\0\x63\x70\x6c\0\0\0\0\0\x77\x07\0\0\x20\0\0\0\x63\x70\x70\0\0\0\0\0= \xb7\ -\x01\0\0\x05\0\0\0\x18\x62\0\0\0\0\0\0\0\0\0\0\0\x0d\0\0\xb7\x03\0\0\x8c\0= \0\0\ -\x85\0\0\0\xa6\0\0\0\xbf\x07\0\0\0\0\0\0\x18\x60\0\0\0\0\0\0\0\0\0\0\x70\x= 0d\0\ -\0\x61\x01\0\0\0\0\0\0\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0= \xa8\ -\0\0\0\xc5\x07\x3e\xfe\0\0\0\0\x63\x7a\x80\xff\0\0\0\0\x61\xa1\x78\xff\0\0= \0\0\ -\xd5\x01\x02\0\0\0\0\0\xbf\x19\0\0\0\0\0\0\x85\0\0\0\xa8\0\0\0\x61\xa0\x80= \xff\ -\0\0\0\0\x63\x06\x98\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x61\x10= \0\0\ -\0\0\0\0\x63\x06\x18\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\x61\x= 10\0\ -\0\0\0\0\0\x63\x06\x28\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x08\0\0\0\x61= \x10\ -\0\0\0\0\0\0\x63\x06\x38\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x0c\0\0\0\x= 61\ -\x10\0\0\0\0\0\0\x63\x06\x48\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x10\0\0= \0\ -\x61\x10\0\0\0\0\0\0\x63\x06\x58\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x14= \0\0\ -\0\x61\x10\0\0\0\0\0\0\x63\x06\x68\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0\x= 18\0\ -\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x78\0\0\0\0\0\x18\x61\0\0\0\0\0\0\0\0\0\0= \x1c\ -\0\0\0\x61\x10\0\0\0\0\0\0\x63\x06\x88\0\0\0\0\0\xb7\0\0\0\0\0\0\0\x95\0\0= \0\0\ -\0\0\0"; opts.ctx =3D (struct bpf_loader_ctx *)skel; - opts.data_sz =3D sizeof(opts_data) - 1; + opts.data_sz =3D opts_data_sz; opts.data =3D (void *)opts_data; - opts.insns_sz =3D sizeof(opts_insn) - 1; + opts.insns_sz =3D opts_insn_sz; opts.insns =3D (void *)opts_insn; =20 err =3D bpf_load_and_run(&opts); diff --git a/kernel/kexec_bpf_loader.c b/kernel/kexec_bpf_loader.c index 5ad67672dead1..9f1c5aede42ef 100644 --- a/kernel/kexec_bpf_loader.c +++ b/kernel/kexec_bpf_loader.c @@ -23,14 +23,62 @@ #include #include "kexec_internal.h" =20 +#include "kexec_bpf/kexec_pe_parser_bpf.lskel.h" + +static struct kexec_pe_parser_bpf *pe_parser; + +static void *get_symbol_from_elf(const char *elf_data, size_t elf_size, + const char *symbol_name, unsigned int *symbol_size) +{ + Elf_Ehdr *ehdr =3D (Elf_Ehdr *)elf_data; + Elf_Shdr *shdr, *dst_shdr; + const Elf_Sym *sym; + void *symbol_data; + + if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG) !=3D 0) { + pr_err("Not a valid ELF file\n"); + return NULL; + } + + sym =3D elf_find_symbol(ehdr, symbol_name); + if (!sym) + return NULL; + shdr =3D (struct elf_shdr *)(elf_data + ehdr->e_shoff); + dst_shdr =3D &shdr[sym->st_shndx]; + symbol_data =3D (void *)(elf_data + dst_shdr->sh_offset + sym->st_value); + *symbol_size =3D sym->st_size; + + return symbol_data; +} + /* Load a ELF */ static int arm_bpf_prog(char *bpf_elf, unsigned long sz) { + opts_data =3D get_symbol_from_elf(bpf_elf, sz, "opts_data", &opts_data_sz= ); + opts_insn =3D get_symbol_from_elf(bpf_elf, sz, "opts_insn", &opts_insn_sz= ); + if (!opts_data || !opts_insn) + return -1; + /* + * When light skeleton generates opts_data[] and opts_insn[], it appends a + * NULL terminator at the end of string + */ + opts_data_sz =3D opts_data_sz - 1; + opts_insn_sz =3D opts_insn_sz - 1; + + pe_parser =3D kexec_pe_parser_bpf__open_and_load(); + if (!pe_parser) + return -1; + kexec_pe_parser_bpf__attach(pe_parser); + return 0; } =20 static void disarm_bpf_prog(void) { + kexec_pe_parser_bpf__destroy(pe_parser); + pe_parser =3D NULL; + opts_data =3D NULL; + opts_insn =3D NULL; } =20 struct kexec_context { --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9929C256C70 for ; Mon, 19 Jan 2026 03:27:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793253; cv=none; b=fMq1zO+CbRC0scGkR+kCzwqQhB7+Gb9rOe1SUZ9YrtbdAmMBEy5m/PyD4YFnuYb8+IZ3CL6DVBH1cXTystuJSnMMwLZUVR+EkqQjnTTvrCuh71U6kUYafx3k+RTUfer+nUpPbSpvQzt22GyhPZNPRq2hVt6Ny4j782f87iu84bo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793253; c=relaxed/simple; bh=rgRHUFFl6ithnXiqRohoSSG33YA67WQ28UScvFQEVa0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hjc3f2vCJ0oC807auLdKZcHJTDkKxS+bx49ZO90wHQtScFYztMnv9rKodJdVxU51ibFLDsBAXqBQXJPMCJt6mLtyHMFcHDrNwVpbklJAOxVxOxRcrxU8moF2a5yxNC6lMYqjjgGdRntO6XEdipstLHToSAdopURWKvNK9pevcI4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=XBrufhKO; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="XBrufhKO" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793250; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=5hLVLj6T9HR767S/+F3jf5pcqfuxp717t4Xo0QfiSrs=; b=XBrufhKOWfhNasNZ+I1BmOo0TfLXZUMzpvtMiHKKaONe2OnZ3GhiKkMc2De5k0t5w9ht/4 dp77tOiHpINoQkgiossTlJRc0fxCP/2WuSBuritdBHGw2S3gYt4Bg/lt8UI+AfCQSEPTCg 8Kk+NwCGQZbEqrhbsLPbWr6MLx5oR7E= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-652-Yo2Jk1SZMJS_uj0K0yS76w-1; Sun, 18 Jan 2026 22:27:27 -0500 X-MC-Unique: Yo2Jk1SZMJS_uj0K0yS76w-1 X-Mimecast-MFC-AGG-ID: Yo2Jk1SZMJS_uj0K0yS76w_1768793245 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id CF9BE18005A7; Mon, 19 Jan 2026 03:27:24 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B33B71955F22; Mon, 19 Jan 2026 03:27:13 +0000 (UTC) From: Pingfan Liu To: linux-arm-kernel@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , kexec@lists.infradead.org, bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 11/13] arm64/kexec: Select KEXEC_BPF to support UEFI-style kernel image Date: Mon, 19 Jan 2026 11:24:22 +0800 Message-ID: <20260119032424.10781-12-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" Now everything is ready for kexec PE image parser. Select it on arm64 for zboot and UKI image support. Signed-off-by: Pingfan Liu Cc: Catalin Marinas Cc: Will Deacon To: linux-arm-kernel@lists.infradead.org --- arch/arm64/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 93173f0a09c7d..922d58abbbd67 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1587,6 +1587,7 @@ config ARCH_SELECTS_KEXEC_FILE def_bool y depends on KEXEC_FILE select HAVE_IMA_KEXEC if IMA + select KEXEC_BPF if DEBUG_INFO_BTF && BPF_SYSCALL =20 config ARCH_SUPPORTS_KEXEC_SIG def_bool y --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5851B256C70 for ; Mon, 19 Jan 2026 03:27:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793265; cv=none; b=dIgJOlzTX/LuS8aNLCpe5uUjahQqh6ry+UVhP8WOJlkeMSbRQnvo4r4DHJ9gg0lV8C5c9saRdwmmVOIpW8afLKoQ9cwdoUOTw8zWtEofQum7RFHS1HtYJre3H2pg7v4uI3RRZisW9PAhYYc17svwpPAF4p2k97sixmDC09NVueo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793265; c=relaxed/simple; bh=aCbZkW8kghpGHxk1L3WWQksjBwASoq8bfVrudB8THwg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=k5yNI3eGuXEjpZiyXdleuG8oo1bxT6V+nvK0rY8aSLa/eJYAibazFV7Fp1/4SkMRD1L44q0rtKOQx78Wv8oqa/esh+oCv/QyYRZZc/Hk9X4MP8AGKbgUUV7Hlf/QFkPLqfu8uQOy+xP+ShoKZtT2hZGkluwLHazfhnHxsKGRSOM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Zbg3D1MW; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Zbg3D1MW" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793262; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=7e1a7E+uvRoZBCO9NzWoxFmszs+807PaqpN5o4A8o3o=; b=Zbg3D1MWbpx5dIHg5m3baTdF8azdeeAPxgqIY74vVJH8rR18R1OFRizrbDIS1BeZWS8L3R CXjxAySRJqyzsn8xLIdvF2ymVsNBdFFZVMZQqth2N/+v7btp8hrhLF3IuJaq2TYSeMdeHP azgLQApstukodavW++VEcajZawlu84U= Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-676-clfPM9rKOCWoZFDTAR5pXA-1; Sun, 18 Jan 2026 22:27:38 -0500 X-MC-Unique: clfPM9rKOCWoZFDTAR5pXA-1 X-Mimecast-MFC-AGG-ID: clfPM9rKOCWoZFDTAR5pXA_1768793256 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8063119560B2; Mon, 19 Jan 2026 03:27:36 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 8AB861955F22; Mon, 19 Jan 2026 03:27:25 +0000 (UTC) From: Pingfan Liu To: kexec@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 12/13] tools/kexec: Introduce a bpf-prog to parse zboot image format Date: Mon, 19 Jan 2026 11:24:23 +0800 Message-ID: <20260119032424.10781-13-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" This BPF program aligns with the convention defined in the kernel file kexec_pe_parser_bpf.lskel.h. This can be easily achieved by include "template.c", which includes: four maps: struct bpf_map_desc ringbuf_1; struct bpf_map_desc ringbuf_2; struct bpf_map_desc ringbuf_3; struct bpf_map_desc ringbuf_4; four sections: struct bpf_map_desc rodata; struct bpf_map_desc data; struct bpf_map_desc bss; struct bpf_map_desc rodata_str1_1; The only left thing is to implement a prog SEC("fentry.s/kexec_image_parser_anchor") int BPF_PROG(parse_pe, struct kexec_context *context, unsigned long parser_= id) This BPF program only uses ringbuf_1, so it minimizes the size of the other three ringbufs to one byte. The size of ringbuf_1 is derived from the size of the uncompressed file 'vmlinux.bin', which is usually less than 64MB. With the help of the BPF kfunc bpf_buffer_parser(), the BPF program passes instructions to the kexec BPF component to perform the appropriate actions. Signed-off-by: Pingfan Liu Cc: Alexei Starovoitov Cc: Baoquan He Cc: Dave Young Cc: Andrew Morton Cc: Philipp Rudo Cc: bpf@vger.kernel.org To: kexec@lists.infradead.org --- tools/kexec/Makefile | 83 ++++++++++++++++++++++++ tools/kexec/template.c | 68 ++++++++++++++++++++ tools/kexec/zboot_parser_bpf.c | 114 +++++++++++++++++++++++++++++++++ 3 files changed, 265 insertions(+) create mode 100644 tools/kexec/Makefile create mode 100644 tools/kexec/template.c create mode 100644 tools/kexec/zboot_parser_bpf.c diff --git a/tools/kexec/Makefile b/tools/kexec/Makefile new file mode 100644 index 0000000000000..88db6d11bde61 --- /dev/null +++ b/tools/kexec/Makefile @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: GPL-2.0 + +# Ensure Kbuild variables are available +include ../scripts/Makefile.include + +srctree :=3D $(patsubst %/tools/kexec,%,$(CURDIR)) +VMLINUX =3D $(srctree)/vmlinux +TOOLSDIR :=3D $(srctree)/tools +LIBDIR :=3D $(TOOLSDIR)/lib +BPFDIR :=3D $(LIBDIR)/bpf +ARCH ?=3D $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ -e s/aarc= h64.*/arm64/ -e s/riscv64/riscv/ -e s/loongarch.*/loongarch/) +# At present, zboot image format is used by arm64, riscv, loongarch +# And arch/$(ARCH)/boot/vmlinux.bin is the uncompressed file instead of ar= ch/$(ARCH)/boot/Image +ifeq ($(ARCH),$(filter $(ARCH),arm64 riscv loongarch)) + EFI_IMAGE :=3D $(srctree)/arch/$(ARCH)/boot/vmlinuz.efi + KERNEL_IMAGE :=3D $(srctree)/arch/$(ARCH)/boot/vmlinux.bin +else + @echo "Unsupported architecture: $(ARCH)" + @exit 1 +endif + + +CC =3D clang +CFLAGS =3D -O2 +BPF_PROG_CFLAGS =3D -g -O2 -target bpf -Wall -I $(BPFDIR) -I . +BPFTOOL =3D bpftool + +# List of generated target files +HEADERS =3D vmlinux.h bpf_helper_defs.h image_size.h +ZBOOT_TARGETS =3D zboot_parser_bpf.o zboot_parser_bpf.lskel.h bytecode.c b= ytecode.o + + +# Targets +zboot: $(HEADERS) $(ZBOOT_TARGETS) + +# Rule to generate vmlinux.h from vmlinux +vmlinux.h: $(VMLINUX) + @command -v $(BPFTOOL) >/dev/null 2>&1 || { echo >&2 "$(BPFTOOL) is requi= red but not found. Please install it."; exit 1; } + @$(BPFTOOL) btf dump file $(VMLINUX) format c > vmlinux.h + +bpf_helper_defs.h: $(srctree)/tools/include/uapi/linux/bpf.h + @$(QUIET_GEN)$(srctree)/scripts/bpf_doc.py --header \ + --file $(srctree)/tools/include/uapi/linux/bpf.h > bpf_helper_defs.h + +image_size.h: $(KERNEL_IMAGE) + @{ \ + if [ ! -f "$(KERNEL_IMAGE)" ]; then \ + echo "Error: File '$(KERNEL_IMAGE)' does not exist"; \ + exit 1; \ + fi; \ + FILE_SIZE=3D$$(stat -c '%s' "$(KERNEL_IMAGE)" 2>/dev/null); \ + POWER=3D4096; \ + while [ $$POWER -le $$FILE_SIZE ]; do \ + POWER=3D$$((POWER * 2)); \ + done; \ + RINGBUF_SIZE=3D$$POWER; \ + echo "#define IMAGE_SIZE_POWER2_ALIGN $$RINGBUF_SIZE" > $@; \ + echo "#define IMAGE_SIZE $$FILE_SIZE" >> $@; \ + } + + +# Rule to generate zboot_parser_bpf.o, depends on vmlinux.h +zboot_parser_bpf.o: zboot_parser_bpf.c vmlinux.h bpf_helper_defs.h + @$(CC) $(BPF_PROG_CFLAGS) -c zboot_parser_bpf.c -o zboot_parser_bpf.o + +# Generate zboot_parser_bpf.lskel.h using bpftool +zboot_parser_bpf.lskel.h: zboot_parser_bpf.o + @$(BPFTOOL) gen skeleton -L zboot_parser_bpf.o > zboot_parser_bpf.lskel.h + +# Then, extract the opts_data[] and opts_insn[] arrays and remove 'static' +# keywords to avoid being optimized away. +bytecode.c: zboot_parser_bpf.lskel.h + @sed -n '/static const char opts_data\[\]/,/;/p' zboot_parser_bpf.lskel.h= | sed 's/static const/const/' > $@ + @sed -n '/static const char opts_insn\[\]/,/;/p' zboot_parser_bpf.lskel.h= | sed 's/static const/const/' >> $@ + +bytecode.o: bytecode.c + @$(CC) -c $< -o $@ + +# Clean up generated files +clean: + @rm -f $(HEADERS) $(ZBOOT_TARGETS) + +.PHONY: all clean diff --git a/tools/kexec/template.c b/tools/kexec/template.c new file mode 100644 index 0000000000000..9f17a4952ecd4 --- /dev/null +++ b/tools/kexec/template.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2026 Red Hat, Inc +// +// Original file: kernel/kexec_bpf/template.c +// +#include "vmlinux.h" +#include +#include +#include +#include + +/* Command to kernel kexec bpf loader, which is defined on the stream */ +#define KEXEC_BPF_CMD_DECOMPRESS 0x1 +#define KEXEC_BPF_CMD_COPY 0x2 + +#define KEXEC_BPF_SUBCMD_KERNEL 0x1 +#define KEXEC_BPF_SUBCMD_INITRD 0x2 +#define KEXEC_BPF_SUBCMD_CMDLINE 0x3 + +/* + * The ringbufs can have different capacity. But only four ringbuf are pro= vided. + */ +#ifndef RINGBUF1_SIZE +#define RINGBUF1_SIZE 4 +#endif +#ifndef RINGBUF2_SIZE +#define RINGBUF2_SIZE 4 +#endif +#ifndef RINGBUF3_SIZE +#define RINGBUF3_SIZE 4 +#endif +#ifndef RINGBUF4_SIZE +#define RINGBUF4_SIZE 4 +#endif + +/* ringbuf is safe since the user space has no write access to them */ +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, RINGBUF1_SIZE); +} ringbuf_1 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, RINGBUF2_SIZE); +} ringbuf_2 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, RINGBUF3_SIZE); +} ringbuf_3 SEC(".maps"); + +struct { + __uint(type, BPF_MAP_TYPE_RINGBUF); + __uint(max_entries, RINGBUF4_SIZE); +} ringbuf_4 SEC(".maps"); + +char LICENSE[] SEC("license") =3D "GPL"; + +/* + * This function ensures that the sections .rodata, .data, .rodata.str1.1 = and .bss + * are created for a bpf prog. + */ +static const char dummy_rodata[16] __attribute__((used)) =3D "rodata"; +static char dummy_data[16] __attribute__((used)) =3D "data"; +static char *dummy_mergeable_str __attribute__((used)) =3D ".rodata.str1.= 1"; +static char dummy_bss[16] __attribute__((used)); + diff --git a/tools/kexec/zboot_parser_bpf.c b/tools/kexec/zboot_parser_bpf.c new file mode 100644 index 0000000000000..54c4b762b3324 --- /dev/null +++ b/tools/kexec/zboot_parser_bpf.c @@ -0,0 +1,114 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2025, 2026 Red Hat, Inc +// +#include "vmlinux.h" +#include +#include +#include "image_size.h" + +/* ringbuf 2,3,4 are useless */ +#define MIN_BUF_SIZE 1 +#define MAX_RECORD_SIZE (IMAGE_SIZE + 40960) +#define RINGBUF1_SIZE IMAGE_SIZE_POWER2_ALIGN +#define RINGBUF2_SIZE MIN_BUF_SIZE +#define RINGBUF3_SIZE MIN_BUF_SIZE +#define RINGBUF4_SIZE MIN_BUF_SIZE + + +#include "template.c" + +/* see drivers/firmware/efi/libstub/zboot-header.S */ +struct linux_pe_zboot_header { + unsigned int mz_magic; + char image_type[4]; + unsigned int payload_offset; + unsigned int payload_size; + unsigned int reserved[2]; + char comp_type[4]; + unsigned int linux_pe_magic; + unsigned int pe_header_offset; +} __attribute__((packed)); + + +SEC("fentry.s/kexec_image_parser_anchor") +int BPF_PROG(parse_pe, struct kexec_context *context, unsigned long parser= _id) +{ + struct linux_pe_zboot_header *zboot_header; + unsigned int image_sz; + char *buf; + int ret =3D 0; + + image_sz =3D context->kernel_sz; + bpf_printk("begin parse PE\n"); + /* BPF verifier should know each variable initial state */ + if (!context->kernel || (image_sz > MAX_RECORD_SIZE)) { + bpf_printk("Err: image size is greater than 0x%lx\n", MAX_RECORD_SIZE); + return 0; + } + + /* In order to access bytes not aligned on 2 order, copy into ringbuf. + * And allocate the memory all at once, later overwriting. + * + * R2 is ARG_CONST_ALLOC_SIZE_OR_ZERO, should be decided at compling time + */ + buf =3D (char *)bpf_ringbuf_reserve(&ringbuf_1, MAX_RECORD_SIZE, 0); + if (!buf) { + bpf_printk("Err: fail to reserve ringbuf to parse zboot header\n"); + return 0; + } + bpf_probe_read((void *)buf, sizeof(struct linux_pe_zboot_header), context= ->kernel); + zboot_header =3D (struct linux_pe_zboot_header *)buf; + if (!!__builtin_memcmp(&zboot_header->image_type, "zimg", + sizeof(zboot_header->image_type))) { + bpf_ringbuf_discard(buf, BPF_RB_NO_WAKEUP); + bpf_printk("Err: image is not zboot image\n"); + return 0; + } + + unsigned int payload_offset =3D zboot_header->payload_offset; + unsigned int payload_size =3D zboot_header->payload_size; + bpf_printk("zboot image payload offset=3D0x%x, size=3D0x%x\n", payload_of= fset, payload_size); + /* sane check */ + if (payload_size > image_sz) { + bpf_ringbuf_discard(buf, BPF_RB_NO_WAKEUP); + bpf_printk("Invalid zboot image payload offset and size\n"); + return 0; + } + unsigned int max_payload =3D MAX_RECORD_SIZE - sizeof(struct cmd_hdr); + if (payload_size >=3D max_payload) { + bpf_ringbuf_discard(buf, BPF_RB_NO_WAKEUP); + bpf_printk("Err: payload_size > MAX_RECORD_SIZE\n"); + return 0; + } + void *dst =3D (void *)buf + sizeof(struct cmd_hdr); + /* Overwrite buf */ + struct cmd_hdr *cmd =3D (struct cmd_hdr *)buf; + cmd->cmd =3D KEXEC_BPF_CMD_DECOMPRESS; + cmd->subcmd =3D KEXEC_BPF_SUBCMD_KERNEL; + /* 4 bytes original size is appended after vmlinuz.bin */ + cmd->payload_len =3D payload_size - 4; + bpf_probe_read(dst, payload_size, context->kernel + payload_offset); + if (payload_size < 4) { + bpf_ringbuf_discard(buf, BPF_RB_NO_WAKEUP); + return 0; + } + bpf_printk("Calling bpf_kexec_decompress()\n"); + struct bpf_parser_context *bpf =3D bpf_get_parser_context(parser_id); + if (!bpf) { + bpf_ringbuf_discard(buf, BPF_RB_NO_WAKEUP); + bpf_printk("No parser in kernel\n"); + return 0; + } + ret =3D bpf_buffer_parser(buf, sizeof(struct cmd_hdr) + payload_size - 4,= bpf); + if (ret < 0) { + bpf_ringbuf_discard(buf, BPF_RB_NO_WAKEUP); + bpf_put_parser_context(bpf); + bpf_printk("Decompression fails\n"); + return 0; + } + bpf_ringbuf_discard(buf, BPF_RB_NO_WAKEUP); + bpf_put_parser_context(bpf); + + return 0; +} --=20 2.49.0 From nobody Sat Feb 7 07:10:30 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3451D1DF736 for ; Mon, 19 Jan 2026 03:27:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793276; cv=none; b=ruASAGL5vhAreN6lVWN5cqKYBNRgYkF9jg3pHwrCOR0ZxnhyMFuT+Gh9OJ0xNuR+MhgYngnC3z4KSK+Ube/7lDTvPB3+oi9On39Q+qykQBHxzREN+f/D3E8DJTFuhZR4+tDouPp4/3/zP4X8vA852yKiLe3eqPtiI2DMObqrJCg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768793276; c=relaxed/simple; bh=14SMqByPsIQVfl8pKGP++G+4sUAPPLEJi/eyu0x1564=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=eFoKIu7lyAkzsDiYT4KJo3pqxk2fvHpEBO3s3cIJajcQnRV7KtjtKxFB9Db+NHv1E4TLFHIRv9QNUNo3RRgF+aMa2IhUusXoa+o+TBnpI19wMuH9ApDWUaDjHPjBB/nYkHk7k2K1iaSlE4AJoMwf5vcNiFyNnAVOwrnCfCh7Q/0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=GIzyGpl2; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="GIzyGpl2" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1768793273; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=e54Q/Wn1M/aW4uiAmyk1v5WG6DDrOBedFc1qY/t+0Og=; b=GIzyGpl2O8iCtNF0r2VV/JEQeQ1Sheymb64z9xoNxsYlClZlJiWbVDfnmIr+T3cHI+Xoh8 YzpEGGbFS/7sIpr9Z/r2P2vfShrX5taFdEkUEGgK3Rmjvahv6iZM8Gpp0KoRs6Yq7KlvW5 LRgmPmb97pmdWMhqzRtOeiKIIr4OeUE= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-198-MZQWu_1TPlKFgy6xGA2pFw-1; Sun, 18 Jan 2026 22:27:50 -0500 X-MC-Unique: MZQWu_1TPlKFgy6xGA2pFw-1 X-Mimecast-MFC-AGG-ID: MZQWu_1TPlKFgy6xGA2pFw_1768793267 Received: from mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.17]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 9CC69180044D; Mon, 19 Jan 2026 03:27:47 +0000 (UTC) Received: from fedora.redhat.com (unknown [10.72.112.74]) by mx-prod-int-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 25AFF1955F22; Mon, 19 Jan 2026 03:27:36 +0000 (UTC) From: Pingfan Liu To: kexec@lists.infradead.org Cc: Pingfan Liu , "David S. Miller" , Alexei Starovoitov , Daniel Borkmann , John Fastabend , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Song Liu , Yonghong Song , Jeremy Linton , Catalin Marinas , Will Deacon , Ard Biesheuvel , Simon Horman , Gerd Hoffmann , Vitaly Kuznetsov , Philipp Rudo , Viktor Malik , Jan Hendrik Farr , Baoquan He , Dave Young , Andrew Morton , bpf@vger.kernel.org, systemd-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCHv6 13/13] tools/kexec: Add a zboot image building tool Date: Mon, 19 Jan 2026 11:24:24 +0800 Message-ID: <20260119032424.10781-14-piliu@redhat.com> In-Reply-To: <20260119032424.10781-1-piliu@redhat.com> References: <20260119032424.10781-1-piliu@redhat.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.0 on 10.30.177.17 Content-Type: text/plain; charset="utf-8" The objcopy binary can append a section to a PE file, but it disregards the DOS header. However, the zboot format carries important information in the DOS header: payload offset and size. To track this information and append a new PE section, here a dedicated binary tool is introduced to build zboot images. The payload's relative offset within the .data section remains unchanged. Therefore, the .data section offset in the new PE file, plus the payload offset within that section, yields the payload offset within the new PE file. Finally, the new PE file 'zboot.efi', with a .bpf section, can be got by the command: make -C tools/kexec zboot Signed-off-by: Pingfan Liu Cc: Alexei Starovoitov Cc: Baoquan He Cc: Dave Young Cc: Andrew Morton Cc: Philipp Rudo Cc: bpf@vger.kernel.org To: kexec@lists.infradead.org --- tools/kexec/Makefile | 10 +- tools/kexec/pe.h | 177 +++++++++++++++++++ tools/kexec/zboot_image_builder.c | 278 ++++++++++++++++++++++++++++++ 3 files changed, 464 insertions(+), 1 deletion(-) create mode 100644 tools/kexec/pe.h create mode 100644 tools/kexec/zboot_image_builder.c diff --git a/tools/kexec/Makefile b/tools/kexec/Makefile index 88db6d11bde61..acb045367adfa 100644 --- a/tools/kexec/Makefile +++ b/tools/kexec/Makefile @@ -27,7 +27,7 @@ BPFTOOL =3D bpftool =20 # List of generated target files HEADERS =3D vmlinux.h bpf_helper_defs.h image_size.h -ZBOOT_TARGETS =3D zboot_parser_bpf.o zboot_parser_bpf.lskel.h bytecode.c b= ytecode.o +ZBOOT_TARGETS =3D zboot_parser_bpf.o zboot_parser_bpf.lskel.h bytecode.c b= ytecode.o zboot_image_builder zboot.efi =20 =20 # Targets @@ -76,6 +76,14 @@ bytecode.c: zboot_parser_bpf.lskel.h bytecode.o: bytecode.c @$(CC) -c $< -o $@ =20 +# Rule to build zboot_image_builder executable +zboot_image_builder: zboot_image_builder.c + @$(CC) $(CFLAGS) $< -o $@ + +zboot.efi: zboot_image_builder bytecode.o + @chmod +x zboot_image_builder + @./zboot_image_builder $(EFI_IMAGE) bytecode.o $@ + # Clean up generated files clean: @rm -f $(HEADERS) $(ZBOOT_TARGETS) diff --git a/tools/kexec/pe.h b/tools/kexec/pe.h new file mode 100644 index 0000000000000..c2273d3fc3bb3 --- /dev/null +++ b/tools/kexec/pe.h @@ -0,0 +1,177 @@ +/* + * Extract from linux kernel include/linux/pe.h + */ + +#ifndef __PE_H__ +#define __PE_H__ + +#define IMAGE_DOS_SIGNATURE 0x5a4d /* "MZ" */ +#define IMAGE_NT_SIGNATURE 0x00004550 /* "PE\0\0" */ + +struct mz_hdr { + uint16_t magic; /* MZ_MAGIC */ + uint16_t lbsize; /* size of last used block */ + uint16_t blocks; /* pages in file, 0x3 */ + uint16_t relocs; /* relocations */ + uint16_t hdrsize; /* header size in "paragraphs" */ + uint16_t min_extra_pps; /* .bss */ + uint16_t max_extra_pps; /* runtime limit for the arena size */ + uint16_t ss; /* relative stack segment */ + uint16_t sp; /* initial %sp register */ + uint16_t checksum; /* word checksum */ + uint16_t ip; /* initial %ip register */ + uint16_t cs; /* initial %cs relative to load segment */ + uint16_t reloc_table_offset; /* offset of the first relocation */ + uint16_t overlay_num; /* overlay number. set to 0. */ + uint16_t reserved0[4]; /* reserved */ + uint16_t oem_id; /* oem identifier */ + uint16_t oem_info; /* oem specific */ + uint16_t reserved1[10]; /* reserved */ + uint32_t peaddr; /* address of pe header */ + char message[]; /* message to print */ +}; + +struct pe_hdr { + uint32_t magic; /* PE magic */ + uint16_t machine; /* machine type */ + uint16_t sections; /* number of sections */ + uint32_t timestamp; /* time_t */ + uint32_t symbol_table; /* symbol table offset */ + uint32_t symbols; /* number of symbols */ + uint16_t opt_hdr_size; /* size of optional header */ + uint16_t flags; /* flags */ +}; + +/* the fact that pe32 isn't padded where pe32+ is 64-bit means union won't + * work right. vomit. */ +struct pe32_opt_hdr { + /* "standard" header */ + uint16_t magic; /* file type */ + uint8_t ld_major; /* linker major version */ + uint8_t ld_minor; /* linker minor version */ + uint32_t text_size; /* size of text section(s) */ + uint32_t data_size; /* size of data section(s) */ + uint32_t bss_size; /* size of bss section(s) */ + uint32_t entry_point; /* file offset of entry point */ + uint32_t code_base; /* relative code addr in ram */ + uint32_t data_base; /* relative data addr in ram */ + /* "windows" header */ + uint32_t image_base; /* preferred load address */ + uint32_t section_align; /* alignment in bytes */ + uint32_t file_align; /* file alignment in bytes */ + uint16_t os_major; /* major OS version */ + uint16_t os_minor; /* minor OS version */ + uint16_t image_major; /* major image version */ + uint16_t image_minor; /* minor image version */ + uint16_t subsys_major; /* major subsystem version */ + uint16_t subsys_minor; /* minor subsystem version */ + uint32_t win32_version; /* reserved, must be 0 */ + uint32_t image_size; /* image size */ + uint32_t header_size; /* header size rounded up to + file_align */ + uint32_t csum; /* checksum */ + uint16_t subsys; /* subsystem */ + uint16_t dll_flags; /* more flags! */ + uint32_t stack_size_req;/* amt of stack requested */ + uint32_t stack_size; /* amt of stack required */ + uint32_t heap_size_req; /* amt of heap requested */ + uint32_t heap_size; /* amt of heap required */ + uint32_t loader_flags; /* reserved, must be 0 */ + uint32_t data_dirs; /* number of data dir entries */ +}; + +struct pe32plus_opt_hdr { + uint16_t magic; /* file type */ + uint8_t ld_major; /* linker major version */ + uint8_t ld_minor; /* linker minor version */ + uint32_t text_size; /* size of text section(s) */ + uint32_t data_size; /* size of data section(s) */ + uint32_t bss_size; /* size of bss section(s) */ + uint32_t entry_point; /* file offset of entry point */ + uint32_t code_base; /* relative code addr in ram */ + /* "windows" header */ + uint64_t image_base; /* preferred load address */ + uint32_t section_align; /* alignment in bytes */ + uint32_t file_align; /* file alignment in bytes */ + uint16_t os_major; /* major OS version */ + uint16_t os_minor; /* minor OS version */ + uint16_t image_major; /* major image version */ + uint16_t image_minor; /* minor image version */ + uint16_t subsys_major; /* major subsystem version */ + uint16_t subsys_minor; /* minor subsystem version */ + uint32_t win32_version; /* reserved, must be 0 */ + uint32_t image_size; /* image size */ + uint32_t header_size; /* header size rounded up to + file_align */ + uint32_t csum; /* checksum */ + uint16_t subsys; /* subsystem */ + uint16_t dll_flags; /* more flags! */ + uint64_t stack_size_req;/* amt of stack requested */ + uint64_t stack_size; /* amt of stack required */ + uint64_t heap_size_req; /* amt of heap requested */ + uint64_t heap_size; /* amt of heap required */ + uint32_t loader_flags; /* reserved, must be 0 */ + uint32_t data_dirs; /* number of data dir entries */ +}; + +struct data_dirent { + uint32_t virtual_address; /* relative to load address */ + uint32_t size; +}; + +struct data_directory { + struct data_dirent exports; /* .edata */ + struct data_dirent imports; /* .idata */ + struct data_dirent resources; /* .rsrc */ + struct data_dirent exceptions; /* .pdata */ + struct data_dirent certs; /* certs */ + struct data_dirent base_relocations; /* .reloc */ + struct data_dirent debug; /* .debug */ + struct data_dirent arch; /* reservered */ + struct data_dirent global_ptr; /* global pointer reg. Size=3D0 */ + struct data_dirent tls; /* .tls */ + struct data_dirent load_config; /* load configuration structure */ + struct data_dirent bound_imports; /* no idea */ + struct data_dirent import_addrs; /* import address table */ + struct data_dirent delay_imports; /* delay-load import table */ + struct data_dirent clr_runtime_hdr; /* .cor (object only) */ + struct data_dirent reserved; +}; + +struct section_header { + char name[8]; /* name or "/12\0" string tbl offset */ + uint32_t virtual_size; /* size of loaded section in ram */ + uint32_t virtual_address; /* relative virtual address */ + uint32_t raw_data_size; /* size of the section */ + uint32_t data_addr; /* file pointer to first page of sec */ + uint32_t relocs; /* file pointer to relocation entries */ + uint32_t line_numbers; /* line numbers! */ + uint16_t num_relocs; /* number of relocations */ + uint16_t num_lin_numbers; /* srsly. */ + uint32_t flags; +}; + +struct win_certificate { + uint32_t length; + uint16_t revision; + uint16_t cert_type; +}; + +/* + * Return -1 if not PE, else offset of the PE header + */ +static int get_pehdr_offset(const char *buf) +{ + int pe_hdr_offset; + + pe_hdr_offset =3D *((int *)(buf + 0x3c)); + buf +=3D pe_hdr_offset; + if (!!memcmp(buf, "PE\0\0", 4)) { + printf("Not a PE file\n"); + return -1; + } + + return pe_hdr_offset; +} + +#endif diff --git a/tools/kexec/zboot_image_builder.c b/tools/kexec/zboot_image_bu= ilder.c new file mode 100644 index 0000000000000..c0a785074970e --- /dev/null +++ b/tools/kexec/zboot_image_builder.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2025 Red Hat, Inc. + * The zboot format carries the compressed kernel image offset and size + * information in the DOS header. The program appends a bpf section to PE = file, + * meanwhile maintains the offset and size information, which is lost when= using + * objcopy to handle zboot image. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "pe.h" + +#ifdef DEBUG_DETAIL + #define dprintf(...) printf(__VA_ARGS__) +#else + #define dprintf(...) ((void)0) +#endif + +typedef struct { + union { + struct { + unsigned int mz_magic; + char image_type[4]; + /* offset to the whole file start */ + unsigned int payload_offset; + unsigned int payload_size; + unsigned int reserved[2]; + char comp_type[4]; + }; + char raw_bytes[56]; + }; + unsigned int linux_pe_magic; + /* offset at: 0x3c or 60 */ + unsigned int pe_header_offset; +} __attribute__((packed)) pe_zboot_header; + +typedef unsigned long uintptr_t; +#define ALIGN_UP(p, size) (__typeof__(p))(((uintptr_t)(p) + ((size) - 1)) = & ~((size) - 1)) + +int main(int argc, char **argv) +{ + uint32_t payload_new_offset, payload_sect_off; + uint32_t payload_size; + uint32_t payload_sect_idx; + pe_zboot_header *zheader; + struct pe_hdr *pe_hdr; + struct pe32plus_opt_hdr *opt_hdr; + int base_fd, out_fd; + char *base_start_addr, *base_cur; + char *out_start_addr, *out_cur; + uint32_t out_sz, max_va_end =3D 0; + struct stat sb; + int i =3D 0, ret =3D 0; + + if (argc !=3D 4) { + fprintf(stderr, "Usage: %s \n", a= rgv[0]); + return -1; + } + + const char *original_pe =3D argv[1]; + const char *binary_file =3D argv[2]; + const char *new_pe =3D argv[3]; + FILE *bin_fp =3D fopen(binary_file, "rb"); + if (!bin_fp) { + perror("Failed to open binary file"); + return -1; + } + fseek(bin_fp, 0, SEEK_END); + size_t bin_size =3D ftell(bin_fp); + fseek(bin_fp, 0, SEEK_SET); + base_fd =3D open(original_pe, O_RDWR); + out_fd =3D open(new_pe, O_RDWR | O_CREAT, 0644); + if (base_fd =3D=3D -1 || out_fd =3D=3D -1) { + perror("Error opening file"); + exit(1); + } + + if (fstat(base_fd, &sb) =3D=3D -1) { + perror("Error getting file size"); + exit(1); + } + base_start_addr =3D mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, base_fd= , 0); + if (base_start_addr =3D=3D MAP_FAILED) { + perror("Error mmapping the file"); + exit(1); + } + /* 64KB for section table extending */ + out_sz =3D sb.st_size + bin_size + (1 << 16); + out_start_addr =3D mmap(NULL, out_sz, PROT_WRITE, MAP_SHARED, out_fd, 0); + if (ftruncate(out_fd, out_sz) =3D=3D -1) { + perror("Failed to resize output file"); + ret =3D -1; + goto err; + } + if (out_start_addr =3D=3D MAP_FAILED) { + perror("Error mmapping the file"); + exit(1); + } + + zheader =3D (pe_zboot_header *)base_start_addr; + if (zheader->mz_magic !=3D 0x5A4D) { // 'MZ' + fprintf(stderr, "Invalid DOS signature\n"); + return -1; + } + uint32_t pe_hdr_offset =3D get_pehdr_offset((const char *)base_start_addr= ); + base_cur =3D base_start_addr + pe_hdr_offset; + pe_hdr =3D (struct pe_hdr *)base_cur; + if (pe_hdr->magic!=3D 0x00004550) { // 'PE\0\0' + fprintf(stderr, "Invalid PE signature\n"); + return -1; + } + base_cur +=3D sizeof(struct pe_hdr); + opt_hdr =3D (struct pe32plus_opt_hdr *)base_cur; + uint32_t file_align =3D opt_hdr->file_align; + uint32_t section_alignment =3D opt_hdr->section_align; + + uint16_t num_sections =3D pe_hdr->sections; + struct section_header *base_sections, *sect; + uint32_t section_table_offset =3D pe_hdr_offset + sizeof(struct pe_hdr) += pe_hdr->opt_hdr_size; + base_sections =3D (struct section_header *)(base_start_addr + section_tab= le_offset); + + /* Decide the section idx and the payload offset within the section */ + for (i =3D 0; i < num_sections; i++) { + sect =3D &base_sections[i]; + if (zheader->payload_offset >=3D sect->data_addr && + zheader->payload_offset < (sect->data_addr + sect->raw_data_size)) { + payload_sect_idx =3D i; + payload_sect_off =3D zheader->payload_offset - sect->data_addr; + } + } + + /* Calculate the end of the last section in virtual memory */ + for (i =3D 0; i < num_sections; i++) { + uint32_t section_end =3D base_sections[i].virtual_address + base_sect= ions[i].virtual_size; + if (section_end > max_va_end) { + max_va_end =3D section_end; + } + } + + /* Calculate virtual address for the new .bpf section */ + uint32_t bpf_virtual_address =3D ALIGN_UP(max_va_end, section_alignment); + + pe_zboot_header *new_zhdr =3D malloc(sizeof(pe_zboot_header)); + memcpy(new_zhdr, zheader, sizeof(pe_zboot_header)); + struct pe_hdr *new_hdr =3D malloc(sizeof(struct pe_hdr)); + memcpy(new_hdr, pe_hdr, sizeof(struct pe_hdr)); + new_hdr->sections +=3D 1; + struct pe32plus_opt_hdr *new_opt_hdr =3D malloc(pe_hdr->opt_hdr_size); + memcpy(new_opt_hdr, opt_hdr, pe_hdr->opt_hdr_size); + /* Create new section headers array (original + new section) */ + struct section_header *new_sections =3D calloc(1, new_hdr->sections * siz= eof(struct section_header)); + if (!new_sections) { + perror("Failed to allocate memory for new section headers"); + return -1; + } + memcpy(new_sections, base_sections, pe_hdr->sections * sizeof(struct sect= ion_header)); + + /* Configure the new .bpf section */ + struct section_header *bpf_section =3D &new_sections[new_hdr->sections - = 1]; + memset(bpf_section, 0, sizeof(struct section_header)); + strncpy((char *)bpf_section->name, ".bpf", 8); + bpf_section->virtual_size =3D bin_size; + bpf_section->virtual_address =3D bpf_virtual_address; + bpf_section->raw_data_size =3D bin_size; + bpf_section->flags =3D 0x40000000; //Readable + + /* Update headers */ + uint32_t new_size_of_image =3D bpf_section->virtual_address + bpf_section= ->virtual_size; + new_size_of_image =3D ALIGN_UP(new_size_of_image, section_alignment); + new_opt_hdr->image_size =3D new_size_of_image; + + size_t section_table_size =3D new_hdr->sections * (sizeof(struct section_= header)); + size_t headers_size =3D section_table_offset + section_table_size; + size_t aligned_headers_size =3D ALIGN_UP(headers_size, file_align); + new_opt_hdr->header_size =3D aligned_headers_size; + + + uint32_t current_offset =3D aligned_headers_size; + /* + * If the original PE data_addr is covered by enlarged header_size + * re-assign new data_addr for all sections + */ + if (base_sections[0].data_addr < aligned_headers_size) { + for (i =3D 0; i < new_hdr->sections; i++) { + new_sections[i].data_addr =3D current_offset; + current_offset +=3D ALIGN_UP(new_sections[i].raw_data_size, file_ali= gn); + } + /* Keep unchanged, just allocating file pointer for bpf section */ + } else { + uint32_t t; + i =3D new_hdr->sections - 2; + t =3D new_sections[i].data_addr + new_sections[i].raw_data_size; + i++; + new_sections[i].data_addr =3D ALIGN_UP(t, file_align); + } + + payload_new_offset =3D new_sections[payload_sect_idx].data_addr + payload= _sect_off; + /* Update */ + new_zhdr->payload_offset =3D payload_new_offset; + new_zhdr->payload_size =3D zheader->payload_size; + dprintf("zboot payload_offset updated from 0x%x to 0x%x, size:0x%x\n", + zheader->payload_offset, payload_new_offset, new_zhdr->payload_size); + + + /* compose the new PE file */ + + /* Write Dos header */ + memcpy(out_start_addr, new_zhdr, sizeof(pe_zboot_header)); + out_cur =3D out_start_addr + pe_hdr_offset; + + /* Write PE header */ + memcpy(out_cur, new_hdr, sizeof(struct pe_hdr)); + out_cur +=3D sizeof(struct pe_hdr); + + /* Write PE optional header */ + memcpy(out_cur, new_opt_hdr, new_hdr->opt_hdr_size); + out_cur +=3D new_hdr->opt_hdr_size; + + /* Write all section headers */ + memcpy(out_cur, new_sections, new_hdr->sections * sizeof(struct section_h= eader)); + + /* Skip padding and copy the section data */ + for (i =3D 0; i < pe_hdr->sections; i++) { + base_cur =3D base_start_addr + base_sections[i].data_addr; + out_cur =3D out_start_addr + new_sections[i].data_addr; + memcpy(out_cur, base_cur, base_sections[i].raw_data_size); + } + msync(out_start_addr, new_sections[i].data_addr + new_sections[i].raw_dat= a_size, MS_ASYNC); + /* For the bpf section */ + out_cur =3D out_start_addr + new_sections[i].data_addr; + + /* Write .bpf section data */ + char *bin_data =3D calloc(1, bin_size); + if (!bin_data) { + perror("Failed to allocate memory for binary data"); + free(new_sections); + ret =3D -1; + goto err; + } + if (fread(bin_data, bin_size, 1, bin_fp) !=3D 1) { + perror("Failed to read binary data"); + free(bin_data); + free(new_sections); + ret =3D -1; + goto err; + } + + if (out_cur + bin_size > out_start_addr + out_sz) { + perror("out of out_fd mmap\n"); + ret =3D -1; + goto err; + } + memcpy(out_cur, bin_data, bin_size); + /* calculate the real size */ + out_sz =3D out_cur + bin_size - out_start_addr; + msync(out_start_addr, out_sz, MS_ASYNC); + /* truncate to the real size */ + if (ftruncate(out_fd, out_sz) =3D=3D -1) { + perror("Failed to resize output file"); + ret =3D -1; + goto err; + } + printf("Create a new PE file with bpf section: %s\n", new_pe); +err: + munmap(out_start_addr, out_sz); + munmap(base_start_addr, sb.st_size); + close(base_fd); + close(out_fd); + fclose(bin_fp); + + return ret; +} --=20 2.49.0