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

Bill Evans at Mariposa

Active Member

Reaction score: 16
Messages: 118

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
 
OP
OP
Bill Evans at Mariposa

Bill Evans at Mariposa

Active Member

Reaction score: 16
Messages: 118

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.
 

unitrunker

Active Member

Reaction score: 63
Messages: 175

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?
 
OP
OP
Bill Evans at Mariposa

Bill Evans at Mariposa

Active Member

Reaction score: 16
Messages: 118

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 esd 0000, and failed if msgflg was 0100. (Again, "Permission denied".)
 

unitrunker

Active Member

Reaction score: 63
Messages: 175

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.
 
Top