The branch main has been updated by novel: URL: https://cgit.FreeBSD.org/src/commit/?id=ed7e0ebfa20e7e798d2e4e20623d452f1c715aa5
commit ed7e0ebfa20e7e798d2e4e20623d452f1c715aa5 Author: Roman Bogorodskiy <[email protected]> AuthorDate: 2026-06-07 07:31:30 +0000 Commit: Roman Bogorodskiy <[email protected]> CommitDate: 2026-07-08 16:10:14 +0000 bhyve: allow overriding snapshot socket directory By default bhyve(8) creates a snapshot socket in "/var/run/bhyve/" (BHYVE_RUN_DIR). As this is a system directory not writable by users, this does not work when bhyve(8) is being started as a non-root user. Address that by allowing to override this directory. In bhyve(8) it is done by setting 'rundir' option with '-o rundir=<path>'. In bhyvectl(8) it is done with '--rundir=<path>'. MFC after: 1 month Reviewed by: bcr (manpages), bnovkov Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D57494 --- usr.sbin/bhyve/amd64/bhyverun_machdep.c | 6 ++++++ usr.sbin/bhyve/bhyve_config.5 | 9 ++++++++- usr.sbin/bhyve/bhyverun.c | 2 +- usr.sbin/bhyve/snapshot.c | 14 ++++++++++---- usr.sbin/bhyve/snapshot.h | 2 +- usr.sbin/bhyvectl/bhyvectl.8 | 8 +++++++- usr.sbin/bhyvectl/bhyvectl.c | 32 +++++++++++++++++++++++++------- 7 files changed, 58 insertions(+), 15 deletions(-) diff --git a/usr.sbin/bhyve/amd64/bhyverun_machdep.c b/usr.sbin/bhyve/amd64/bhyverun_machdep.c index 98a756551272..2c8f825b4a7c 100644 --- a/usr.sbin/bhyve/amd64/bhyverun_machdep.c +++ b/usr.sbin/bhyve/amd64/bhyverun_machdep.c @@ -37,6 +37,9 @@ #include "acpi.h" #include "atkbdc.h" #include "bhyverun.h" +#ifdef BHYVE_SNAPSHOT +#include "snapshot.h" +#endif #include "bootrom.h" #include "config.h" #include "debug.h" @@ -65,6 +68,9 @@ bhyve_init_config(void) set_config_bool("x86.strictmsr", true); set_config_bool("x86.verbosemsr", false); set_config_value("lpc.fwcfg", "bhyve"); +#ifdef BHYVE_SNAPSHOT + set_config_value("rundir", BHYVE_RUN_DIR); +#endif } void diff --git a/usr.sbin/bhyve/bhyve_config.5 b/usr.sbin/bhyve/bhyve_config.5 index 8bfe9afd0b24..dd82bea61d20 100644 --- a/usr.sbin/bhyve/bhyve_config.5 +++ b/usr.sbin/bhyve/bhyve_config.5 @@ -24,7 +24,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd December 26, 2025 +.Dd July 8, 2026 .Dt BHYVE_CONFIG 5 .Os .Sh NAME @@ -226,6 +226,13 @@ This value is used for the guest's System Management BIOS System Information str Stock keeping unit of the chassis. It's also called product ID or purchase order number. This value is used for the guest's System Management BIOS System Information structure. +.It Va rundir Ta String Ta Pa /var/run/bhyve/ Ta +Path to the runtime directory for +.Xr bhyve 8 +to store its service files, such as the checkpoint socket. +Overriding this path is useful when running +.Xr bhyve 8 +as an unprivileged user. .El .Ss x86-Specific Settings .Bl -column "x86.vmexit_on_pause" "integer" "Default" diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index 8cbc19fcfef8..ace631594544 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -1068,7 +1068,7 @@ main(int argc, char *argv[]) /* * checkpointing thread for communication with bhyvectl */ - if (init_checkpoint_thread(ctx) != 0) + if (init_checkpoint_thread(ctx, get_config_value("rundir")) != 0) errx(EX_OSERR, "Failed to start checkpoint thread"); #endif diff --git a/usr.sbin/bhyve/snapshot.c b/usr.sbin/bhyve/snapshot.c index 5b941984c0c0..fdb5941bf1d0 100644 --- a/usr.sbin/bhyve/snapshot.c +++ b/usr.sbin/bhyve/snapshot.c @@ -1399,13 +1399,13 @@ IPC_COMMAND(ipc_cmd_set, checkpoint, vm_do_checkpoint); * Create the listening socket for IPC with bhyvectl */ int -init_checkpoint_thread(struct vmctx *ctx) +init_checkpoint_thread(struct vmctx *ctx, const char *bhyve_run_dir) { struct checkpoint_thread_info *checkpoint_info = NULL; struct sockaddr_un addr; int socket_fd; pthread_t checkpoint_pthread; - int err; + int err, ret; #ifndef WITHOUT_CAPSICUM cap_rights_t rights; #endif @@ -1421,8 +1421,14 @@ init_checkpoint_thread(struct vmctx *ctx) addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s%s", - BHYVE_RUN_DIR, vm_get_name(ctx)); + ret = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", + bhyve_run_dir, vm_get_name(ctx)); + if ((ret < 0) || ((size_t)ret >= sizeof(addr.sun_path))) { + EPRINTLN("%s: error setting socket path (%d)", __func__, ret); + err = -1; + goto fail; + } + addr.sun_len = SUN_LEN(&addr); unlink(addr.sun_path); diff --git a/usr.sbin/bhyve/snapshot.h b/usr.sbin/bhyve/snapshot.h index 8bebdafd6117..5c71640f3f09 100644 --- a/usr.sbin/bhyve/snapshot.h +++ b/usr.sbin/bhyve/snapshot.h @@ -99,7 +99,7 @@ int vm_resume_devices(void); int get_checkpoint_msg(int conn_fd, struct vmctx *ctx); void *checkpoint_thread(void *param); -int init_checkpoint_thread(struct vmctx *ctx); +int init_checkpoint_thread(struct vmctx *ctx, const char *bhyve_run_dir); int load_restore_file(const char *filename, struct restore_state *rstate); diff --git a/usr.sbin/bhyvectl/bhyvectl.8 b/usr.sbin/bhyvectl/bhyvectl.8 index 550c4f10d8e6..b999230cfd73 100644 --- a/usr.sbin/bhyvectl/bhyvectl.8 +++ b/usr.sbin/bhyvectl/bhyvectl.8 @@ -25,7 +25,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd May 8, 2025 +.Dd July 8, 2026 .Dt BHYVECTL 8 .Os .Sh NAME @@ -41,6 +41,7 @@ .Op Fl -force-reset .Op Fl -force-poweroff .Op Fl -checkpoint= Ns Ar <file> +.Op Fl -rundir= Ns Ar <path> .Op Fl -suspend= Ns Ar <file> .Sh DESCRIPTION The @@ -77,6 +78,11 @@ Save a snapshot of a virtual machine similar to .Fl -checkpoint . The virtual machine will terminate after the snapshot has been saved. +.It Fl -rundir= Ns Ar <path> +Specify path to the directory containing the checkpoint socket. +If not specified, +.Pa /var/run/bhyve +is used. .El .Pp .Em Note : diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c index 96768383d4ca..b63cd5dc8c6e 100644 --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -86,6 +86,7 @@ enum { #ifdef BHYVE_SNAPSHOT SET_CHECKPOINT_FILE, SET_SUSPEND_FILE, + SET_RUNDIR, #endif OPT_LAST, }; @@ -138,6 +139,7 @@ setup_options(void) #ifdef BHYVE_SNAPSHOT { "checkpoint", REQ_ARG, 0, SET_CHECKPOINT_FILE}, { "suspend", REQ_ARG, 0, SET_SUSPEND_FILE}, + { "rundir", REQ_ARG, 0, SET_RUNDIR}, #endif }; @@ -155,6 +157,7 @@ usage(const struct option *opts) #ifdef BHYVE_SNAPSHOT [SET_CHECKPOINT_FILE] = "filename", [SET_SUSPEND_FILE] = "filename", + [SET_RUNDIR] = "path", #endif }; (void)fprintf(stderr, "Usage: %s --vm=<vmname>\n", progname); @@ -252,10 +255,10 @@ show_memseg(struct vmctx *ctx) #ifdef BHYVE_SNAPSHOT static int -send_message(const char *vmname, nvlist_t *nvl) +send_message(const char *vmname, nvlist_t *nvl, const char *rundir) { struct sockaddr_un addr; - int err = 0, socket_fd; + int err = 0, ret, socket_fd; socket_fd = socket(PF_UNIX, SOCK_STREAM, 0); if (socket_fd < 0) { @@ -265,8 +268,15 @@ send_message(const char *vmname, nvlist_t *nvl) } memset(&addr, 0, sizeof(struct sockaddr_un)); - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s%s", - BHYVE_RUN_DIR, vmname); + ret = snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/%s", + rundir, vmname); + if ((ret < 0) || ((size_t)ret >= sizeof(addr.sun_path))) { + fprintf(stderr, "%s: error setting socket path (%d)", + __func__, ret); + err = 1; + goto done; + } + addr.sun_family = AF_UNIX; addr.sun_len = SUN_LEN(&addr); @@ -305,7 +315,7 @@ open_directory(const char *file) } static int -snapshot_request(const char *vmname, char *file, bool suspend) +snapshot_request(const char *vmname, char *file, bool suspend, const char *rundir) { nvlist_t *nvl; int fd; @@ -319,7 +329,7 @@ snapshot_request(const char *vmname, char *file, bool suspend) nvlist_add_bool(nvl, "suspend", suspend); nvlist_move_descriptor(nvl, "fddir", fd); - return (send_message(vmname, nvl)); + return (send_message(vmname, nvl, rundir)); } #endif @@ -335,6 +345,7 @@ main(int argc, char *argv[]) struct option *opts; #ifdef BHYVE_SNAPSHOT char *checkpoint_file = NULL; + char *rundir = NULL; #endif opts = setup_options(); @@ -379,6 +390,11 @@ main(int argc, char *argv[]) checkpoint_file = optarg; vm_suspend_opt = (ch == SET_SUSPEND_FILE); break; + + case SET_RUNDIR: + rundir = optarg; + break; + #endif default: usage(opts); @@ -528,7 +544,9 @@ main(int argc, char *argv[]) #ifdef BHYVE_SNAPSHOT if (!error && checkpoint_file) - error = snapshot_request(vmname, checkpoint_file, vm_suspend_opt); + error = snapshot_request(vmname, checkpoint_file, + vm_suspend_opt, + rundir ? rundir : BHYVE_RUN_DIR); #endif if (error)
