From 18126b647a43ff8fbb127cc036084110ac302d32 Mon Sep 17 00:00:00 2001 From: Vitaliy Gusev Date: Fri, 28 Apr 2023 09:00:48 +0200 Subject: [PATCH] bhyve: use directory file descriptor for checkpoint This is required to enable capsicum for the snapshot code. Reviewed by: corvink Sponsored by: vStack Differential Revision: https://reviews.freebsd.org/D38858 --- usr.sbin/bhyve/snapshot.c | 21 ++++++++++++++------- usr.sbin/bhyvectl/bhyvectl.c | 25 +++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/usr.sbin/bhyve/snapshot.c b/usr.sbin/bhyve/snapshot.c index 866fc265b8aa..6d543c1b37e3 100644 --- a/usr.sbin/bhyve/snapshot.c +++ b/usr.sbin/bhyve/snapshot.c @@ -1308,9 +1308,10 @@ vm_vcpu_resume(struct vmctx *ctx) } static int -vm_checkpoint(struct vmctx *ctx, const char *checkpoint_file, bool stop_vm) +vm_checkpoint(struct vmctx *ctx, int fddir, const char *checkpoint_file, + bool stop_vm) { - int fd_checkpoint = 0, kdata_fd = 0; + int fd_checkpoint = 0, kdata_fd = 0, fd_meta; int ret = 0; int error = 0; size_t memsz; @@ -1325,14 +1326,14 @@ vm_checkpoint(struct vmctx *ctx, const char *checkpoint_file, bool stop_vm) return (-1); } - kdata_fd = open(kdata_filename, O_WRONLY | O_CREAT | O_TRUNC, 0700); + kdata_fd = openat(fddir, kdata_filename, O_WRONLY | O_CREAT | O_TRUNC, 0700); if (kdata_fd < 0) { perror("Failed to open kernel data snapshot file."); error = -1; goto done; } - fd_checkpoint = open(checkpoint_file, O_RDWR | O_CREAT | O_TRUNC, 0700); + fd_checkpoint = openat(fddir, checkpoint_file, O_RDWR | O_CREAT | O_TRUNC, 0700); if (fd_checkpoint < 0) { perror("Failed to create checkpoint file"); @@ -1346,9 +1347,12 @@ vm_checkpoint(struct vmctx *ctx, const char *checkpoint_file, bool stop_vm) goto done; } - meta_file = fopen(meta_filename, "w"); + fd_meta = openat(fddir, meta_filename, O_WRONLY | O_CREAT | O_TRUNC, 0700); + if (fd_meta != -1) + meta_file = fdopen(fd_meta, "w"); if (meta_file == NULL) { perror("Failed to open vm metadata snapshot file."); + close(fd_meta); goto done; } @@ -1474,10 +1478,13 @@ vm_do_checkpoint(struct vmctx *ctx, const nvlist_t *nvl) int error; if (!nvlist_exists_string(nvl, "filename") || - !nvlist_exists_bool(nvl, "suspend")) + !nvlist_exists_bool(nvl, "suspend") || + !nvlist_exists_descriptor(nvl, "fddir")) error = EINVAL; else - error = vm_checkpoint(ctx, nvlist_get_string(nvl, "filename"), + error = vm_checkpoint(ctx, + nvlist_get_descriptor(nvl, "fddir"), + nvlist_get_string(nvl, "filename"), nvlist_get_bool(nvl, "suspend")); return (error); diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c index 5c3440ce8343..12f92eb8d96d 100644 --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -1711,14 +1711,35 @@ send_message(const char *vmname, nvlist_t *nvl) } static int -snapshot_request(const char *vmname, const char *file, bool suspend) +open_directory(const char *file) +{ + char *path; + int fd; + + if ((path = strdup(file)) == NULL) + return (-1); + + dirname(path); + fd = open(path, O_DIRECTORY); + free(path); + + return (fd); +} + +static int +snapshot_request(const char *vmname, char *file, bool suspend) { nvlist_t *nvl; + int fd; + + if ((fd = open_directory(file)) < 0) + return (errno); nvl = nvlist_create(0); nvlist_add_string(nvl, "cmd", "checkpoint"); - nvlist_add_string(nvl, "filename", file); + nvlist_add_string(nvl, "filename", basename(file)); nvlist_add_bool(nvl, "suspend", suspend); + nvlist_move_descriptor(nvl, "fddir", fd); return (send_message(vmname, nvl)); }