Discussion:
mq_open - permission denied
(too old to reply)
gogol
2011-05-21 13:53:11 UTC
Permalink
I try to get a comm channel between the request handler of Apache2 and
another process referred to as app process. The request handler
process and the app process are owned by different users (request
handler process has uid of 1, the app process has uid of 1000). The
app process creates successfully a message queue with the following
code:

/* set the message queue attributes */
struct mq_attr attr;
attr.mq_maxmsg = max_msgs;
attr.mq_msgsize = max_msgsize;
attr.mq_flags = O_NONBLOCK;

errno = 0;
mqd_t msgQ = mq_open(
mqname, /* message queue name */
O_RDWR | O_NONBLOCK | O_CREAT | O_EXCL, /* oflag */
S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH |
S_IWOTH | S_IXOTH, /* mode */
&attr); /* attributes */

The request handler attempts to open that (existing) messaege queue
with:

mqd_t msgQ = mq_open(
mqname, /* message queue name */
O_RDWR | O_NONBLOCK); /* mode */

The attempt to open the existing message queue fails with errno=13 -
permission denied.
The opening of the existing message queue works fine if attempted from
a process that has the same owner as the process that created the
message queue - in this case the app process. Any help will be
appreciated. Thx.
Rainer Weikusat
2011-05-22 20:42:27 UTC
Permalink
Post by gogol
I try to get a comm channel between the request handler of Apache2 and
another process referred to as app process. The request handler
process and the app process are owned by different users (request
handler process has uid of 1, the app process has uid of 1000). The
app process creates successfully a message queue with the following
/* set the message queue attributes */
struct mq_attr attr;
attr.mq_maxmsg = max_msgs;
attr.mq_msgsize = max_msgsize;
attr.mq_flags = O_NONBLOCK;
errno = 0;
mqd_t msgQ = mq_open(
mqname, /* message queue name */
O_RDWR | O_NONBLOCK | O_CREAT | O_EXCL, /* oflag */
S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH |
S_IWOTH | S_IXOTH, /* mode */
&attr); /* attributes */
Making a message queue executable makes preciously little sense. Also,
do yourself a favor and ignore this set of inpronouncible acronyms in
favor of using octal numbers, like everyone else does. The values are
actually standardized as

0400 owner read
0200 owner write
0100 owner execute

with 'group' and 'other' permission encoded just like that, but using
00x0 for group permissions and 000x for other permissions. This reduces
the ASCII character flatworm to a simple 0777 (0666 in order to omit
the execute permission).
Post by gogol
The request handler attempts to open that (existing) messaege queue
mqd_t msgQ = mq_open(
mqname, /* message queue name */
O_RDWR | O_NONBLOCK); /* mode */
The attempt to open the existing message queue fails with errno=13 -
permission denied.
Only the first two arguments to mq_open have standardized
semantics. At least on Linux, the third argument is interpreted like
all other access permission arguments, meaning, a set of effective
permission bits is calculated by masking the bits which are currently
set in the umask of the executing process. Assuming that x is your
input value, the value which gets applied is actually

x & ~umask

and umask will usually by 022 or 002, cause the group write and other
write bits to be disabled.
gogol
2011-05-22 21:42:29 UTC
Permalink
Post by Rainer Weikusat
Post by gogol
I try to get a comm channel between the request handler of Apache2 and
another process referred to as app process. The request handler
process and the app process are owned by different users (request
handler process has uid of 1, the app process has uid of 1000). The
app process creates successfully a message queue with the following
/* set the message queue attributes */
struct mq_attr attr;
attr.mq_maxmsg  = max_msgs;
attr.mq_msgsize = max_msgsize;
attr.mq_flags   = O_NONBLOCK;
errno = 0;
mqd_t msgQ = mq_open(
   mqname, /* message queue name */
   O_RDWR | O_NONBLOCK | O_CREAT | O_EXCL, /* oflag */
   S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH |
S_IWOTH | S_IXOTH, /* mode */
   &attr); /* attributes */
Making a message queue executable makes preciously little sense. Also,
do yourself a favor and ignore this set of inpronouncible acronyms in
favor of using octal numbers, like everyone else does. The values are
actually standardized as
        0400    owner read
        0200    owner write
        0100    owner execute
with 'group' and 'other' permission encoded just like that, but using
00x0 for group permissions and 000x for other permissions. This reduces
the ASCII character flatworm to a simple 0777 (0666 in order to omit
the execute permission).
Post by gogol
The request handler attempts to open that (existing) messaege queue
mqd_t msgQ = mq_open(
   mqname,               /* message queue name */
   O_RDWR | O_NONBLOCK); /* mode */
The attempt to open the existing message queue fails with errno=13 -
permission denied.
Only the first two arguments to mq_open have standardized
semantics. At least on Linux, the third argument is interpreted like
all other access permission arguments, meaning, a set of effective
permission bits is calculated by masking the bits which are currently
set in the umask of the executing process. Assuming that x is your
input value, the value which gets applied is actually
        x & ~umask
