静态链接的程序OK与gcc 4.7,与gcc 4.8失败。在运行时使用dlopen

时间:2014-12-08 11:06:49

标签: linux gcc glibc static-linking

我有一个程序在运行时使用以下代码将用户名解析为uids:

pw_user = getpwnam(username);

此特定调用在运行时需要系统的libc,即使程序是静态链接的。

由于我无法信任运行时环境,因此该程序是静态链接的,并且此调用是在用户nobody下的专用分支中运行的。

当在带有GCC 4.7.2的Debian Wheezy盒子上构建时,这在任何运行时环境中都可以正常工作。相反,当使用带GCC 4.8.2的GCC构建Ubuntu Trusty时,构建工作正常但用户名解析总是失败。

这是建立的:

gcc -Wall -W -Werror -g -O2 -fstack-protector --param=ssp-buffer-size=4 -Wformat \
    -Werror=format-security -static  main.c -o main

这里的大多数参数来自dpkg-buildflags --get CFLAGS,它在两种环境下产生相同的输出。

我怀疑GCC 4.8中可能存在影响静态链接二进制文件中的ldopen的变化,但我没有注意到GCC的Changelog(https://gcc.gnu.org/gcc-4.8/changes.html)中的任何类似内容。

另一个可能的嫌疑人可能是glibc。 wheezy下的版本是glibc-2.13-1,而Ubuntu下的版本是glibc-2.19-1。

1 个答案:

答案 0 :(得分:0)

  

此特定调用在运行时需要系统的libc,即使程序是静态链接的。

这是正确的,但这不是整个的故事。您应该收到一条警告,指出运行时安装的libc.so版本必须与您在链接时使用的相同

换句话说,通过静态链接您的二进制文件,您使二进制文件极不可移植。它适用于glibc-2.13(或glibc-2.19)和无处其他系统的系统。

  

当在带有GCC 4.7.2的Debian Wheezy盒子上构建时,这在任何运行时环境中都可以正常工作。

如果是这样,那只是偶然的。

  

在使用GCC和GCC 4.8.2的Ubuntu Trusty框上构建时,构建工作正常但用户名解析总是失败。

它应该在同一台机器上失败(即glibc-2.19),并且它可能在任何其他机器上失败。这是按照设计的。

  

由于我无法信任运行时环境,因此该程序是静态链接的,并且此调用是在用户nobody下的专用分支中运行的。

您还必须在chroot中运行此程序,libc.so与您的构建环境相匹配。预计其他任何事情都无法奏效。