5.3. 文件描述符

程序会接收到一组“打开的文件描述符”,即预先打开的文件。setuid/setgid 程序必须处理用户可以选择打开哪些文件以及打开到什么程度(在其权限限制内)这一事实。setuid/setgid 程序不得假定打开新文件总是会打开到固定的文件描述符 ID,或者打开一定会成功。它也不得假定标准输入 (stdin)、标准输出 (stdout) 和标准错误 (stderr) 指的是终端,甚至假定它们是打开的。

这背后的原理很简单;由于攻击者可以在程序启动之前打开或关闭文件描述符,因此攻击者可能会制造意想不到的情况。如果攻击者关闭了标准输出,当程序打开下一个文件时,该文件将被打开,就好像它是标准输出一样,然后它也会将所有标准输出发送到该文件。一些 C 库会自动打开 stdin、stdout 和 stderr(如果它们尚未打开)(到 /dev/null),但这并非在所有类 Unix 系统上都是如此。此外,这些库也不能完全依赖;例如,在某些系统上,可能会出现竞争条件,导致此自动打开失败(并且仍然运行程序)。