System V shared memory permission bits: meaning, a

2019-08-10 19:50发布

问题:

I know that when i create a shared memory block, we set the permission so that every proccess can read and write in that block with 0777 (no idea why, my teacher just said to use it like that).

I'm creating with shmget as:

shmget(IPC_PRIVATE, sizeof(server_config), IPC_CREAT|0777)

However I'd like to know:

  • What each number means

  • How to change the flag after the shared memory block is created

  • How to only allow 1 proccess to write, while all the other proccesses can only read

回答1:

It's an octal number of ORed options the same ones that you use for directory permissions.

This is their meaning (source)

rwx rwx rwx = 111 111 111
rw- rw- rw- = 110 110 110
rwx --- --- = 111 000 000

and so on...

rwx = 111 in binary = 7
rw- = 110 in binary = 6
r-x = 101 in binary = 5
r-- = 100 in binary = 4

Where of course, r stands for read and w for write then x means execute.

There are also constants defined with these values (see man open(2))

S_IRWXU  00700 user (file owner) has read, write and execute permission
S_IRUSR  00400 user has read permission
S_IWUSR  00200 user has write permission
S_IXUSR  00100 user has execute permission
S_IRWXG  00070 group has read, write and execute permission
S_IRGRP  00040 group has read permission
S_IWGRP  00020 group has write permission
S_IXGRP  00010 group has execute permission
S_IRWXO  00007 others have read, write and execute permission
S_IROTH  00004 others have read permission
S_IWOTH  00002 others have write permission
S_IXOTH  00001 others have execute permission

As you can see 0777 has a leading 0 because it's octal and is equivalent to S_IRWXU | S_IRWXG | S_IRWXO.

To answer your other two questions:

  • You can change the permissions on a shared memory block with shmctl. It goes something like this -- completely untested, may be buggy:

    int change_shm_perm(int shmid, mode_t new_permissions)
    {
      struct shmid_ds buf;
      if (shmctl(shmid, IPC_STAT, &buf)) {
        perror("shmctl(IPC_STAT)");
        return -1;
      }
      buf.shm_perm = (buf.shm_perm & ~0777) | (new_permissions & 0777);
      if (shmctl(shmid, IPC_SET, &buf)) {
        perror("shmctl(IPC_SET)");
        return -1;
      }
      return 0;
    }
    
  • To allow only one process to write, while all others can only read, the process with write privileges must run under its own uid. Then you have that process create the memory segment and set its permissions to 0644. It should be clear from the explanation of mode bits why this has the desired effect.