跳过导航链接 | |
退出打印视图 | |
Oracle Solaris 11.1 链接程序和库指南 Oracle Solaris 11.1 Information Library (简体中文) |
通常,非绑定产品用于在唯一的位置上安装。此产品由二进制文件、共享目标文件依赖项和关联的配置文件组成。例如,非绑定产品 ABC 可能具有下图所示的布局。
图 10-1 非绑定依赖项
假定此产品适用于安装在 /opt 下。通常,您会向 PATH 中增加 /opt/ABC/bin,以定位产品的二进制代码。每个二进制代码均使用硬编码的运行路径在二进制代码内查找其依赖项。对于应用程序 abc,此运行路径将如下所示:
$ cc -o abc abc.c -R/opt/ABC/lib -L/opt/ABC/lib -lA $ elfdump -d abc | egrep 'NEEDED|RUNPATH' [0] NEEDED 0x1b5 libA.so.1 .... [4] RUNPATH 0x1bf /opt/ABC/lib
类似地,对于依赖项 libA.so.1,此运行路径将如下所示:
$ cc -o libA.so.1 -G -Kpic A.c -R/opt/ABC/lib -L/opt/ABC/lib -lB $ elfdump -d libA.so.1 | egrep 'NEEDED|RUNPATH' [0] NEEDED 0x96 libB.so.1 [4] RUNPATH 0xa0 /opt/ABC/lib
此依赖项表示法将一直有效,直到将产品安装到除建议的缺省目录之外的某个目录中。
动态标记 $ORIGIN 扩展到目标文件的原始目录中。此标记可用于过滤器、运行路径或依赖项定义。可以使用此技术重新定义非绑定应用程序,根据 $ORIGIN 查找其依赖项:
$ cc -o abc abc.c '-R$ORIGIN/../lib' -L/opt/ABC/lib -lA $ elfdump -d abc | egrep 'NEEDED|RUNPATH' [0] NEEDED 0x1b5 libA.so.1 .... [4] RUNPATH 0x1bf $ORIGIN/../lib
而依赖项 libA.so.1 也可以根据 $ORIGIN 进行定义:
$ cc -o libA.so.1 -G -Kpic A.c '-R$ORIGIN' -L/opt/ABC/lib -lB $ elfdump -d lib/libA.so.1 | egrep 'NEEDED|RUNPATH' [0] NEEDED 0x96 libB.so.1 [4] RUNPATH 0xa0 $ORIGIN
如果此产品目前安装在 /usr/local/ABC 下,并在您的 PATH 中增加 /usr/local/ABC/bin,则调用应用程序 abc 将产生如下所示的路径名查询,以查找其依赖项:
$ ldd -s abc .... find object=libA.so.1; required by abc search path=$ORIGIN/../lib (RUNPATH/RPATH from file abc) trying path=/usr/local/ABC/lib/libA.so.1 libA.so.1 => /usr/local/ABC/lib/libA.so.1 find object=libB.so.1; required by /usr/local/ABC/lib/libA.so.1 search path=$ORIGIN (RUNPATH/RPATH from file /usr/local/ABC/lib/libA.so.1) trying path=/usr/local/ABC/lib/libB.so.1 libB.so.1 => /usr/local/ABC/lib/libB.so.1
注 - 包含 $ORIGIN 标记的目标文件可使用符号链接进行引用。在这种情况下,符号链接完全解析以确定目标文件的真正来源。
另一个与依赖项位置相关的问题是如何建立非绑定产品能借以表达相互之间依赖性的模型。
例如,非绑定产品 XYZ 可能依赖于产品 ABC。可以通过主机软件包安装脚本来建立此依赖性。此脚本生成一个指向 ABC 产品安装点的符号链接,如下图所示:
图 10-2 非绑定共同依赖项
XYZ 产品的二进制代码和共享目标文件可使用符号链接来表示其对于 ABC 产品的依赖性。此链接现在是一个稳定的参照点。对于应用程序 xyz,此运行路径将如下所示:
$ cc -o xyz xyz.c '-R$ORIGIN/../lib:$ORIGIN/../ABC/lib' \ -L/opt/ABC/lib -lX -lA $ elfdump -d xyz | egrep 'NEEDED|RUNPATH' [0] NEEDED 0x1b5 libX.so.1 [1] NEEDED 0x1bf libA.so.1 .... [2] NEEDED 0x18f libc.so.1 [5] RUNPATH 0x1c9 $ORIGIN/../lib:$ORIGIN/../ABC/lib
类似地,对于依赖项 libX.so.1,此运行路径将如下所示:
$ cc -o libX.so.1 -G -Kpic X.c '-R$ORIGIN:$ORIGIN/../ABC/lib' \ -L/opt/ABC/lib -lY -lC $ elfdump -d libX.so.1 | egrep 'NEEDED|RUNPATH' [0] NEEDED 0x96 libY.so.1 [1] NEEDED 0xa0 libC.so.1 [5] RUNPATH 0xaa $ORIGIN:$ORIGIN/../ABC/lib
如果此产品目前安装在 /usr/local/XYZ 下,则需要使用其后安装脚本来建立以下内容的符号链接:
$ ln -s ../ABC /usr/local/XYZ/ABC
如果在您的 PATH 中增加 /usr/local/XYZ/bin,则调用应用程序 xyz 将产生如下所示的路径名查询,以查找其依赖项:
$ ldd -s xyz .... find object=libX.so.1; required by xyz search path=$ORIGIN/../lib:$ORIGIN/../ABC/lib (RUNPATH/RPATH from file xyz) trying path=/usr/local/XYZ/lib/libX.so.1 libX.so.1 => /usr/local/XYZ/lib/libX.so.1 find object=libA.so.1; required by xyz search path=$ORIGIN/../lib:$ORIGIN/../ABC/lib (RUNPATH/RPATH from file xyz) trying path=/usr/local/XYZ/lib/libA.so.1 trying path=/usr/local/ABC/lib/libA.so.1 libA.so.1 => /usr/local/ABC/lib/libA.so.1 find object=libY.so.1; required by /usr/local/XYZ/lib/libX.so.1 search path=$ORIGIN:$ORIGIN/../ABC/lib \ (RUNPATH/RPATH from file /usr/local/XYZ/lib/libX.so.1) trying path=/usr/local/XYZ/lib/libY.so.1 libY.so.1 => /usr/local/XYZ/lib/libY.so.1 find object=libC.so.1; required by /usr/local/XYZ/lib/libX.so.1 search path=$ORIGIN:$ORIGIN/../ABC/lib \ (RUNPATH/RPATH from file /usr/local/XYZ/lib/libX.so.1) trying path=/usr/local/XYZ/lib/libC.so.1 trying path=/usr/local/ABC/lib/libC.so.1 libC.so.1 => /usr/local/ABC/lib/libC.so.1 find object=libB.so.1; required by /usr/local/ABC/lib/libA.so.1 search path=$ORIGIN (RUNPATH/RPATH from file /usr/local/ABC/lib/libA.so.1) trying path=/usr/local/ABC/lib/libB.so.1 libB.so.1 => /usr/local/ABC/lib/libB.so.1
在安全的进程中,只有将 $ORIGIN 字符串扩展到可信目录时才允许对其进行扩展。出现其他相对路径名将产生安全风险。
$ORIGIN/../lib 之类的路径明显指向由可执行文件的位置决定的固定位置。但是,此位置实际上并不固定。相同文件系统上的可写入目录可能会利用使用 $ORIGIN 的安全程序。
以下示例显示,如果在安全进程中随意扩展 $ORIGIN,可能会发生这种安全违规。
$ cd /worldwritable/dir/in/same/fs $ mkdir bin lib $ ln $ORIGIN/bin/program bin/program $ cp ~/crooked-libc.so.1 lib/libc.so.1 $ bin/program .... using crooked-libc.so.1
可以使用实用程序 crle(1) 指定让安全应用程序能够使用 $ORIGIN 的可信目录。使用此技术的管理员应确保已对目标目录进行了适当的保护,以防受到恶意入侵。