1# Android bionic status 2 3This document details libc/libm/libdl additions and behavior changes. 4 5See also 6[Android linker changes for NDK developers](../android-changes-for-ndk-developers.md) 7for changes related to native code loading in various Android releases. 8 9## Bionic function availability 10 11### POSIX 12 13You can see the current status with respect to POSIX in the form of tests: 14https://android.googlesource.com/platform/bionic/+/main/tests/headers/posix/ 15 16Some POSIX functionality is not supported by the Linux kernel, and 17is guarded with tests for `__linux__`. Other functionality is not 18supported by bionic or glibc, and guarded with tests for `__BIONIC__` 19and `__GLIBC__`. In other cases historical accidents mean 32-bit 20bionic diverged but 64-bit bionic matches POSIX; these are guarded with 21`__LP64__`. 22 23Most bionic-only diversions should be accompanied by an explanatory comment. 24 25Missing functions are either obsolete or explicitly disallowed by SELinux: 26 * `a64l`/`l64a` 27 * `confstr` 28 * `crypt`/`encrypt`/`setkey` 29 * `gethostid` 30 * `shm_open`/`shm_unlink` 31 * `sockatmark` 32 * `ualarm` 33 34Missing functionality: 35 * `<aio.h>`. No particular reason not to have this other than that no-one's 36 needed it yet, and it's relatively complex. If/when llvm-libc adds this, 37 maybe we'll just reuse that. 38 * `<monetary.h>`. See 39 [discussion](https://github.com/android/ndk/issues/1182). 40 * `<wordexp.h>`. Unsafe because it passes user input to the shell (!), 41 and often should just be a call to glob() anyway. See also 42 [OpenBSD's discussion about adding wordexp()](https://www.mail-archive.com/[email protected]/msg02325.html). 43 * Locales. Although bionic contains the various `_l()` functions, the only 44 locale supported is a UTF-8 C/POSIX locale. Most of the POSIX APIs are 45 insufficient to support the wide range of languages used by Android users, 46 and apps should use icu4c (or do their i18n work in Java) instead. 47 * Robust mutexes. See 48 [discussion](https://github.com/android/ndk/issues/1181). 49 * Thread cancellation (`pthread_cancel`). Unlikely to ever be implemented 50 because of the difficulty and cost of implementing it, and the difficulty 51 of using it correctly. See 52 [This is why we can't have safe cancellation points](https://lwn.net/Articles/683118/) 53 for more about thread cancellation. 54 55Run `./libc/tools/check-symbols-glibc.py` in bionic/ for the current 56list of POSIX functions implemented by glibc but not by bionic. 57 58### libc 59 60Current libc symbols: https://android.googlesource.com/platform/bionic/+/main/libc/libc.map.txt 61 62New libc functions in API level 36: 63 * `qsort_r`, `sig2str`/`str2sig` (POSIX Issue 8 additions). 64 * GNU/BSD extension `lchmod`. 65 * GNU extensions `pthread_getaffinity_np`/`pthread_setaffinity_np`. 66 * New system call wrapper: `mseal` (`<sys/mman.h>`). 67 68New libc functions in V (API level 35): 69 * New `android_crash_detail_register`, `android_crash_detail_unregister`, 70 `android_crash_detail_replace_name`, and `android_crash_detail_replace_data` 71 functionality for adding arbitrary data to tombstones 72 (see `<android/crash_detail.h>` for full documentation). 73 * `tcgetwinsize`, `tcsetwinsize`, `_Fork` (POSIX Issue 8 additions). 74 * `timespec_getres` (C23 addition). 75 * `localtime_rz`, `mktime_z`, `tzalloc`, and `tzfree` (NetBSD 76 extensions implemented in tzcode, and the "least non-standard" 77 functions for avoiding $TZ if you need to use multiple timezones in 78 multi-threaded C). 79 * `mbsrtowcs_l` and `wcsrtombs_l` aliases for `mbsrtowcs` and `wcsrtombs`. 80 * GNU extensions `strerrordesc_np` and `strerrorname_np`. 81 * New system call wrappers: `__riscv_flush_icache` (`<sys/cachectl.h>`), 82 `__riscv_hwprobe` (`<sys/hwprobe.h>`), `epoll_pwait2`/`epoll_pwait2_64` (`<sys/epoll.h>`). 83 84New libc behavior in V (API level 35): 85 * Added `LD_SHOW_AUXV` to the dynamic linker to dump the ELF auxiliary 86 vector if the environment variable is set. 87 * The printf family now supports `%#m` to print the name of the errno 88 constant (rather than the description printed by `%m`). 89 90New libc functions in U (API level 34): 91 * `close_range` and `copy_file_range` (Linux-specific GNU extensions). 92 * `memset_explicit` in <string.h> (C23 addition). 93 * `__freadahead` in <stdio_ext.h> (in musl but not glibc). 94 * `posix_spawn_file_actions_addchdir_np` and 95 `posix_spawn_file_actions_addfchdir_np` in <spawn.h> (in musl/glibc 96 and macOS, but not iOS). 97 98New libc behavior in U (API level 34): 99 * Support for `%b` and `%B` in the printf/wprintf family, `%b` in the 100 scanf/wscanf family, and `0b` prefixes with base 0 in the strtol/wcstol 101 family. 102 * Support for `wN` length modifiers in the printf/wprintf family. 103 * tmpfile() now respects $TMPDIR. 104 105New libc functions in T (API level 33): 106 * `backtrace`, `backtrace_symbols`, `backtrace_symbols_fd` (`<execinfo.h>`). 107 * New system call wrappers: `preadv2`, `preadv64v2`, `pwritev2`, 108 `pwritev64v2`. 109 110New libc functions in S (API level 31): 111 * New hooks for sanitizers for TLS access: `__libc_get_static_tls_bounds`, 112 `__libc_register_thread_exit_callback`, `__libc_iterate_dynamic_tls`, 113 `__libc_register_dynamic_tls_listeners`. 114 * New helper to allow the zygote to give each zygote child its own stack 115 cookie (currently unused): `android_reset_stack_guards`. 116 * Non-inline symbols for `ffsl`, `ffsll`. 117 * New system call wrappers: `pidfd_getfd`, `pidfd_open`, `pidfd_send_signal`, 118 `process_madvise`. 119 120New libc functions in R (API level 30): 121 * Full C11 `<threads.h>` (available as inlines for older API levels). 122 * `memfd_create` and `mlock2` (Linux-specific GNU extensions). 123 * `renameat2` and `statx` (Linux-specific GNU extensions). 124 * `pthread_cond_clockwait`/`pthread_mutex_clocklock`/`pthread_rwlock_clockrdlock`/`pthread_rwlock_clockwrlock`/`sem_clockwait` 125 126New libc behavior in R (API level 30): 127 * [fdsan](fdsan.md) now aborts when it detects common file descriptor errors, 128 rather than just logging. 129 130New libc functions in Q (API level 29): 131 * `timespec_get` (C11 `<time.h>` addition) 132 * `reallocarray` (BSD/GNU extension in `<malloc.h>` and `<stdlib.h>`) 133 * `res_randomid` (in `<resolv.h>`) 134 * `pthread_sigqueue` (GNU extension) 135 * `getloadavg` (BSD/GNU extension in <stdlib.h>) 136 137New libc behavior in Q (API level 29): 138 * Support for [ELF TLS](elf-tls.md). 139 * Whole printf family now supports the GNU `%m` extension, rather than a 140 special-case hack in `syslog`. 141 * `popen` now always uses `O_CLOEXEC`, not just with the `e` extension. 142 * Bug fixes to handling of UTF-8 U+fffe/U+ffff and code points above U+10ffff. 143 * `aligned_alloc` correctly verifies that `size` is a multiple of `alignment`. 144 * Using `%n` with the printf family is now reported as a FORTIFY failure. 145 Previous versions of Android would ignore the `%n` but not consume the 146 corresponding pointer argument, leading to obscure errors. The scanf family 147 is unchanged. 148 * Support in strptime for `%F`, `%G`, `%g`, `%P`, `%u`, `%V`, and `%v`. 149 (strftime already supported them all.) 150 * [fdsan](fdsan.md) detects and logs common file descriptor errors at runtime. 151 152New libc functions in P (API level 28): 153 * `aligned_alloc` 154 * `__freading`/`__fwriting` (completing <stdio_ext.h>) 155 * `endhostent`/`endnetent`/`endprotoent`/`getnetent`/`getprotoent`/`sethostent`/`setnetent`/`setprotoent` (completing <netdb.h>) 156 * `fexecve` 157 * `fflush_unlocked`/`fgetc_unlocked`/`fgets_unlocked`/`fputc_unlocked`/`fputs_unlocked`/`fread_unlocked`/`fwrite_unlocked` 158 * `getentropy`/`getrandom` (adding <sys/random.h>) 159 * `getlogin_r` 160 * `glob`/`globfree` (adding <glob.h>) 161 * `hcreate`/`hcreate_r`/`hdestroy`/`hdestroy_r`/`hsearch`/`hsearch_r` (completing <search.h>) 162 * `iconv`/`iconv_close`/`iconv_open` (adding <iconv.h>) 163 * `pthread_attr_getinheritsched`/`pthread_attr_setinheritsched`/`pthread_setschedprio` 164 * `pthread_mutexattr_getprotocol`/`pthread_mutexattr_setprotocol` (mutex priority inheritance) 165 * <signal.h> support for `sigaction64_t` and `sigset64_t` allowing LP32 access to real-time signals 166 * <spawn.h> 167 * `swab` 168 * `syncfs` 169 170New libc behavior in P (API level 28): 171 * `%C` and `%S` support in the printf family (previously only the wprintf family supported these). 172 * `%mc`/`%ms`/`%m[` support in the scanf family. 173 * `%s` support in strptime (strftime already supported it). 174 * Using a `pthread_mutex_t` after it's been destroyed will be detected at 175 runtime and reported as a FORTIFY failure. 176 * Passing a null `FILE*` or `DIR*` to libc is now detected at runtime and 177 reported as a FORTIFY failure. 178 179New libc functions in O (API level 26): 180 * `sendto` FORTIFY support 181 * `__system_property_read_callback`/`__system_property_wait` 182 * legacy `bsd_signal` 183 * `catclose`/`catgets`/`catopen` (adding <nl_types.h>) 184 * `ctermid` 185 * all 6 <grp.h>/<pwd.h> (get|set|end)(gr|pw)ent functions 186 * `futimes`/`futimesat`/`lutimes` 187 * `getdomainname`/`setdomainname` 188 * `getsubopt` 189 * `hasmntopt` 190 * `mallopt` 191 * `mblen` 192 * 4 <sys/msg.h> `msg*` functions 193 * <langinfo.h> `nl_langinfo`/`nl_langinfo_l` 194 * `pthread_getname_np` 195 * 2 new Linux system calls `quotactl` and `sync_file_range` 196 * 4 <sys/sem.h> `sem*` functions 197 * 4 <sys/shm.h> `shm*` functions 198 * 5 legacy <signal.h> functions: `sighold`/`sigignore`/`sigpause`/`sigrelse`/`sigset` 199 * `strtod_l`/`strtof_l`/`strtol_l`/`strtoul_l` 200 * <wctype.h> `towctrans`/`towctrans_l`/`wctrans`/`wctrans_l` 201 202New libc behavior in O (API level 26): 203 * Passing an invalid `pthread_t` to libc is now detected at runtime and 204 reported as a FORTIFY failure. Most commonly this is a result of confusing 205 `pthread_t` and `pid_t`. 206 207New libc functions in N (API level 24): 208 * more FORTIFY support functions (`fread`/`fwrite`/`getcwd`/`pwrite`/`write`) 209 * all remaining `_FILE_OFFSET_BITS=64` functions, completing `_FILE_OFFSET_BITS=64` support in bionic (8) 210 * all 7 `pthread_barrier*` functions 211 * all 5 `pthread_spin*` functions 212 * `lockf`/`preadv`/`pwritev`/`scandirat` and `off64_t` variants 213 * `adjtimex`/`clock_adjtime` 214 * <ifaddrs.h> `getifaddrs`/`freeifaddrs`/`if_freenameindex`/`if_nameindex` 215 * `getgrgid_r`/`getgrnam_r` 216 * GNU extensions `fileno_unlocked`/`strchrnul` 217 * 32-bit `prlimit` 218 219New libc behavior in N (API level 24): 220 * `sem_wait` now returns EINTR when interrupted by a signal. 221 222New libc functions in M (API level 23): 223 * <dirent.h> `telldir`, `seekdir`. 224 * <malloc.h> `malloc_info`. 225 * <netdb.h> `gethostbyaddr_r`, `gethostbyname2_r`. 226 * <pthread.h> `pthread_rwlockattr_getkind_np`/`pthread_rwlockattr_setkind_np`. 227 * <pty.h> `forkpty`, `openpty`. 228 * <signal.h> `sigqueue`, `sigtimedwait`, `sigwaitinfo`. 229 * <stdio.h> `fmemopen`, `open_memstream`, `feof_unlocked`, `ferror_unlocked`, `clearerr_unlocked`. 230 * <stdio_ext.h> `__flbf`, `__freadable`, `__fsetlocking`, `__fwritable`, `__fbufsize`, `__fpending`, `_flushlbf`, `__fpurge`. 231 * <stdlib.h> `mkostemp`/`mkostemps`, `lcong48`. 232 * <string.h> `basename`, `strerror_l`, `strerror_r`, `mempcpy`. 233 * <sys/sysinfo.h> `get_nprocs_conf`/`get_nprocs`, `get_phys_pages`, `get_avphys_pages`. 234 * <sys/uio.h> `process_vm_readv`/`process_vm_writev`. 235 * `clock_getcpuclockid`, `login_tty`, `mkfifoat`, `posix_madvise`, `sethostname`, `strcasecmp_l`/`strncasecmp_l`. 236 * <wchar.h> `open_wmemstream`, `wcscasecmp_l`/`wcsncasecmp_l`, `wmempcpy`. 237 * all of <error.h>. 238 * re-introduced various <resolv.h> functions: `ns_format_ttl`, `ns_get16`, `ns_get32`, `ns_initparse`, `ns_makecanon`, `ns_msg_getflag`, `ns_name_compress`, `ns_name_ntol`, `ns_name_ntop`, `ns_name_pack`, `ns_name_pton`, `ns_name_rollback`, `ns_name_skip`, `ns_name_uncompress`, `ns_name_unpack`, `ns_parserr`, `ns_put16`, `ns_put32`, `ns_samename`, `ns_skiprr`, `ns_sprintrr`, and `ns_sprintrrf`. 239 240New libc functions in L (API level 21): 241 * <android/dlext.h>. 242 * <android/set_abort_message.h>. 243 * <arpa/inet.h> `inet_lnaof`, `inet_netof`, `inet_network`, `inet_makeaddr`. 244 * <wctype.h> `iswblank`. 245 * <ctype.h> `isalnum_l`, `isalpha_l`, `isblank_l`, `icntrl_l`, `isdigit_l`, `isgraph_l`, `islower_l`, `isprint_l`, `ispunct_l`, `isspace_l`, `isupper_l`, `isxdigit_l`, `_tolower`, `tolower_l`, `_toupper`, `toupper_l`. 246 * <fcntl.h> `fallocate`, `posix_fadvise`, `posix_fallocate`, `splice`, `tee`, `vmsplice`. 247 * <inttypes.h> `wcstoimax`, `wcstoumax`. 248 * <link.h> `dl_iterate_phdr`. 249 * <mntent.h> `setmntent`, `endmntent`, `getmntent_r`. 250 * <poll.h> `ppoll`. 251 * <pthread.h> `pthread_condattr_getclock`, `pthread_condattr_setclock`, `pthread_mutex_timedlock`, `pthread_gettid_np`. 252 * <sched.h> `setns`. 253 * <search.h> `insque`, `remque`, `lfind`, `lsearch`, `twalk`. 254 * <stdio.h> `dprintf`, `vdprintf`. 255 * <stdlib.h> `initstate`, `setstate`, `getprogname`/`setprogname`, `atof`/`strtof`, `at_quick_exit`/`_Exit`/`quick_exit`, `grantpt`, `mbtowc`/`wctomb`, `posix_openpt`, `rand_r`/`rand`/`random`/`srand`/`srandom`, `strtold_l`/`strtoll_l`/`strtoull_l`. 256 * <string.h> `strcoll_l`/`strxfrm_l`, `stpcpy`/`stpncpy`. 257 * <sys/resource.h> `prlimit`. 258 * <sys/socket.h> `accept4`, `sendmmsg`. 259 * <sys/stat.h> `mkfifo`/`mknodat`. 260 * <time.h> `strftime_l`. 261 * <unistd.h> `dup3`, `execvpe`, `getpagesize`, `linkat`/`symlinkat`/`readlinkat`, `truncate`. 262 * <wchar.h> `wcstof`, `vfwscanf`/`vswscanf`/`vwscanf`, `wcstold_l`/`wcstoll`/`wcstoll_l`/`wcstoull`/`wcstoull_l`, `mbsnrtowcs`/`wcsnrtombs`, `wcscoll_l`/`wcsxfrm_l`. 263 * <wctype.h> `iswalnum_l`/`iswalpha_l`/`iswblank_l`/`iswcntrl_l`/`iswctype_l`/`iswdigit_l`/`iswgraph_l`/`iswlower_l`/`iswprint_l`/`iswpunct_l`/`iswspace_l`/`iswupper_l`/`iswxdigit_l`, `wctype_l`, `towlower_l`/`towupper_l`. 264 * all of <fts.h>. 265 * all of <locale.h>. 266 * all of <sys/epoll.h>. 267 * all of <sys/fsuid.h>. 268 * all of <sys/inotify.h>. 269 * all of <uchar.h>. 270 271New libc functions in K (API level 19): 272 * <inttypes.h> `imaxabs`, `imaxdiv`. 273 * <stdlib.h> `abs`, `labs`, `llabs`. 274 * <sys/stat.h> `futimens`. 275 * all of <sys/statvfs.h>. 276 * all of <sys/swap.h>. 277 * all of <sys/timerfd.h>. 278 279New libc functions in J-MR2 (API level 18): 280 * <stdio.h> `getdelim` and `getline`. 281 * <sys/auxv.h> `getauxval`. 282 * <sys/signalfd.h> `signalfd`. 283 284New libc functions in J-MR1 (API level 17): 285 * <ftw.h>. 286 * <signal.h> `psiginfo` and `psignal`. 287 * `getsid`, `malloc_usable_size`, `mlockall`/`munlockall`, `posix_memalign`, `unshare`. 288 289New libc functions in J (API level 16): 290 * the <search.h> tree functions `tdelete`, `tdestroy`, `tfind`, and `tsearch`. 291 * `faccessat`, `readahead`, `tgkill`. 292 * all of <sys/xattr.h>. 293 294libc function count over time: 295 296| API level | Function count | 297|-----------|----------------| 298| 16 | 842 | 299| 17 | 870 | 300| 18 | 878 | 301| 19 | 893 | 302| 21 | 1016 | 303| 22 | 1038 | 304| 23 | 1103 | 305| 24 | 1147 | 306| 25 | 1147 | 307| 26 | 1199 | 308| 27 | 1199 | 309| 28 | 1298 | 310| 29 | 1312 | 311| 30 | 1368 | 312| 31 | 1379 | 313| 32 | 1379 | 314| 33 | 1386 | 315| 34 | 1392 | 316 317Data collected by: 318``` 319ndk-r26c$ for i in `ls -1v toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/aarch64-linux-android/*/libc.so` ; \ 320 do echo $i; nm $i | grep -w T | wc -l ; done 321``` 322 323### libm 324 325Current libm symbols: https://android.googlesource.com/platform/bionic/+/main/libm/libm.map.txt 326 3270 remaining missing C11/POSIX libm functions. 328 329New libm functions in O (API level 26): 330 * <complex.h> `clog`/`clogf`, `cpow`/`cpowf` functions. 331 332New libm functions in M (API level 23): 333 * <complex.h> `cabs`, `carg`, `cimag`, `cacos`, `cacosh`, `casin`, `casinh`, `catan`, `catanh`, `ccos`, `ccosh`, `cexp`, `conj`, `cproj`, `csin`, `csinh`, `csqrt`, `ctan`, `ctanh`, `creal`, `cabsf`, `cargf`, `cimagf`, `cacosf`, `cacoshf`, `casinf`, `casinhf`, `catanf`, `catanhf`, `ccosf`, `ccoshf`, `cexpf`, `conjf`, `cprojf`, `csinf`, `csinhf`, `csqrtf`, `ctanf`, `ctanhf`, `crealf`, `cabsl`, `cprojl`, `csqrtl`. 334 * <math.h> `lgammal_r`. 335 336New libm functions in L (API level 21): 337 * <complex.h> `cabsl`, `cprojl`, `csqrtl`. 338 * <math.h> `isinf`, `significandl`. 339 340New libm functions in J-MR2 (API level 18): 341 * <math.h> `log2`, `log2f`. 342 343 344## Target API level behavioral differences 345 346Most bionic bug fixes and improvements have been made without checks for 347the app's `targetSdkVersion`. There are a handful of exceptions. (If in 348doubt, search the source for `android_get_application_target_sdk_version()`.) 349 350### Destroyed mutex checking (targetSdkVersion >= 28) 351 352If a destroyed `pthread_mutex_t` is passed to any of the mutex functions, apps 353targeting API level 28 or higher will see a 354"<function> called on a destroyed mutex" fortify failure. Apps targeting older 355API levels will just have the function fail with EBUSY (matching the likely 356behavior before we added the check). 357 358### Invalid `pthread_t` handling (targetSdkVersion >= 26) 359 360As part of a long-term goal to remove the global thread list, 361and in an attempt to flush out racy code, we changed how an invalid 362`pthread_t` is handled. For `pthread_detach`, `pthread_getcpuclockid`, 363`pthread_getschedparam`/`pthread_setschedparam`, `pthread_join`, and 364`pthread_kill`, instead of returning ESRCH when passed an invalid 365`pthread_t`, if you're targeting API level 26 or above, they'll abort with the 366message "attempt to use invalid pthread\_t". 367 368Note that this doesn't change behavior as much as you might think: the 369old lookup only held the global thread list lock for the duration of 370the lookup, so there was still a race between that and the dereference 371in the caller, given that callers actually need the tid to pass to some 372syscall or other, and sometimes update fields in the `pthread_internal_t` 373struct too. 374 375We can't check a thread's tid against 0 to see whether a `pthread_t` 376is still valid because a dead thread gets its thread struct unmapped 377along with its stack, so the dereference isn't safe. 378 379To fix your code, taking the affected functions one by one: 380 381 * `pthread_getcpuclockid` and `pthread_getschedparam`/`pthread_setschedparam` 382 should be fine. Unsafe calls to those seem highly unlikely. 383 384 * Unsafe `pthread_detach` callers probably want to switch to 385 `pthread_attr_setdetachstate` instead, or use 386 `pthread_detach(pthread_self());` from the new thread's start routine 387 rather than calling detach in the parent. 388 389 * `pthread_join` calls should be safe anyway, because a joinable thread 390 won't actually exit and unmap until it's joined. If you're joining an 391 unjoinable thread, the fix is to stop marking it detached. If you're 392 joining an already-joined thread, you need to rethink your design! 393 394 * Unsafe `pthread_kill` calls aren't portably fixable. (And are obviously 395 inherently non-portable as-is.) The best alternative on Android is to 396 use `pthread_gettid_np` at some point that you know the thread to be 397 alive, and then call `kill`/`tgkill` with signal 0 (which checks 398 whether a process exists rather than actually sending a 399 signal). That's still not completely safe because if you're too late 400 the tid may have been reused, but your code is inherently unsafe without 401 a redesign anyway. 402 403### Interruptable `sem_wait` (targetSdkVersion >= 24) 404 405POSIX says that `sem_wait` can be interrupted by delivery of a 406signal. This wasn't historically true in Android, and when we fixed this 407bug we found that existing code relied on the old behavior. To preserve 408compatibility, `sem_wait` can only return EINTR on Android if the app 409targets API level 24 or later. 410 411 412## FORTIFY 413 414The `_FORTIFY_SOURCE` macro can be used to enable extra 415automatic bounds checking for common libc functions. If a buffer 416overrun is detected, the program is safely aborted as in this 417[example](https://source.android.com/devices/tech/debug/native-crash#fortify). 418 419Note that Android's FORTIFY has been extended to cover other issues. It can 420detect, for example, passing `O_CREAT` to open(2) without specifying a mode. It 421also performs some checking regardless of whether the caller was built with 422FORTIFY enabled. From API level 28, for example, calling a `pthread_mutex_` 423function on a destroyed mutex, calling a `<dirent.h>` function on a null 424pointer, using `%n` with the printf(3) family, or using the scanf(3) `m` 425modifier incorrectly will all result in FORTIFY failures even for code not built 426with FORTIFY. 427 428More background information is available in our 429[FORTIFY in Android](https://android-developers.googleblog.com/2017/04/fortify-in-android.html) 430blog post, and there's more detail about the implementation in 431[The Anatomy of Clang FORTIFY](clang_fortify_anatomy.md). 432 433The Android platform is built with `-D_FORTIFY_SOURCE=2`. Users of ndk-build 434or the NDK's CMake toolchain file also get this by default with NDK r21 or 435newer. Users of other build systems 436need to manually enable FORTIFY by setting `_FORTIFY_SOURCE` themselves in 437whatever build system they're using. The exact subset of FORTIFY available to 438NDK users will depend on their target ABI level, because when a FORTIFY 439check can't be guaranteed at compile-time, a call to a run-time `_chk` 440function is added. 441