我有一个程序在运行时使用以下代码将用户名解析为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。
答案 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
与您的构建环境相匹配。预计其他任何事情都无法奏效。