0

Update:

I've just discovered that the issue was specifically with a pre-built library included in my project (libxml2). It had been built with stack protection enabled, and so was relying on the __stack_chk_fail_local method. I've now rebuilt that library with -fno-stack-protector too, and everything works.

Leaving this question here, in case anyone else trips up on this too.

Original question:

When the NDK updated to version 22, the x86 build of my Android app stopped working with error:

undefined hidden symbol: __stack_chk_fail_local

This seems to be quite a common thing, and everyone says to either go back to NDK 21 or add -fno-stack-protector to the cFlags.

I dropped x86 from my build at the time, but I've since had complaints from users on older Chromebooks that parts of my app crash (due to using ARM emulation) - even Crashlytics itself crashes due to the emulation (armeabi-v7a/libcrashlytics-handler.so" has unexpected e_machine: 40 (EM_ARM)), so I don't get crash reports. I therefore want to add x86 support back, whilst still using the latest NDK.

I've added this to the android.defaultConfig block of my build.gradle:

externalNativeBuild.cmake.cFlags "-fno-stack-protector"

but when I view the command line it ran, I see that it's still adding "-fstack-protector-strong" to the beginning of the command, and my extra flag is added to the end:

D:\Android\sdk\ndk\23.1.7779620\toolchains\llvm\prebuilt\windows-x86_64\bin\clang.exe --target=i686-none-linux-android21 --gcc-toolchain=D:/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64 --sysroot=D:/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/windows-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -mstackrealign -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security -fno-stack-protector ...

Other articles appear to suggest that adding no-stack-protector should automatically remove stack-protector-strong, but it doesn't.

I've searched for anyone else with this problem, and can't find anything. I've searched the NDK issues list, and don't see it mentioned.

Any ideas on what else I can try?

Darren Taft
  • 198
  • 1
  • 8
  • 2
    Presumably you could work around by just defining that function for yourself. It can be one line that just calls `abort()`, or emits more debug info if you wish. It should never be called except in case of a buffer overflow bug or exploit. – Nate Eldredge Feb 15 '23 at 16:35
  • Thanks @NateEldredge - I've now tried that, but it didn't work. Instead, it said I was declaring it multiple times. I've just found where the issue actually was though - I'll update the main question now. – Darren Taft Feb 16 '23 at 12:58
  • `gcc -fno-stack-protector` does override the default if GCC is configured so that's on by default. It also overrides an explicit `-fstack-protector-strong` if it's later on the command line: https://godbolt.org/z/eYaMMPPeq (with GCC13.1 for x86-64). But if `-fstack-protector-strong` is last on the command line, it takes precedence. – Peter Cordes Jul 13 '23 at 19:34
  • Older canonical Q&A about linker errors from a missing stack_chk_fail function: [undefined reference to \`\_\_stack\_chk\_fail'](https://stackoverflow.com/q/4492799) – Peter Cordes Jul 13 '23 at 19:36

1 Answers1

1

You probably have some prebuilt libraries compiled with stack-protector. I got it to compile by defining the symbols myself by adding the following code to one of my cpp files.

extern "C" {
void __stack_chk_fail(void)
{
    abort();
}
/* On some architectures, this helps needless PIC pointer setup
   that would be needed just for the __stack_chk_fail call.  */

void __stack_chk_fail_local (void)
{
    __stack_chk_fail ();
}
}

Alternatively you could copy the functionality from here https://codebrowser.dev/glibc/glibc/debug/stack_chk_fail.c.html Basically the app should crash when that function is called.

Cristi
  • 1,488
  • 1
  • 14
  • 14
  • 1
    I'd recommend defining it to call `abort()` instead of return. Callers assume it's `__attribute__((noreturn))` so there's no `ret` after the `call __stack_chk_fail`: https://godbolt.org/z/nvKrGT9P5 Or yeah, if `__fortify_fail()` is defined, then call that. – Peter Cordes Jun 30 '23 at 21:15