MREMAP_DONTUNMAP corrupts initial mapping

From: stsp
Date: Thu Mar 30 2023 - 08:38:56 EST


Hello.

Attached is a small test-case that
demonstrates the problem.
The problem happens if you change
some data in a file-backed private
mapping and then use mremap on
it with MREMAP_DONTUNMAP flag.
The result is:
- destination copy is valid
- source copy restored from the original file

So the 2 copies do not match.
#define _GNU_SOURCE
#include <sys/mman.h>
#include <assert.h>
#include <stdlib.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif

int main(void)
{
const char *file = "mretst.c";
char *addr, *addr2;
int fd;
char c;

fd = open (file, O_RDONLY);
if (fd == -1)
return EXIT_FAILURE;
addr = mmap (NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
close(fd);
if (addr == MAP_FAILED)
return EXIT_FAILURE;
c = addr[0];
assert(addr[0]);
addr[0] = 0;
assert(!addr[0]);
addr2 = mremap (addr, PAGE_SIZE, PAGE_SIZE,
MREMAP_MAYMOVE | MREMAP_DONTUNMAP);
assert(!addr2[0]);
if (addr[0] == c)
printf("Test FAILED\n");
else
printf("Test PASSED\n");
return 0;
}