int check_img_inventory(void) { int fd, ret = -1; InventoryEntry *he; fd = open_image(CR_FD_INVENTORY, O_RSTR); if (fd < 0) return -1; if (pb_read_one(fd, &he, PB_INVENTORY) < 0) goto out_close; fdinfo_per_id = he->has_fdinfo_per_id ? he->fdinfo_per_id : false; ns_per_id = he->has_ns_per_id ? he->ns_per_id : false; if (he->root_ids) { root_ids = xmalloc(sizeof(*root_ids)); if (!root_ids) goto out_err; memcpy(root_ids, he->root_ids, sizeof(*root_ids)); } if (he->img_version != CRTOOLS_IMAGES_V1) { pr_err("Not supported images version %u\n", he->img_version); goto out_err; } ret = 0; out_err: inventory_entry__free_unpacked(he, NULL); out_close: close(fd); return ret; }
static int prepare_ipc_var(int pid) { int ret; struct cr_img *img; IpcVarEntry *var; pr_info("Restoring IPC variables\n"); img = open_image(CR_FD_IPC_VAR, O_RSTR, pid); if (!img) return -1; ret = pb_read_one(img, &var, PB_IPC_VAR); close_image(img); if (ret <= 0) { pr_err("Failed to read IPC namespace variables\n"); return -EFAULT; } ret = ipc_sysctl_req(var, CTL_WRITE); ipc_var_entry__free_unpacked(var, NULL); if (ret < 0) { pr_err("Failed to prepare IPC namespace variables\n"); return -EFAULT; } return 0; }
int prepare_utsns(int pid) { int fd, ret; UtsnsEntry *ue; struct sysctl_req req[3] = { { "kernel/hostname" }, { "kernel/domainname" }, { }, }; fd = open_image_ro(CR_FD_UTSNS, pid); if (fd < 0) return -1; ret = pb_read_one(fd, &ue, PB_UTSNS); if (ret < 0) goto out; req[0].arg = ue->nodename; req[0].type = CTL_STR(strlen(ue->nodename)); req[1].arg = ue->domainname; req[1].type = CTL_STR(strlen(ue->domainname)); ret = sysctl_op(req, CTL_WRITE); utsns_entry__free_unpacked(ue, NULL); out: close(fd); return ret; }
int prepare_utsns(int pid) { int ret; struct cr_img *img; UtsnsEntry *ue; struct sysctl_req req[] = { { "kernel/hostname" }, { "kernel/domainname" }, }; img = open_image(CR_FD_UTSNS, O_RSTR, pid); if (!img) return -1; ret = pb_read_one(img, &ue, PB_UTSNS); if (ret < 0) goto out; req[0].arg = ue->nodename; req[0].type = CTL_STR(strlen(ue->nodename)); req[1].arg = ue->domainname; req[1].type = CTL_STR(strlen(ue->domainname)); ret = sysctl_op(req, ARRAY_SIZE(req), CTL_WRITE, CLONE_NEWUTS); utsns_entry__free_unpacked(ue, NULL); out: close_image(img); return ret; }
int check_img_inventory(void) { int ret = -1; struct cr_img *img; InventoryEntry *he; img = open_image(CR_FD_INVENTORY, O_RSTR); if (!img) return -1; if (pb_read_one(img, &he, PB_INVENTORY) < 0) goto out_close; fdinfo_per_id = he->has_fdinfo_per_id ? he->fdinfo_per_id : false; ns_per_id = he->has_ns_per_id ? he->ns_per_id : false; if (he->root_ids) { root_ids = xmalloc(sizeof(*root_ids)); if (!root_ids) goto out_err; memcpy(root_ids, he->root_ids, sizeof(*root_ids)); } if (he->has_root_cg_set) { if (he->root_cg_set == 0) { pr_err("Corrupted root cgset\n"); goto out_err; } root_cg_set = he->root_cg_set; } image_lsm = he->lsmtype; switch (he->img_version) { case CRTOOLS_IMAGES_V1: /* good old images. OK */ img_common_magic = false; break; case CRTOOLS_IMAGES_V1_1: /* newer images with extra magic in the head */ break; default: pr_err("Not supported images version %u\n", he->img_version); goto out_err; } ret = 0; out_err: inventory_entry__free_unpacked(he, NULL); out_close: close_image(img); return ret; }
static void show_inventory(int fd, struct cr_options *o) { InventoryEntry *he; if (pb_read_one(fd, &he, PB_INVENTORY) < 0) return; pr_msg("Version: %u\n", he->img_version); inventory_entry__free_unpacked(he, NULL); }
static int restore_tcp_conn_state(int sk, struct inet_sk_info *ii) { int ifd, aux; TcpStreamEntry *tse; pr_info("Restoring TCP connection id %x ino %x\n", ii->ie->id, ii->ie->ino); ifd = open_image(CR_FD_TCP_STREAM, O_RSTR, ii->ie->ino); if (ifd < 0) goto err; if (pb_read_one(ifd, &tse, PB_TCP_STREAM) < 0) goto err_c; if (restore_tcp_seqs(sk, tse)) goto err_c; if (inet_bind(sk, ii)) goto err_c; if (inet_connect(sk, ii)) goto err_c; if (restore_tcp_opts(sk, tse)) goto err_c; if (restore_tcp_queues(sk, tse, ifd)) goto err_c; if (tse->has_nodelay && tse->nodelay) { aux = 1; if (restore_opt(sk, SOL_TCP, TCP_NODELAY, &aux)) goto err_c; } if (tse->has_cork && tse->cork) { aux = 1; if (restore_opt(sk, SOL_TCP, TCP_CORK, &aux)) goto err_c; } tcp_stream_entry__free_unpacked(tse, NULL); close(ifd); return 0; err_c: tcp_stream_entry__free_unpacked(tse, NULL); close(ifd); err: return -1; }
static int open_remap_ghost(struct reg_file_info *rfi, RemapFilePathEntry *rfe) { struct ghost_file *gf = container_of(rfi->remap, struct ghost_file, remap); GhostFileEntry *gfe = NULL; struct cr_img *img; if (rfi->remap->rpath[0]) return 0; img = open_image(CR_FD_GHOST_FILE, O_RSTR, rfe->remap_id); if (!img) goto err; if (pb_read_one(img, &gfe, PB_GHOST_FILE) < 0) goto close_ifd; /* * For old formats where optional has_[dev|ino] is * not present we will have zeros here which is quite * a sign for "absent" fields. */ gf->dev = gfe->dev; gf->ino = gfe->ino; gf->remap.rmnt_id = rfi->rfe->mnt_id; if (S_ISDIR(gfe->mode)) strncpy(gf->remap.rpath, rfi->path, PATH_MAX); else ghost_path(gf->remap.rpath, PATH_MAX, rfi, rfe); if (create_ghost(gf, gfe, img)) goto close_ifd; close_image(img); gf->remap.is_dir = S_ISDIR(gfe->mode); gf->remap.uid = gfe->uid; gf->remap.gid = gfe->gid; ghost_file_entry__free_unpacked(gfe, NULL); return 0; close_ifd: close_image(img); err: if (gfe) ghost_file_entry__free_unpacked(gfe, NULL); return -1; }
struct cr_img *open_pages_image_at(int dfd, unsigned long flags, struct cr_img *pmi, u32 *id) { if (flags == O_RDONLY || flags == O_RDWR) { PagemapHead *h; if (pb_read_one(pmi, &h, PB_PAGEMAP_HEAD) < 0) return NULL; *id = h->pages_id; pagemap_head__free_unpacked(h, NULL); } else { PagemapHead h = PAGEMAP_HEAD__INIT; *id = h.pages_id = page_ids++; if (pb_write_one(pmi, &h, PB_PAGEMAP_HEAD) < 0) return NULL; } return open_image_at(dfd, CR_FD_PAGES, flags, *id); }
static int prepare_ipc_msg_queue_messages(struct cr_img *img, const IpcMsgEntry *msq) { IpcMsg *msg = NULL; int msg_nr = 0; int ret = 0; while (msg_nr < msq->qnum) { struct msgbuf { long mtype; char mtext[MSGMAX]; } data; ret = pb_read_one(img, &msg, PB_IPCNS_MSG); if (ret <= 0) return -EIO; pr_info_ipc_msg(msg_nr, msg); if (msg->msize > MSGMAX) { ret = -1; pr_err("Unsupported message size: %d (MAX: %d)\n", msg->msize, MSGMAX); break; } ret = read_img_buf(img, data.mtext, round_up(msg->msize, sizeof(u64))); if (ret < 0) { pr_err("Failed to read IPC message data\n"); break; } data.mtype = msg->mtype; ret = msgsnd(msq->desc->id, &data, msg->msize, IPC_NOWAIT); if (ret < 0) { pr_perror("Failed to send IPC message"); ret = -errno; break; } msg_nr++; } if (msg) ipc_msg__free_unpacked(msg, NULL); return ret; }
int open_pages_image_at(int dfd, unsigned long flags, int pm_fd) { unsigned id; if (flags == O_RDONLY || flags == O_RDWR) { PagemapHead *h; if (pb_read_one(pm_fd, &h, PB_PAGEMAP_HEAD) < 0) return -1; id = h->pages_id; pagemap_head__free_unpacked(h, NULL); } else { PagemapHead h = PAGEMAP_HEAD__INIT; id = h.pages_id = page_ids++; if (pb_write_one(pm_fd, &h, PB_PAGEMAP_HEAD) < 0) return -1; } return open_image_at(dfd, CR_FD_PAGES, flags, id); }
int cpu_validate_cpuinfo(void) { CpuinfoX86Entry *img_x86_entry; CpuinfoEntry *img_cpu_info; struct cr_img *img; int ret = -1; img = open_image(CR_FD_CPUINFO, O_RSTR); if (!img) return -1; if (pb_read_one(img, &img_cpu_info, PB_CPUINFO) < 0) goto err; if (img_cpu_info->n_x86_entry != 1) { pr_err("No x86 related cpuinfo in image, " "corruption (n_x86_entry = %zi)\n", img_cpu_info->n_x86_entry); goto err; } img_x86_entry = img_cpu_info->x86_entry[0]; if (img_x86_entry->vendor_id != CPUINFO_X86_ENTRY__VENDOR__INTEL && img_x86_entry->vendor_id != CPUINFO_X86_ENTRY__VENDOR__AMD) { pr_err("Unknown cpu vendor %d\n", img_x86_entry->vendor_id); goto err; } if (img_x86_entry->n_capability != ARRAY_SIZE(rt_cpu_info.x86_capability)) { pr_err("Image carries %u words while %u expected\n", (unsigned)img_x86_entry->n_capability, (unsigned)ARRAY_SIZE(rt_cpu_info.x86_capability)); goto err; } ret = cpu_validate_features(img_x86_entry); err: close_image(img); return ret; }
int check_img_inventory(void) { int fd, ret; InventoryEntry *he; fd = open_image_ro(CR_FD_INVENTORY); if (fd < 0) return -1; ret = pb_read_one(fd, &he, PB_INVENTORY); close(fd); if (ret < 0) return ret; ret = he->img_version; inventory_entry__free_unpacked(he, NULL); if (ret != CRTOOLS_IMAGES_V1) { pr_err("Not supported images version %u\n", ret); return -1; } return 0; }
InventoryEntry *get_parent_inventory(void) { struct cr_img *img; InventoryEntry *ie; int dir; dir = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY); if (dir == -1) { pr_warn("Failed to open parent directory\n"); return NULL; } img = open_image_at(dir, CR_FD_INVENTORY, O_RSTR); if (!img) { pr_warn("Failed to open parent pre-dump inventory image\n"); close(dir); return NULL; } if (pb_read_one(img, &ie, PB_INVENTORY) < 0) { pr_warn("Failed to read parent pre-dump inventory entry\n"); close_image(img); close(dir); return NULL; } if (!ie->has_dump_uptime) { pr_warn("Parent pre-dump inventory has no uptime\n"); inventory_entry__free_unpacked(ie, NULL); ie = NULL; } close_image(img); close(dir); return ie; }
static int open_remap_ghost(struct reg_file_info *rfi, RemapFilePathEntry *rfe) { struct ghost_file *gf; GhostFileEntry *gfe = NULL; struct cr_img *img; list_for_each_entry(gf, &ghost_files, list) if (gf->id == rfe->remap_id) goto gf_found; /* * Ghost not found. We will create one in the same dir * as the very first client of it thus resolving any * issues with cross-device links. */ pr_info("Opening ghost file %#x for %s\n", rfe->remap_id, rfi->path); gf = shmalloc(sizeof(*gf)); if (!gf) return -1; gf->remap.rpath = xmalloc(PATH_MAX); if (!gf->remap.rpath) goto err; img = open_image(CR_FD_GHOST_FILE, O_RSTR, rfe->remap_id); if (!img) goto err; if (pb_read_one(img, &gfe, PB_GHOST_FILE) < 0) goto close_ifd; /* * For old formats where optional has_[dev|ino] is * not present we will have zeros here which is quite * a sign for "absent" fields. */ gf->dev = gfe->dev; gf->ino = gfe->ino; gf->remap.rmnt_id = rfi->rfe->mnt_id; if (S_ISDIR(gfe->mode)) strncpy(gf->remap.rpath, rfi->path, PATH_MAX); else ghost_path(gf->remap.rpath, PATH_MAX, rfi, rfe); if (create_ghost(gf, gfe, img)) goto close_ifd; ghost_file_entry__free_unpacked(gfe, NULL); close_image(img); gf->id = rfe->remap_id; gf->remap.users = 0; gf->remap.is_dir = S_ISDIR(gfe->mode); gf->remap.owner = gfe->uid; list_add_tail(&gf->list, &ghost_files); gf_found: rfi->remap = &gf->remap; return 0; close_ifd: close_image(img); err: if (gfe) ghost_file_entry__free_unpacked(gfe, NULL); xfree(gf->remap.rpath); shfree_last(gf); return -1; }
int cpu_validate_cpuinfo(void) { CpuinfoEntry *cpu_info; CpuinfoPpc64Entry *cpu_ppc64_entry; struct cr_img *img; int ret = -1; img = open_image(CR_FD_CPUINFO, O_RSTR); if (!img) return -1; if (pb_read_one(img, &cpu_info, PB_CPUINFO) < 0) goto error; if (cpu_info->n_ppc64_entry != 1) { pr_err("No PPC64 related entry in image"); goto error; } cpu_ppc64_entry = cpu_info->ppc64_entry[0]; if (cpu_ppc64_entry->endian != CURRENT_ENDIANNESS) { pr_err("Bad endianness"); goto error; } if (cpu_ppc64_entry->n_hwcap != 2) { pr_err("Hardware capabilities information missing\n"); goto error; } #define CHECK_FEATURE(s,f) do { \ if ((cpu_ppc64_entry->hwcap[s] & f) && \ !(rt_cpuinfo.hwcap[s] & f)) { \ pr_err("CPU Feature %s required by image " \ "is not supported on host.\n", #f); \ goto error; \ } \ } while(0) #define REQUIRE_FEATURE(s,f) do { \ if (!(cpu_ppc64_entry->hwcap[s] & f)) { \ pr_err("CPU Feature %s missing in image.\n", #f); \ goto error; \ } \ } while(0) REQUIRE_FEATURE(0, PPC_FEATURE_64); REQUIRE_FEATURE(0, PPC_FEATURE_HAS_FPU); REQUIRE_FEATURE(0, PPC_FEATURE_HAS_MMU); REQUIRE_FEATURE(0, PPC_FEATURE_HAS_VSX); REQUIRE_FEATURE(1, PPC_FEATURE2_ARCH_2_07); CHECK_FEATURE(0, PPC_FEATURE_TRUE_LE); CHECK_FEATURE(1, PPC_FEATURE2_HTM); CHECK_FEATURE(1, PPC_FEATURE2_DSCR); CHECK_FEATURE(1, PPC_FEATURE2_EBB); CHECK_FEATURE(1, PPC_FEATURE2_ISEL); CHECK_FEATURE(1, PPC_FEATURE2_TAR); CHECK_FEATURE(1, PPC_FEATURE2_VEC_CRYPTO); ret = 0; error: close_image(img); return ret; }