All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] kexec: fix probe error codes and error propagation
@ 2026-08-19 17:47 ` Mukesh Pilaniya
  0 siblings, 0 replies; 10+ messages in thread
From: Mukesh Pilaniya @ 2026-08-19 17:47 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Mark Rutland, Huacai Chen,
	WANG Xuerui, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Andrew Morton, Baoquan He, Mike Rapoport,
	Pasha Tatashin, Pratyush Yadav, Tao Liu, Philipp Rudo
  Cc: linux-arm-kernel, linux-kernel, loongarch, linux-riscv, kexec,
	Mukesh Pilaniya

While debugging a misleading error on s390x where kexec -s reported
"syscall kexec_file_load not available" instead of the actual EINVAL
from a kernel command line that exceeded the architecture limit, we
found that some kexec image probe functions return -EINVAL instead of
-ENOEXEC for format mismatches, and kexec_image_probe_default() has a
bug where it returns whatever the last loader returned rather than
always returning -ENOEXEC when no loader matches.

Patch 1 fixes all probe functions to return -ENOEXEC when they do not
recognize the image format.

Patch 2 fixes kexec_image_probe_default() to distinguish format
mismatches (-ENOEXEC) from real errors (e.g. -ENOMEM), propagating
real errors immediately and only continuing to the next loader on
-ENOEXEC.

kexec-tools patch:
https://lore.kernel.org/all/20260814075329.30203-1-mpilaniy@redhat.com/

Signed-off-by: Mukesh Pilaniya <mpilaniy@redhat.com>
---
Changes in v2:
- Added patch 2 to fix error propagation in kexec_image_probe_default(),
  as suggested by Pratyush Yadav.
- Link to v1: https://patch.msgid.link/20260813-mpilaniy-v1-1-777d4d0e30f7@redhat.com

To: Catalin Marinas <catalin.marinas@arm.com>
To: Will Deacon <will@kernel.org>
To: Mark Rutland <mark.rutland@arm.com>
To: Huacai Chen <chenhuacai@kernel.org>
To: WANG Xuerui <kernel@xen0n.name>
To: Paul Walmsley <pjw@kernel.org>
To: Palmer Dabbelt <palmer@dabbelt.com>
To: Albert Ou <aou@eecs.berkeley.edu>
To: Alexandre Ghiti <alex@ghiti.fr>
To: Andrew Morton <akpm@linux-foundation.org>
To: Baoquan He <baoquan.he@linux.dev>
To: Mike Rapoport <rppt@kernel.org>
To: Pasha Tatashin <pasha.tatashin@soleen.com>
To: Pratyush Yadav <pratyush@kernel.org>
To: Philipp Rudo <prudo@redhat.com>
To: Tao Liu <ltao@redhat.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: loongarch@lists.linux.dev
Cc: linux-riscv@lists.infradead.org
Cc: kexec@lists.infradead.org

---
Mukesh Pilaniya (2):
      kexec: return -ENOEXEC from image probe functions on mismatch
      kexec: fix error propagation in kexec_image_probe_default()

 arch/arm64/kernel/kexec_image.c   |  4 ++--
 arch/loongarch/kernel/kexec_efi.c |  4 ++--
 arch/riscv/kernel/kexec_image.c   |  4 ++--
 kernel/kexec_elf.c                |  4 ++--
 kernel/kexec_file.c               | 12 +++++++-----
 5 files changed, 15 insertions(+), 13 deletions(-)
---
base-commit: dd8c49a14f169d58e7a07a2c96fb588f3456efa0
change-id: 20260813-mpilaniy-ffb0cc92c313

Best regards,
--  
Mukesh Pilaniya <mpilaniy@redhat.com>



^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 0/2] kexec: fix probe error codes and error propagation
@ 2026-08-19 17:47 ` Mukesh Pilaniya
  0 siblings, 0 replies; 10+ messages in thread
From: Mukesh Pilaniya @ 2026-08-19 17:47 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Mark Rutland, Huacai Chen,
	WANG Xuerui, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Andrew Morton, Baoquan He, Mike Rapoport,
	Pasha Tatashin, Pratyush Yadav, Tao Liu, Philipp Rudo
  Cc: linux-arm-kernel, linux-kernel, loongarch, linux-riscv, kexec,
	Mukesh Pilaniya

While debugging a misleading error on s390x where kexec -s reported
"syscall kexec_file_load not available" instead of the actual EINVAL
from a kernel command line that exceeded the architecture limit, we
found that some kexec image probe functions return -EINVAL instead of
-ENOEXEC for format mismatches, and kexec_image_probe_default() has a
bug where it returns whatever the last loader returned rather than
always returning -ENOEXEC when no loader matches.

Patch 1 fixes all probe functions to return -ENOEXEC when they do not
recognize the image format.

Patch 2 fixes kexec_image_probe_default() to distinguish format
mismatches (-ENOEXEC) from real errors (e.g. -ENOMEM), propagating
real errors immediately and only continuing to the next loader on
-ENOEXEC.