and umask will usually by 022 or 002, cause the group write and other
write bits to be disabled.
Thx for your response Rainer. Do you have any suggestion on how to
transfer data between an app process and the request handler process
of Apache? I tried to create a message queue in Apache main init
process, and open it within an app process. That works. The problem is
that the request handler process (a child process of Apache main
process) cannot open the message queue, so the request handler is
still unable to communicate with an app process.

Gogol
Rainer Weikusat
2011-05-23 10:14:18 UTC
Permalink
[...]
Post by gogol
errno = 0;
mqd_t msgQ = mq_open(
   mqname, /* message queue name */
   O_RDWR | O_NONBLOCK | O_CREAT | O_EXCL, /* oflag */
   S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH |
S_IWOTH | S_IXOTH, /* mode */
   &attr); /* attributes */
[...]
Post by gogol
The request handler attempts to open that (existing) messaege queue
mqd_t msgQ = mq_open(
   mqname,               /* message queue name */
   O_RDWR | O_NONBLOCK); /* mode */
The attempt to open the existing message queue fails with errno=13 -
permission denied.
[...]
Assuming that x is your> input value, the value which gets applied
is actually
        x & ~umask
and umask will usually by 022 or 002, cause the group write and other
write bits to be disabled.
[...]
I tried to create a message queue in Apache main init process, and
open it within an app process. That works. The problem is that the
request handler process (a child process of Apache main process)
cannot open the message queue,
As I already wrote: Most likely, your problem is that the 'other
write' permission bit you gave in the mq_open call used to create the
message queue got disabled because the umask setting of the apache
process requested this to be done. Provided this was actually the case
(apache inherits the umask from the shell it was started from), you
could change the umask before creating the message queue, eg, by doing
something like this:

mode_t omask;

omask = umask(0); /* use permissions as specified */
mq_t = mq_open(...);
umask(omask);
gogol
2011-05-23 13:15:27 UTC
Permalink
Post by Rainer Weikusat
[...]
Post by gogol
errno = 0;
mqd_t msgQ = mq_open(
   mqname, /* message queue name */
   O_RDWR | O_NONBLOCK | O_CREAT | O_EXCL, /* oflag */
   S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH |
S_IWOTH | S_IXOTH, /* mode */
   &attr); /* attributes */
[...]
Post by gogol
The request handler attempts to open that (existing) messaege queue
mqd_t msgQ = mq_open(
   mqname,               /* message queue name */
   O_RDWR | O_NONBLOCK); /* mode */
The attempt to open the existing message queue fails with errno=13 -
permission denied.
[...]
Assuming that x is your> input value, the value which gets applied
is actually
        x & ~umask
and umask will usually by 022 or 002, cause the group write and other
write bits to be disabled.
[...]
I tried to create a message queue in Apache main init process, and
open it within an app process. That works. The problem is that the
request handler process (a child process of Apache main process)
cannot open the message queue,
As I already wrote: Most likely, your problem is that the 'other
write' permission bit you gave in the mq_open call used to create the
message queue got disabled because the umask setting of the apache
process requested this to be done. Provided this was actually the case
(apache inherits the umask from the shell it was started from), you
could change the umask before creating the message queue, eg, by doing
        mode_t omask;
        omask = umask(0);       /* use permissions as specified */
        mq_t = mq_open(...);
        umask(omask);
It doesn't seem to make any difference. This is what I have in the
message queue creation:

mode_t omask = umask(0666);
printf("1st call to umask returned %o\n", omask);
printf("2nd call to umask returned %o\n", umask(0666));
mdq_t mq = mq_open("/mqname", O_RDWR | O_NONBLOCK | O_CREAT |
O_EXCL, 0666, &attr);
umask(omask);
if (mq < 0)
{
printf("mq_open() failed, errno=%d\n", errno);
return 0;
}
printf("mq_open successful\n");

The execution of this code shows:
1st call to unmask returned 22
2nd call to unmask return 777
mq_open() successful

In the Apache request handler I simply try (while the process that
created the queue is still running and the queue is not closed):

mqd_t mq = mq_open("/mqname", O_RDWR | O_NONBLOCK);

It fails with errno-13 - permission denied.

Phew...
Thx,
Rainer Weikusat
2011-05-23 14:19:24 UTC
Permalink
[...]
Post by gogol
Post by Rainer Weikusat
        mode_t omask;
        omask = umask(0);       /* use permissions as specified */
        mq_t = mq_open(...);
        umask(omask);
It doesn't seem to make any difference. This is what I have in the
mode_t omask = umask(0666);
Rest assured that it does: You are now creating the message queue with
all read and write permission bits disabled.
gogol
2011-05-23 23:34:56 UTC
Permalink
Post by Rainer Weikusat
[...]
Post by gogol
Post by Rainer Weikusat
        mode_t omask;
        omask = umask(0);       /* use permissions as specified */
        mq_t = mq_open(...);
        umask(omask);
It doesn't seem to make any difference. This is what I have in the
    mode_t omask = umask(0666);
