-
Notifications
You must be signed in to change notification settings - Fork 34
Add HTTP/3 fuzzing harness #97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 6 commits
ae86ce8
c43ca0e
8015b69
4189553
4630c29
890ad20
2f9cecf
3007983
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,21 +8,26 @@ SCRIPTDIR=${BUILD_ROOT}/scripts | |
|
||
CURLDIR=/tmp/curl | ||
OPENSSLDIR=/tmp/openssl | ||
NGHTTPDIR=/tmp/nghttp2 | ||
NGHTTP2DIR=/tmp/nghttp2 | ||
NGHTTP3DIR=/tmp/nghttp3 | ||
NGTCP2DIR=/tmp/ngtcp2 | ||
OPENSLLQUICDIR=/tmp/openssl_quic | ||
INSTALLDIR=/tmp/curl_install | ||
|
||
# Parse the options. | ||
OPTIND=1 | ||
|
||
while getopts "c:n:o:" opt | ||
while getopts "c:n:o:t:" opt | ||
do | ||
case "$opt" in | ||
c) CURLDIR=$OPTARG | ||
;; | ||
n) NGHTTPDIR=$OPTARG | ||
n) NGHTTP2DIR=$OPTARG | ||
;; | ||
o) OPENSSLDIR=$OPTARG | ||
;; | ||
t) NGTCP2DIR=$OPTARG | ||
;; | ||
esac | ||
done | ||
shift $((OPTIND-1)) | ||
|
@@ -34,13 +39,22 @@ FUZZ_FLAG="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION" | |
export CFLAGS="-fsanitize=address" | ||
export CXXFLAGS="-fsanitize=address -stdlib=libstdc++ $FUZZ_FLAG" | ||
export CPPFLAGS="$FUZZ_FLAG" | ||
export OPENSSLFLAGS="-fno-sanitize=alignment" | ||
export OPENSSLFLAGS="-fno-sanitize=alignment -lstdc++" | ||
|
||
# Install openssl_quic (need openssl_quic, nghttp3, and ngtcp2 for HTTP3 support) | ||
${SCRIPTDIR}/handle_x.sh openssl_quic ${OPENSLLQUICDIR} ${INSTALLDIR} || exit 1 | ||
|
||
# Install openssl | ||
${SCRIPTDIR}/handle_x.sh openssl ${OPENSSLDIR} ${INSTALLDIR} || exit 1 | ||
# ${SCRIPTDIR}/handle_x.sh openssl ${OPENSSLDIR} ${INSTALLDIR} || exit 1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If this is the solution, commenting this out is wrong. Remove the block altogether. |
||
|
||
# Install nghttp2 | ||
${SCRIPTDIR}/handle_x.sh nghttp2 ${NGHTTPDIR} ${INSTALLDIR} || exit 1 | ||
${SCRIPTDIR}/handle_x.sh nghttp2 ${NGHTTP2DIR} ${INSTALLDIR} || exit 1 | ||
|
||
# Install nghttp3 | ||
${SCRIPTDIR}/handle_x.sh nghttp3 ${NGHTTP3DIR} ${INSTALLDIR} || exit 1 | ||
|
||
# Install ngtcp2 | ||
${SCRIPTDIR}/handle_x.sh ngtcp2 ${NGTCP2DIR} ${INSTALLDIR} || exit 1 | ||
|
||
# Install curl after all other dependencies | ||
${SCRIPTDIR}/handle_x.sh curl ${CURLDIR} ${INSTALLDIR} || exit 1 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#!/bin/bash | ||
|
||
# If any commands fail, fail the script immediately. | ||
set -ex | ||
|
||
git clone --depth 1 --branch v1.1.0 https://github.com/ngtcp2/nghttp3 $1 | ||
cmeister2 marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#!/bin/bash | ||
|
||
# If any commands fail, fail the script immediately. | ||
set -ex | ||
|
||
# Clone the repository to the specified directory. | ||
git clone --depth 1 --branch v1.1.0 https://github.com/ngtcp2/ngtcp2 $1 | ||
cmeister2 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
# Teach ngtcp2 about sockets | ||
pushd $1 | ||
patch -p1 <<'EOF' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inlining the patch here is nasty. I'd rather this were in a patch file. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, doing this via a patch mechanism severely limits updating this dependency in the future. What's the long-term plan here - add support to ngtcp2 upstream? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, having the patch here is not a permanent solution. The long-term plan would be to work with ngtcp2 to make it more fuzzing friendly -- e.g. by allowing it to work with AF_UNIX sockets like this patch does. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bagder do you have an opinion here? In my experience this kind of mechanism is fairly brittle; I don't know if it's something we want to support moving forwards. |
||
From 52690d08112ccd9a5c01b5991735bf3f8e5121b0 Mon Sep 17 00:00:00 2001 | ||
From: =?UTF-8?q?Emilio=20L=C3=B3pez?= <[email protected]> | ||
Date: Sat, 16 Dec 2023 21:33:17 +0000 | ||
Subject: [PATCH] Teach ngtcp2 about sockets | ||
|
||
--- | ||
crypto/shared.c | 4 ++++ | ||
lib/includes/ngtcp2/ngtcp2.h | 5 +++++ | ||
lib/ngtcp2_addr.c | 8 ++++++++ | ||
3 files changed, 17 insertions(+) | ||
|
||
diff --git a/crypto/shared.c b/crypto/shared.c | ||
index 162094a3..08c9ed44 100644 | ||
--- a/crypto/shared.c | ||
+++ b/crypto/shared.c | ||
@@ -1096,6 +1096,10 @@ static size_t crypto_generate_regular_token_aad(uint8_t *dest, | ||
(const uint8_t *)&((const ngtcp2_sockaddr_in6 *)(void *)sa)->sin6_addr; | ||
addrlen = sizeof(((const ngtcp2_sockaddr_in6 *)(void *)sa)->sin6_addr); | ||
break; | ||
+ case NGTCP2_AF_UNIX: | ||
+ addr = NULL; | ||
+ addrlen = 0; | ||
+ break; | ||
default: | ||
assert(0); | ||
abort(); | ||
diff --git a/lib/includes/ngtcp2/ngtcp2.h b/lib/includes/ngtcp2/ngtcp2.h | ||
index a8d4b4af..63958e4c 100644 | ||
--- a/lib/includes/ngtcp2/ngtcp2.h | ||
+++ b/lib/includes/ngtcp2/ngtcp2.h | ||
@@ -1235,6 +1235,10 @@ typedef struct ngtcp2_pkt_stateless_reset { | ||
# error NGTCP2_AF_INET6 must be defined | ||
# endif /* !NGTCP2_AF_INET6 */ | ||
|
||
+# ifndef NGTCP2_AF_UNIX | ||
+# error NGTCP2_AF_UNIX must be defined | ||
+# endif /* !NGTCP2_AF_UNIX */ | ||
+ | ||
typedef unsigned short int ngtcp2_sa_family; | ||
typedef uint16_t ngtcp2_in_port; | ||
|
||
@@ -1270,6 +1274,7 @@ typedef uint32_t ngtcp2_socklen; | ||
#else /* !NGTCP2_USE_GENERIC_SOCKADDR */ | ||
# define NGTCP2_AF_INET AF_INET | ||
# define NGTCP2_AF_INET6 AF_INET6 | ||
+# define NGTCP2_AF_UNIX AF_UNIX | ||
|
||
/** | ||
* @typedef | ||
diff --git a/lib/ngtcp2_addr.c b/lib/ngtcp2_addr.c | ||
index f389abe7..26b57f3d 100644 | ||
--- a/lib/ngtcp2_addr.c | ||
+++ b/lib/ngtcp2_addr.c | ||
@@ -67,6 +67,10 @@ static int sockaddr_eq(const ngtcp2_sockaddr *a, const ngtcp2_sockaddr *b) { | ||
return ai->sin6_port == bi->sin6_port && | ||
memcmp(&ai->sin6_addr, &bi->sin6_addr, sizeof(ai->sin6_addr)) == 0; | ||
} | ||
+ case NGTCP2_AF_UNIX: { | ||
+ // TODO: see what makes sense here | ||
+ return 1; | ||
+ } | ||
default: | ||
ngtcp2_unreachable(); | ||
} | ||
@@ -109,6 +113,10 @@ uint32_t ngtcp2_addr_compare(const ngtcp2_addr *aa, const ngtcp2_addr *bb) { | ||
} | ||
return flags; | ||
} | ||
+ case NGTCP2_AF_UNIX: { | ||
+ // TODO: see what makes sense here? | ||
+ return 0; | ||
+ } | ||
default: | ||
ngtcp2_unreachable(); | ||
} | ||
EOF | ||
popd |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#!/bin/bash | ||
|
||
# If any commands fail, fail the script immediately. | ||
set -ex | ||
|
||
# Clone the curl repository to the specified directory. | ||
git clone --depth 1 -b openssl-3.1.4+quic https://github.com/quictls/openssl $1 | ||
cmeister2 marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
#!/bin/bash | ||
|
||
export FUZZ_TARGETS="curl_fuzzer_dict curl_fuzzer_file curl_fuzzer_ftp curl_fuzzer_gopher curl_fuzzer_http curl_fuzzer_https curl_fuzzer_imap curl_fuzzer_ldap curl_fuzzer_mqtt curl_fuzzer_pop3 curl_fuzzer_rtmp curl_fuzzer_rtsp curl_fuzzer_scp curl_fuzzer_sftp curl_fuzzer_smb curl_fuzzer_smtp curl_fuzzer_tftp curl_fuzzer_ws curl_fuzzer fuzz_url" | ||
export FUZZ_TARGETS="curl_fuzzer_dict curl_fuzzer_file curl_fuzzer_ftp curl_fuzzer_gopher curl_fuzzer_http curl_fuzzer_https curl_fuzzer_http3 curl_fuzzer_imap curl_fuzzer_ldap curl_fuzzer_mqtt curl_fuzzer_pop3 curl_fuzzer_rtmp curl_fuzzer_rtsp curl_fuzzer_scp curl_fuzzer_sftp curl_fuzzer_smb curl_fuzzer_smtp curl_fuzzer_tftp curl_fuzzer_ws curl_fuzzer fuzz_url" |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,16 +45,39 @@ fi | |
|
||
pushd ${SRCDIR} | ||
|
||
# TODO: Ignore HTTP3 socket connection failures | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto: inline patches. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is this a TODO? Should it be? |
||
pushd $1 | ||
patch -p1 <<'EOF' | ||
diff --git a/lib/cf-socket.c b/lib/cf-socket.c | ||
index e42b4a87b..f99fcd80c 100644 | ||
--- a/lib/cf-socket.c | ||
+++ b/lib/cf-socket.c | ||
@@ -1650,7 +1650,7 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf, | ||
|
||
rc = connect(ctx->sock, &ctx->addr.sa_addr, ctx->addr.addrlen); | ||
if(-1 == rc) { | ||
- return socket_connect_result(data, ctx->r_ip, SOCKERRNO); | ||
+ /* return socket_connect_result(data, ctx->r_ip, SOCKERRNO); */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This feels wrong - why are we disabling this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is quite hacky as you noticed, so I've specially marked it with a TODO. The harness uses AF_UNIX sockets and it makes the connect() call fail, which blocks fuzzing. Ideally we would have something nicer than this patch on cURL itself, to allow for fuzzing to proceed. |
||
} | ||
set_local_ip(cf, data); | ||
CURL_TRC_CF(data, cf, "%s socket %" CURL_FORMAT_SOCKET_T | ||
EOF | ||
popd | ||
|
||
# Build the library. | ||
./buildconf | ||
./configure --prefix=${INSTALLDIR} \ | ||
./configure PKG_CONFIG_PATH=${INSTALLDIR}/lib/pkgconfig \ | ||
--prefix=${INSTALLDIR} \ | ||
--disable-shared \ | ||
--enable-debug \ | ||
--enable-maintainer-mode \ | ||
--disable-symbol-hiding \ | ||
--enable-ipv6 \ | ||
--enable-websockets \ | ||
--with-random=/dev/null \ | ||
--with-openssl \ | ||
--with-nghttp3 \ | ||
--with-ngtcp2 \ | ||
${SSLOPTION} \ | ||
${NGHTTPOPTION} \ | ||
${CODE_COVERAGE_OPTION} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#!/bin/bash | ||
|
||
# If any commands fail, fail the script immediately. | ||
set -ex | ||
|
||
SRCDIR=$1 | ||
INSTALLDIR=$2 | ||
|
||
if [[ ! -d ${INSTALLDIR} ]] | ||
then | ||
# Make an install target directory. | ||
mkdir ${INSTALLDIR} | ||
fi | ||
|
||
pushd ${SRCDIR} | ||
|
||
# Build the library. | ||
autoreconf -fi | ||
./configure --prefix=${INSTALLDIR} \ | ||
--disable-shared \ | ||
--enable-static \ | ||
--disable-threads \ | ||
--enable-lib-only | ||
|
||
make | ||
make install |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
#!/bin/bash | ||
|
||
# If any commands fail, fail the script immediately. | ||
set -ex | ||
|
||
SRCDIR=$1 | ||
INSTALLDIR=$2 | ||
|
||
if [[ ! -d ${INSTALLDIR} ]] | ||
then | ||
# Make an install target directory. | ||
mkdir ${INSTALLDIR} | ||
fi | ||
|
||
pushd ${SRCDIR} | ||
|
||
autoreconf -fi | ||
./configure PKG_CONFIG_PATH=${INSTALLDIR}/lib/pkgconfig \ | ||
LDFLAGS="-Wl,-rpath,${INSTALLDIR}" \ | ||
--prefix=${INSTALLDIR} \ | ||
--disable-shared \ | ||
--enable-static \ | ||
--disable-threads \ | ||
--enable-lib-only \ | ||
--with-openssl \ | ||
|
||
|
||
make | ||
make install |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
|
||
#!/bin/bash | ||
|
||
# If any commands fail, fail the script immediately. | ||
set -ex | ||
|
||
SRCDIR=$1 | ||
INSTALLDIR=$2 | ||
|
||
$(dirname "$0")/install_openssl.sh $SRCDIR $INSTALLDIR |
Uh oh!
There was an error while loading. Please reload this page.