Since effective userid/groupid may be different from the real userid/groupid, so the permission granting result is different by using effective and real id. System will use effective id to determine the permission, but user may want to use "real id" to test if the current process has permission.
definition:
R_OK, W_OK, X_OK, F_OK 4 bits are used on "access" to test if real id has the corresponding permission.
ubuntu@ip-172-31-23-227:~$ less /usr/include/unistd.h
.......
/* Values for the second argument to access.
These may be OR'd together. */
#define R_OK 4 /* Test for read permission. */
#define W_OK 2 /* Test for write permission. */
#define X_OK 1 /* Test for execute permission. */
#define F_OK 0 /* Test for existence. */
/* Test for access to NAME using the real UID and real GID. */
extern int access (const char *__name, int __type) __THROW __nonnull ((1));
......
fileio.c:
For a given file, check its access permission by "access" and "open".
"access" is based on its real id permission.
"open" is based on its effective id permission.
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
int main(int argc, char* argv[])
{
if(argc != 2) {
printf("usage: io.out <pathname>\n");
exit(1);
}
if(access(argv[1], R_OK) <0 ) {
printf("access error!\n");
}
else {
printf("access read ok!\n");
}
if(open(argv[1], O_RDONLY) < 0) {
printf("open error!\n");
}
else {
printf("open ok!\n");
}
exit(0);
}
shell:
1) We change the io.out owner to "root", which is user itself.
2) List all files, now io.out's owner is already root
3) Turn on the "set-user-id" on "io.out", then any process who executes this file will have the effective user id as "root", file's owner user id.
4) List all files, now io.out's "set-user-id" bit is already on.
5) Run ./io.out against ./test, right now for current process, real id is "ubuntu", effective user id is "root". For ./test, user's permission and group's permission is all off, only other's read permission is on.
So, "access" function will not access the file successfully, since its real user id is ubuntu. "open" function will access the file successfully, since its effective user id is "root", which falls into the "other" users.
ubuntu@ip-172-31-23-227:~$ sudo chown root ./io.out
ubuntu@ip-172-31-23-227:~$ ls -lrt
total 20
-rw-rw-r-- 1 ubuntu ubuntu 97 Aug 21 02:05 fileio.c~
-rw-rw-r-- 1 ubuntu ubuntu 426 Aug 21 02:10 fileio.c
-rwxrwxr-x 1 root ubuntu 9768 Aug 21 02:10 io.out
-------r-- 1 ubuntu ubuntu 0 Aug 21 02:16 test
ubuntu@ip-172-31-23-227:~$ sudo chmod u+s ./io.out
ubuntu@ip-172-31-23-227:~$ ls -lrt
total 20
-rw-rw-r-- 1 ubuntu ubuntu 97 Aug 21 02:05 fileio.c~
-rw-rw-r-- 1 ubuntu ubuntu 426 Aug 21 02:10 fileio.c
-rwsrwxr-x 1 root ubuntu 9768 Aug 21 02:10 io.out
-------r-- 1 ubuntu ubuntu 0 Aug 21 02:16 test
ubuntu@ip-172-31-23-227:~$ ./io.out ./test
access error!
open ok!
2. umask
The umask functoin sets the file mode creation mask for the process and returns the previous value.
definition:
ubuntu@ip-172-31-23-227:~$ less /usr/include/x86_64-linux-gnu/sys/stat.h
......
/* Set the file creation mask of the current process to MASK,
and return the old creation mask. */
extern __mode_t umask (__mode_t __mask) __THROW;
......
creation mask: if one specific mask bit is on, then for newly created file, corresponding permission bit will be turned off.
fileio.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/stat.h>
int main(int argc, char* argv[])
{
// Enable all bits
umask(0);
if(creat("foo", S_IRWXU | S_IRWXG) < 0) {
printf("create error for foo\n");
exit(1);
}
// Disable group read and write bits
umask(S_IRGRP | S_IWGRP);
if(creat("bar", S_IRWXU | S_IRWXG) < 0) {
printf("create error for bar\n");
exit(2);
}
exit(0);
}
shell:
1) Run the umask command at the shell, current mask value is 0002, which means disable the "other write" permission, to prevent others writing your file
2) run above program, it will create foo and bar files.
For foo file, since umask is setup to be 0, which means not "masking off" any bit. So its permission bit will be same as the one specified by creat system calls.
For bar file, since umask is setup to be group read and write bits, which means it will mask off these two bits. So its permission bits will be the one specified by creat system call "minus" bits set by umask command.
3) List these 2 files to prove that bits setup are right.
4) Run the umask command, the mask bits is still 0002. It means, ./io.out was run at the different process, and umask bits changed on that process doesn't affect umask bits at the shell process.
ubuntu@ip-172-31-23-227:~$ umask
0002
ubuntu@ip-172-31-23-227:~$ ./io.out
ubuntu@ip-172-31-23-227:~$ ls -lrt foo bar
-rwxrwx--- 1 ubuntu ubuntu 0 Aug 23 12:31 foo
-rwx--x--- 1 ubuntu ubuntu 0 Aug 23 12:31 bar
ubuntu@ip-172-31-23-227:~$ umask
0002
symbolic form of umask:
this is more easy to understand that which bit is turned off. In this case, other's write permission is masked off.
ubuntu@ip-172-31-23-227:~$ umask -S
u=rwx,g=rwx,o=rx
ubuntu@ip-172-31-23-227:~$ umask
0002
No comments:
Post a Comment