C msgget() w/o IPC_CREAT -> Permission denied (sometimes)

The workaround for the following problem is trivial, but I'm still curious about what's going on.

If you call msgget(2) with a positive key and a zero msgflg, it works as advertised. But if msgflg is octal 0100, you get "Permission denied". No other bit in the final nine bits of the flag makes this happen. What's going on? For example, you get this (with a possibly different message ID):

Code:
ipcrm -q -1
set -e
cc -Werror -Wall 3a.c -o 3a
cc -Werror -Wall 3b.c -o 3b
cc -Werror -Wall 3c.c -o 3c
set +e
./3a
3932161
./3b
3932161
./3c
msgget: Permission denied

when you run this shell script:

Code:
#!/bin/sh

cat <<EOD > 3a.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
int main(void)
{
  int result=msgget(5,IPC_CREAT | 0777);
  if(result==-1)
  {
    perror("msgget");
  }
  else
  {
    printf("%d\n",result);
  }
  return 0;
} /* main() */
EOD
cat <<EOD > 3b.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
int main(void)
{
  int result=msgget(5,0000);
  if(result==-1)
  {
    perror("msgget");
  }
  else
  {
    printf("%d\n",result);
  }
  return 0;
} /* main() */
EOD
cat <<EOD > 3c.c
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
int main(void)
{
  int result=msgget(5,0100);
  if(result==-1)
  {
    perror("msgget");
  }
  else
  {
    printf("%d\n",result);
  }
  return 0;
} /* main() */
EOD
set -v
ipcrm -q -1
set -e
cc -Werror -Wall 3a.c -o 3a
cc -Werror -Wall 3b.c -o 3b
cc -Werror -Wall 3c.c -o 3c
set +e
./3a
./3b
./3c
 
Thanks for your response. It turns out that my question is not about the man page, but about the actual behavior under certain circumstances. As I said, "I'm curious about what's going on."

EDIT

Nonetheless, if we pursue the man page aspect, we have an incomplete man page, not only because bits 0100, 0010, and 0001 are not (even indirectly) listed on the man page, but also it does not completely instruct what one should do when attempting to get the id of a message queue when one doesn't want to create a new queue.
 
I dare speculate the R/W permission bit masks were borrowed. An execute bit serves no purpose so it is not used.

Re-reading the man page ... if you omit IPC_CREAT, does it work when the queue exists and fail if not?
 
If you omit IPC_CREAT, then:

If the queue does not exist, it fails. (That's a good thing.)

If the queue exists, then it works UNLESS msgflg is 0100, as demonstrated in the original post.

I then modified the original experiment so that when first creating the queue with IPC_CREAT, the protection mode was 0666, not 0777; I was curious to see what would happen if I didn't use the 0111 bits, whose meaning is undocumented.

I got the same results afterwards when getting that queue without IPC_CREAT; it worked if msgflg was 0000, and failed if msgflg was 0100. (Again, "Permission denied".)
 
Last edited:
Old joke ...
Patient: "Doc, I get a sharp pain in my eye every time I drink iced tea."
Doctor: "Take the spoon out."

So leave the 0100 out.
 
Back
Top