Rest assured that it does: You are now creating the message queue with
all read and write permission bits disabled.
Your are right Rainer, the umask(0) does the trick. When I tried the
first time umask(0) I had the queue undeleted. Now I do the cleaning
and it works fine. Thx a bunch.
Scott Lurndal
2011-05-23 16:34:44 UTC
Permalink
Post by Rainer Weikusat
Post by Rainer Weikusat
[...]
write' permission bit you gave in the mq_open call used to create the
message queue got disabled because the umask setting of the apache
process requested this to be done. Provided this was actually the case
(apache inherits the umask from the shell it was started from), you
could change the umask before creating the message queue, eg, by doing
=A0 =A0 =A0 =A0 mode_t omask;
=A0 =A0 =A0 =A0 omask =3D umask(0); =A0 =A0 =A0 /* use permissions as spe=
cified */
Post by Rainer Weikusat
=A0 =A0 =A0 =A0 mq_t =3D mq_open(...);
=A0 =A0 =A0 =A0 umask(omask);
It doesn't seem to make any difference. This is what I have in the
mode_t omask =3D umask(0666);
So, when Rainer suggested "umask(0)", why did use umask(0666)?

You are masking off write permission for everyone.

scott
gogol
2011-05-23 19:28:50 UTC
Permalink
Post by Scott Lurndal
Post by Rainer Weikusat
Post by Rainer Weikusat
[...]
write' permission bit you gave in the mq_open call used to create the
message queue got disabled because the umask setting of the apache
process requested this to be done. Provided this was actually the case
(apache inherits the umask from the shell it was started from), you
could change the umask before creating the message queue, eg, by doing
=A0 =A0 =A0 =A0 mode_t omask;
=A0 =A0 =A0 =A0 omask =3D umask(0); =A0 =A0 =A0 /* use permissions as spe=
cified */
Post by Rainer Weikusat
=A0 =A0 =A0 =A0 mq_t =3D mq_open(...);
=A0 =A0 =A0 =A0 umask(omask);
It doesn't seem to make any difference. This is what I have in the
   mode_t omask =3D umask(0666);
So, when Rainer suggested "umask(0)", why did use umask(0666)?
You are masking off write permission for everyone.
scott
This is the description of umask function:
-----------------------------------------------------------------------------------------------------
Synopsis
#include <sys/types.h>
#include <sys/stat.h>

mode_t umask(mode_t mask);
Description
umask() sets the calling process's file mode creation mask (umask) to
mask & 0777.
----------------------------------------------------------------------------------------------------------

So, if I call umask(0), then the mode creation mask is: 0 & 0777,
which is 0. I.e. all bits are reset. Anyways, against my logic, I
tried with umask(0) and got the same result in the request handler
when tried to open the message queue: errno=13 - permission denied.
If you guys see something wrong in what I am doing, please let me
know. I am really in a deep hole with my project.
Thx.
Rainer Weikusat
2011-05-24 10:29:13 UTC
Permalink
gogol <***@gmail.com> writes:

[...]
Post by gogol
-----------------------------------------------------------------------------------------------------
Synopsis
#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
Description
umask() sets the calling process's file mode creation mask (umask) to
mask & 0777.
----------------------------------------------------------------------------------------------------------
So, if I call umask(0), then the mode creation mask is: 0 & 0777,
which is 0. I.e. all bits are reset.
It is often helpful to read a text completely before believing to know
what it was meant to say. Specifically, the text you partially quoted
continues with

(i.e., only the file permission bits of mask are used)

which means that if you use, say, 04022 as argument (04000 is the
set-user-id bit), the resulting umask will be 022. Somewhat later in
the same text, you could find this sentence:

Specifically, permissions in the umask are turned off from the
mode argument to open(2) and mkdir(2).

which is what I wrote in my reply to your original post.

gogol
2011-05-23 13:18:48 UTC
Permalink
Post by Rainer Weikusat
[...]
Post by gogol
errno = 0;
mqd_t msgQ = mq_open(
   mqname, /* message queue name */
   O_RDWR | O_NONBLOCK | O_CREAT | O_EXCL, /* oflag */
   S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH |
S_IWOTH | S_IXOTH, /* mode */
   &attr); /* attributes */
[...]
Post by gogol
The request handler attempts to open that (existing) messaege queue
mqd_t msgQ = mq_open(
   mqname,               /* message queue name */
   O_RDWR | O_NONBLOCK); /* mode */
The attempt to open the existing message queue fails with errno=13 -
permission denied.
[...]
Assuming that x is your> input value, the value which gets applied
is actually
        x & ~umask
and umask will usually by 022 or 002, cause the group write and other
write bits to be disabled.
[...]
I tried to create a message queue in Apache main init process, and
open it within an app process. That works. The problem is that the
request handler process (a child process of Apache main process)
cannot open the message queue,
As I already wrote: Most likely, your problem is that the 'other
write' permission bit you gave in the mq_open call used to create the
message queue got disabled because the umask setting of the apache
process requested this to be done. Provided this was actually the case
(apache inherits the umask from the shell it was started from), you
could change the umask before creating the message queue, eg, by doing
        mode_t omask;
        omask = umask(0);       /* use permissions as specified */
        mq_t = mq_open(...);
        umask(omask);
Need to make a correction to my previous response:

1st call to unmask returned 22
2nd call to unmask returned 666
mq_open() successful
Loading...