kexec-tools patch:
https://lore.kernel.org/all/20260814075329.30203-1-mpilaniy@redhat.com/

Signed-off-by: Mukesh Pilaniya <mpilaniy@redhat.com>
---
Changes in v2:
- Added patch 2 to fix error propagation in kexec_image_probe_default(),
  as suggested by Pratyush Yadav.
- Link to v1: https://patch.msgid.link/20260813-mpilaniy-v1-1-777d4d0e30f7@redhat.com

To: Catalin Marinas <catalin.marinas@arm.com>
To: Will Deacon <will@kernel.org>
To: Mark Rutland <mark.rutland@arm.com>
To: Huacai Chen <chenhuacai@kernel.org>
To: WANG Xuerui <kernel@xen0n.name>
To: Paul Walmsley <pjw@kernel.org>
To: Palmer Dabbelt <palmer@dabbelt.com>
To: Albert Ou <aou@eecs.berkeley.edu>
To: Alexandre Ghiti <alex@ghiti.fr>
To: Andrew Morton <akpm@linux-foundation.org>
To: Baoquan He <baoquan.he@linux.dev>
To: Mike Rapoport <rppt@kernel.org>
To: Pasha Tatashin <pasha.tatashin@soleen.com>
To: Pratyush Yadav <pratyush@kernel.org>
To: Philipp Rudo <prudo@redhat.com>
To: Tao Liu <ltao@redhat.com>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: loongarch@lists.linux.dev
Cc: linux-riscv@lists.infradead.org
Cc: kexec@lists.infradead.org

---
Mukesh Pilaniya (2):
      kexec: return -ENOEXEC from image probe functions on mismatch
      kexec: fix error propagation in kexec_image_probe_default()

 arch/arm64/kernel/kexec_image.c   |  4 ++--
 arch/loongarch/kernel/kexec_efi.c |  4 ++--
 arch/riscv/kernel/kexec_image.c   |  4 ++--
 kernel/kexec_elf.c                |  4 ++--
 kernel/kexec_file.c               | 12 +++++++-----
 5 files changed, 15 insertions(+), 13 deletions(-)
---
base-commit: dd8c49a14f169d58e7a07a2c96fb588f3456efa0
change-id: 20260813-mpilaniy-ffb0cc92c313

Best regards,
--  
Mukesh Pilaniya <mpilaniy@redhat.com>


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 1/2] kexec: return -ENOEXEC from image probe functions on mismatch
  2026-08-19 17:47 ` Mukesh Pilaniya
@ 2026-08-19 17:47   ` Mukesh Pilaniya
  -1 siblings, 0 replies; 10+ messages in thread
From: Mukesh Pilaniya @ 2026-08-19 17:47 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Mark Rutland, Huacai Chen,
	WANG Xuerui, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Andrew Morton, Baoquan He, Mike Rapoport,
	Pasha Tatashin, Pratyush Yadav, Tao Liu, Philipp Rudo
  Cc: linux-arm-kernel, linux-kernel, loongarch, linux-riscv, kexec,
	Mukesh Pilaniya

Several kexec_file_load() image probe functions return -EINVAL when
they do not recognize the image format.  A probe function that rejects
an image should return -ENOEXEC to indicate that the image is not a
recognized executable format.  -EINVAL implies a problem with the
syscall parameters, not with image recognition.

kexec_image_probe_default() iterates through registered loaders and
returns the last probe's error code to the caller.  That error
propagates as the kexec_file_load() return value to userspace.
Returning -EINVAL from a probe when no loader matches is semantically
incorrect and misleads userspace about the nature of the failure.

Return -ENOEXEC from all probe functions and their helpers when the
image format is not recognized.

Signed-off-by: Mukesh Pilaniya <mpilaniy@redhat.com>
Reviewed-by: Philipp Rudo <prudo@redhat.com>
Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
---
 arch/arm64/kernel/kexec_image.c   | 4 ++--
 arch/loongarch/kernel/kexec_efi.c | 4 ++--
 arch/riscv/kernel/kexec_image.c   | 4 ++--
 kernel/kexec_elf.c                | 4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
index b70f4df15a1a..101259874d44 100644
--- a/arch/arm64/kernel/kexec_image.c
+++ b/arch/arm64/kernel/kexec_image.c
@@ -25,10 +25,10 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
 		(const struct arm64_image_header *)(kernel_buf);
 
 	if (!h || (kernel_len < sizeof(*h)))
-		return -EINVAL;
+		return -ENOEXEC;
 
 	if (memcmp(&h->magic, ARM64_IMAGE_MAGIC, sizeof(h->magic)))
-		return -EINVAL;
+		return -ENOEXEC;
 
 	return 0;
 }
