将 $ORIGIN 与 setuid 应用程序一起使用不会像预期的那样失败

Using $ORIGIN with setuid application does not fail as expected

我有一个 librandom.so 库和一个 main 可执行文件,编译如下:

$ clang++ -o main main.o -lrandom -L. -Wl,-rpath,"$ORIGIN"

它们都在同一个目录中。由于 main 在其 rpath 中有 $ORIGIN,它工作正常 - ./main returns 没有错误。

现在,我将 main 设置为 运行,将 setuid 设置为 root:

$ sudo chown root main
$ sudo chmod a+s main
$ ./main

我预计 main 会失败,因为 $ORIGIN 未在 setuid 应用程序中展开。令人惊讶的是,它有效。

如果我 运行 main 来自另一个目录,它 确实 会按预期失败:

$ cd /tmp    
$ /path/to/main
/path/to/main: error while loading shared libraries: librandom.so: cannot open shared object file: No such file or directory

为什么当我从它的包含目录 运行 main 时它可以工作?

I expected main to fail since $ORIGIN is not expanded in setuid applications. Surprisingly, it works.

Glibc 在扩展 $ORIGIN 方面有着悠久的历史,甚至对于 suid 二进制文件也是如此(参见 CVE-2010-3847)。这背后的动机是使用 $ORIGIN 作为 rpath 的 suid 二进制文件被设计破坏了,所以 Glibc 开发人员从来没有费心去修复这个问题。一些下游发行版在库存 Glibc 之上提供了补丁,这些补丁禁用了 ORIGIN 扩展,因此具体情况取决于您的发行版。

有趣的是,只有独立的 $ORIGIN 会展开 - 如果您将其替换为例如$ORIGIN/libs 它将开始失败。

Why does it work when I run main from its containing directory?

移动文件后,$ORIGIN 将扩展到不再包含所需库的不同文件夹。