Home | History | Annotate | Line # | Download | only in fuzz
README revision 1.1
      1 libfido2 can be fuzzed using AFL or libFuzzer, with or without
      2 ASAN/MSAN/UBSAN.
      3 
      4 AFL is more convenient when fuzzing the path from the authenticator to
      5 libfido2 in an existing application. To do so, use preload-snoop.c with a real
      6 authenticator to obtain an initial corpus, rebuild libfido2 with -DFUZZ=1
      7 -DAFL=1, and use preload-fuzz.c to read device data from stdin. Examples of
      8 this approach can be found in the harnesses under fuzz/harnesses/ that fuzz
      9 the standalone examples and tools bundled with libfido2.
     10 
     11 libFuzzer is better suited for bespoke fuzzers; see fuzz_cred.c, fuzz_credman.c,
     12 fuzz_assert.c, and fuzz_mgmt.c for examples. To build these harnesses,
     13 use -DFUZZ=1 -DLIBFUZZER=1.
     14 
     15 To run under ASAN/MSAN/UBSAN, libfido2 needs to be linked against flavours of
     16 libcbor and OpenSSL built with the respective sanitiser. In order to keep
     17 memory utilisation at a manageable level, you can either enforce limits at
     18 the OS level (e.g. cgroups on Linux) or, alternatively, patch libcbor with
     19 the diff at the bottom of this file.
     20 
     21 1. Using ASAN + UBSAN
     22 
     23 - Make sure you have libcbor built with -fsanitize=address;
     24 - Make sure you have OpenSSL built with -fsanitize=address;
     25 - Rebuild libfido2 with -DASAN=1 -DUBSAN=1.
     26 
     27 1.1 Decide where your workspace will live
     28 
     29 $ export FAKEROOT=/home/pedro/fakeroot
     30 $ mkdir -p ${FAKEROOT}/src
     31 
     32 1.2 Building libcbor with ASAN
     33 
     34 $ git clone https://github.com/pjk/libcbor ${FAKEROOT}/src/libcbor
     35 $ cd ${FAKEROOT}/src/libcbor
     36 
     37 Assuming libfido2 is under ${FAKEROOT}/src/libfido2:
     38 
     39 $ patch -p0 < ${FAKEROOT}/src/libfido2/fuzz/README
     40 $ mkdir build
     41 $ cd build
     42 $ cmake -DCMAKE_C_FLAGS_DEBUG="-g2 -fno-omit-frame-pointer" \
     43 	-DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug \
     44 	-DCMAKE_INSTALL_PREFIX=${FAKEROOT} -DSANITIZE=ON \
     45 	-DCMAKE_INSTALL_LIBDIR=lib ..
     46 $ make
     47 $ make install
     48 
     49 1.3 Building OpenSSL with ASAN
     50 
     51 $ git clone https://github.com/openssl/openssl ${FAKEROOT}/src/openssl
     52 $ cd ${FAKEROOT}/src/openssl
     53 $ ./Configure linux-x86_64-clang enable-asan --prefix=${FAKEROOT} \
     54 	--openssldir=${FAKEROOT}/openssl
     55 $ make clean
     56 $ make
     57 $ make install_sw
     58 
     59 1.4 Building libfido2 with libFuzzer and ASAN + UBSAN
     60 
     61 $ cd ${FAKEROOT}/src/libfido2
     62 $ mkdir build
     63 $ cd build
     64 $ cmake -DFUZZ=1 -DLIBFUZZER=1 -DASAN=1 -DUBSAN=1 -DCMAKE_C_COMPILER=clang \
     65 	-DCRYPTO_INCLUDE_DIRS=${FAKEROOT}/include \
     66 	-DCRYPTO_LIBRARY_DIRS=${FAKEROOT}/lib \
     67 	-DCBOR_INCLUDE_DIRS=${FAKEROOT}/include \
     68 	-DCBOR_LIBRARY_DIRS=${FAKEROOT}/lib \
     69 	-DCMAKE_BUILD_TYPE=Debug ..
     70 $ make
     71 
     72 2. Using MSAN + UBSAN
     73 
     74 - Make sure you have libcbor built with -fsanitize=memory;
     75 - Make sure you have OpenSSL built with -fsanitize=memory;
     76 - Rebuild libfido2 with -DMSAN=1 -DUBSAN=1.
     77 
     78 2.1 Decide where your workspace will live
     79 
     80 $ export FAKEROOT=/home/pedro/fakeroot
     81 $ mkdir -p ${FAKEROOT}/src
     82 
     83 2.2 Building libcbor with MSAN
     84 
     85 $ git clone https://github.com/pjk/libcbor ${FAKEROOT}/src/libcbor
     86 $ cd ${FAKEROOT}/src/libcbor
     87 
     88 Assuming libfido2 is under ${FAKEROOT}/src/libfido2:
     89 
     90 $ patch -p0 < ${FAKEROOT}/src/libfido2/fuzz/README
     91 $ mkdir build
     92 $ cd build
     93 $ cmake -DCMAKE_C_FLAGS_DEBUG="-fsanitize=memory,undefined -g2 -fno-omit-frame-pointer" \  
     94 	-DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=Debug \
     95 	-DCMAKE_INSTALL_PREFIX=${FAKEROOT} -DSANITIZE=OFF \
     96 	-DCMAKE_INSTALL_LIBDIR=lib ..
     97 $ make
     98 $ make install
     99 
    100 2.2 Building OpenSSL with MSAN
    101 
    102 $ mkdir -p ${FAKEROOT}/src
    103 $ git clone https://github.com/openssl/openssl ${FAKEROOT}/src/openssl
    104 $ cd ${FAKEROOT}/src/openssl
    105 $ ./Configure linux-x86_64-clang enable-msan --prefix=${FAKEROOT} \
    106 	--openssldir=${FAKEROOT}/openssl
    107 $ make clean
    108 $ make
    109 $ make install_sw
    110 
    111 2.3 Building libfido2 with libFuzzer and MSAN + UBSAN
    112 
    113 $ cd ${FAKEROOT}/src/libfido2
    114 $ mkdir build
    115 $ cd build
    116 $ cmake -DFUZZ=1 -DLIBFUZZER=1 -DMSAN=1 -DUBSAN=1 -DCMAKE_C_COMPILER=clang \
    117 	-DCRYPTO_INCLUDE_DIRS=${FAKEROOT}/include \
    118 	-DCRYPTO_LIBRARY_DIRS=${FAKEROOT}/lib \
    119 	-DCBOR_INCLUDE_DIRS=${FAKEROOT}/include \
    120 	-DCBOR_LIBRARY_DIRS=${FAKEROOT}/lib \
    121 	-DCMAKE_BUILD_TYPE=Debug ..
    122 $ make
    123 
    124 3. Running the libFuzzer harnesses
    125 
    126 When running under ASAN, you may want to set ASAN_OPTIONS to
    127 'allocator_may_return_null=1:detect_stack_use_after_return=1'.
    128 
    129 The recommended way to run the harnesses is:
    130 
    131 $ fuzz_{assert,cred,credman,mgmt} -use_value_profile=1 -reload=30 \
    132 	-print_pcs=1 -print_funcs=30 -timeout=10 CORPUS_DIR
    133 
    134 You may want to use -jobs or -workers depending on the number of logical
    135 cores available for fuzzing.
    136 
    137 4. Auxiliary scripts
    138 
    139 A set of harnesses and auxiliary scripts can be found under harnesses/. To
    140 compile coverage reports, adjust the harnesses to your setup and run 'report'.
    141 
    142 diff --git src/cbor/internal/memory_utils.c src/cbor/internal/memory_utils.c
    143 index aa049a2..e294b38 100644
    144 --- src/cbor/internal/memory_utils.c
    145 +++ src/cbor/internal/memory_utils.c
    146 @@ -28,7 +28,10 @@ bool _cbor_safe_to_multiply(size_t a, size_t b) {
    147  
    148  void* _cbor_alloc_multiple(size_t item_size, size_t item_count) {
    149    if (_cbor_safe_to_multiply(item_size, item_count)) {
    150 -    return _CBOR_MALLOC(item_size * item_count);
    151 +    if (item_count > 1000) {
    152 +      return NULL;
    153 +    } else
    154 +      return _CBOR_MALLOC(item_size * item_count);
    155    } else {
    156      return NULL;
    157    }
    158