diff --git a/arch/loongarch/kernel/kexec_efi.c b/arch/loongarch/kernel/kexec_efi.c
index 5ee78ebb1546..28a1d0420ba3 100644
--- a/arch/loongarch/kernel/kexec_efi.c
+++ b/arch/loongarch/kernel/kexec_efi.c
@@ -24,12 +24,12 @@ static int efi_kexec_probe(const char *kernel_buf, unsigned long kernel_len)
 
 	if (!h || (kernel_len < sizeof(*h))) {
 		kexec_dprintk("No LoongArch image header.\n");
-		return -EINVAL;
+		return -ENOEXEC;
 	}
 
 	if (!loongarch_header_check_dos_sig(h)) {
 		kexec_dprintk("No LoongArch PE image header.\n");
-		return -EINVAL;
+		return -ENOEXEC;
 	}
 
 	return 0;
diff --git a/arch/riscv/kernel/kexec_image.c b/arch/riscv/kernel/kexec_image.c
index 51dc89259f16..963a25f5b55b 100644
--- a/arch/riscv/kernel/kexec_image.c
+++ b/arch/riscv/kernel/kexec_image.c
@@ -20,7 +20,7 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
 	const struct riscv_image_header *h = (const struct riscv_image_header *)kernel_buf;
 
 	if (!h || kernel_len < sizeof(*h))
