diff --git a/criu/files-reg.c b/criu/files-reg.c index 6759e00e5..c339876b4 100644 --- a/criu/files-reg.c +++ b/criu/files-reg.c @@ -2322,6 +2322,7 @@ static int open_filemap(int pid, struct vma_area *vma) { u32 flags; int ret; + int plugin_fd = -1; /* * The vma->fd should have been assigned in collect_filemap @@ -2335,25 +2336,34 @@ static int open_filemap(int pid, struct vma_area *vma) /* update the new device file page offsets and file paths set during restore */ if (vma->e->status & VMA_UNSUPP) { uint64_t new_pgoff; - char new_path[PATH_MAX]; int ret; struct reg_file_info *rfi = container_of(vma->vmfd, struct reg_file_info, d); - ret = run_plugins(UPDATE_VMA_MAP, rfi->rfe->name, new_path, vma->e->start, vma->e->pgoff, &new_pgoff); + ret = run_plugins(UPDATE_VMA_MAP, rfi->rfe->name, vma->e->start, vma->e->pgoff, &new_pgoff, &plugin_fd); if (ret == 1) { - pr_info("New mmap %#016" PRIx64 "->%#016" PRIx64 " path %s\n", vma->e->pgoff, new_pgoff, - new_path); + pr_info("New mmap %#016" PRIx64 ":%#016" PRIx64 "->%#016" PRIx64 " fd %d\n", vma->e->start, + vma->e->pgoff, new_pgoff, plugin_fd); vma->e->pgoff = new_pgoff; - rfi->path = xstrdup(new_path); - pr_debug("Updated rfi->path %s\n", rfi->path); } + /* Device plugin will restore vma contents, so no need for write permission */ + vma->e->status |= VMA_NO_PROT_WRITE; } if (ctx.flags != flags || ctx.desc != vma->vmfd) { - if (vma->e->status & VMA_AREA_MEMFD) + if (plugin_fd >= 0) { + /* + * Vma handled by device plugin. + * Some device drivers (e.g DRM) only allow the file descriptor that was used to create vma to + * be used when calling mmap. In this case, use the FD returned by plugin. FD can be copied + * using dup because dup returns a reference to the same struct file inside kernel, but we + * cannot open a new FD. + */ + ret = dup(plugin_fd); + } else if (vma->e->status & VMA_AREA_MEMFD) { ret = memfd_open(vma->vmfd, &flags); - else + } else { ret = open_path(vma->vmfd, do_open_reg_noseek_flags, &flags); + } if (ret < 0) return ret; diff --git a/criu/include/criu-plugin.h b/criu/include/criu-plugin.h index 0bc7a4255..886832eaa 100644 --- a/criu/include/criu-plugin.h +++ b/criu/include/criu-plugin.h @@ -69,8 +69,8 @@ DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_EXT_MOUNT, char *mountpoint, int i DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESTORE_EXT_MOUNT, int id, char *mountpoint, char *old_root, int *is_file); DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__DUMP_EXT_LINK, int index, int type, char *kind); DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__HANDLE_DEVICE_VMA, int fd, const struct stat *stat); -DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__UPDATE_VMA_MAP, const char *old_path, char *new_path, const uint64_t addr, - const uint64_t old_pgoff, uint64_t *new_pgoff); +DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__UPDATE_VMA_MAP, const char *path, const uint64_t addr, + const uint64_t old_pgoff, uint64_t *new_pgoff, int *plugin_fd); DECLARE_PLUGIN_HOOK_ARGS(CR_PLUGIN_HOOK__RESUME_DEVICES_LATE, int pid); enum { @@ -143,8 +143,8 @@ typedef int(cr_plugin_dump_ext_mount_t)(char *mountpoint, int id); typedef int(cr_plugin_restore_ext_mount_t)(int id, char *mountpoint, char *old_root, int *is_file); typedef int(cr_plugin_dump_ext_link_t)(int index, int type, char *kind); typedef int(cr_plugin_handle_device_vma_t)(int fd, const struct stat *stat); -typedef int(cr_plugin_update_vma_map_t)(const char *old_path, char *new_path, const uint64_t addr, - const uint64_t old_pgoff, uint64_t *new_pgoff); +typedef int(cr_plugin_update_vma_map_t)(const char *path, const uint64_t addr, const uint64_t old_pgoff, + uint64_t *new_pgoff, int *plugin_fd); typedef int(cr_plugin_resume_devices_late_t)(int pid); #endif /* __CRIU_PLUGIN_H__ */