UNIX檔案的許可權之“設定使用者ID位”
用stat函式可以獲取一個檔案的狀態資訊,原型是這樣的:
int stat(const char *path, struct stat *buf);
其中結構體stat的結構:
struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ nlink_t st_nlink;/* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes */ blksize_t st_blksize;/* blocksize for file system I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change*/ };
從傳出的引數buf中可以拿到用st_uid,st_gid 表示的檔案所有者ID,和檔案所有者所在的組ID。
在UNIX程序中也有幾組ID的概念。分別是實際使用者ID,實際使用者組ID,有效使用者ID和有效使用者組ID等等。當我們開始一個程序是,通常這個程序的有效使用者ID就是這個程序的實際ID(比如我用eric使用者登入,這個有效使用者就我eric對應的ID)。然而當“設定使用者ID位”開啟以後,有效ID就是程序的程式檔案對應的所有者的ID。
$ls -l 1.txt -rw------- 1 root root 16 4月 29 14:31 1.txt
當前目錄下面有一個檔案“1.txt”是所有者root,並且只有root具有讀和寫許可權。
1 int main() 2 { 3 int fd; 4 if((fd=open("1.txt",O_RDONLY)) == -1) 5 { 6 printf("Open failed.\n"); 7 exit(-1); 8 } 9 char buf[1024]={0}; 10 read(fd,buf,1024); 11 printf(buf); 12 printf("\n"); 13 }
首先我在終端裡使用su命令使用root使用者。gcc read.c -omain。得到main程式。
# gcc read.c -omain
# exit
exit
$ main
Open failed.
顯然main的所有者也是root,但是main程式依舊不可以開啟“1.txt”,這是因為main啟動後這個程序的有效ID是程序的實際使用者ID(也就是eric賬戶的ID),而“1.txt”只對root使用者具有讀寫許可權,所以open失敗。
把main的設定使用者ID位開啟可以用shell指令: chmod u+s main
我用的是c程式,主要程式碼如下:
1 struct stat buf = {0}; 2 stat("main",&buf); 3 buf.st_mode |= S_ISUID; 4 chmod("main",buf.st_mode);
執行後,main的“設定使用者ID位”就打開了。再在非root終端下 執行main程式 就可以成功的讀出 1.txt的內容
$ main
ilovecpp.com
個人覺得linux許可權設計還是比較合理的,雖然這裡main程式可以執行時是已所有者root的許可權,但是這需要root使用者的授權:開啟這個程式檔案的“set uid bit”(設定使用者ID位)。只要在開啟這個set uid bit 時充分考慮到這個程式存在的風險。當然授權需謹慎。O(∩_∩)O