使用$ORIGIN与setuid应用程序一起时不会如预期那样失败

17

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

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

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

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

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

我本来预料main会失败,因为在setuid应用程序中没有扩展$ORIGIN。但令人惊讶的是,它起作用了。

然而,如果我从另一个目录运行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时它可以工作?
1个回答

7
我本来以为主程序会失败,因为在setuid应用程序中不会扩展$ORIGIN。出乎意料的是,它却奏效了。
Glibc长期以来一直扩展$ORIGIN,即使对于suid二进制文件也是如此(例如参见CVE-2010-3847)。这背后的动机是使用$ORIGIN进行rpath的suid二进制文件存在设计缺陷,因此Glibc开发人员从未过多关注修复此问题。一些下游的发行版在原始Glibc上提供了补丁,禁用了ORIGIN扩展,因此确切的情况取决于您的发行版。
有趣的是,只有独立的$ORIGIN才会被扩展——如果将其替换为例如$ORIGIN/libs,它将开始失败。
“当我从包含它的目录运行main时,为什么它能正常工作?”
一旦移动文件,$ORIGIN就会扩展到不再包含所需库的不同文件夹中。

1
关于第二部分 - 我不是在移动文件,而是当前目录。$ORIGIN 是相对于可执行文件的位置,而不是当前工作目录。 - Amir Rachum
好的。看起来Ubuntu使用了Glibc补丁的变体,将$ORIGIN扩展为空字符串(例如在此评论中描述)。动态链接器将把这个视为CWD,这可以解释这种行为。你可能会想要向开发人员报告此问题,但我怀疑他们会感兴趣。 - yugr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接