【问题标题】:android ndk: are -fPIC and -pie mututally exclusive?android ndk:-fPIC 和 -pie 是互斥的吗?
【发布时间】:2016-02-13 01:59:00
【问题描述】:

我正在使用 Android r10e NDK 为 Android 构建 Unison(一个文件同步可执行文件),但这并不是一个真正的 Android 问题。

Android > 5.0 (SDK 21) 要求可执行文件与位置无关。所以我 编译时将 -pie 传递给 arm-linux-androideabi-gcc,这样可以:

% hardening-check ./unison
./unison:
Position Independent Executable: yes
...

这在 Android 5.0 设备上运行良好。

Android > 6.0 (SDK 21) 仍然要求可执行文件与位置无关, 但需要在没有文本重定位的情况下构建可执行文件。所以我 编译时将 -fPIC 传递给 arm-linux-androideabi-gcc,它似乎可以构建 没有文本重定位的二进制文件:

% arm-linux-androideabi-readelf -a ./unison |& grep TEXTREL
(no output is shown)

问题是,我一次只能满足一个要求。如果我使用 -pie 和 -fPIC 一起,生成的可执行文件与位置无关(耶!),但是 还有文本重定位(嘘!):

% hardening-check ./unison
./unison:
Position Independent Executable: yes
...

% arm-linux-androideabi-readelf -a ./unison |& grep TEXTREL
0x00000016 (TEXTREL)                    0x0
0x0000001e (FLAGS)                      TEXTREL BIND_NOW

...Android 6.0 设备拒绝运行它:

% adb push unison /data/local/tmp 
% adb shell '/data/local/tmp/unison -version'
WARNING: linker: /data/local/tmp/unison has text relocations. This is wasting memory and prevents security hardening. Please fix.
CANNOT LINK EXECUTABLE: can't protect segments for "/data/local/tmp/unison": Permission denied

让这些标志协同工作所需的特殊调味料是什么?要么, 或者,我错过了什么? PIC 和 PIE 是否互斥?

谢谢!

编辑:

我正在手动完成 OPAM 存储库为 Android 构建 Unison 所经历的相同过程。即:

  1. 构建 ocaml 交叉编译器。

  2. 下拉 Unison 源。

  3. 应用补丁:

    --- pty.c~  2010-04-15 19:29:31.000000000 +0200
    +++ pty.c   2013-01-16 19:28:56.258812188 +0100
    @@ -10,7 +10,7 @@
    extern void uerror (char * cmdname, value arg) Noreturn;
    
    // openpty
    -#if defined(__linux)
    +#if defined(__linux) && !defined(__ANDROID__)
    #include <pty.h>
    #define HAS_OPENPTY 1
    #endif
    --- Makefile.OCaml~ 2013-01-16 19:27:10.686807807 +0100
    +++ Makefile.OCaml  2013-01-16 19:29:46.814814286 +0100
    @@ -136,7 +136,9 @@
        # openpty is in the libutil library
        ifneq ($(OSARCH),solaris)
        ifneq ($(OSARCH),osx)
    -        CLIBS+=-cclib -lutil
    +        ifneq ($(OSCOMP),android)
    +          CLIBS+=-cclib -lutil
    +        endif
        endif
        endif
        buildexecutable::
    
  4. 构建:

    % make \
        UISTYLE=text \
        OCAMLOPT="arm-linux-androideabi-ocamlopt -verbose -ccopt '-fPIC -pie'" \
        OSCOMP=android
    

上述过程构建了一个 PIE 可执行文件,该可执行文件在 Android 5 上运行良好,但在 Android 6 上失败,因为它具有文本重定位。删除上面的“-pie”会构建一个没有文本重定位的二进制文件,但它不是 PIE 可执行文件,因此它不会在 Android 5 或 6 上运行。

【问题讨论】:

  • 您能否提供有关如何配置和构建的详细信息,以帮助其他人重现? (构建一个简单的测试应用程序可能不会产生相同的文本重定位。)
  • 你解决了这个问题吗?

标签: android gcc android-ndk ocaml


【解决方案1】:

只是补充一点,对于一些看到这个问题的人来说,认为它完全符合他们的问题,

text relocations despite -fPIC?

将是正确的答案。简而言之,在仔细检查所有“C”代码设置后,不要忘记汇编代码问题。

【讨论】:

    【解决方案2】:

    Lollipop 发布后,我遇到了类似的问题。从那一刻起,为了确保更好的 ASLR,强制使用 PIE 可执行文件。

    如果你只能忍受 4.1+ 的支持,一个简单的解决方案就是设置APP_PLATFORM := android-16。 通过这样做,编译器将在某个阶段激活 -fPIE 标志。

    这可能是您的 Application.mk 外观的一个非常简单的示例。

    LOCAL_PATH:= $(call my-dir)
    
    include $(CLEAR_VARS)
    APP_PLATFORM := android-16
    APP_OPTIM : = release
    APP_ABI := armeabi
    include $(BUILD_EXECUTABLE)
    

    【讨论】:

    • 谢谢大卫,但这并不能完全解决我的问题。 -fPIE 标志已成功传递给构建过程。问题是生成的二进制文件无法在 Android > 6.0 (Marshmallow) 上运行,因为它不是使用 -fPIC 编译的。将 -fPIC 添加到构建过程会导致非 PIE 可执行文件无法在 Android > 5.0 (Lollipop) 上运行。
    • 出于这个原因,恕我直言,如果您可以在没有 4.1+ 支持的情况下生活,最简单和安全的方法就是让编译器自己解决这些标志。
    【解决方案3】:

    您使用的标志应该是正确的,尽管我没有尝试使用 ocaml(交叉)编译器。在一个大型的纯 C 代码库上,我通过在编译期间传递 -fPIC 和在链接期间传递 -fPIE -pie 来设法构建没有文本重定位的 PIE 可执行文件。

    您描述标志相互覆盖的方式听起来很奇怪。我的猜测是它以某种方式来自 ocaml 前端如何通过 -ccopt 参数将它们传递给后端工具。 -pie 标志是一个链接器标志,因此根本不需要将它传递给编译步骤。如果没有传递到编译步骤,生成的代码应该和之前一样,只是链接步骤应该改变,对吧?

    您能否检查哪些目标文件实际上包含文本重定位,以及它们是使用哪些编译器选项构建的? (我不确定这是否在任何地方可见,我假设它是由ocamlopt 在内部调用的。)如果单个目标文件都不包含文本重定位,那么它们似乎来自某些 ocaml 特定的目标文件链接?

    【讨论】:

    • 我也有同样的想法,但我不确定如何检查单个对象文件的文本重定位。你能启发我吗?谢谢!
    • 嗯,我在发布此内容后注意到,检查它并不像我想象的那么容易,所以目前我真的没有什么好主意。
    • 您是否能够在没有-pie 的情况下进行构建,然后手动重新运行链接器命令并添加该命令?
    • 刚刚尝试过,结果相同。我不清楚对象是否具有进入生成的可执行文件的重定位,或者重定位是否纯粹是链接的产物。如果是前者,那么找到一种方法来测试对象的重定位将非常有助于识别有问题的对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-22
    • 2011-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多