___str*_chk symbol(s) not found in any library kext
Closed this issue · 4 comments
Make kext output snippet:
For x86_64:
2 symbols not found in any library kext:
___strlcpy_chk
___strncpy_chk
macOS 10.13+ kernel added _str*_chk()
for all str*()
family functions(Need reconfirm), which its corresponding header located in Kernel.framework/Headers/string.h
If you encountered above compile issue, it certainly indicates that your Command Line Tools version is byond current macOS version, so there're symbol-mismatch.
FIX: please visit More Downloads for Apple Developers and download correct version of Command Line Tools matchs your macOS version
In my case, I installed the brew(which it installed a bit high version of Command Line Tools) in macOS 10.12(16G29).
Check /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/SDKSettings.plist
's MACOSX_DEPLOYMENT_TARGET
HOWTO reproduce above missing symbol bug:
-
Install brew in macOS(16G29), as it'll install Command Line Tools automatically
-
Clone generic_kext project
-
Inside
example/
directory, create a.c
file and put some code which usesstr*()
:
#include <string.h>
#include <libkern/libkern.h>
void foobar(const char *s)
{
char t[1024];
strlcpy(t, s, strlen(s) >> 1); /* Uses str*() family function */
printf(KEXTNAME_S ": %s\n", t);
}
- Make the example kext, you'll something like this:
For x86_64:
1 symbol not found in any library kext:
___strlcpy_chk
If you put the foobar()
function into example.c
solely(i.e. there is only one .c
source), and recompile, the missing symbol bug disappeared. which is weird :-(
There must be something wrong with multiple-file compilation...
FYI:
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.12.6
BuildVersion: 16G29
$ clang -v
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
I have a faint suspicious that there are some "critical" compile/load flags missing in Makefile
Final solution:
As you check Kernel.framework/string.h
, you will find the following code for macOS SDK >= 10.13
#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_13
/* older deployment target */
#elif defined(KASAN) || (defined (_FORTIFY_SOURCE) && _FORTIFY_SOURCE == 0)
/* FORTIFY_SOURCE disabled */
#else /* _chk macros */
#if __has_builtin(__builtin___memcpy_chk)
/*
* TL;DL
*/
#endif /* _chk macros */
#ifdef __cplusplus
You'll find that the control flow goes into the #else
block
and #if __has_builtin(__builtin___*_chk)
yields true
Thus you can use some dirty wordaround to dismiss __builtin___*_chk
Solutions:
-
Add
-D_FORTIFY_SOURCE=0
to MakefileCPPFLAGS
-
Add
-DKASAN
to MakefileCPPFLAGS
. FYI,KASAN
stands for Kernel Address SANitizer -
[BAD] Add
-D__MAC_OS_X_VERSION_MIN_REQUIRED=XXXXXX
to MakefileCPPFLAGS
For example, in my case, macOS 10.12.6(16G29), it's 101206
see:<Kernel.framework/Availability.h>
Solution 3 is not applicable, the macro __MAC_OS_X_VERSION_MIN_REQUIRED is use by Kernel.framework
internally
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Headers/Availability.h:202:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Headers/AvailabilityInternal.h:27141:13: warning:
'__MAC_OS_X_VERSION_MIN_REQUIRED' macro redefined [-Wmacro-redefined]
#define __MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
^
<command line>:7:9: note: previous definition is here
#define __MAC_OS_X_VERSION_MIN_REQUIRED 101206
^
1 warning generated.
see:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Kernel.framework/Versions/A/Headers