Message ID | 049f0da40ed76d94c419f83dd42deb413d6afb44.1737000287.git.tavianator@tavianator.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | coredump: allow interrupting dumps of large anonymous regions | expand |
diff --git a/fs/coredump.c b/fs/coredump.c index d48edb37bc35..fd29d3f15f1e 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -950,6 +950,10 @@ int dump_user_range(struct coredump_params *cprm, unsigned long start, } } else { dump_skip(cprm, PAGE_SIZE); + if (dump_interrupted()) { + dump_page_free(dump_page); + return 0; + } } cond_resched(); }
dump_user_range() supports sparse core dumps by skipping anonymous pages which have not been modified. If get_dump_page() returns NULL, the page is skipped rather than written to the core dump with dump_emit_page(). Sadly, dump_emit_page() contains the only check for dump_interrupted(), so when dumping a very large sparse region, the core dump becomes effectively uninterruptible. This can be observed with the following test program: #include <stdlib.h> #include <stdio.h> #include <sys/mman.h> int main(void) { char *mem = mmap(NULL, 1ULL << 40, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE, -1, 0); printf("%p %m\n", mem); if (mem != MAP_FAILED) { mem[0] = 1; } abort(); } The program allocates 1 TiB of anonymous memory, touches one page of it, and aborts. During the core dump, SIGKILL has no effect. It takes about 30 seconds to finish the dump, burning 100% CPU. This issue naturally arises with things like Address Sanitizer, which allocate a large sparse region of virtual address space for their shadow memory. Fix it by checking dump_interrupted() explicitly in dump_user_pages(). Signed-off-by: Tavian Barnes <tavianator@tavianator.com> --- fs/coredump.c | 4 ++++ 1 file changed, 4 insertions(+)