Index: Makefile.inc1 =================================================================== --- Makefile.inc1 +++ Makefile.inc1 @@ -2779,7 +2779,7 @@ -DNO_CPU_CFLAGS \ -DNO_PIC \ SSP_CFLAGS= \ - MK_CASPER=yes \ + MK_CASPER=no \ MK_CLANG_EXTRAS=no \ MK_CLANG_FORMAT=no \ MK_CLANG_FULL=no \ Index: usr.sbin/bhyve/bhyverun.c =================================================================== --- usr.sbin/bhyve/bhyverun.c +++ usr.sbin/bhyve/bhyverun.c @@ -1229,44 +1229,6 @@ set_config_bool("x86.strictmsr", true); } -#ifndef WITHOUT_CAPSICUM -char *get_ckp_path(char *str) -{ - char *strcopy; - char *aux1, *aux2, *aux3, *aux4, *aux5; - char *path = NULL; - const char delim[2] = ","; - - strcopy = strdup(str); - assert(strcopy != NULL); - - - aux1 = strtok(strcopy, delim); - aux2 = strtok(NULL, delim); - aux3 = strtok(NULL, delim); - if (aux3 != NULL) { - if (strcmp(aux3, "virtio-blk") || - strcmp(aux3, "ahci-hd") || - strcmp(aux3, "ahci")) { - - aux4 = realpath(aux3, NULL); - if (aux4 != NULL) { - aux5 = strrchr(aux4, '/'); - if (aux5 != NULL) { - *aux5 = '\0'; - path = strdup(aux4); - } - free(aux4); - } - } - } - - free(strcopy); - - return path; -} -#endif - int main(int argc, char *argv[]) { @@ -1284,7 +1246,6 @@ restore_file = NULL; #endif - cap_channel_t *capcas = NULL; char *ckp_path = NULL; init_config(); @@ -1292,7 +1253,7 @@ progname = basename(argv[0]); #ifdef BHYVE_SNAPSHOT - optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:K:U:r:"; + optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:K:U:r:t:"; #else optstr = "aehuwxACDHIPSWYk:o:p:G:c:s:m:l:K:U:"; #endif @@ -1344,6 +1305,9 @@ case 'r': restore_file = optarg; break; + case 't': + ckp_path = optarg; + break; #endif case 's': if (strncmp(optarg, "help", strlen(optarg)) == 0) { @@ -1351,13 +1315,8 @@ exit(0); } else if (pci_parse_slot(optarg) != 0) exit(4); - else { -#ifndef WITHOUT_CAPSISCUM - if (ckp_path == NULL) - ckp_path = get_ckp_path(optarg); -#endif + else break; - } case 'S': set_config_bool("memory.wired", true); break; @@ -1594,13 +1553,6 @@ */ setproctitle("%s", vmname); -#ifndef WITHOUT_CAPSICUM - /* Open capability to Casper. */ - capcas = cap_init(); - if (capcas == NULL) - errx(EX_OSERR, "cap_init() failed"); -#endif - #ifdef BHYVE_SNAPSHOT if (restore_file != NULL) destroy_restore_state(&rstate); @@ -1608,10 +1560,13 @@ /* initialize mutex/cond variables */ init_snapshot(); + /* initialize snapshot files parent directory and casper channel */ + init_capsicum_info(ckp_path); + /* * checkpointing thread for communication with bhyvectl */ - if (init_checkpoint_thread(ctx, ckp_path, capcas) < 0) + if (init_checkpoint_thread(ctx) < 0) printf("Failed to start checkpoint thread!\r\n"); if (restore_file != NULL) @@ -1619,7 +1574,6 @@ #endif #ifndef WITHOUT_CAPSICUM - free(ckp_path); caph_cache_catpages(); if (caph_limit_stdout() == -1 || caph_limit_stderr() == -1) Index: usr.sbin/bhyve/snapshot.h =================================================================== --- usr.sbin/bhyve/snapshot.h +++ usr.sbin/bhyve/snapshot.h @@ -68,7 +68,6 @@ struct checkpoint_thread_info { struct vmctx *ctx; int socket_fd; - cap_channel_t *channel; }; typedef int (*vm_snapshot_dev_cb)(struct vm_snapshot_meta *); @@ -108,7 +107,8 @@ int get_checkpoint_msg(int conn_fd, struct vmctx *ctx); void *checkpoint_thread(void *param); void init_snapshot(void); -int init_checkpoint_thread(struct vmctx *ctx, char *ckp_path, cap_channel_t *chn); +int init_checkpoint_thread(struct vmctx *ctx); +void init_capsicum_info(char *ckp_path); int load_restore_file(const char *filename, struct restore_state *rstate); Index: usr.sbin/bhyve/snapshot.c =================================================================== --- usr.sbin/bhyve/snapshot.c +++ usr.sbin/bhyve/snapshot.c @@ -172,6 +172,8 @@ static bool checkpoint_active; static int cdir_fd = AT_FDCWD; +static cap_channel_t *casper_channel = NULL; + /* * TODO: Harden this function and all of its callers since 'base_str' is a user * provided string. @@ -1088,8 +1090,8 @@ ret = vm_snapshot_req(meta); if (ret != 0) { - fprintf(stderr, "%s: Failed to snapshot struct %s\r\n", - __func__, meta->dev_name); + fprintf(stderr, "%s: Failed to snapshot struct %s(%d - %s)\r\n", + __func__, meta->dev_name, errno, strerror(errno)); ret = -1; goto done; } @@ -1381,39 +1383,39 @@ } #ifndef WITHOUT_CAPSICUM -#define DESTROY(vm, ch, err, LABEL) \ -do { \ - cap_channel_t *capsysctl = NULL; \ - char *name = "hw.vmm.destroy"; \ - void *limit; \ - \ - /* Create capability to the system.sysctl service with Casper. */ \ - capsysctl = cap_service_open(ch, "system.sysctl"); \ - if (capsysctl == NULL) \ +#define DESTROY(vm, ch, err, LABEL) \ +do { \ + cap_channel_t *capsysctl = NULL; \ + char *name = "hw.vmm.destroy"; \ + void *limit; \ + \ + /* Create capability to the system.sysctl service with Casper. */ \ + capsysctl = cap_service_open(ch, "system.sysctl"); \ + if (capsysctl == NULL) \ fprintf(stderr, "%s: Unable to open system.sysctl service", __func__); \ - \ - cap_close(ch); \ - \ - /* Create limit for one MIB with write access only. */ \ - limit = cap_sysctl_limit_init(capsysctl); \ - (void)cap_sysctl_limit_name(limit, name, CAP_SYSCTL_WRITE); \ - \ - /* Limit system.sysctl. */ \ - if (cap_sysctl_limit(limit) < 0) \ - fprintf(stderr, "%s: Unable to set limits", __func__); \ - \ + \ + cap_close(ch); \ + \ + /* Create limit for one MIB with write access only. */ \ + limit = cap_sysctl_limit_init(capsysctl); \ + (void)cap_sysctl_limit_name(limit, name, CAP_SYSCTL_WRITE); \ + \ + /* Limit system.sysctl. */ \ + if (cap_sysctl_limit(limit) < 0) \ + fprintf(stderr, "%s: Unable to set limits", __func__); \ + \ err = cap_sysctlbyname(capsysctl, name, NULL, NULL, (vm), strlen((vm))); \ - \ - cap_close(capsysctl); \ - if (err != 0) { \ - fprintf(stderr, "%s: err is %d\r\n", __func__, errno); \ - goto LABEL; \ - } \ + \ + cap_close(capsysctl); \ + if (err != 0) { \ + fprintf(stderr, "%s: err is %d\r\n", __func__, errno); \ + goto LABEL; \ + } \ } while(0) #endif static int -vm_checkpoint(struct vmctx *ctx, char *checkpoint_file, cap_channel_t *chn, bool stop_vm) +vm_checkpoint(struct vmctx *ctx, const char *checkpoint_file, bool stop_vm) { int fd_checkpoint = 0, kdata_fd = 0, meta_fd = 0; int ret = 0; @@ -1476,10 +1478,6 @@ fprintf(stderr, "Could not pause devices\r\n"); error = ret; goto done; -#ifndef WITHOUT_CAPSICUM - if (cdir_fd > 0) - close(cdir_fd); -#endif } memsz = vm_snapshot_mem(ctx, fd_checkpoint, 0, true); @@ -1514,13 +1512,13 @@ if (stop_vm) { - if (chn != NULL) { + if (casper_channel != NULL) { error = vm_get_name(ctx, vmname, MAX_VMNAME - 1); if (error != 0) { fprintf(stderr, "%s: Failed to get VM name", __func__); goto done; } - DESTROY(vmname, chn, error, done); + DESTROY(vmname, casper_channel, error, done); free(ctx); } else vm_destroy(ctx); @@ -1553,7 +1551,7 @@ } int -handle_message(struct vmctx *ctx, nvlist_t *nvl, cap_channel_t *chn) +handle_message(struct vmctx *ctx, nvlist_t *nvl) { int err; const char *cmd; @@ -1565,10 +1563,10 @@ if (strcmp(cmd, "checkpoint") == 0) { if (!nvlist_exists_string(nvl, "filename") || !nvlist_exists_bool(nvl, "suspend")) - err = -1; + err = -1; else - err = vm_checkpoint(ctx, nvlist_get_string(nvl, "filename"), - chn, nvlist_get_bool(nvl, "suspend")); + err = vm_checkpoint(ctx, nvlist_get_string(nvl, "filename"), + nvlist_get_bool(nvl, "suspend")); } else { EPRINTLN("Unrecognized checkpoint operation\n"); err = -1; @@ -1594,14 +1592,14 @@ thread_info = (struct checkpoint_thread_info *)param; for (;;) { - n = recvfrom(thread_info->socket_fd, &imsg, sizeof(imsg), 0, NULL, 0); + nvl = nvlist_recv(thread_info->socket_fd, 0); /* * slight sanity check: see if there's enough data to at * least determine the type of message. */ - if (n >= sizeof(imsg.code)) - handle_message(&imsg, thread_info->ctx, thread_info->channel); + if (nvl != NULL) + handle_message(thread_info->ctx, nvl); else EPRINTLN("nvlist_recv() failed: %s", strerror(errno)); } @@ -1631,7 +1629,7 @@ { cap_rights_t rights; - cap_rights_init(&rights, CAP_BIND, CAP_READ); + cap_rights_init(&rights, CAP_BIND, CAP_READ, CAP_GETSOCKOPT); if (caph_rights_limit(s, &rights) == -1) errx(EX_OSERR, "Unable to apply rights for sandbox"); } @@ -1648,18 +1646,34 @@ #endif +void +init_capsicum_info(char *ckp_path) +{ + /* Open capability to Casper. */ + casper_channel = cap_init(); + if (casper_channel == NULL) + errx(EX_OSERR, "cap_init() failed"); + + if (ckp_path != NULL) { + cdir_fd = open(ckp_path, O_RDONLY | O_DIRECTORY); + if (cdir_fd < 0) + errc(1, cdir_fd, "open snapshot files directory"); + limit_file_operations(); + } +} + /* * Create the listening socket for IPC with bhyvectl */ int -init_checkpoint_thread(struct vmctx *ctx, char *ckp_path, cap_channel_t *chn) +init_checkpoint_thread(struct vmctx *ctx) { struct checkpoint_thread_info *checkpoint_info = NULL; struct sockaddr_un addr; int socket_fd; pthread_t checkpoint_pthread; char vmname_buf[MAX_VMNAME]; - int ret, err = 0; + int err = 0; memset(&addr, 0, sizeof(addr)); @@ -1670,16 +1684,7 @@ goto fail; } - if (ckp_path != NULL) { - cdir_fd = open(ckp_path, O_RDONLY | O_DIRECTORY); - if (cdir_fd < 0) { - perror("Failed to open working directory."); - err = -1; - goto fail; - } - limit_control_socket(socket_fd); - limit_file_operations(); - } + limit_control_socket(socket_fd); addr.sun_family = AF_UNIX; @@ -1704,7 +1709,6 @@ checkpoint_info = calloc(1, sizeof(*checkpoint_info)); checkpoint_info->ctx = ctx; checkpoint_info->socket_fd = socket_fd; - checkpoint_info->channel = chn; err = pthread_create(&checkpoint_pthread, NULL, checkpoint_thread, checkpoint_info);