Search code examples
clinuxfile-permissionsmqueue

mq_open's oflag argument doesn't reflect actual access bits of created mqueue file


I'm calling mq_open on linux 5.5.6 like so:

mq_open("/testing12345", O_RDWR | O_CREAT | O_NONBLOCK, 0777, & (struct mq_attr) {0, 10, 255, 0));

Note that I passed 0777 as the 3rd argument.

The function succeeds and the appropriate mqueue is created, after which I mount the mqueue filesystem from my shell:

mount -t mqueue none ./mqueue_dir

However, stat-ing the new mqueue's node reveals 0755 as the access bits:

stat -c %a ./mqueue_dir/testing12345

0755

Why is that? I clearly passed the 0777 constant when calling mq_open.


Reproducible example

compiled with gcc -Wall -Werror -lrt a.c -o ./a

#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <mqueue.h>
#include <sys/types.h>
#include <sys/stat.h>

int main(void) {
    const mqd_t descriptor = mq_open("/testing12345", O_RDWR | O_CREAT | O_NONBLOCK, 0777, & (struct mq_attr) {0, 10, 255, 0});
    if(descriptor == -1) {
        perror("parent: failed opening mqueue");
        return EXIT_FAILURE;
    }

    sleep(30u);

    mq_unlink("/testing123");

    return EXIT_SUCCESS;
}

Solution

  • Your "file creation mask" setting is almost certainly set to 022, thereby "masking" the 0777 you specified "down" to 0755.

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

    NAME

    umask - set and get the file mode creation mask

    SYNOPSIS

    #include <sys/stat.h>
    
    mode_t umask(mode_t cmask);
    

    DESCRIPTION

    The umask() function shall set the file mode creation mask of the process to cmask and return the previous value of the mask. Only the file permission bits of cmask (see <sys/stat.h>) are used; the meaning of the other bits is implementation-defined.

    The file mode creation mask of the process is used to turn off permission bits in the mode argument supplied during calls to the following functions:

    • open(), openat(), creat(), mkdir(), mkdirat(), mkfifo(), and mkfifoat()

    • mknod(), mknodat()

    • mq_open()

    • sem_open()

    Bit positions that are set in cmask are cleared in the mode of the created file.

    See also When is umask() useful?.

    Effectively, in order to ensure the file(s) you create have a specific mode, you either have to blank out the file creation mask with umask( 0 ), or you have to explicitly set the exact mode you want after you create the file. Since calling umask() affects the state of the entire process, it's almost always better to explicitly set the mode directly.