如何限制对共享对象中符号的访问?

Posted

技术标签:

【中文标题】如何限制对共享对象中符号的访问?【英文标题】:How to restrict access to symbols in shared object? 【发布时间】:2011-09-05 21:01:25 【问题描述】:

我有一个共享库 (bar.so) 形式的插件,它链接到一个更大的程序 (foo)。 foo 和 bar.so 都依赖于同一个第三方库 (baz),但它们需要将 baz 的实现完全分开。因此,当我链接 foo(使用提供的目标文件和档案)时,我需要它忽略 bar.so 中对 baz 的任何使用,反之亦然。

现在,如果我将 foo 与 --trace-symbol=baz_fun 链接,其中 baz_fun 是违规符号之一,我会得到以下输出:

bar.so: definition of baz_fun
foo/src.a(baz.o): reference to baz_fun

我相信这告诉我 foo 正在从 bar.so 引用 baz_fun(并且 foo 的执行证实了这一点)。

我尝试过的解决方案:

使用objcopy 对感兴趣的符号进行“本地化”:objcopy --localize-symbols=local.syms bar.so 其中local.syms 包含所有感兴趣的符号。我想我可能只是在这里感到困惑,也许“本地”并不意味着我认为的意思。无论如何,我从上面的链接中得到了相同的输出。我应该注意,如果我在使用objcopy 之前在 bar.so 上运行nm 工具,则所有有问题的符号都有T 标志(大写表示全局)并且在objcopy 之后它们有一个@ 987654329@ 表示他们现在是本地的。所以看来我正确地使用了objcopy。 使用-fvisibility=hidden 编译但是由于其他一些限制,我需要使用似乎不支持该功能的GCC 3.3。我也许可以升级到较新版本的 GCC,但想确认使用此标志进行编译会对我有所帮助,然后再继续前进。

其他注意事项:

我无权访问 foo 或 baz 的源代码 我希望将所有插件保存在一个共享对象 (bar.so) 中。 baz 实际上是一个许可库,所以我不希望它分开

【问题讨论】:

【参考方案1】:

使用dlopen 加载带有RTLD_DEEPBIND 标志的插件。

(编辑)

请注意,RTLD_DEEPBIND 是特定于 Linux 的,需要 glibc 2.3.4 或更高版本。

【讨论】:

也许我理解错了,但是如果我无法访问加载我的插件 bar.so 的 foo 的源代码,我该怎么办? 好的,如果你只控制bar而不控制foo,你可以将bar分成两个库,bar1和bar2。 bar1 提供插件接口并将所有调用转发给 bar2,bar2 实现一切。 bar1 应该调用 dlopen("libbar2.so",RTLD_NOW|RTLD_DEEPBIND)dlsym 它需要的所有函数。或者您可以保留一个栏,然后从那里保留dlopen("libbaz.so",RTLD_NOW|RTLD_DEEPBIND),以及dlsym您需要的所有功能。使用需要较少调用 dlsym 的任何方法。

以上是关于如何限制对共享对象中符号的访问?的主要内容,如果未能解决你的问题,请参考以下文章

链接共享库时限制符号的可见性

如何找出从共享对象导出的所有符号?

限制子进程访问共享内存和消息队列

将共享对象中的符号解析为可执行文件

在共享对象中命名不兼容的符号 - 在哪里寻找问题

共享对象中的符号