Linux有三种主要的UID:

  • Real user ID(ruid) - Login时所用的ID,表示用户的真实身份
  • Effective user ID(euid) - 有效ID,执行各种操作,进行权限检查,创建文件、目录时所用的ID
  • Saved set-user ID - 执行具有setuid位的程序时用于保存该程序文件的属主ID

ruid和euid好理解吧?ruid就是说你是谁,euid就是说你以什么身份干事,一般情况下ruid = euid。但是在执行具有setuid位的程序时就不一样了。这些程序会把euid设置为该程序文件的属主ID,比如A执行了一个以B为属主的具有setuid位的程序,那么这个执行进程的euid就是B,而ruid还是A。同时saved set-user ID也被设置为B。

为什么要存saved set-user ID这个东西呢?因为前面说了干事时的身份是由euid来决定的。那么如果某个具有setuid位的程序想要切回使用者的身份,在没有saved set-user ID的情况下就切不回来了。例如上例中A执行的那个进程获得了euid为B,如果中途想要切换euid为A,就再也切不回B了。多了saved set-user ID之后就好办了。在exec时把euid和saved set-user ID都设置为B(实际上exec时saved set-user ID总是被设置为euid)。然后就算中间切到A了也还能再切回B(通过设置euid = saved set-user ID即可)。

当然为了安全,saved set-user ID是不能乱设的。我所知道的设置saved set-user ID的方法只有两种:一是exec时总是设置saved set-user ID = euid。二是只有root可以可以通过setuid来设置saved set-user ID(当然这样的话ruid和euid也都变了)。

另外,setuid和seteuid两个东西的区别仅在于以root执行时。以root执行时setuid会把3个ID(ruid/euid/saved set-user ID)全改成指定值,seteuid则只会改euid。以非root执行时setuid和seteuid一样。

Links: