[CRIU] [PATCH 1/9] vdso: Introduce type for checking vdso hint in maps file
Dmitry Safonov
dsafonov at virtuozzo.com
Thu Jun 22 14:04:24 MSK 2017
Let's hide those kernel details in enum.
Further in this patches set I'll add kdat test for presence
of "[vdso]" hint after mremap(), so we will skip any checking
on kernels > v3.16 and do not init vdso_pfn also
(skipping parsing of self-pagemap).
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
criu/vdso.c | 67 ++++++++++++++++++++++++++++++++++++++++++-------------------
1 file changed, 46 insertions(+), 21 deletions(-)
diff --git a/criu/vdso.c b/criu/vdso.c
index 83f30807eea5..a0b8a4e0b39a 100644
--- a/criu/vdso.c
+++ b/criu/vdso.c
@@ -33,6 +33,42 @@ struct vdso_maps vdso_maps = VDSO_MAPS_INIT;
struct vdso_maps vdso_maps_compat = VDSO_MAPS_INIT;
/*
+ * Starting with 3.16 the [vdso]/[vvar] marks are reported correctly
+ * even when they are remapped into a new place, but only since that
+ * particular version of the kernel!
+ * On previous kernels we need to check if vma is vdso by some means:
+ * - if pagemap is present, by pfn
+ * - by parsing ELF and filling vdso symtable otherwise
+ */
+enum vdso_check_t {
+ /* from slowest to fastest */
+ VDSO_CHECK_SYMS = 0,
+ VDSO_CHECK_PFN,
+ VDSO_NO_CHECK,
+};
+
+static enum vdso_check_t get_vdso_check_type(struct parasite_ctl *ctl)
+{
+ /*
+ * ia32 C/R depends on mremap() for vdso patches (v4.8),
+ * so we can omit any check and be sure that "[vdso]"
+ * hint stays in /proc/../maps file and is correct.
+ */
+ if (!compel_mode_native(ctl)) {
+ pr_info("Don't check vdso\n");
+ return VDSO_NO_CHECK;
+ }
+
+ if (kdat.pmap == PM_FULL) {
+ pr_info("Check vdso by pfn from pagemap\n");
+ return VDSO_CHECK_PFN;
+ }
+
+ pr_info("Pagemap is unavailable, check vdso by filling symtable\n");
+ return VDSO_CHECK_SYMS;
+}
+
+/*
* The VMAs list might have proxy vdso/vvar areas left
* from previous dump/restore cycle so we need to detect
* them and eliminated from the VMAs list, they will be
@@ -47,18 +83,19 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
struct vma_area *proxy_vvar_marked = NULL;
struct parasite_vdso_vma_entry *args;
int fd = -1, ret, exit_code = -1;
+ enum vdso_check_t vcheck;
u64 pfn = VDSO_BAD_PFN;
struct vma_area *vma;
off_t off;
+ vcheck = get_vdso_check_type(ctl);
args = compel_parasite_args(ctl, struct parasite_vdso_vma_entry);
- if (kdat.pmap == PM_FULL) {
+ if (vcheck == VDSO_CHECK_PFN) {
BUG_ON(vdso_pfn == VDSO_BAD_PFN);
fd = open_proc(pid, "pagemap");
if (fd < 0)
return -1;
- } else
- pr_info("Pagemap is unavailable, trying a slow way\n");
+ }
list_for_each_entry(vma, &vma_area_list->h, list) {
if (!vma_area_is(vma, VMA_AREA_REGULAR))
@@ -105,10 +142,7 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
*/
args->start = vma->e->start;
args->len = vma_area_len(vma);
- if (!compel_mode_native(ctl))
- args->try_fill_symtable = false;
- else
- args->try_fill_symtable = (fd < 0) ? true : false;
+ args->try_fill_symtable = (vcheck == VDSO_CHECK_SYMS);
args->is_vdso = false;
if (compel_rpc_call_sync(PARASITE_CMD_CHECK_VDSO_MARK, ctl)) {
@@ -132,6 +166,9 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
continue;
}
+ if (vcheck == VDSO_NO_CHECK)
+ continue;
+
/*
* If we have an access to pagemap we can handle vDSO
* status early. Otherwise, in worst scenario, where
@@ -140,7 +177,7 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
* detected via procfs status so we have to parse
* symbols in parasite code.
*/
- if (fd >= 0) {
+ if (vcheck == VDSO_CHECK_PFN) {
off = (vma->e->start / PAGE_SIZE) * sizeof(u64);
ret = pread(fd, &pfn, sizeof(pfn), off);
if (ret < 0 || ret != sizeof(pfn)) {
@@ -155,13 +192,6 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
}
}
- /*
- * Setup proper VMA status. Note starting with 3.16
- * the [vdso]/[vvar] marks are reported correctly
- * even when they are remapped into a new place,
- * but only since that particular version of the
- * kernel!
- */
if ((pfn == vdso_pfn && pfn != VDSO_BAD_PFN) || args->is_vdso) {
if (!vma_area_is(vma, VMA_AREA_VDSO)) {
pr_debug("Restore vDSO status by pfn/symtable at %lx\n",
@@ -169,12 +199,7 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid,
vma->e->status |= VMA_AREA_VDSO;
}
} else {
- /*
- * Compat vDSO mremap support is only after v4.8,
- * [vdso] vma name always stays after mremap.
- */
- if (unlikely(vma_area_is(vma, VMA_AREA_VDSO)) &&
- compel_mode_native(ctl)) {
+ if (unlikely(vma_area_is(vma, VMA_AREA_VDSO))) {
pr_debug("Drop mishinted vDSO status at %lx\n",
(long)vma->e->start);
vma->e->status &= ~VMA_AREA_VDSO;
--
2.13.1
More information about the CRIU
mailing list