Skip to content

Commit 556d1c4

Browse files
mihalicynrst0git
authored andcommitted
criu/{mem, vdso, cr-restore}: introduce VMA_AREA_GUARD fake VMAs
Introduce a new kind of VMA - VMA_AREA_GUARD. In fact, it is not a real VMA as it is not represented as struct vm_area_struct in the kernel. We want to reuse an existing vma infrastructure in CRIU to dump an information about MADV_GUARD_INSTALL-covered address space ranges as VMAs. Then, on restore, we need to carefully skip those fake VMAs everywhere we expect a normal VMAs to be processed. And only in restorer we use these VMAs to get an information about where to call MADV_GUARD_INSTALL. Suggested-by: Andrei Vagin <[email protected]> Signed-off-by: Alexander Mikhalitsyn <[email protected]>
1 parent 6ca4d6f commit 556d1c4

File tree

4 files changed

+28
-4
lines changed

4 files changed

+28
-4
lines changed

criu/cr-restore.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2447,7 +2447,8 @@ static long restorer_get_vma_hint(struct list_head *tgt_vma_list, struct list_he
24472447

24482448
while (1) {
24492449
if (prev_vma_end + vma_len > s_vma->e->start) {
2450-
if (s_vma->list.next == self_vma_list) {
2450+
if ((s_vma->list.next == self_vma_list) ||
2451+
vma_area_is(vma_next(s_vma), VMA_AREA_GUARD)) {
24512452
s_vma = &end_vma;
24522453
continue;
24532454
}
@@ -2460,7 +2461,8 @@ static long restorer_get_vma_hint(struct list_head *tgt_vma_list, struct list_he
24602461
}
24612462

24622463
if (prev_vma_end + vma_len > t_vma->e->start) {
2463-
if (t_vma->list.next == tgt_vma_list) {
2464+
if ((t_vma->list.next == tgt_vma_list) ||
2465+
vma_area_is(vma_next(t_vma), VMA_AREA_GUARD)) {
24642466
t_vma = &end_vma;
24652467
continue;
24662468
}

criu/include/image.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@
6868
* processing exiting with error; while the rest of bits
6969
* are part of image ABI, this particular one must never
7070
* be used in image.
71+
* - guard
72+
* stands for a fake VMA (not represented in the kernel
73+
* by a struct vm_area_struct). Used to keep an information
74+
* about virtual address space ranges covered by
75+
* MADV_GUARD_INSTALL guards. These ones must be always at
76+
* the end of the vma_area_list and properly skipped a.e.
7177
*/
7278
#define VMA_AREA_NONE (0 << 0)
7379
#define VMA_AREA_REGULAR (1 << 0)
@@ -87,6 +93,7 @@
8793
#define VMA_AREA_AIORING (1 << 13)
8894
#define VMA_AREA_MEMFD (1 << 14)
8995
#define VMA_AREA_SHSTK (1 << 15)
96+
#define VMA_AREA_GUARD (1 << 16)
9097

9198
#define VMA_EXT_PLUGIN (1 << 27)
9299
#define VMA_CLOSE (1 << 28)

criu/mem.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,9 @@ static int __parasite_dump_pages_seized(struct pstree_item *item, struct parasit
599599
parent_predump_mode = mdc->parent_ie->pre_dump_mode;
600600

601601
list_for_each_entry(vma_area, &vma_area_list->h, list) {
602+
if (vma_area_is(vma_area, VMA_AREA_GUARD))
603+
continue;
604+
602605
ret = generate_vma_iovs(item, vma_area, pp, &xfer, args, ctl, &pmc, has_parent, mdc->pre_dump,
603606
parent_predump_mode);
604607
if (ret < 0)
@@ -861,14 +864,14 @@ static void prepare_cow_vmas_for(struct vm_area_list *vmas, struct vm_area_list
861864
/* <= here to shift from matching VMAs and ... */
862865
while (vma->e->start <= pvma->e->start) {
863866
vma = vma_next(vma);
864-
if (&vma->list == &vmas->h)
867+
if ((&vma->list == &vmas->h) || vma_area_is(vma, VMA_AREA_GUARD))
865868
return;
866869
}
867870

868871
/* ... no == here since we must stop on matching pair */
869872
while (pvma->e->start < vma->e->start) {
870873
pvma = vma_next(pvma);
871-
if (&pvma->list == &pvmas->h)
874+
if ((&pvma->list == &pvmas->h) || vma_area_is(pvma, VMA_AREA_GUARD))
872875
return;
873876
}
874877
}
@@ -1069,6 +1072,9 @@ static int premap_priv_vmas(struct pstree_item *t, struct vm_area_list *vmas, vo
10691072
filemap_ctx_init(true);
10701073

10711074
list_for_each_entry(vma, &vmas->h, list) {
1075+
if (vma_area_is(vma, VMA_AREA_GUARD))
1076+
continue;
1077+
10721078
if (task_size_check(vpid(t), vma->e)) {
10731079
ret = -1;
10741080
break;
@@ -1276,6 +1282,9 @@ static int restore_priv_vma_content(struct pstree_item *t, struct page_read *pr)
12761282
unsigned long size, i = 0;
12771283
void *addr = decode_pointer(vma->premmaped_addr);
12781284

1285+
if (vma_area_is(vma, VMA_AREA_GUARD))
1286+
continue;
1287+
12791288
if (!vma_inherited(vma))
12801289
continue;
12811290

criu/vdso.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,9 @@ static void drop_rt_vdso(struct vm_area_list *vma_area_list, struct vdso_quarter
145145
* Also BTW search for rt-vvar to remove it later.
146146
*/
147147
list_for_each_entry(vma, &vma_area_list->h, list) {
148+
if (vma_area_is(vma, VMA_AREA_GUARD))
149+
continue;
150+
148151
if (vma->e->start == addr->orig_vdso) {
149152
vma->e->status |= VMA_AREA_REGULAR | VMA_AREA_VDSO;
150153
pr_debug("vdso: Restore orig vDSO status at %lx\n", (long)vma->e->start);
@@ -276,6 +279,9 @@ int parasite_fixup_vdso(struct parasite_ctl *ctl, pid_t pid, struct vm_area_list
276279
}
277280

278281
list_for_each_entry(vma, &vma_area_list->h, list) {
282+
if (vma_area_is(vma, VMA_AREA_GUARD))
283+
continue;
284+
279285
/*
280286
* Defer handling marked vdso until we walked over
281287
* all vmas and restore potentially remapped vDSO

0 commit comments

Comments
 (0)