0

If I perform a mmap() on some file or a device in /dev/ that exposes memory, what happens to that mapping if the file is deleted or that device disconnected?

I've written a test program to experiment but I can't find any solid documentation on what should happen. The test program does the following

#include <stdio.h>
#include <fcntl.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/mman.h>

int main()
{
    int fd = open("test_file", O_CREAT | O_RDWR);

    uint32_t data[10000] = {0};
    data[3] = 22;
    write(fd, data, sizeof data);
    sync();
    
    struct stat s;
    fstat(fd, &s);
    
    uint32_t *map = (uint32_t *)mmap(NULL, s.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    close(fd);
    
    sleep(10);
    
    printf("%u\n", *(map+3));
    *(map+9000) = 91;
    printf("%u\n", *(map+9000));

    return 0;
}

My page size is 4096 bytes so I made the file larger than that so the map would span multiple pages. During that 10s sleep I run the following commands:

$ rm test_file
$ sync; echo 3 > /proc/sys/vm/drop_caches

Which I believe should destroy the backing file of the map and remove all pages so that it must seek the backing file out to perform any operations on it. Then after that 10s sleep the program attempts to read from page 1 and w/r to page 3.

Surprisingly the 2 values I get printed back out are 22 and 91

Why does this happen, is this behavior guaranteed or undefined? Is it because I was using a regular file and not a device? What if the mapping was really large, would things change? Should I expect to get a SIGSEGV or a SIGBUS under some conditions?

  • 1
    `is this behavior guaranteed` you mean, that you can read from removed a file? Does https://stackoverflow.com/questions/2028874/what-happens-to-an-open-file-handle-on-linux-if-the-pointed-file-gets-moved-or-d answer your question? https://stackoverflow.com/questions/19441823/a-file-opened-for-read-and-write-can-be-unlinked – KamilCuk Apr 29 '22 at 16:23
  • @KamilCuk Mainly that it won't crash or access out of bounds memory. Does it maintain some sort of copy of the map + zeroed space for un-accessed pages that you can continue to use (even if the data is wrong)? If it's shared do multiple programs see the same space? – dazed_and_confused Apr 29 '22 at 16:26
  • @KamilCuk I think those links answer the question when referring to a regular file, assuming mmap maintains the descriptor behind the scenes, but the non-regular files are still unanswered. someone mentioned you'll probably get i/o errors if a device is disconnected, so how will it present itself when using your map pointer for reading and writing? can you check for it? – dazed_and_confused Apr 29 '22 at 20:11
  • 1
    What you're seeing is [undefined behavior](https://en.wikipedia.org/wiki/Undefined_behavior). Don't do it. And *CERTAINLY* don't expect identical behavior from platform to platform! Or device to device. Or even necessarily from test run to test run... – paulsm4 Apr 30 '22 at 00:42

2 Answers2

1

rm just unlinks the file from a location in the filesystem (removes it from a directory). If there are other references to the file (such as a process that has it open), the file won't actually be removed -- the OS keeps a reference count of all the references to the file and only deletes it when the reference count drop to 0.

So in this case, the reference count will still be non-zero after the rm as the process has the file open. Only when the files is unmapped and closed (which happens when the process exits) will the file actually be deleted.

In the case of a device, the device file (in the filesystem) is similarly just a reference to the device driver. Removing it won't have any effect. However, if the device itself has some concept of being removed (such as removable storage), doing that will result in future access returning some error.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • where would this error be returned if I did something like trying to read or write to the mmap pointer? in errno, or somewhere else? Or by error do you mean I'd get a SIGBUS signal? – dazed_and_confused Apr 29 '22 at 22:53
-1

What happens if you try to read/write a mapping with a deleted ... file

You will still write to that file. rm only unlinks the name from the directory, the file still exists.

disconnected backing ... device?

The process will receive a SIGBUS signal.

Why does this happen, is this behavior guaranteed or undefined?

Guaranteed, files keep reference count since always.

Is it because I was using a regular file and not a device?

No. A device kind of is a regular file. You can open("/dev/sda" and write to it and rm /dev/sda. In Linux almost everything is a regular file. A file has only one more layer of indirection in kernel - a filesystem.

What if the mapping was really large, would things change?

Should I expect to get a SIGSEGV or a SIGBUS under some conditions?

See man mmap. Search for SIGBUS.

KamilCuk
  • 120,984
  • 8
  • 59
  • 111