git: 389c124fecb0 - main - imgact_elf.c indicate that interpreter is an interpreter

From: Simon J. Gerraty <sjg_at_FreeBSD.org>
Date: Fri, 19 Jun 2026 20:22:54 UTC
The branch main has been updated by sjg:

URL: https://cgit.FreeBSD.org/src/commit/?id=389c124fecb04cf6ae2b0f8ab1047c19badec40c

commit 389c124fecb04cf6ae2b0f8ab1047c19badec40c
Author:     Simon J. Gerraty <sjg@FreeBSD.org>
AuthorDate: 2026-06-19 20:21:46 +0000
Commit:     Simon J. Gerraty <sjg@FreeBSD.org>
CommitDate: 2026-06-19 20:21:46 +0000

    imgact_elf.c indicate that interpreter is an interpreter
    
    Use a value that do_execve will ignore since there's nothing there to do.
    With this we can set the 'indirect' flag on rtld, to prevent direct execution
    being used to bypass the 'indirect' flag on python3:
    
    root@vuefi:~ # /libexec/ld-elf32.so.1 /usr/bin/python3 -c 'print("pwned")'
    pwned
    root@vuefi:~ # veriexec -z enforce
    root@vuefi:~ # /libexec/ld-elf32.so.1 /usr/bin/python3 -c 'print("pwned")'
    /libexec/ld-elf32.so.1: Operation not permitted.
    root@vuefi:~ #
    
    load_file seems missnamed since it is only used by load_interp
    so rename it to load_interp_file.
    
    Reviewed by:    imp
    Sponsored by:   Hewlett Packard Enterprise Development LP
    Differential Revision:  https://reviews.freebsd.org/D57649
---
 sys/kern/imgact_elf.c | 11 ++++++-----
 sys/kern/kern_exec.c  |  3 ++-
 sys/sys/imgact.h      |  1 +
 3 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 65e0e6089dca..a0dc96e74ed6 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -94,7 +94,7 @@
 static int __elfN(check_header)(const Elf_Ehdr *hdr);
 static const Elf_Brandinfo *__elfN(get_brandinfo)(struct image_params *imgp,
     const Elf_Phdr *phdr, const char *interp, int32_t *osrel, uint32_t *fctl0);
-static int __elfN(load_file)(struct thread *td, const char *file, u_long *addr,
+static int __elfN(load_interp_file)(struct thread *td, const char *file, u_long *addr,
     u_long *entry);
 static int __elfN(load_section)(const struct image_params *imgp,
     vm_ooffset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz,
@@ -785,7 +785,7 @@ __elfN(load_sections)(const struct image_params *imgp, const Elf_Ehdr *hdr,
  * the entry point for the loaded file.
  */
 static int
-__elfN(load_file)(struct thread *td, const char *file, u_long *addr,
+__elfN(load_interp_file)(struct thread *td, const char *file, u_long *addr,
     u_long *entry)
 {
 	struct {
@@ -823,7 +823,8 @@ __elfN(load_file)(struct thread *td, const char *file, u_long *addr,
 	imgp->td = td;
 	imgp->proc = td->td_proc;
 	imgp->attr = attr;
-
+	imgp->interpreted = IMGACT_INTERP_IGNORE; /* ignored by do_execve */
+	
 	NDINIT(nd, LOOKUP, ISOPEN | FOLLOW | LOCKSHARED | LOCKLEAF,
 	    UIO_SYSSPACE, file);
 	if ((error = namei(nd)) != 0) {
@@ -1092,13 +1093,13 @@ __elfN(load_interp)(struct image_params *imgp, const Elf_Brandinfo *brand_info,
 	if (brand_info->interp_newpath != NULL &&
 	    (brand_info->interp_path == NULL ||
 	    strcmp(interp, brand_info->interp_path) == 0)) {
-		error = __elfN(load_file)(imgp->td,
+		error = __elfN(load_interp_file)(imgp->td,
 		    brand_info->interp_newpath, addr, entry);
 		if (error == 0)
 			return (0);
 	}
 
-	error = __elfN(load_file)(imgp->td, interp, addr, entry);
+	error = __elfN(load_interp_file)(imgp->td, interp, addr, entry);
 	if (error == 0)
 		return (0);
 
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 8ea00543989e..de6d8b08cec3 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -678,7 +678,8 @@ interpret:
 	 * Special interpreter operation, cleanup and loop up to try to
 	 * activate the interpreter.
 	 */
-	if (imgp->interpreted) {
+	if (imgp->interpreted != 0 &&
+	    imgp->interpreted != IMGACT_INTERP_IGNORE) {
 		exec_unmap_first_page(imgp);
 		/*
 		 * The text reference needs to be removed for scripts.
diff --git a/sys/sys/imgact.h b/sys/sys/imgact.h
index 51cda4406cad..f99b1273ee02 100644
--- a/sys/sys/imgact.h
+++ b/sys/sys/imgact.h
@@ -86,6 +86,7 @@ struct image_params {
 	struct ucred *newcred;		/* new credentials if changing */
 #define IMGACT_SHELL	0x1
 #define IMGACT_BINMISC	0x2
+#define IMGACT_INTERP_IGNORE 0x3
 	unsigned char interpreted;	/* mask of interpreters that have run */
 	bool credential_setid;		/* true if becoming setid */
 	bool vmspace_destroyed;		/* we've blown away original vm space */