Skip to content

Commit

Permalink
kerndat: Make pagemap check more robust against swapped out pages.
Browse files Browse the repository at this point in the history
Fix test of whether the kernel exposes page frame numbers to cope with the
possibility that the top of the stack is swapped out, which was happening
in about one 1 out of 3 million runs.  This lead to a later failure when
trying to read the PFN of the zero page, after which criu would exit with
no error message.

Original-From: Ambrose Feinstein <ambrose@google.com>
Signed-off-by: Michał Mirosław <emmir@google.com>
  • Loading branch information
osctobe committed Aug 25, 2023
1 parent 411db48 commit df753e2
Showing 1 changed file with 20 additions and 6 deletions.
26 changes: 20 additions & 6 deletions criu/kerndat.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,11 @@
#include "util-caps.h"

struct kerndat_s kdat = {};
volatile int dummy_var;

static int check_pagemap(void)
{
int ret, fd;
int ret, fd, retry;
u64 pfn = 0;

fd = __open_proc(PROC_SELF, EPERM, O_RDONLY, "pagemap");
Expand All @@ -72,11 +73,24 @@ static int check_pagemap(void)
return -1;
}

/* Get the PFN of some present page. Stack is here, so try it :) */
ret = pread(fd, &pfn, sizeof(pfn), (((unsigned long)&ret) / page_size()) * sizeof(pfn));
if (ret != sizeof(pfn)) {
pr_perror("Can't read pagemap");
return -1;
retry = 3;
while (retry--) {
++dummy_var;
/* Get the PFN of a page likely to be present. */
ret = pread(fd, &pfn, sizeof(pfn), PAGE_PFN((uintptr_t)&dummy_var) * sizeof(pfn));
if (ret != sizeof(pfn)) {
pr_perror("Can't read pagemap");
return -1;
}
/* The page can be swapped out by the time the read occurs,
* in which case the rest of the bits are a swap offset,
* and can't be used to determine whether PFNs are visible.
* Retry if this happens. */
if (pfn & PME_PRESENT)
break;
pr_warn("got non-present PFN %#lx for the dummy data page; %s\n", (unsigned long)pfn,
retry ? "retrying" : "giving up");
pfn = 0;
}

close(fd);
Expand Down

0 comments on commit df753e2

Please sign in to comment.