From 2c9ee0abd2f18acde879cdc38c967caf8b7eafa4 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Wed, 6 May 2026 02:21:33 +0000 Subject: [PATCH] restore: update prev_vma_end after processing the last vma in a list Here is actually two issues: First, prev_vma_end isn't updated properly after processing the last vma in a list. Second, a dummy end_vma isn't fully initialized and vma_area_is can access uninitilized data. Signed-off-by: Andrei Vagin --- criu/cr-restore.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index eae261619..75afc2415 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -2487,36 +2487,48 @@ static long restorer_get_vma_hint(struct list_head *tgt_vma_list, struct list_he end_e.start = end_e.end = kdat.task_size; INIT_LIST_HEAD(&end_vma.list); + /* Both lists should not be empty. */ s_vma = list_first_entry(self_vma_list, struct vma_area, list); t_vma = list_first_entry(tgt_vma_list, struct vma_area, list); while (1) { if (prev_vma_end + vma_len > s_vma->e->start) { + if (s_vma == &end_vma) + break; + + if (prev_vma_end < s_vma->e->end) + prev_vma_end = s_vma->e->end; + /* + * VMA_AREA_GUARD entries are synthetic and they are + * always after real vma entries. + */ if ((s_vma->list.next == self_vma_list) || vma_area_is(vma_next(s_vma), VMA_AREA_GUARD)) { s_vma = &end_vma; continue; } - if (s_vma == &end_vma) - break; - if (prev_vma_end < s_vma->e->end) - prev_vma_end = s_vma->e->end; + s_vma = vma_next(s_vma); - continue; } if (prev_vma_end + vma_len > t_vma->e->start) { + if (t_vma == &end_vma) + break; + + if (prev_vma_end < t_vma->e->end) + prev_vma_end = t_vma->e->end; + + /* + * VMA_AREA_GUARD entries are synthetic and they are + * always after real vma entries. + */ if ((t_vma->list.next == tgt_vma_list) || vma_area_is(vma_next(t_vma), VMA_AREA_GUARD)) { t_vma = &end_vma; continue; } - if (t_vma == &end_vma) - break; - if (prev_vma_end < t_vma->e->end) - prev_vma_end = t_vma->e->end; + t_vma = vma_next(t_vma); - continue; } return prev_vma_end;