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,48 +1,52 @@
sudo: false
dist: trusty
language: c
compiler:
- gcc
- clang
- clang-3.8
branches:
only:
- master
- develop
only:
- master
- clang-cfi
env:
- RUNTIME=libicu
- RUNTIME=libidn2
- RUNTIME=libidn
- RUNTIME=no
- RUNTIME=libicu
- RUNTIME=libidn2
- RUNTIME=libidn
- RUNTIME=no
addons:
apt:
packages:
- automake
- autoconf
- autopoint
- libtool
- gtk-doc-tools
- gettext
- libidn11
- libidn11-dev
- libidn2-0
- libidn2-0-dev
- libicu48
- libicu-dev
- libunistring0
- libunistring-dev
- lcov
apt:
packages:
- automake
- autoconf
- autopoint
- libtool
- gtk-doc-tools
- gettext
- libidn11-dev
- libidn2-0-dev
- libicu-dev
- libunistring-dev
- lcov
- clang-3.8
- llvm-3.8-dev
- llvm-dev
script:
- ./autogen.sh
- ./configure && make -j4 && make check -j4
- ./configure --enable-runtime=$RUNTIME --enable-builtin=libicu && make clean && make -j4 && make check -j4
- ./configure --enable-runtime=$RUNTIME --enable-builtin=libidn2 && make clean && make -j4 && make check -j4
- ./configure --enable-runtime=$RUNTIME --enable-builtin=libidn && make clean && make -j4 && make check -j4
- ./configure --enable-runtime=$RUNTIME --disable-builtin && make clean && 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.
# clang-3.4 doesn't know CFI yet.
# The only chance with Travis-CI is to switch to docker and use Ubuntu 16.04 or whatever.
# - if [[ $CC == "gcc" ]]; then CFI=""; else CFI="--enable-cfi"; fi
- ./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
- make distcheck
- if [[ $CC == "gcc" && $RUNTIME == "libicu" ]]; then ./.travis_coveralls.sh; fi

View File

@ -1,11 +1,12 @@
#!/bin/bash
make check-coverage-libicu
pip install --upgrade pip
pip install --user urllib3[secure] cpp-coveralls
# Work around https://github.com/eddyxu/cpp-coveralls/issues/108 by manually
# installing the pyOpenSSL module and injecting it into urllib3 as per
# 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/

View File

@ -77,6 +77,23 @@ AM_PATH_PYTHON([2.7])
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.
# For information on how to properly maintain the 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}
LDFlags: ${LDFLAGS}
Libs: ${LIBS}
CFI: ${clang_cfi}
Runtime: ${enable_runtime}
Builtin: ${enable_builtin}
PSL Dist File: ${PSL_DISTFILE}

View File

@ -43,6 +43,9 @@ for CC in gcc clang; do
"--enable-runtime=libidn --enable-builtin=libidn" \
"--disable-runtime --enable-builtin=libicu"; do
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 " *** ./configure $DISTCHECK_CONFIGURE_FLAGS"
./configure $DISTCHECK_CONFIGURE_FLAGS CFLAGS="$CFLAGS" > /dev/null

View File

@ -1,7 +1,8 @@
AM_CFLAGS = $(WERROR_CFLAGS) $(WARN_CFLAGS) -Wno-unused-parameter
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(srcdir) -DSRCDIR=\"$(abs_srcdir)\" -DTEST_RUN
AM_LDFLAGS = -static
LDADD = ../src/libpsl.la
#AM_LDFLAGS = -static
AM_LDFLAGS = -no-install
LDADD = ../src/libpsl.la $(LIBICU_LIBS) $(LIBIDN_LIBS) $(LIBIDN2_LIBS)
PSL_TESTS = \
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/
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)\"
AM_CPPFLAGS = -I$(top_srcdir)/include
LDADD = ../src/libpsl.la
AM_LDFLAGS = -no-install
# ./configure'd with '--disable-builtin'
# Do not call test-is-public-builtin here: it does not make sense.