Saturday, August 23, 2014

Unix Prog: Files -- Permissions(3)

1. chmod, fchmod
These two functions allows us to change the file access permissions for an existing file.

definition:
 ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/sys/stat.h  
 ......  
 /* Set file access permissions for FILE to MODE.  
   If FILE is a symbolic link, this affects its target instead. */  
 extern int chmod (const char *__file, __mode_t __mode)  
    __THROW __nonnull ((1));  
 ......  
 /* Set file access permissions of the file FD is open on to MODE. */  
 #if defined __USE_BSD || defined __USE_POSIX  
 extern int fchmod (int __fd, __mode_t __mode) __THROW;  
 #endif  
 ......  

User needs to provide the mode information as the second argument.
mode definition:
S_ISVTX: sticky bit, if a program is set up with this bit, then first time it runs, it will be loaded into swap area(memory), then next time, it will be faster to run.
 ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/sys/stat.h  
 ......  
 /* Protection bits. */  
   
 #define S_ISUID __S_ISUID    /* Set user ID on execution. */  
 #define S_ISGID __S_ISGID    /* Set group ID on execution. */  
 #if defined __USE_BSD || defined __USE_MISC || defined __USE_XOPEN  
 /* Save swapped text after use (sticky bit). This is pretty well obsolete. */  
 # define S_ISVTX    __S_ISVTX  
 #endif  
   
 #define S_IRUSR __S_IREAD    /* Read by owner. */  
 #define S_IWUSR __S_IWRITE   /* Write by owner. */  
 #define S_IXUSR __S_IEXEC    /* Execute by owner. */  
 /* Read, write, and execute by owner. */  
 #define S_IRWXU (__S_IREAD|__S_IWRITE|__S_IEXEC)  
 ......  
 #define S_IRGRP (S_IRUSR >> 3) /* Read by group. */  
 #define S_IWGRP (S_IWUSR >> 3) /* Write by group. */  
 #define S_IXGRP (S_IXUSR >> 3) /* Execute by group. */  
 /* Read, write, and execute by group. */  
 #define S_IRWXG (S_IRWXU >> 3)  
 ......  
 #define S_IROTH (S_IRGRP >> 3) /* Read by others. */  
 #define S_IWOTH (S_IWGRP >> 3) /* Write by others. */  
 #define S_IXOTH (S_IXGRP >> 3) /* Execute by others. */  
 /* Read, write, and execute by others. */  
 #define S_IRWXO (S_IRWXG >> 3)  
 ......  

fileio.c:
 #include<stdio.h>  
 #include<stdlib.h>  
 #include<unistd.h>  
 #include<sys/stat.h>  
   
 int main(int argc, char* argv[])  
 {  
  struct stat statbuff;  
   
  // Retrieve the foo's stat buffer information  
  if(stat("foo", &statbuff) < 0) {  
   printf("stat error for foo\n");  
   exit(1);  
  }  
   
  // Turn off the group execute permission and turn on the set-group-id bit  
  if(chmod("foo", (statbuff.st_mode & ~S_IXGRP) | S_ISGID) < 0){  
   printf("chmod error for foo\n");  
   exit(2);  
  }  
   
  // Setup the absolute permission bit for bar: rw-rw----  
  if(chmod("bar", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0) {  
   printf("chmod error for bar\n");  
   exit(3);  
  }  
   
  exit(0);  
 }  

shell:
1) List files foo and bar, they all fixed permission: rwxrwx--- now.
2) Run the program to change permission bits
3) For foo: we disabled the group execution bit and turn on the set-group-id bit, so it will have "S"(capital S) at the group execution bit position.
For bar, we set the absolute permissions: rw-rw----
4) Add the group execution bit for foo, then foo has both group execution bit and set-group-id bit on.
5) List files foo and bar, foo now has one "lower-case s" at the group execution bit position to indicate that both execution bit and set-group-id bit is on.
 ubuntu@ip-172-31-23-227:~$ ls -lrt foo bar  
 -rwxrwx--- 1 ubuntu ubuntu 0 Aug 23 12:31 foo  
 -rwxrwx--- 1 ubuntu ubuntu 0 Aug 23 12:31 bar  
 ubuntu@ip-172-31-23-227:~$ ./io.out  
 ubuntu@ip-172-31-23-227:~$ ls -lrt foo bar  
 -rwxrwS--- 1 ubuntu ubuntu 0 Aug 23 12:31 foo  
 -rw-rw---- 1 ubuntu ubuntu 0 Aug 23 12:31 bar  
 ubuntu@ip-172-31-23-227:~$ chmod g+x foo  
 ubuntu@ip-172-31-23-227:~$ ls -lrt foo bar  
 -rwxrws--- 1 ubuntu ubuntu 0 Aug 23 12:31 foo  
 -rw-rw---- 1 ubuntu ubuntu 0 Aug 23 12:31 bar  

Note:
1) The time stamp on ls doesn't change, since it is last modification time, which is when the file content is changed. We didn't change the file content in above code.

2) Only owner of the file can use chmod system call to change file's permission.

3) Only superuser can setup the sticky bit(S_ISVTX) to avoid badly affecting the system performance.

4) If the file group id doesn't belong to process's effective group id and any other supplementary group ids, then set-group-id bit can't be setup with chmod or open (with O_CREAT) or create system call.

2. sticky bit
S_ISVTX: it can be setup with chmod or creat system calls. Sticky bit means: the file will be loaded to swap area in memory for the first time run, which will accelerate the execution for following runs. It is normally setup at some frequently running program like c++ compiler.

In contemporary unix system, because of more advanced technique, like virtual memory, the role of S_ISVTX disappeared. And right now, its role has been extended: if one directory is setup with S_ISVTX, then a file in that directory can only be removed or renamed when user has the write permission of that directory and also one of them:
owns the file
owns the directory
superuser.

Example: /tmp. Every one could only touch their own file.

3. chown
Change the owner and group id of given file.

definition:
 ubuntu@ip-172-31-23-227:~$ sudo find /usr/include -name *.h | xargs grep chown  
 ......  
 /usr/include/unistd.h:extern int chown (const char *__file, __uid_t __owner, __gid_t __group)  
 /usr/include/unistd.h:extern int fchown (int __fd, __uid_t __owner, __gid_t __group) __THROW __wur;  
 /usr/include/unistd.h:extern int lchown (const char *__file, __uid_t __owner, __gid_t __group)  
 /usr/include/unistd.h:extern int fchownat (int __fd, const char *__file, __uid_t __owner,  
 ......  

If the POSIX_CHOWN_RESTRICTED option is set, then it will has restrictions as specified below.
 ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h  
 ......  
 /* Get values of POSIX options:  
   
   If these symbols are defined, the corresponding features are  
   always available. If not, they may be available sometimes.  
   The current values can be obtained with `sysconf'.  
 ......  
   
   _POSIX_CHOWN_RESTRICTED   Only the super user can use `chown' to change  
                 the owner of a file. `chown' can only be used  
                 to change the group ID of a file to a group of  
                 which the calling process is a member.  
   
 ......  

Also if the running process is not superuser, then after successful return of these system calls, set-user-ID and set-group-ID bits are cleared automatically.

No comments:

Post a Comment