4
votes

I am trying to allocate memory blocks with MAP_ANONYMOUS flag, but it is not creating any memory blocks along with MAP_SHARED_VALIDATE flag, but MAP_ANONYMOUS with MAP_PRIVATE or MAP_SHARED flags creates the blocks of memory. Could someone explain why this happens.

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/mman.h>
#include <unistd.h>

int main(void)
{
  size_t size = getpagesize();

  errno = 0;
  void *first = mmap(0, size, PROT_READ|PROT_WRITE,
                     MAP_ANONYMOUS|MAP_SHARED_VALIDATE, -1, 0);
  printf("first: %p %s\n", first, strerror(errno));

  errno = 0;
  void *second = mmap(0, size, PROT_READ|PROT_WRITE,
                      MAP_ANONYMOUS|MAP_SHARED, -1, 0);
  printf("second: %p %s\n", second, strerror(errno));

  return 0;
}

has been observed to print, on both Linux 4.19 and Linux 5.8,

first: 0xffffffffffffffff Invalid argument
second: 0x7f56b274d000 Success

The flags seem to be getting passed down to the kernel accurately...

$ strace -e trace=mmap ./a.out 2>&1 | tail -n5
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED_VALIDATE|MAP_ANONYMOUS, -1, 0) = -1 EINVAL (Invalid argument)
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0) = 0x7fd3145bb000
first: 0xffffffffffffffff Invalid argument
second: 0x7fd3145bb000 Success
+++ exited with 0 +++
1
In your code sample, there is no difference between mmap calls (but then I'm not sure what you wanted to showcase with 2 calls). Also, your printf calls access out of bounds memory, as you haven't provided an argument for %p format. If mmap returns -1, you should look at errno and see what the error is first.Pawel Veselov
Note that the second call to mmap may change the value of errno, so you need to look at it immediately after each mmap call, something like: uint8_t *first = mmap(...); printf("first: %p %s\n", (void *)first, strerror(errno)); (repeat for second).zwol
I can reproduce the behavior reported (mmap failing, not the segfault) on Linux 5.8 and I have absolutely no idea why. errno is EINVAL. As best I can tell from the manpage, MAP_SHARED_VALIDATE | MAP_ANONYMOUS should be a valid combination of flags.zwol
Does your kernel support MAP_SHARED_VALIDATE? The man page says "since Linux 4.15".Ian Abbott
@AndrewHenle Edited into question.zwol

1 Answers

7
votes

Looking at do_mmap in linux/mm/mmap.c (kernel version 5.9), MAP_SHARED_VALIDATE only seems to be supported for file-backed mappings (see the if (file) and else sections). I do not know if that is a bug or if it is intentional.

EDIT: I have submitted a bug report.