fortify-headers

standalone fortify-source implementation
git clone git://git.2f30.org/fortify-headers
Log | Files | Refs | README | LICENSE

commit 2ccfced2116d00e6ddf3aa6f10cfacab5a863c76
parent 75b95fa25df74fcd0498bf59e3524f20f594755d
Author: jvoisin <julien.voisin@dustri.org>
Date:   Wed, 27 Sep 2023 21:52:06 +0200

Add an option to make use of compiler-provided _chk builtins

Diffstat:
M.github/workflows/testsuite.yaml | 27+++++++++++++++------------
MREADME.md | 3+++
Minclude/stdio.h | 9+++++++++
Minclude/string.h | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 87 insertions(+), 12 deletions(-)

diff --git a/.github/workflows/testsuite.yaml b/.github/workflows/testsuite.yaml @@ -11,6 +11,7 @@ jobs: strategy: matrix: version: [9, 10, 11, 12] + use_native_chk: [true, false] steps: - name: Checking out the code uses: actions/checkout@v3 @@ -30,18 +31,21 @@ jobs: run: | sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${{ matrix.version }} 100 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${{ matrix.version }} 100 - - name: Build + - name: Build with native chk + if: ${{ matrix.use_native_chk == true }} shell: bash - run: make -C tests gcc - - name: Running the testsuite + run: make CFLAGS=-DUSE_NATIVE_CHK -C tests gcc + - name: Build without native chk, and run the testsuite + if: ${{ matrix.use_native_chk == false }} shell: bash - run: make -C tests run + run: make -C tests gcc run clang: runs-on: ubuntu-latest strategy: matrix: - version: [12, 13, 14, 15] + version: [13, 14, 15] + use_native_chk: [true, false] steps: - name: Checking out the code uses: actions/checkout@v3 @@ -61,12 +65,11 @@ jobs: run: | sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${{ matrix.version }} 100 sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${{ matrix.version }} 100 - - name: Build + - name: Build with native chk + if: ${{ matrix.use_native_chk == true }} shell: bash - run: make -C tests clang - - name: Running the compile-time testsuite + run: make CFLAGS=-DUSE_NATIVE_CHK -C tests clang + - name: Building and running without native chk + if: ${{ matrix.use_native_chk == false }} shell: bash - run: make -C tests clang - - name: Running the run-time testsuite - shell: bash - run: make -C tests run + run: make -C tests clang run diff --git a/README.md b/README.md @@ -27,6 +27,9 @@ on Clang. It was initially intended to be used on - It has a [comprehensive suite of tests](https://github.com/jvoisin/fortify-headers/tree/master/tests), running both on Clang and on GCC for every commit, with [significant coverage](https://jvoisin.github.io/fortify-headers/) +- Defining `USE_NATIVE_CHK` will make use of compiler-provided builtin `_chk` + functions, which might be a bit better in term of diagnostics, + but won't necesarily provide the same amount of security checks. # Sample usage diff --git a/include/stdio.h b/include/stdio.h @@ -145,11 +145,15 @@ __diagnose_as_builtin(__builtin_vsnprintf, 1, 2, 3, 4) _FORTIFY_FN(vsnprintf) int vsnprintf(char * _FORTIFY_POS0 __s, size_t __n, const char *__f, __builtin_va_list __v) { +#if __has_builtin(__builtin___vsnprintf_chk) && USE_NATIVE_CHK + return __builtin___vsnprintf_chk(__s, __n, _FORTIFY_SOURCE, __bos(__s, 0), __f, __v,); +#else size_t __b = __bos(__s, 0); if (__n > __b) __builtin_trap(); return __orig_vsnprintf(__s, __n, __f, __v); +#endif } __format(printf, 2, 0) @@ -161,6 +165,9 @@ __diagnose_as_builtin(__builtin_vsprintf, 1, 2, 3) _FORTIFY_FN(vsprintf) int vsprintf(char * _FORTIFY_POS0 __s, const char *__f, __builtin_va_list __v) { +#if __has_builtin(__builtin___vsnprintf_chk) && USE_NATIVE_CHK + return __builtin___vsprintf_chk(__s, _FORTIFY_SOURCE, __bos(__s, 0), __f, __v,); +#else size_t __b = __bos(__s, 0); int __r; @@ -172,8 +179,10 @@ _FORTIFY_FN(vsprintf) int vsprintf(char * _FORTIFY_POS0 __s, const char *__f, __r = __orig_vsprintf(__s, __f, __v); } return __r; +#endif } + #if __has_builtin(__builtin_va_arg_pack) /* clang is missing __builtin_va_arg_pack, so we cannot use these impls diff --git a/include/string.h b/include/string.h @@ -47,6 +47,9 @@ _FORTIFY_FN(memcpy) void *memcpy(void * _FORTIFY_POS0 __od, const void * _FORTIFY_POS0 __os, size_t __n) __error_if((__bos(__od, 0) < __n), "'memcpy' called with `n` bigger than the size of `d`.") { +#if __has_builtin(__builtin___memcpy_chk) && USE_NATIVE_CHK + return __builtin___memcpy_chk(__od, __os, __n, __bos(__od, 0)); +#else size_t __bd = __bos(__od, 0); size_t __bs = __bos(__os, 0); char *__d = (char *)__od; @@ -57,6 +60,7 @@ __error_if((__bos(__od, 0) < __n), "'memcpy' called with `n` bigger than the siz if (__n > __bd || __n > __bs) __builtin_trap(); return __builtin_memcpy(__od, __os, __n); +#endif } __access(write_only, 1, 3) @@ -67,12 +71,16 @@ __diagnose_as_builtin(__builtin_memmove, 1, 2, 3) _FORTIFY_FN(memmove) void *memmove(void * _FORTIFY_POS0 __d, const void * _FORTIFY_POS0 __s, size_t __n) { +#if __has_builtin(__builtin___memmove_chk) && USE_NATIVE_CHK + return __builtin___memcpy_chk(__d, __s, __n, __bos(__d, 0)); +#else size_t __bd = __bos(__d, 0); size_t __bs = __bos(__s, 0); if (__n > __bd || __n > __bs) __builtin_trap(); return __orig_memmove(__d, __s, __n); +#endif } __access(write_only, 1, 3) @@ -82,11 +90,15 @@ __diagnose_as_builtin(__builtin_memset, 1, 2, 3) _FORTIFY_FN(memset) void *memset(void * _FORTIFY_POS0 __d, int __c, size_t __n) __warning_if(__c != 0 && __n == 0, "'memset' will set `0` bytes; did you invert the arguments?") { +#if __has_builtin(__builtin___memset_chk) && USE_NATIVE_CHK + return __builtin___memset_chk(__d, __c, __n, __bos(__d, 0)); +#else size_t __b = __bos(__d, 0); if (__n > __b) __builtin_trap(); return __builtin_memset(__d, __c, __n); +#endif } __access(read_only, 1, 3) @@ -95,33 +107,45 @@ __diagnose_as_builtin(__builtin_memchr, 1, 2, 3) #endif _FORTIFY_FN(memchr) void *memchr(const void * _FORTIFY_POS0 __d, int __c, size_t __n) { +#if __has_builtin(__builtin___memchr_chk) && USE_NATIVE_CHK + return __builtin___memchr_chk(__d, __c, __n, __bos(__d, 0)); +#else size_t __b = __bos(__d, 0); if (__n > __b) __builtin_trap(); return __builtin_memchr(__d, __c, __n); +#endif } __access(read_only, 1, 2) _FORTIFY_FN(strchr) char *strchr(const char * _FORTIFY_POS0 __s, int __c) { +#if __has_builtin(__builtin___strchr_chk) && USE_NATIVE_CHK + return __builtin___strchr_chk(__s, __c, __bos(__s, 0)); +#else size_t __b = __bos(__s, 0); char* __r = __builtin_strchr(__s, __c); if (__r - __s > __b) __builtin_trap(); return __r; +#endif } __access(read_only, 1, 2) _FORTIFY_FN(strrchr) char *strrchr(const char * _FORTIFY_POS0 __s, int __c) { +#if __has_builtin(__builtin___strrchr_chk) && USE_NATIVE_CHK + return __builtin___strrchr_chk(__s, __c, __bos(__s, 0)); +#else size_t __b = __bos(__s, 0); char* __r = __builtin_strrchr(__s, __c); if (__r - __s > __b) __builtin_trap(); return __r; +#endif } #if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ @@ -135,6 +159,9 @@ __diagnose_as_builtin(__builtin_stpcpy, 1, 2) #endif _FORTIFY_FN(stpcpy) char *stpcpy(char * _FORTIFY_POS0 __d, const char *__s) { +#if __has_builtin(__builtin___stpcpy_chk) && USE_NATIVE_CHK + return __builtin___stpcpy_chk(__d, __s, __bos(__d, 0)); +#else size_t __n = strlen(__s) + 1; if (__fh_overlap(__d, __s, __n)) @@ -144,6 +171,7 @@ _FORTIFY_FN(stpcpy) char *stpcpy(char * _FORTIFY_POS0 __d, const char *__s) if (__n > __b) __builtin_trap(); return __orig_stpcpy(__d, __s); +#endif } #undef stpncpy @@ -155,6 +183,9 @@ __diagnose_as_builtin(__builtin_stpncpy, 1, 2, 3) _FORTIFY_FN(stpncpy) char *stpncpy(char * _FORTIFY_POS0 __d, const char *__s, size_t __n) { +#if __has_builtin(__builtin___stpncpy_chk) && USE_NATIVE_CHK + return __builtin___stpncpy_chk(__d, __s, __n, __bos(__d, 0)); +#else if (__fh_overlap(__d, __s, __n)) __builtin_trap(); @@ -162,6 +193,7 @@ _FORTIFY_FN(stpncpy) char *stpncpy(char * _FORTIFY_POS0 __d, const char *__s, if (__n > __b && strlen(__s) + 1 > __b) __builtin_trap(); return __orig_stpncpy(__d, __s, __n); +#endif } #endif @@ -172,11 +204,15 @@ __diagnose_as_builtin(__builtin_strcat, 1, 2) #endif _FORTIFY_FN(strcat) char *strcat(char * _FORTIFY_POS0 __d, const char *__s) { +#if __has_builtin(__builtin___strcat_chk) && USE_NATIVE_CHK + return __builtin___strcat_chk(__d, __s, __bos(__d, 0)); +#else size_t __b = __bos(__d, 0); if (strlen(__s) + strlen(__d) + 1 > __b) __builtin_trap(); return __orig_strcat(__d, __s); +#endif } __access (write_only, 1) @@ -186,6 +222,9 @@ __diagnose_as_builtin(__builtin_strcpy, 1, 2) #endif _FORTIFY_FN(strcpy) char *strcpy(char * _FORTIFY_POS0 __d, const char *__s) { +#if __has_builtin(__builtin___strcpy_chk) && USE_NATIVE_CHK + return __builtin___strcpy_chk(__d, __s, __bos(__d, 0)); +#else size_t __n = strlen(__s) + 1; if (__fh_overlap(__d, __s, __n)) @@ -195,6 +234,7 @@ _FORTIFY_FN(strcpy) char *strcpy(char * _FORTIFY_POS0 __d, const char *__s) if (__n > __b) __builtin_trap(); return __orig_strcpy(__d, __s); +#endif } __access (read_write, 1) @@ -205,6 +245,9 @@ __diagnose_as_builtin(__builtin_strncat, 1, 2, 3) _FORTIFY_FN(strncat) char *strncat(char * _FORTIFY_POS0 __d, const char *__s, size_t __n) { +#if __has_builtin(__builtin___strncat_chk) && USE_NATIVE_CHK + return __builtin___strncat_chk(__d, __s, __n, __bos(__d, 0)); +#else size_t __b = __bos(__d, 0); if (__n > __b) { @@ -214,6 +257,7 @@ _FORTIFY_FN(strncat) char *strncat(char * _FORTIFY_POS0 __d, const char *__s, __builtin_trap(); } return __orig_strncat(__d, __s, __n); +#endif } __access (write_only, 1) @@ -224,6 +268,9 @@ __diagnose_as_builtin(__builtin_strncpy, 1, 2, 3) _FORTIFY_FN(strncpy) char *strncpy(char * _FORTIFY_POS0 __d, const char *__s, size_t __n) { +#if __has_builtin(__builtin___strncpy_chk) && USE_NATIVE_CHK + return __builtin___strncpy_chk(__d, __s, __n, __bos(__d, 0)); +#else if (__fh_overlap(__d, __s, __n)) __builtin_trap(); @@ -231,6 +278,7 @@ _FORTIFY_FN(strncpy) char *strncpy(char * _FORTIFY_POS0 __d, if (__n > __b) __builtin_trap(); return __orig_strncpy(__d, __s, __n); +#endif } #ifdef _GNU_SOURCE @@ -243,12 +291,16 @@ __diagnose_as_builtin(__builtin_mempcpy, 1, 2, 3) _FORTIFY_FN(mempcpy) void *mempcpy(void * _FORTIFY_POS0 __d, const void * _FORTIFY_POS0 __s, size_t __n) { +#if __has_builtin(__builtin___mempcpy_chk) && USE_NATIVE_CHK + return __builtin___mempcpy_chk(__d, __s, __n, __bos(__d, 0)); +#else size_t __bd = __bos(__d, 0); size_t __bs = __bos(__s, 0); if (__n > __bd || __n > __bs) __builtin_trap(); return __orig_mempcpy(__d, __s, __n); +#endif } #endif @@ -263,11 +315,15 @@ __diagnose_as_builtin(__builtin_strlcat, 1, 2, 3) _FORTIFY_FN(strlcat) size_t strlcat(char * _FORTIFY_POS0 __d, const char *__s, size_t __n) { +#if __has_builtin(__builtin___strlcat_chk) && USE_NATIVE_CHK + return __builtin___strlcat_chk(__d, __s, __n, __bos(__d, 0)); +#else size_t __b = __bos(__d, 0); if (__n > __b) __builtin_trap(); return __orig_strlcat(__d, __s, __n); +#endif } __access (write_only, 1) @@ -278,11 +334,15 @@ __diagnose_as_builtin(__builtin_strlcpy, 1, 2, 3) _FORTIFY_FN(strlcpy) size_t strlcpy(char * _FORTIFY_POS0 __d, const char *__s, size_t __n) { +#if __has_builtin(__builtin___strlcpy_chk) && USE_NATIVE_CHK + return __builtin___strlcpy_chk(__d, __s, __n, __bos(__d, 0)); +#else size_t __b = __bos(__d, 0); if (__n > __b) __builtin_trap(); return __orig_strlcpy(__d, __s, __n); +#endif } #endif