C程序使用glibc编译而不是默认库:执行权限被拒绝

这是我在stackoverflow的第一个问题,所以我会尽力做好。

语境:

我想提供一个可以在每个Linux发行版上运行的程序(例如,将使用C ++ 11的程序,在没有C ++ 11程序库的系统上运行)。 为此,我想复制我的程序使用的所有库,并将它们放在一个带有可执行文件的文件夹中,以便它可以使用这些库而不是系统的库。

我有两个环境来testing: – Opensuse,(GNU libc)2.19 – Ubuntu,(Ubuntu EGLIBC 2.17-Oubuntu5.1)2.17

我在Opensuse下编译我的程序,并在Ubuntu下运行它。 该程序使用默认库时效果很好。

项目:

这里是main.c

int main(int ac, char **av) { printf("Hello World !\n"); } 

这里是Opensuse下的文件夹树(在没有main.c和exec.sh的Ubuntu下也一样):

 + project | +--- main.c +--- a.out +--- exec.sh +---+ lib | +--- libc.so.6 +--- ld-linux-x86-64.so.2 

最后,当我用一个简单的编译启动程序时,这里是ldd和readelf:

 > gcc main.c -o a.out > ldd ./a.out linux-vdso.so.1 (0x00007fff85f57000) libc.so.6 => /lib64/libc.so.6 (0x00007f1fdaaaf000) /lib64/ld-linux-x86-64.so.2 (0x00007f1dae75000) > readelf -d a.out | grep "library\|Library" 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 

我已经做了一些研究,终于find了这个职位的人解释一下ld-linux.so。

这是我用来编译的脚本:

 #!/bin/bash dir=`pwd` execName="a.out" libDir="/lib" linker="ld-linux-x86-64.so.2" gcc main.c -o ${execName} -Wl,--rpath=${dir}${libDir} -Wl,--dynamic-linker=${dir}${libDir}/${linker} 

当我启动我的a.out编译与我的Opensuse脚本我得到以下几点:

 > ./a.out Hello World ! > ldd ./a.out linux-vdso.so.1 (0x00007f3222e27000) libc.so.6 => /path/to/project/lib/libc.so.6 (0x00007f3222a7e000) /path/to/project/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x000073222e2b000) > readelf -d a.out | grep "library\|Library" 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000001d (RUNPATH) Library runpath: [/path/to/project/lib] 

问题:

现在,当我在Ubuntu上启动这个可执行文件a.out(在Opensuse下编译)时,我得到了以下输出:

 > ./a.out ./a.out: Permission denied. > ldd ./a.out linux-vdso.so.1 (0x00007fff5b5fe000) libc.so.6 => /path/to/project/lib/libc.so.6 (0x00007f47df480000) /path/to/project/lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f47df82a000) > readelf -d a.out | grep "library\|Library" 0x0000000000000001 (NEEDED) Shared library: [libc.so.6] 0x000000000000001d (RUNPATH) Library runpath: [/path/to/project/lib] 

当我启动可执行文件时,我一直拒绝这个权限,我不知道为什么。

我把我的a.out和我的lib文件夹从Opensuse转移到Ubuntu与Filezilla,和a.out不是一个可执行文件后,传输,所以我需要做的:

 chmod 755 a.out 

我在Opensuse和Ubuntu下有相同的树。在lib文件夹中的2个库是Opensuse的默认库

任何关于拒绝许可的帮助,或其他方式来做我想做的事情都会受到欢迎。 在此先感谢您的帮助!

注意:我不能使用LD_PRELOAD,因为你需要root来使用它,它不能用于我想要做的事情。 另外我想避免静态编译,但如果这是唯一的解决scheme,我会考虑它

Solutions Collecting From Web of "C程序使用glibc编译而不是默认库:执行权限被拒绝"

有很多事情可能是错误的。 这里有一些建议。

检查复制库的文件权限

你已经提到过,无论你用什么来复制你的a.out改变这个文件的权限。 库也需要特定的权限,所以请检查这些权限。

检查是否有符号链接错误

这些库中的许多通常实际上是对真正的二进制文件的符号链接。 如果您只复制链接而不是底层的二进制文件,则不起作用。

检查不匹配的库

如您所知, libc不仅仅是一个文件。 例如,在我的Linux机器上,如果我运行ldd /lib64/libc.so.6我得到这个结果:

 /lib64/ld-linux-x86-64.so.2 (0x0000003531200000) linux-vdso.so.1 => (0x00007ffe2c78c000) 

除非你也复制了所有需要的库,否则它将不起作用。

考虑使用-R作为链接器

-L标志告诉链接器它可以在哪里找到库,但是还有一个-R标志,告诉结果可执行文件在运行时在哪里找到库。 我不清楚你是否需要这个。

您可以按照更简单的方式编译应用程序,而不依赖于共享对象。 在这种情况下,你的应用程序将被静态编译,你应该使用标志-static

看看我的例子:

 $ cat main.c #include <stdio.h> int main(int ac, char **av) { printf("Hello World !\n"); } $ gcc main.c -o main -static $ ldd main not a dynamic executable 

任何有关权限的帮助被拒绝

这一部分很简单:不仅必须使用chmod使a.out可执行,而且/path/to/project/lib/ld-linux-x86-64.so.2必须可执行。

注意:我不能使用LD_PRELOAD,因为你需要root来使用它

你错了:你绝对不需要root来使用LD_PRELOAD (除非你在set-uid binary上使用它)。

通过在strace实用程序下运行应用程序来重现权限错误,并分析日志以隔离真正的运行时问题。

$ strace -fv ./a.out