Add clang's CFI instrumentation

Add --enable-cfi ./configure option to enable
LLVM/Clang's Control Flow Integrity for builds.

CFI aborts a program upon detecting certain forms of undefined behavior
that can potentially allow attackers to subvert the program’s control flow.
This commit is contained in:
Tim Rühsen 2017-06-16 16:51:33 +02:00
parent d417badedb
commit e20e6f369b
7 changed files with 70 additions and 33 deletions

View File

@ -1,15 +1,16 @@
sudo: false sudo: false
dist: trusty
language: c language: c
compiler: compiler:
- gcc - gcc
- clang - clang-3.8
branches: branches:
only: only:
- master - master
- develop - clang-cfi
env: env:
- RUNTIME=libicu - RUNTIME=libicu
@ -26,23 +27,26 @@ addons:
- libtool - libtool
- gtk-doc-tools - gtk-doc-tools
- gettext - gettext
- libidn11
- libidn11-dev - libidn11-dev
- libidn2-0
- libidn2-0-dev - libidn2-0-dev
- libicu48
- libicu-dev - libicu-dev
- libunistring0
- libunistring-dev - libunistring-dev
- lcov - lcov
- clang-3.8
- llvm-3.8-dev
- llvm-dev
script: script:
- ./autogen.sh - ./autogen.sh
- ./configure && make -j4 && make check -j4 # CFI doesn't work out on Ubuntu 14.04 (Trusty). They dont't include LLVMgold.so for clang-3.8.
- ./configure --enable-runtime=$RUNTIME --enable-builtin=libicu && make clean && make -j4 && make check -j4 # clang-3.4 doesn't know CFI yet.
- ./configure --enable-runtime=$RUNTIME --enable-builtin=libidn2 && make clean && make -j4 && make check -j4 # The only chance with Travis-CI is to switch to docker and use Ubuntu 16.04 or whatever.
- ./configure --enable-runtime=$RUNTIME --enable-builtin=libidn && make clean && make -j4 && make check -j4 # - if [[ $CC == "gcc" ]]; then CFI=""; else CFI="--enable-cfi"; fi
- ./configure --enable-runtime=$RUNTIME --disable-builtin && make clean && make -j4 && make check -j4 - ./configure $CFI && make -j4 && make check -j4 || (cat config.log; ls -la /usr/lib/*gold*)
- ./configure $CFI --enable-runtime=$RUNTIME --enable-builtin=libicu && make clean && make -j4 && make check -j4
- ./configure $CFI --enable-runtime=$RUNTIME --enable-builtin=libidn2 && make clean && make -j4 && make check -j4
- ./configure $CFI --enable-runtime=$RUNTIME --enable-builtin=libidn && make clean && make -j4 && make check -j4
- ./configure $CFI --enable-runtime=$RUNTIME --disable-builtin && make clean && make -j4 && make check -j4
- ./configure --enable-gtk-doc && make -j4 && make check -j4 - ./configure --enable-gtk-doc && make -j4 && make check -j4
- make distcheck - make distcheck
- if [[ $CC == "gcc" && $RUNTIME == "libicu" ]]; then ./.travis_coveralls.sh; fi - if [[ $CC == "gcc" && $RUNTIME == "libicu" ]]; then ./.travis_coveralls.sh; fi

View File

@ -1,11 +1,12 @@
#!/bin/bash #!/bin/bash
make check-coverage-libicu make check-coverage-libicu
pip install --upgrade pip
pip install --user urllib3[secure] cpp-coveralls pip install --user urllib3[secure] cpp-coveralls
# Work around https://github.com/eddyxu/cpp-coveralls/issues/108 by manually # Work around https://github.com/eddyxu/cpp-coveralls/issues/108 by manually
# installing the pyOpenSSL module and injecting it into urllib3 as per # installing the pyOpenSSL module and injecting it into urllib3 as per
# https://urllib3.readthedocs.io/en/latest/user-guide.html#ssl-py2 # https://urllib3.readthedocs.io/en/latest/user-guide.html#ssl-py2
sed -i -e '/^import sys$/a import urllib3.contrib.pyopenssl\nurllib3.contrib.pyopenssl.inject_into_urllib3()' `which coveralls` #sed -i -e '/^import sys$/a import urllib3.contrib.pyopenssl\nurllib3.contrib.pyopenssl.inject_into_urllib3()' `which coveralls`
coveralls -t d9uGTP4NSD092kh2b85aDSsEDxatcYC6F --include src/ coveralls -t d9uGTP4NSD092kh2b85aDSsEDxatcYC6F --include src/

View File

@ -77,6 +77,23 @@ AM_PATH_PYTHON([2.7])
PKG_PROG_PKG_CONFIG PKG_PROG_PKG_CONFIG
AC_ARG_ENABLE([cfi],
[AS_HELP_STRING([--enable-cfi], [Turn on clang's Control Flow Integrity (CFI) (for developers)])],
[
clang_cfi=$enableval;
if test "$enableval" = yes; then
CFLAGS=$CFLAGS" -B/usr/bin/gold -fsanitize=cfi -flto -fvisibility=default -fno-sanitize-trap=all"
AC_LINK_IFELSE([
AC_LANG_PROGRAM([], [])
], [], [
AC_MSG_ERROR([clang 3.7+ and the 'gold' linker are required for --enable-cfi])
])
else
clang_cfi=no
fi
],
[clang_cfi=no])
# Define these substitions here to keep all version information in one place. # Define these substitions here to keep all version information in one place.
# For information on how to properly maintain the library version information, # For information on how to properly maintain the library version information,
# refer to the libtool manual, section "Updating library version information": # refer to the libtool manual, section "Updating library version information":
@ -287,6 +304,7 @@ AC_MSG_NOTICE([Summary of build options:
CFlags: ${CFLAGS} ${CPPFLAGS} CFlags: ${CFLAGS} ${CPPFLAGS}
LDFlags: ${LDFLAGS} LDFlags: ${LDFLAGS}
Libs: ${LIBS} Libs: ${LIBS}
CFI: ${clang_cfi}
Runtime: ${enable_runtime} Runtime: ${enable_runtime}
Builtin: ${enable_builtin} Builtin: ${enable_builtin}
PSL Dist File: ${PSL_DISTFILE} PSL Dist File: ${PSL_DISTFILE}

View File

@ -43,6 +43,9 @@ for CC in gcc clang; do
"--enable-runtime=libidn --enable-builtin=libidn" \ "--enable-runtime=libidn --enable-builtin=libidn" \
"--disable-runtime --enable-builtin=libicu"; do "--disable-runtime --enable-builtin=libicu"; do
export DISTCHECK_CONFIGURE_FLAGS="-C --cache-file=$CACHEFILE $options" export DISTCHECK_CONFIGURE_FLAGS="-C --cache-file=$CACHEFILE $options"
if test "$CC" == "clang"; then
export DISTCHECK_CONFIGURE_FLAGS=$DISTCHECK_CONFIGURE_FLAGS" --enable-cfi"
fi
echo echo
echo " *** ./configure $DISTCHECK_CONFIGURE_FLAGS" echo " *** ./configure $DISTCHECK_CONFIGURE_FLAGS"
./configure $DISTCHECK_CONFIGURE_FLAGS CFLAGS="$CFLAGS" > /dev/null ./configure $DISTCHECK_CONFIGURE_FLAGS CFLAGS="$CFLAGS" > /dev/null

View File

@ -1,7 +1,8 @@
AM_CFLAGS = $(WERROR_CFLAGS) $(WARN_CFLAGS) -Wno-unused-parameter AM_CFLAGS = $(WERROR_CFLAGS) $(WARN_CFLAGS) -Wno-unused-parameter
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(srcdir) -DSRCDIR=\"$(abs_srcdir)\" -DTEST_RUN AM_CPPFLAGS = -I$(top_srcdir)/include -I$(srcdir) -DSRCDIR=\"$(abs_srcdir)\" -DTEST_RUN
AM_LDFLAGS = -static #AM_LDFLAGS = -static
LDADD = ../src/libpsl.la AM_LDFLAGS = -no-install
LDADD = ../src/libpsl.la $(LIBICU_LIBS) $(LIBIDN_LIBS) $(LIBIDN2_LIBS)
PSL_TESTS = \ PSL_TESTS = \
libpsl_fuzzer$(EXEEXT) \ libpsl_fuzzer$(EXEEXT) \

View File

@ -65,3 +65,12 @@ To work on corpora for better coverage, `cd fuzz` and use e.g.
Each reproducer file should be dropped into the appropriate *.repro/ Each reproducer file should be dropped into the appropriate *.repro/
directory. directory.
# Clang CFI instrumentation
```
CC=clang-5.0 CFLAGS="-B/usr/bin/gold -O0 -fsanitize=cfi -flto -fvisibility=default -fno-sanitize-trap=all" ./configure
make clean
make
make check
```

View File

@ -1,6 +1,7 @@
DEFS = @DEFS@ -DSRCDIR=\"$(srcdir)\" -DPSL_FILE=\"$(PSL_FILE)\" -DPSL_TESTFILE=\"$(PSL_TESTFILE)\" DEFS = @DEFS@ -DSRCDIR=\"$(srcdir)\" -DPSL_FILE=\"$(PSL_FILE)\" -DPSL_TESTFILE=\"$(PSL_TESTFILE)\"
AM_CPPFLAGS = -I$(top_srcdir)/include AM_CPPFLAGS = -I$(top_srcdir)/include
LDADD = ../src/libpsl.la LDADD = ../src/libpsl.la
AM_LDFLAGS = -no-install
# ./configure'd with '--disable-builtin' # ./configure'd with '--disable-builtin'
# Do not call test-is-public-builtin here: it does not make sense. # Do not call test-is-public-builtin here: it does not make sense.