Skip to content

Instantly share code, notes, and snippets.

@wjt
Last active November 23, 2018 10:15
Show Gist options
  • Select an option

  • Save wjt/2407e426f63cc49b5350ac5c4d5c8034 to your computer and use it in GitHub Desktop.

Select an option

Save wjt/2407e426f63cc49b5350ac5c4d5c8034 to your computer and use it in GitHub Desktop.

Demonstrates that unmounting a filesystem with MNT_DETACH allows open file descriptors on that filesystem to be inherited by new children of processes than already held them open. I believe this is expected behaviour from the definition of the flag in man 2 umount2.

Steps:

$ gcc -o forkme forkme.c
$ mkdir /tmp/real /tmp/bind
$ sudo mount --bind /tmp/real /tmp/bind
$ ./forkme /tmp/bind/foo
[ wait for confirmation that it has opened & written to the file ]
[ in another shell ]
$ sudo umount --lazy /tmp/bind
[ back in the first shell, press any key ]
$ cat /tmp/real/foo
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <inttypes.h>
int
main (int argc,
char **argv)
{
if (argc != 2 ||
strcmp (argv[1], "--help") == 0 ||
strcmp (argv[1], "-h") == 0)
{
fprintf (stderr, "Usage: %s PATH", argv[0]);
return 1;
}
int fd = creat (argv[1], 0644);
if (fd < 0)
{
perror ("open");
return 2;
}
char hello_from_parent[] = "hello from parent\n";
ssize_t written = write (fd, hello_from_parent, sizeof (hello_from_parent) - 1);
if (written < 0)
{
perror ("write");
return 2;
}
printf ("%ld bytes written to %s\n"
"unmount its filesystem with --lazy, then press any key to fork a child\n", written, argv[1]);
char in;
if (fread (&in, 1, 1, stdin) <= 0)
{
perror ("fread");
return 3;
}
pid_t p = fork ();
if (p == 0)
{
char hello_from_child[] = "hello from child\n";
written = write (fd, hello_from_child, sizeof (hello_from_child) - 1);
if (written < 0)
{
perror ("write in child");
return 4;
}
}
else if (p < 0)
{
perror ("fork");
return 4;
}
else
{
int status;
if (waitpid (p, &status, 0) < 0)
{
perror ("waitpid");
return 5;
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment