38 编写安全的特权程序

本文讲的很多东西是适用于 set-user/group-ID 的。

避免使用 set-user-ID 和 set-group-ID 程序

如题。

使用尽可能少的权限

这里的权限指的是用户的身份,即 user ID。组 ID 可以类比过来,操作方式相似。

只在需要权限的时候暂时改变权限

  1. 一个 set-user-ID 的进程启动时保存其有效用户 ID。
  2. seteuid(getuid()) 更换有效用户 ID 为真实用户 ID 以执行其他程序。
  3. 在需要权限的时候暂时设置有效用户 ID,之后切换回来。

永久放弃权限

为了保证进程以后不再能获取权限,出了恢复有效用户 ID 之外,也应该恢复保存的用户 ID。但是只有进程有特权时,setuid() 才能设置真实用户 ID 和保存的用户 ID。因此,如果一个 root 用户的 set-user-ID 程序想要永久放弃权限,需要:

  1. seteuid() 恢复自己的身份为 root(如果之前暂时降低了自己的权限)。
  2. 然后再用 setuid(getuid()) 永久放弃权限(注意这里的 setuid 和前面的 seteuid 不同)。

对于非 root 用户,就没办法这么做了。

Linux 提供了非标准的 setreuid() 系统调用可以解决普通用户无法设置真实用户 ID 和保存的用户 ID 的问题,也更推荐使用。

其他建议

很多,不好总结。