untrusted comment: verify with openbsd-79-base.pub
RWTSdNN9A3yvWEfNlP0MAvvm7T8p5+RSAZdvhVXGxdubTyTECmmSNRvT2O2Hlss0edqo5PCjvKFEF/gJn+kixLctF8XKGFmdoQ8=

OpenBSD 7.9 errata 004, July 16, 2026:

Fix some info leaks, kernel crashes, and pinsyscall(8) / kbind(8)
locking failures.

Apply by doing:
    signify -Vep /etc/signify/openbsd-79-base.pub -x 004_elf.patch.sig \
        -m - | (cd /usr/src && patch -p0)

And then rebuild and install a new kernel:
    KK=`sysctl -n kern.osversion | cut -d# -f1`
    cd /usr/src/sys/arch/`machine`/compile/$KK
    make obj
    make config
    make
    make install

Index: sys/kern/exec_elf.c
===================================================================
RCS file: /cvs/src/sys/kern/exec_elf.c,v
diff -u -p -r1.196 exec_elf.c
--- sys/kern/exec_elf.c	11 Apr 2026 16:12:40 -0000	1.196
+++ sys/kern/exec_elf.c	10 Jul 2026 11:22:00 -0000
@@ -88,7 +88,6 @@
 #include <uvm/uvm_extern.h>
 
 #include <machine/reg.h>
-#include <machine/exec.h>
 #include <machine/elf.h>
 
 int	elf_load_file(struct proc *, char *, struct exec_package *,
@@ -357,7 +356,7 @@ elf_load_file(struct proc *p, char *path
 	} loadmap[ELF_MAX_VALID_PHDR];
 	int nload, idx = 0;
 	Elf_Addr pos;
-	int file_align;
+	Elf_Off file_align = PAGE_SIZE;
 	int loop;
 	size_t randomizequota = ELF_RANDOMIZE_LIMIT;
 	vaddr_t text_start = -1, text_end = 0;
@@ -410,11 +409,16 @@ elf_load_file(struct proc *p, char *path
 			loadmap[idx].vaddr = trunc_page(ph[i].p_vaddr);
 			loadmap[idx].memsz = round_page (ph[i].p_vaddr +
 			    ph[i].p_memsz - loadmap[idx].vaddr);
-			file_align = ph[i].p_align;
+			if (ph[i].p_align > file_align)
+				file_align = ph[i].p_align;
 			idx++;
 		}
 	}
 	nload = idx;
+	if (nload == 0) {
+		error = EINVAL;
+		goto bad1;
+	}
 
 	/*
 	 * Load the interpreter where a non-fixed mmap(NULL, ...)
@@ -737,10 +741,6 @@ exec_elf_makecmds(struct proc *p, struct
 			} else
 				addr = ELF_NO_ADDR;
 
-			/* Static binaries may not call pinsyscalls() */
-			if (interp == NULL)
-				p->p_vmspace->vm_map.flags |= VM_MAP_PINSYSCALL_ONCE;
-
 			/*
 			 * Calculates size of text and data segments
 			 * by starting at first and going to end of last.
@@ -943,17 +943,19 @@ exec_elf_fixup(struct proc *p, struct ex
 	struct	elf_args *ap;
 	AuxInfo ai[ELF_AUX_ENTRIES], *a;
 
+	interp = epp->ep_interp;
+
+	/* disable kbind() and pinsyscalls() in programs that don't use ld.so */
+	if (interp == NULL) {
+		p->p_p->ps_kbind_addr = BOGO_PC;
+		p->p_vmspace->vm_map.flags |= VM_MAP_PINSYSCALL_ONCE;
+	}
+
 	ap = epp->ep_args;
 	if (ap == NULL) {
 		return (0);
 	}
 
-	interp = epp->ep_interp;
-
-	/* disable kbind in programs that don't use ld.so */
-	if (interp == NULL)
-		p->p_p->ps_kbind_addr = BOGO_PC;
-
 	if (interp &&
 	    (error = elf_load_file(p, interp, epp, ap)) != 0) {
 		free(ap, M_TEMP, sizeof *ap);
@@ -1037,7 +1039,7 @@ elf_os_pt_note_name(Elf_Note *np, int *t
 
 	for (i = 0; i < nitems(elf_note_names); i++) {
 		size_t namlen = strlen(elf_note_names[i].name);
-		if (np->namesz < namlen)
+		if (np->namesz <= namlen)
 			continue;
 		/* verify name padding (after the NUL) is NUL */
 		for (j = namlen + 1; j < elfround(np->namesz); j++)
@@ -1095,14 +1097,26 @@ elf_os_pt_note(struct proc *p, struct ex
 
 		for (offset = 0; offset < ph->p_filesz; offset += total) {
 			Elf_Note *np2 = (Elf_Note *)((char *)np + offset);
+			size_t remaining = ph->p_filesz - offset;
 			int name, type;
 
-			if (offset + sizeof(Elf_Note) > ph->p_filesz)
+			if (sizeof(Elf_Note) > remaining)
+				break;
+			remaining -= sizeof(Elf_Note);
+
+			if (elfround(np2->namesz) < np2->namesz ||
+			    elfround(np2->descsz) < np2->descsz)
 				break;
+
+			if (elfround(np2->namesz) > remaining)
+				break;
+			remaining -= elfround(np2->namesz);
+			if (elfround(np2->descsz) > remaining)
+				break;
+			remaining -= elfround(np2->descsz);
+
 			total = sizeof(Elf_Note) + elfround(np2->namesz) +
 			    elfround(np2->descsz);
-			if (offset + total > ph->p_filesz)
-				break;
 			name = elf_os_pt_note_name(np2, &type);
 			if (name == ELF_NOTE_NAME_OPENBSD &&
 			    type == NT_OPENBSD_PROF)
@@ -1555,6 +1569,7 @@ coredump_note_elf(struct proc *p, void *
 
 	notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(intreg));
 	if (iocookie) {
+		memset(&intreg, 0, sizeof(intreg));
 		error = process_read_regs(p, &intreg);
 		if (error)
 			return (error);
@@ -1574,6 +1589,7 @@ coredump_note_elf(struct proc *p, void *
 #ifdef PT_GETFPREGS
 	notesize = sizeof(nhdr) + elfround(namesize) + elfround(sizeof(freg));
 	if (iocookie) {
+		memset(&freg, 0, sizeof(freg));
 		error = process_read_fpregs(p, &freg);
 		if (error)
 			return (error);
Index: sys/kern/kern_exec.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_exec.c,v
diff -u -p -r1.268 kern_exec.c
--- sys/kern/kern_exec.c	16 Sep 2025 12:15:06 -0000	1.268
+++ sys/kern/kern_exec.c	10 Jul 2026 11:22:00 -0000
@@ -90,11 +90,31 @@ int exec_sigcode_map(struct process *);
 int exec_timekeep_map(struct process *);
 
 /*
+ * Free exec-package allocations owned by image-format loaders.
+ */
+void exec_free_package(struct exec_package *);
+
+/*
  * If non-zero, stackgap_random specifies the upper limit of the random gap size
  * added to the fixed stack position. Must be n^2.
  */
 int stackgap_random = STACKGAP_RANDOM;
 
+void
+exec_free_package(struct exec_package *pack)
+{
+	if (pack->ep_interp != NULL) {
+		pool_put(&namei_pool, pack->ep_interp);
+		pack->ep_interp = NULL;
+	}
+	free(pack->ep_args, M_TEMP, sizeof(*pack->ep_args));
+	pack->ep_args = NULL;
+	free(pack->ep_pins, M_PINSYSCALL,
+	    pack->ep_npins * sizeof(*pack->ep_pins));
+	pack->ep_pins = NULL;
+	pack->ep_npins = 0;
+}
+
 /*
  * check exec:
  * given an "executable" described in the exec package's namei info,
@@ -222,6 +242,7 @@ check_exec(struct proc *p, struct exec_p
 	 * and release their references
 	 */
 	kill_vmcmds(&epp->ep_vmcmds);
+	exec_free_package(epp);
 
 bad2:
 	/*
@@ -586,10 +607,7 @@ sys_execve(struct proc *p, void *v, regi
 		atomic_clearbits_int(&pr->ps_flags, PS_PLEDGE);
 		p->p_pledge = 0;
 		pr->ps_pledge = 0;
-		/* XXX XXX XXX XXX */
-		/* Clear our unveil paths out so the child
-		 * starts afresh
-		 */
+		/* Clear our unveil paths out so the child starts afresh */
 		unveil_destroy(pr);
 		pr->ps_uvdone = 0;
 	}
@@ -767,10 +785,7 @@ bad:
 		/* fdrelease unlocks p->p_fd. */
 		(void) fdrelease(p, pack.ep_fd);
 	}
-	if (pack.ep_interp != NULL)
-		pool_put(&namei_pool, pack.ep_interp);
-	free(pack.ep_args, M_TEMP, sizeof *pack.ep_args);
-	free(pack.ep_pins, M_PINSYSCALL, pack.ep_npins * sizeof(u_int));
+	exec_free_package(&pack);
 	/* close and put the exec'd file */
 	vn_close(pack.ep_vp, FREAD, cred, p);
 	pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf);
@@ -790,9 +805,7 @@ exec_abort:
 	 * of our namei data and vnode, and exit noting failure
 	 */
 	uvm_unmap(&vm->vm_map, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS);
-	if (pack.ep_interp != NULL)
-		pool_put(&namei_pool, pack.ep_interp);
-	free(pack.ep_args, M_TEMP, sizeof *pack.ep_args);
+	exec_free_package(&pack);
 	pool_put(&namei_pool, nid.ni_cnd.cn_pnbuf);
 	vn_close(pack.ep_vp, FREAD, cred, p);
 	km_free(argp, NCARGS, &kv_exec, &kp_pageable);
