diff --git a/criu.changes b/criu.changes index 800fcd6..d0632b9 100644 --- a/criu.changes +++ b/criu.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Thu Jan 23 15:03:04 UTC 2025 - Takashi Iwai + +- Fix the error "vdso: Unexpected rt vDSO area bounds" (bsc#1236330): + taken from the upstream bug tracker + https://github.com/checkpoint-restore/criu/pull/2539 + vdso-handle-vvar_vclock-vma-s.patch + ------------------------------------------------------------------- Thu Jan 23 10:57:38 UTC 2025 - Daniel Garcia diff --git a/criu.spec b/criu.spec index 33e387f..de72e82 100644 --- a/criu.spec +++ b/criu.spec @@ -46,6 +46,7 @@ Patch1: criu-py-install-fix.diff Patch2: 0002-Fix-build-with-nftables-installed-in-different-direc.patch Patch4: plugin-dir-path.patch Patch5: criu-ns-python3-shebang.patch +Patch6: vdso-handle-vvar_vclock-vma-s.patch BuildRequires: libcap-devel %if %{with_amdgpu_plugin} BuildRequires: libdrm-devel diff --git a/vdso-handle-vvar_vclock-vma-s.patch b/vdso-handle-vvar_vclock-vma-s.patch new file mode 100644 index 0000000..09836bf --- /dev/null +++ b/vdso-handle-vvar_vclock-vma-s.patch @@ -0,0 +1,178 @@ +From 60bd08b6a70cc0d7413dc4f80e64f07e6c31d274 Mon Sep 17 00:00:00 2001 +From: Andrei Vagin +Date: Thu, 5 Dec 2024 22:17:38 +0000 +Subject: [PATCH] vdso: handle vvar_vclock vma-s + +The vvar_vclock was introduced by [1]. Basically, the old vvar vma has +been splited on two parts. In term of C/R, these two vma-s can be still +treated as one. + +[1] e93d2521b27f ("x86/vdso: Split virtual clock pages into dedicated mapping") + +Signed-off-by: Andrei Vagin +--- + criu/include/util-vdso.h | 1 + + criu/pie/parasite-vdso.c | 19 ++++++++++++++++++- + criu/proc_parse.c | 23 +++++++++++++++++++---- + criu/vdso.c | 28 +++++++++++++++++++++------- + 4 files changed, 59 insertions(+), 12 deletions(-) + +diff --git a/criu/include/util-vdso.h b/criu/include/util-vdso.h +index c4386cf8ed..9fd9a6de4a 100644 +--- a/criu/include/util-vdso.h ++++ b/criu/include/util-vdso.h +@@ -30,6 +30,7 @@ struct vdso_symbol { + struct vdso_symtable { + unsigned long vdso_size; + unsigned long vvar_size; ++ unsigned long vvar_vclock_size; + struct vdso_symbol symbols[VDSO_SYMBOL_MAX]; + bool vdso_before_vvar; /* order of vdso/vvar pair */ + }; +diff --git a/criu/pie/parasite-vdso.c b/criu/pie/parasite-vdso.c +index 355007fa92..f3ad3107fe 100644 +--- a/criu/pie/parasite-vdso.c ++++ b/criu/pie/parasite-vdso.c +@@ -45,6 +45,7 @@ static int remap_one(char *who, unsigned long *from, unsigned long to, size_t si + static int park_at(struct vdso_maps *rt, unsigned long vdso, unsigned long vvar) + { + unsigned long vvar_size = rt->sym.vvar_size; ++ unsigned long vvar_vclock_size = rt->sym.vvar_vclock_size; + unsigned long vdso_size = rt->sym.vdso_size; + int ret; + +@@ -54,8 +55,24 @@ static int park_at(struct vdso_maps *rt, unsigned long vdso, unsigned long vvar) + + std_log_set_gettimeofday(NULL); /* stop using vdso for timings */ + +- if (vvar) ++ if (vvar) { ++ /* ++ * v6.13-rc1~172^2~9 splits the vvar vma in two parts vvar and ++ * vvar_clock. The last one is mapped right after the first ++ * one. ++ */ ++ if (vvar_vclock_size) { ++ unsigned long from; ++ ++ vvar_size -= vvar_vclock_size; ++ from = rt->vvar_start + vvar_size; ++ ++ ret = remap_one("rt-vvar", &from, vvar + vvar_size, vvar_vclock_size); ++ if (ret) ++ return ret; ++ } + ret = remap_one("rt-vvar", &rt->vvar_start, vvar, vvar_size); ++ } + + if (!ret) + vdso_update_gtod_addr(rt); +diff --git a/criu/proc_parse.c b/criu/proc_parse.c +index 95ebe3a411..6c4303e7dd 100644 +--- a/criu/proc_parse.c ++++ b/criu/proc_parse.c +@@ -579,7 +579,8 @@ static int handle_vma(pid_t pid, struct vma_area *vma_area, const char *file_pat + } else if (!strcmp(file_path, "[vdso]")) { + if (handle_vdso_vma(vma_area)) + goto err; +- } else if (!strcmp(file_path, "[vvar]")) { ++ } else if (!strcmp(file_path, "[vvar]") || ++ !strcmp(file_path, "[vvar_vclock]")) { + if (handle_vvar_vma(vma_area)) + goto err; + } else if (!strcmp(file_path, "[heap]")) { +@@ -771,7 +772,7 @@ static int task_size_check(pid_t pid, VmaEntry *entry) + + int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, dump_filemap_t dump_filemap) + { +- struct vma_area *vma_area = NULL; ++ struct vma_area *vma_area = NULL, *prev_vma_area = NULL; + unsigned long start, end, pgoff, prev_end = 0; + char r, w, x, s; + int ret = -1, vm_file_fd = -1; +@@ -813,8 +814,22 @@ int parse_smaps(pid_t pid, struct vm_area_list *vma_area_list, dump_filemap_t du + continue; + } + +- if (vma_area && vma_list_add(vma_area, vma_area_list, &prev_end, &vfi, &prev_vfi)) +- goto err; ++ if (vma_area && vma_area_is(vma_area, VMA_AREA_VVAR) && ++ prev_vma_area && vma_area_is(prev_vma_area, VMA_AREA_VVAR)) { ++ if (prev_vma_area->e->end != vma_area->e->start) { ++ pr_err("two nonconsecutive vvar vma-s: " ++ "%" PRIx64 "-%" PRIx64 " %" PRIx64 "-%" PRIx64 "\n", ++ prev_vma_area->e->start, prev_vma_area->e->end, ++ vma_area->e->start, vma_area->e->end); ++ goto err; ++ } ++ /* Merge all vvar vma-s into one. */ ++ prev_vma_area->e->end = vma_area->e->end; ++ } else { ++ if (vma_area && vma_list_add(vma_area, vma_area_list, &prev_end, &vfi, &prev_vfi)) ++ goto err; ++ prev_vma_area = vma_area; ++ } + + if (eof) + break; +diff --git a/criu/vdso.c b/criu/vdso.c +index 7de2fae784..d4d3511314 100644 +--- a/criu/vdso.c ++++ b/criu/vdso.c +@@ -310,7 +310,7 @@ static int vdso_parse_maps(pid_t pid, struct vdso_maps *s) + + while (1) { + unsigned long start, end; +- char *has_vdso, *has_vvar; ++ char *has_vdso, *has_vvar, *has_vvar_vclock; + + buf = breadline(&f); + if (buf == NULL) +@@ -318,13 +318,19 @@ static int vdso_parse_maps(pid_t pid, struct vdso_maps *s) + if (IS_ERR(buf)) + goto err; + +- has_vdso = strstr(buf, "[vdso]"); +- if (!has_vdso) ++ has_vvar = NULL; ++ has_vvar_vclock = NULL; ++ do { ++ has_vdso = strstr(buf, "[vdso]"); ++ if (has_vdso) ++ break; + has_vvar = strstr(buf, "[vvar]"); +- else +- has_vvar = NULL; ++ if (has_vvar) ++ break; ++ has_vvar_vclock = strstr(buf, "[vvar_vclock]"); ++ } while (0); + +- if (!has_vdso && !has_vvar) ++ if (!has_vdso && !has_vvar && !has_vvar_vclock) + continue; + + if (sscanf(buf, "%lx-%lx", &start, &end) != 2) { +@@ -339,13 +345,21 @@ static int vdso_parse_maps(pid_t pid, struct vdso_maps *s) + } + s->vdso_start = start; + s->sym.vdso_size = end - start; +- } else { ++ } else if (has_vvar) { + if (s->vvar_start != VVAR_BAD_ADDR) { + pr_err("Got second VVAR entry\n"); + goto err; + } + s->vvar_start = start; + s->sym.vvar_size = end - start; ++ } else { ++ if (s->vvar_start == VDSO_BAD_ADDR || ++ s->vvar_start + s->sym.vvar_size != start) { ++ pr_err("VVAR and VVAR_VCLOCK entries are not subsequent\n"); ++ goto err; ++ } ++ s->sym.vvar_vclock_size = end - start; ++ s->sym.vvar_size += s->sym.vvar_vclock_size; + } + } +