chmod

set-user-IDとset-group-IDのことが恥ずかしながらよくわかってなかったので調べてますよ、と。まずはMAN。

chmod(1)

このマニュアルはGNU版 chmod コマンドについて記述したものである。 chmod コマンドは指定したそれぞれのファイルのアクセス権を mode に従って変更する。変更方法をシンボルで表現するか、もしくは変更後の アクセス権を表すビットパターンを8進数で表現したもののいずれかを 使うことができる。

(中略)

数値モードは1から4桁の8進数(0-7)で表される。 その数値は値4,2,1に対応するビットを加算することにより得られる。 省略された桁は0と見做される。 最初の桁では、ユーザIDの設定(4)、グループIDの設定(2)、 sticky bit(1)といった属性を指定する。 2桁目では、ファイルの所有者のアクセス権を指定する: 読み取り(4)、 書き込み(2)、実行(1)を示す。 3桁目では、グループのアクセス権を指定する: 値は同じ意味を示す。 4桁目では、その他ユーザのアクセス権を指定する: 値は同じ意味を示す。

chmod 755 foo.sh と chmod 0755 foo.shは同じ。そして、最初の桁はset-user-ID(4), set-group-ID(2), sticky-bit(1)ということみたい。

set-user-ID

Advanced Programming in the Unix Environmentによると...

"when this file is executed, set the effective user ID of the process to be the owner of the file(st_uid)."

(中略)

For example, if the owner of the file is the superuser and if the file's set-user-ID bit is set, then while that program file is running as a process, it has superuser privileges.

set-user-IDのフラグが立っていれば、ファイル実行時にプロセスの実効ユーザIDをファイルオーナーと同じに設定するよ、と書かれてます。分かりやすい例としてはpasswd(1)らしい。

stat(2)
#include <stdio.h>                                                                                                                                                                           
#include <unistd.h>                                                                                                                                                                          
#include <sys/stat.h>                                                                                                                                         
                                                                                                                                                                                             
int main(int argc, char* argv[])                                                                                                                                                             
{                                                                                                                                                                                            
    struct stat buf;
                                                                                                                                                                                                                                                                                                         
    stat(argv[1], &buf);                                                                                                                                                                                                                                                                                                                                     
    if ( buf.st_mode & S_ISUID ) {                                                                                                                                                           
        printf("set-user-ID\n");                                                                                                                                                             
    }                                                                                                                                                              
} 
実行してみる
$ ls -la set-user-ID 
-rwsr-xr-x  1 kotaroito 1522739515  10  3 13 09:38 set-user-ID

$ ./a.out set-user-ID 
set-user-ID

ばっちり。

まとめ

set-user-ID(set-group-IDも)の何たるかが分かった!