Skip to content
Advertisement

C program to mkdir in POSIX shared memory missing permissions

I have a POSIX shared memory directory which gets blown away on reboot and needs to be recreated on occasion. An example,

#include <sys/stat.h>
#include <sys/file.h>

int main(int argc, char argv[])
{
    struct stat st = {0};
    if (stat("/dev/shm/example", &st) == -1) {
        mkdir("/dev/shm/example", 0777);
    }
}

This creates the directory with missing write permissions for group/others:

drwxr-xr-x. 2 *** *** *** May 14 12:00 example

I’ve tried experimenting with the mode_t flags and even replaced “0777” with “S_IRWXU | S_IRWXG | S_IRWXO”. I do need the directory to have permission flag 0777.

Advertisement

Answer

You need to set the permission explicitly or reset your file creation mask with the umask() function.

Per the POSIX mkdir() documentation (bolding mine):

The mkdir() function shall create a new directory with name path. The file permission bits of the new directory shall be initialized from mode. These file permission bits of the mode argument shall be modified by the process’ file creation mask.

The only thread-safe way to create a file or directory with the exact permissions you want is to explicitly set them after creation:

mkdir("/dev/shm/example", 0777);
chmod("/dev/shm/example", 0777);

Of course, you’d do well to actually check the return values for those calls.

Calling umask() to set and restore your file creation mask is not thread-safe:

mode_t old = umask( 0 );
mkdir("/dev/shm/example", 0777);
umask( old );

There are multiple race conditions possible with doing that:

  • The old mask you get with the first call to umask() can be the 0 set by another thread
  • Either call can overwrite the value of the file creation mask currently in use by another thread

If either of those race conditions happens, either

  • your file/directory won’t get the permissions you need
  • the other thread’s file/directory won’t get the permissions it needs
  • the original file creation mask setting will be lost

Or all three.

So don’t call umask() when you need to set permission bits exactly. Set the mode explicitly with a call to [f]chmod()

(The possible issues that could arise from creating directories in /dev/shm is probably worth another question…)

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement