git: 844ed4975ace - stable/14 - iuserboot: bump the interface to v6, add an accept_interpreter callback

From: Kyle Evans <kevans_at_FreeBSD.org>
Date: Sat, 24 Oct 2026 01:18:23 UTC
The branch stable/14 has been updated by kevans:

URL: https://cgit.FreeBSD.org/src/commit/?id=844ed4975aced639f431a1a19176f449466584f1

commit 844ed4975aced639f431a1a19176f449466584f1
Author:     Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2026-09-04 15:26:35 +0000
Commit:     Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2026-10-23 02:52:52 +0000

    iuserboot: bump the interface to v6, add an accept_interpreter callback
    
    If an explicit loader wasn't requested, then bhyveload(8) maintains a
    /boot handle that it can use for swapping to a different flavor.  This
    means that we expose all of the host /boot to the sandbox for the
    duration of script execution.
    
    Add a callback to ack that we're OK with the interpreter so that
    bhyveload(8) can release the bootfd.  This is worth doing because it's
    prior to guest script execution, so we're still running a reasonably
    untainted process.
    
    Reviewed by:    imp, jhb
    
    (cherry picked from commit 619d09217720cb82f562b51e98576438dc11c830)
---
 stand/userboot/userboot.h      | 12 ++++++++++++
 stand/userboot/userboot/main.c |  2 ++
 usr.sbin/bhyveload/bhyveload.c | 23 ++++++++++++++++++-----
 3 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/stand/userboot/userboot.h b/stand/userboot/userboot.h
index 34e8cb1d4bb2..1204f5e87f6f 100644
--- a/stand/userboot/userboot.h
+++ b/stand/userboot/userboot.h
@@ -46,6 +46,13 @@
  */
 #define	USERBOOT_VERSION_5      5
 
+/*
+ * Version 6 added a callback for indicating that the guest
+ * is OK with the existing interpreter, so the host can close associated
+ * resources.  The callback structure is still backward compatible.
+ */
+#define	USERBOOT_VERSION_6      6
+
 /*
  * Exit codes from the loader
  */
@@ -225,4 +232,9 @@ struct loader_callbacks {
 	 * Version 5 addition.
 	 */
 	void	(*swap_interpreter)(void *arg, const char *interp);
+
+	/*
+	 * Version 6 addition.
+	 */
+	void	(*accept_interpreter)(void *arg);
 };
diff --git a/stand/userboot/userboot/main.c b/stand/userboot/userboot/main.c
index a3da1b0bfcba..12bec50774ac 100644
--- a/stand/userboot/userboot/main.c
+++ b/stand/userboot/userboot/main.c
@@ -212,6 +212,8 @@ loader_main(struct loader_callbacks *cb, void *arg, int version, int ndisks)
 	 */
 	if (version >= USERBOOT_VERSION_5)
 		check_interpreter();
+	if (version >= USERBOOT_VERSION_6)
+		CALLBACK(accept_interpreter);
 
 	if (setjmp(jb))
 		return;
diff --git a/usr.sbin/bhyveload/bhyveload.c b/usr.sbin/bhyveload/bhyveload.c
index 3f29d642461d..ebc6f9618691 100644
--- a/usr.sbin/bhyveload/bhyveload.c
+++ b/usr.sbin/bhyveload/bhyveload.c
@@ -102,6 +102,7 @@ enum {
 static struct termios term, oldterm;
 static int disk_fd[NDISKS];
 static int ndisks;
+static int bootfd = -1;
 static int consin_fd, consout_fd;
 static int hostbase_fd = -1;
 
@@ -652,6 +653,16 @@ cb_swap_interpreter(void *arg __unused, const char *interp_req)
 	longjmp(jb, JMP_SWAPLOADER);
 }
 
+static void
+cb_accept_interpreter(void *arg __unused)
+{
+	if (bootfd == -1)
+		return;
+
+	close(bootfd);
+	bootfd = -1;
+}
+
 static struct loader_callbacks cb = {
 	.getc = cb_getc,
 	.putc = cb_putc,
@@ -689,6 +700,9 @@ static struct loader_callbacks cb = {
 
 	/* Version 5 additions */
 	.swap_interpreter = cb_swap_interpreter,
+
+	/* Version 6 additions */
+	.accept_interpreter = cb_accept_interpreter,
 };
 
 static int
@@ -790,7 +804,7 @@ hostbase_open(const char *base)
 }
 
 static void
-loader_open(int bootfd)
+loader_open(void)
 {
 	int fd;
 
@@ -820,9 +834,8 @@ main(int argc, char** argv)
 {
 	void (*func)(struct loader_callbacks *, void *, int, int);
 	uint64_t mem_size;
-	int bootfd, opt, error, memflags, need_reinit;
+	int opt, error, memflags, need_reinit;
 
-	bootfd = -1;
 	progname = basename(argv[0]);
 
 	memflags = 0;
@@ -950,7 +963,7 @@ main(int argc, char** argv)
 	if (error)
 		err(1, "vm_setup_memory");
 
-	loader_open(bootfd);
+	loader_open();
 	func = dlsym(loader_hdl, "loader_main");
 	if (!func)
 		errx(1, "dlsym: %s", dlerror());
@@ -965,7 +978,7 @@ main(int argc, char** argv)
 	addenv("smbios.bios.vendor=BHYVE");
 	addenv("boot_serial=1");
 
-	func(&cb, NULL, USERBOOT_VERSION_5, ndisks);
+	func(&cb, NULL, USERBOOT_VERSION_6, ndisks);
 
 	free(loader);
 	return (0);