-		return -EINVAL;
+		return -ENOEXEC;
 
 	/* According to Documentation/arch/riscv/boot-image-header.rst,
 	 * use "magic2" field to check when version >= 0.2.
@@ -28,7 +28,7 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
 
 	if (h->version >= RISCV_HEADER_VERSION &&
 	    memcmp(&h->magic2, RISCV_IMAGE_MAGIC2, sizeof(h->magic2)))
-		return -EINVAL;
+		return -ENOEXEC;
 
 	return 0;
 }
diff --git a/kernel/kexec_elf.c b/kernel/kexec_elf.c
index 3a5c25b2adc9..89a444a00693 100644
--- a/kernel/kexec_elf.c
+++ b/kernel/kexec_elf.c
@@ -172,7 +172,7 @@ static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
 
 	default:
 		pr_debug("Unknown ELF class.\n");
-		return -EINVAL;
+		return -ENOEXEC;
 	}
 
 	return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
@@ -236,7 +236,7 @@ static int elf_read_phdr(const char *buf, size_t len,
 
 	default:
 		pr_debug("Unknown ELF class.\n");
-		return -EINVAL;
+		return -ENOEXEC;
 	}
 
 	return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;

-- 
Git-155)



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 1/2] kexec: return -ENOEXEC from image probe functions on mismatch
@ 2026-08-19 17:47   ` Mukesh Pilaniya
  0 siblings, 0 replies; 10+ messages in thread
From: Mukesh Pilaniya @ 2026-08-19 17:47 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Mark Rutland, Huacai Chen,
	WANG Xuerui, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Andrew Morton, Baoquan He, Mike Rapoport,
	Pasha Tatashin, Pratyush Yadav, Tao Liu, Philipp Rudo
  Cc: linux-arm-kernel, linux-kernel, loongarch, linux-riscv, kexec,
	Mukesh Pilaniya

Several kexec_file_load() image probe functions return -EINVAL when
they do not recognize the image format.  A probe function that rejects
an image should return -ENOEXEC to indicate that the image is not a
recognized executable format.  -EINVAL implies a problem with the
syscall parameters, not with image recognition.

kexec_image_probe_default() iterates through registered loaders and
returns the last probe's error code to the caller.  That error
propagates as the kexec_file_load() return value to userspace.
Returning -EINVAL from a probe when no loader matches is semantically
incorrect and misleads userspace about the nature of the failure.

Return -ENOEXEC from all probe functions and their helpers when the
image format is not recognized.

Signed-off-by: Mukesh Pilaniya <mpilaniy@redhat.com>
Reviewed-by: Philipp Rudo <prudo@redhat.com>
Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
---
 arch/arm64/kernel/kexec_image.c   | 4 ++--
 arch/loongarch/kernel/kexec_efi.c | 4 ++--
 arch/riscv/kernel/kexec_image.c   | 4 ++--
 kernel/kexec_elf.c                | 4 ++--
 4 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
index b70f4df15a1a..101259874d44 100644
--- a/arch/arm64/kernel/kexec_image.c
+++ b/arch/arm64/kernel/kexec_image.c
@@ -25,10 +25,10 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
 		(const struct arm64_image_header *)(kernel_buf);
 
 	if (!h || (kernel_len < sizeof(*h)))
-		return -EINVAL;
+		return -ENOEXEC;
 
 	if (memcmp(&h->magic, ARM64_IMAGE_MAGIC, sizeof(h->magic)))
-		return -EINVAL;
+		return -ENOEXEC;
 
 	return 0;
 }
diff --git a/arch/loongarch/kernel/kexec_efi.c b/arch/loongarch/kernel/kexec_efi.c
index 5ee78ebb1546..28a1d0420ba3 100644
--- a/arch/loongarch/kernel/kexec_efi.c
+++ b/arch/loongarch/kernel/kexec_efi.c
@@ -24,12 +24,12 @@ static int efi_kexec_probe(const char *kernel_buf, unsigned long kernel_len)
 
 	if (!h || (kernel_len < sizeof(*h))) {
 		kexec_dprintk("No LoongArch image header.\n");
-		return -EINVAL;
+		return -ENOEXEC;
 	}
 
 	if (!loongarch_header_check_dos_sig(h)) {
 		kexec_dprintk("No LoongArch PE image header.\n");
-		return -EINVAL;
+		return -ENOEXEC;
 	}
 
 	return 0;
diff --git a/arch/riscv/kernel/kexec_image.c b/arch/riscv/kernel/kexec_image.c
index 51dc89259f16..963a25f5b55b 100644
--- a/arch/riscv/kernel/kexec_image.c
+++ b/arch/riscv/kernel/kexec_image.c
@@ -20,7 +20,7 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
 	const struct riscv_image_header *h = (const struct riscv_image_header *)kernel_buf;
 
 	if (!h || kernel_len < sizeof(*h))
-		return -EINVAL;
+		return -ENOEXEC;
 
 	/* According to Documentation/arch/riscv/boot-image-header.rst,
 	 * use "magic2" field to check when version >= 0.2.
@@ -28,7 +28,7 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
 
 	if (h->version >= RISCV_HEADER_VERSION &&
 	    memcmp(&h->magic2, RISCV_IMAGE_MAGIC2, sizeof(h->magic2)))
-		return -EINVAL;
+		return -ENOEXEC;
 
 	return 0;
 }
diff --git a/kernel/kexec_elf.c b/kernel/kexec_elf.c
index 3a5c25b2adc9..89a444a00693 100644
--- a/kernel/kexec_elf.c
+++ b/kernel/kexec_elf.c
@@ -172,7 +172,7 @@ static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
 
 	default:
 		pr_debug("Unknown ELF class.\n");
-		return -EINVAL;
+		return -ENOEXEC;
 	}
 
 	return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
@@ -236,7 +236,7 @@ static int elf_read_phdr(const char *buf, size_t len,
 
 	default:
 		pr_debug("Unknown ELF class.\n");
-		return -EINVAL;
+		return -ENOEXEC;
 	}
 
 	return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;

-- 
Git-155)


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 2/2] kexec: fix error propagation in kexec_image_probe_default()
  2026-08-19 17:47 ` Mukesh Pilaniya
@ 2026-08-19 17:47   ` Mukesh Pilaniya
  -1 siblings, 0 replies; 10+ messages in thread
From: Mukesh Pilaniya @ 2026-08-19 17:47 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Mark Rutland, Huacai Chen,
	WANG Xuerui, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Andrew Morton, Baoquan He, Mike Rapoport,
	Pasha Tatashin, Pratyush Yadav, Tao Liu, Philipp Rudo
  Cc: linux-arm-kernel, linux-kernel, loongarch, linux-riscv, kexec,
	Mukesh Pilaniya

kexec_image_probe_default() overwrites ret with each loader's probe
return value and returns whatever the last loader returned when no
probe matches.  The error code reaching userspace depends on whichever
loader happens to be last in kexec_file_loaders[].

Only continue to the next loader when a probe returns -ENOEXEC.
Propagate any other error such as -ENOMEM immediately. Return -ENOEXEC
only when all loaders have been tried and none matched.

Suggested-by: Pratyush Yadav <pratyush@kernel.org>
Signed-off-by: Mukesh Pilaniya <mpilaniy@redhat.com>
---
 kernel/kexec_file.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 59fb9d71e9d8..b3060e984ef3 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -68,17 +68,19 @@ int kexec_image_probe_default(struct kimage *image, void *buf,
 			      unsigned long buf_len)
 {
 	const struct kexec_file_ops * const *fops;
-	int ret = -ENOEXEC;
 
 	for (fops = &kexec_file_loaders[0]; *fops && (*fops)->probe; ++fops) {
-		ret = (*fops)->probe(buf, buf_len);
-		if (!ret) {
+		int ret = (*fops)->probe(buf, buf_len);
+
+		if (ret == 0) {
 			image->fops = *fops;
-			return ret;
+			return 0;
 		}
+		if (ret != -ENOEXEC)
+			return ret;
 	}
 
-	return ret;
+	return -ENOEXEC;
 }
 
 static void *kexec_image_load_default(struct kimage *image)

-- 
Git-155)



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 2/2] kexec: fix error propagation in kexec_image_probe_default()
@ 2026-08-19 17:47   ` Mukesh Pilaniya
  0 siblings, 0 replies; 10+ messages in thread
From: Mukesh Pilaniya @ 2026-08-19 17:47 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Mark Rutland, Huacai Chen,
	WANG Xuerui, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Andrew Morton, Baoquan He, Mike Rapoport,
	Pasha Tatashin, Pratyush Yadav, Tao Liu, Philipp Rudo
  Cc: linux-arm-kernel, linux-kernel, loongarch, linux-riscv, kexec,
	Mukesh Pilaniya

kexec_image_probe_default() overwrites ret with each loader's probe
return value and returns whatever the last loader returned when no
probe matches.  The error code reaching userspace depends on whichever
loader happens to be last in kexec_file_loaders[].

Only continue to the next loader when a probe returns -ENOEXEC.
Propagate any other error such as -ENOMEM immediately. Return -ENOEXEC
only when all loaders have been tried and none matched.

Suggested-by: Pratyush Yadav <pratyush@kernel.org>
Signed-off-by: Mukesh Pilaniya <mpilaniy@redhat.com>
---
 kernel/kexec_file.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
index 59fb9d71e9d8..b3060e984ef3 100644
--- a/kernel/kexec_file.c
+++ b/kernel/kexec_file.c
@@ -68,17 +68,19 @@ int kexec_image_probe_default(struct kimage *image, void *buf,
 			      unsigned long buf_len)
 {
 	const struct kexec_file_ops * const *fops;
-	int ret = -ENOEXEC;
 
 	for (fops = &kexec_file_loaders[0]; *fops && (*fops)->probe; ++fops) {
-		ret = (*fops)->probe(buf, buf_len);
-		if (!ret) {
+		int ret = (*fops)->probe(buf, buf_len);
+
+		if (ret == 0) {
 			image->fops = *fops;
-			return ret;
+			return 0;
 		}
+		if (ret != -ENOEXEC)
+			return ret;
 	}
 
-	return ret;
+	return -ENOEXEC;
 }
 
 static void *kexec_image_load_default(struct kimage *image)

-- 
Git-155)


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/2] kexec: return -ENOEXEC from image probe functions on mismatch
  2026-08-19 17:47   ` Mukesh Pilaniya
@ 2026-08-19 18:33     ` Bradley Morgan
  -1 siblings, 0 replies; 10+ messages in thread
From: Bradley Morgan @ 2026-08-19 18:33 UTC (permalink / raw)
  To: mpilaniy
  Cc: akpm, alex, aou, baoquan.he, catalin.marinas, chenhuacai, kernel,
	kexec, linux-arm-kernel, linux-kernel, linux-riscv, loongarch,
	ltao, mark.rutland, palmer, pasha.tatashin, pjw, pratyush, prudo,
	rppt, will

On 19 August 2026 18:47:22 BST, Mukesh Pilaniya <mpilaniy@redhat.com>
wrote:
>Several kexec_file_load() image probe functions return -EINVAL when
>they do not recognize the image format.  A probe function that rejects
>an image should return -ENOEXEC to indicate that the image is not a
>recognized executable format.  -EINVAL implies a problem with the
>syscall parameters, not with image recognition.
>
>kexec_image_probe_default() iterates through registered loaders and
>returns the last probe's error code to the caller.  That error
>propagates as the kexec_file_load() return value to userspace.
>Returning -EINVAL from a probe when no loader matches is semantically
>incorrect and misleads userspace about the nature of the failure.
>
>Return -ENOEXEC from all probe functions and their helpers when the
>image format is not recognized.
>
>Signed-off-by: Mukesh Pilaniya <mpilaniy@redhat.com>
>Reviewed-by: Philipp Rudo <prudo@redhat.com>
>Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
Reviewed-by: Bradley Morgan <include@grrlz.net>

>---
> arch/arm64/kernel/kexec_image.c   | 4 ++--
> arch/loongarch/kernel/kexec_efi.c | 4 ++--
> arch/riscv/kernel/kexec_image.c   | 4 ++--
> kernel/kexec_elf.c                | 4 ++--
> 4 files changed, 8 insertions(+), 8 deletions(-)
>
>diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
>index b70f4df15a1a..101259874d44 100644
>--- a/arch/arm64/kernel/kexec_image.c
>+++ b/arch/arm64/kernel/kexec_image.c
>@@ -25,10 +25,10 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> 		(const struct arm64_image_header *)(kernel_buf);
> 
> 	if (!h || (kernel_len < sizeof(*h)))
>-		return -EINVAL;
>+		return -ENOEXEC;
> 
> 	if (memcmp(&h->magic, ARM64_IMAGE_MAGIC, sizeof(h->magic)))
>-		return -EINVAL;
>+		return -ENOEXEC;
> 
> 	return 0;
> }
>diff --git a/arch/loongarch/kernel/kexec_efi.c b/arch/loongarch/kernel/kexec_efi.c
>index 5ee78ebb1546..28a1d0420ba3 100644
>--- a/arch/loongarch/kernel/kexec_efi.c
>+++ b/arch/loongarch/kernel/kexec_efi.c
>@@ -24,12 +24,12 @@ static int efi_kexec_probe(const char *kernel_buf, unsigned long kernel_len)
> 
> 	if (!h || (kernel_len < sizeof(*h))) {
> 		kexec_dprintk("No LoongArch image header.\n");
>-		return -EINVAL;
>+		return -ENOEXEC;
> 	}
> 
> 	if (!loongarch_header_check_dos_sig(h)) {
> 		kexec_dprintk("No LoongArch PE image header.\n");
>-		return -EINVAL;
>+		return -ENOEXEC;
> 	}
> 
> 	return 0;
>diff --git a/arch/riscv/kernel/kexec_image.c b/arch/riscv/kernel/kexec_image.c
>index 51dc89259f16..963a25f5b55b 100644
>--- a/arch/riscv/kernel/kexec_image.c
>+++ b/arch/riscv/kernel/kexec_image.c
>@@ -20,7 +20,7 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> 	const struct riscv_image_header *h = (const struct riscv_image_header *)kernel_buf;
> 
> 	if (!h || kernel_len < sizeof(*h))
>-		return -EINVAL;
>+		return -ENOEXEC;
> 
> 	/* According to Documentation/arch/riscv/boot-image-header.rst,
> 	 * use "magic2" field to check when version >= 0.2.
>@@ -28,7 +28,7 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> 
> 	if (h->version >= RISCV_HEADER_VERSION &&
> 	    memcmp(&h->magic2, RISCV_IMAGE_MAGIC2, sizeof(h->magic2)))
>-		return -EINVAL;
>+		return -ENOEXEC;
> 
> 	return 0;
> }
>diff --git a/kernel/kexec_elf.c b/kernel/kexec_elf.c
>index 3a5c25b2adc9..89a444a00693 100644
>--- a/kernel/kexec_elf.c
>+++ b/kernel/kexec_elf.c
>@@ -172,7 +172,7 @@ static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
> 
> 	default:
> 		pr_debug("Unknown ELF class.\n");
>-		return -EINVAL;
>+		return -ENOEXEC;
> 	}
> 
> 	return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
>@@ -236,7 +236,7 @@ static int elf_read_phdr(const char *buf, size_t len,
> 
> 	default:
> 		pr_debug("Unknown ELF class.\n");
>-		return -EINVAL;
>+		return -ENOEXEC;
> 	}
> 
> 	return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;
>
>

Thanks!


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/2] kexec: return -ENOEXEC from image probe functions on mismatch
@ 2026-08-19 18:33     ` Bradley Morgan
  0 siblings, 0 replies; 10+ messages in thread
From: Bradley Morgan @ 2026-08-19 18:33 UTC (permalink / raw)
  To: mpilaniy
  Cc: akpm, alex, aou, baoquan.he, catalin.marinas, chenhuacai, kernel,
	kexec, linux-arm-kernel, linux-kernel, linux-riscv, loongarch,
	ltao, mark.rutland, palmer, pasha.tatashin, pjw, pratyush, prudo,
	rppt, will

On 19 August 2026 18:47:22 BST, Mukesh Pilaniya <mpilaniy@redhat.com>
wrote:
>Several kexec_file_load() image probe functions return -EINVAL when
>they do not recognize the image format.  A probe function that rejects
>an image should return -ENOEXEC to indicate that the image is not a
>recognized executable format.  -EINVAL implies a problem with the
>syscall parameters, not with image recognition.
>
>kexec_image_probe_default() iterates through registered loaders and
>returns the last probe's error code to the caller.  That error
>propagates as the kexec_file_load() return value to userspace.
>Returning -EINVAL from a probe when no loader matches is semantically
>incorrect and misleads userspace about the nature of the failure.
>
>Return -ENOEXEC from all probe functions and their helpers when the
>image format is not recognized.
>
>Signed-off-by: Mukesh Pilaniya <mpilaniy@redhat.com>
>Reviewed-by: Philipp Rudo <prudo@redhat.com>
>Reviewed-by: Pratyush Yadav <pratyush@kernel.org>
Reviewed-by: Bradley Morgan <include@grrlz.net>

>---
> arch/arm64/kernel/kexec_image.c   | 4 ++--
> arch/loongarch/kernel/kexec_efi.c | 4 ++--
> arch/riscv/kernel/kexec_image.c   | 4 ++--
> kernel/kexec_elf.c                | 4 ++--
> 4 files changed, 8 insertions(+), 8 deletions(-)
>
>diff --git a/arch/arm64/kernel/kexec_image.c b/arch/arm64/kernel/kexec_image.c
>index b70f4df15a1a..101259874d44 100644
>--- a/arch/arm64/kernel/kexec_image.c
>+++ b/arch/arm64/kernel/kexec_image.c
>@@ -25,10 +25,10 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> 		(const struct arm64_image_header *)(kernel_buf);
> 
> 	if (!h || (kernel_len < sizeof(*h)))
>-		return -EINVAL;
>+		return -ENOEXEC;
> 
> 	if (memcmp(&h->magic, ARM64_IMAGE_MAGIC, sizeof(h->magic)))
>-		return -EINVAL;
>+		return -ENOEXEC;
> 
> 	return 0;
> }
>diff --git a/arch/loongarch/kernel/kexec_efi.c b/arch/loongarch/kernel/kexec_efi.c
>index 5ee78ebb1546..28a1d0420ba3 100644
>--- a/arch/loongarch/kernel/kexec_efi.c
>+++ b/arch/loongarch/kernel/kexec_efi.c
>@@ -24,12 +24,12 @@ static int efi_kexec_probe(const char *kernel_buf, unsigned long kernel_len)
> 
> 	if (!h || (kernel_len < sizeof(*h))) {
> 		kexec_dprintk("No LoongArch image header.\n");
>-		return -EINVAL;
>+		return -ENOEXEC;
> 	}
> 
> 	if (!loongarch_header_check_dos_sig(h)) {
> 		kexec_dprintk("No LoongArch PE image header.\n");
>-		return -EINVAL;
>+		return -ENOEXEC;
> 	}
> 
> 	return 0;
>diff --git a/arch/riscv/kernel/kexec_image.c b/arch/riscv/kernel/kexec_image.c
>index 51dc89259f16..963a25f5b55b 100644
>--- a/arch/riscv/kernel/kexec_image.c
>+++ b/arch/riscv/kernel/kexec_image.c
>@@ -20,7 +20,7 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> 	const struct riscv_image_header *h = (const struct riscv_image_header *)kernel_buf;
> 
> 	if (!h || kernel_len < sizeof(*h))
>-		return -EINVAL;
>+		return -ENOEXEC;
> 
> 	/* According to Documentation/arch/riscv/boot-image-header.rst,
> 	 * use "magic2" field to check when version >= 0.2.
>@@ -28,7 +28,7 @@ static int image_probe(const char *kernel_buf, unsigned long kernel_len)
> 
> 	if (h->version >= RISCV_HEADER_VERSION &&
> 	    memcmp(&h->magic2, RISCV_IMAGE_MAGIC2, sizeof(h->magic2)))
>-		return -EINVAL;
>+		return -ENOEXEC;
> 
> 	return 0;
> }
>diff --git a/kernel/kexec_elf.c b/kernel/kexec_elf.c
>index 3a5c25b2adc9..89a444a00693 100644
>--- a/kernel/kexec_elf.c
>+++ b/kernel/kexec_elf.c
>@@ -172,7 +172,7 @@ static int elf_read_ehdr(const char *buf, size_t len, struct elfhdr *ehdr)
> 
> 	default:
> 		pr_debug("Unknown ELF class.\n");
>-		return -EINVAL;
>+		return -ENOEXEC;
> 	}
> 
> 	return elf_is_ehdr_sane(ehdr, len) ? 0 : -ENOEXEC;
>@@ -236,7 +236,7 @@ static int elf_read_phdr(const char *buf, size_t len,
> 
> 	default:
> 		pr_debug("Unknown ELF class.\n");
>-		return -EINVAL;
>+		return -ENOEXEC;
> 	}
> 
> 	return elf_is_phdr_sane(phdr, len) ? 0 : -ENOEXEC;
>
>

Thanks!

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 2/2] kexec: fix error propagation in kexec_image_probe_default()
  2026-08-19 17:47   ` Mukesh Pilaniya
@ 2026-08-20 12:21     ` Philipp Rudo
  -1 siblings, 0 replies; 10+ messages in thread
From: Philipp Rudo @ 2026-08-20 12:21 UTC (permalink / raw)
  To: Mukesh Pilaniya
  Cc: Catalin Marinas, Will Deacon, Mark Rutland, Huacai Chen,
	WANG Xuerui, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Andrew Morton, Baoquan He, Mike Rapoport,
	Pasha Tatashin, Pratyush Yadav, Tao Liu, linux-arm-kernel,
	linux-kernel, loongarch, linux-riscv, kexec

Hi Mukesh,
Hi Pratyush,

having this patch makes sense. Personally I'd go with having a
switch-case rather than individual if-blocks. E.g.

	switch (ret) {
		case 0:
			image->fops = *fops;
			return 0;
		case -ENOEXEC:
			continue;
		default:
			return ret;
	}

IMHO that is better readable and easier to extend in case other error
codes need special handling as well. But that is only my personal
opinion.

Independent on which implementation you use.

Reviewed-by: Philipp Rudo <prudo@redhat.com>


On Wed, 19 Aug 2026 23:17:23 +0530
Mukesh Pilaniya <mpilaniy@redhat.com> wrote:

> kexec_image_probe_default() overwrites ret with each loader's probe
> return value and returns whatever the last loader returned when no
> probe matches.  The error code reaching userspace depends on whichever
> loader happens to be last in kexec_file_loaders[].
> 
> Only continue to the next loader when a probe returns -ENOEXEC.
> Propagate any other error such as -ENOMEM immediately. Return -ENOEXEC
> only when all loaders have been tried and none matched.
> 
> Suggested-by: Pratyush Yadav <pratyush@kernel.org>
> Signed-off-by: Mukesh Pilaniya <mpilaniy@redhat.com>
> ---
>  kernel/kexec_file.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> index 59fb9d71e9d8..b3060e984ef3 100644
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -68,17 +68,19 @@ int kexec_image_probe_default(struct kimage *image, void *buf,
>  			      unsigned long buf_len)
>  {
>  	const struct kexec_file_ops * const *fops;
> -	int ret = -ENOEXEC;
>  
>  	for (fops = &kexec_file_loaders[0]; *fops && (*fops)->probe; ++fops) {
> -		ret = (*fops)->probe(buf, buf_len);
> -		if (!ret) {
> +		int ret = (*fops)->probe(buf, buf_len);
> +
> +		if (ret == 0) {
>  			image->fops = *fops;
> -			return ret;
> +			return 0;
>  		}
> +		if (ret != -ENOEXEC)
> +			return ret;
>  	}
>  
> -	return ret;
> +	return -ENOEXEC;
>  }
>  
>  static void *kexec_image_load_default(struct kimage *image)
> 


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 2/2] kexec: fix error propagation in kexec_image_probe_default()
@ 2026-08-20 12:21     ` Philipp Rudo
  0 siblings, 0 replies; 10+ messages in thread
From: Philipp Rudo @ 2026-08-20 12:21 UTC (permalink / raw)
  To: Mukesh Pilaniya
  Cc: Catalin Marinas, Will Deacon, Mark Rutland, Huacai Chen,
	WANG Xuerui, Paul Walmsley, Palmer Dabbelt, Albert Ou,
	Alexandre Ghiti, Andrew Morton, Baoquan He, Mike Rapoport,
	Pasha Tatashin, Pratyush Yadav, Tao Liu, linux-arm-kernel,
	linux-kernel, loongarch, linux-riscv, kexec

Hi Mukesh,
Hi Pratyush,

having this patch makes sense. Personally I'd go with having a
switch-case rather than individual if-blocks. E.g.

	switch (ret) {
		case 0:
			image->fops = *fops;
			return 0;
		case -ENOEXEC:
			continue;
		default:
			return ret;
	}

IMHO that is better readable and easier to extend in case other error
codes need special handling as well. But that is only my personal
opinion.

Independent on which implementation you use.

Reviewed-by: Philipp Rudo <prudo@redhat.com>


On Wed, 19 Aug 2026 23:17:23 +0530
Mukesh Pilaniya <mpilaniy@redhat.com> wrote:

> kexec_image_probe_default() overwrites ret with each loader's probe
> return value and returns whatever the last loader returned when no
> probe matches.  The error code reaching userspace depends on whichever
> loader happens to be last in kexec_file_loaders[].
> 
> Only continue to the next loader when a probe returns -ENOEXEC.
> Propagate any other error such as -ENOMEM immediately. Return -ENOEXEC
> only when all loaders have been tried and none matched.
> 
> Suggested-by: Pratyush Yadav <pratyush@kernel.org>
> Signed-off-by: Mukesh Pilaniya <mpilaniy@redhat.com>
> ---
>  kernel/kexec_file.c | 12 +++++++-----
>  1 file changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> index 59fb9d71e9d8..b3060e984ef3 100644
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -68,17 +68,19 @@ int kexec_image_probe_default(struct kimage *image, void *buf,
>  			      unsigned long buf_len)
>  {
>  	const struct kexec_file_ops * const *fops;
> -	int ret = -ENOEXEC;
>  
>  	for (fops = &kexec_file_loaders[0]; *fops && (*fops)->probe; ++fops) {
> -		ret = (*fops)->probe(buf, buf_len);
> -		if (!ret) {
> +		int ret = (*fops)->probe(buf, buf_len);
> +
> +		if (ret == 0) {
>  			image->fops = *fops;
> -			return ret;
> +			return 0;
>  		}
> +		if (ret != -ENOEXEC)
> +			return ret;
>  	}
>  
> -	return ret;
> +	return -ENOEXEC;
>  }
>  
>  static void *kexec_image_load_default(struct kimage *image)
> 


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-08-20 12:21 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-19 17:47 [PATCH v2 0/2] kexec: fix probe error codes and error propagation Mukesh Pilaniya
2026-08-19 17:47 ` Mukesh Pilaniya
2026-08-19 17:47 ` [PATCH v2 1/2] kexec: return -ENOEXEC from image probe functions on mismatch Mukesh Pilaniya
2026-08-19 17:47   ` Mukesh Pilaniya
2026-08-19 18:33   ` Bradley Morgan
2026-08-19 18:33     ` Bradley Morgan
2026-08-19 17:47 ` [PATCH v2 2/2] kexec: fix error propagation in kexec_image_probe_default() Mukesh Pilaniya
2026-08-19 17:47   ` Mukesh Pilaniya
2026-08-20 12:21   ` Philipp Rudo
2026-08-20 12:21     ` Philipp Rudo

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.