Page MenuHome GnuPG
Authored By
catenacyber
Apr 17 2018, 6:05 PM
Size
12 KB
Subscribers
None

fuzz.diff

diff --git a/configure.ac b/configure.ac
index 540dffcd0..99ee9d17c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -954,6 +954,15 @@ AC_CHECK_LIB(util, openpty,
])
AC_SUBST(LIBUTIL_LIBS)
+# TODO choose when to build fuzzing with option ?
+AC_CHECK_LIB(FuzzingEngine, main,
+ [ LIB_FUZZING_ENGINE="-lFuzzingEngine"
+ have_fuzz=yes
+ ])
+AC_SUBST(LIB_FUZZING_ENGINE)
+AC_CHECK_PROG(HAVE_CLANGXX, clang++, 1)
+AM_CONDITIONAL(HAVE_LIB_FUZZING_ENGINE, [test "$have_fuzz" = yes -a "$HAVE_CLANGXX" = 1])
+
# shred is used to clean temporary plain text files.
AC_PATH_PROG(SHRED, shred, /usr/bin/shred)
AC_DEFINE_UNQUOTED(SHRED,
@@ -2039,6 +2048,7 @@ tests/migrations/Makefile
tests/gpgsm/Makefile
tests/gpgme/Makefile
tests/pkits/Makefile
+tests/fuzz/Makefile
g10/gpg.w32-manifest
])
diff --git a/g10/Makefile.am b/g10/Makefile.am
index b8b92d702..233dd282e 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -47,6 +47,7 @@ endif
# NB: We use noinst_ for gpg and gpgv so that we can install them with
# the install-hook target under the name gpg2/gpgv2.
noinst_PROGRAMS = gpg
+noinst_LIBRARIES = libgpg.a
if !HAVE_W32CE_SYSTEM
noinst_PROGRAMS += gpgv
endif
@@ -158,6 +159,9 @@ gpg_SOURCES = gpg.c \
keyedit.c keyedit.h \
$(gpg_sources)
+libgpg_a_SOURCES = keyedit.c keyedit.h \
+ $(gpg_sources)
+
gpgcompose_SOURCES = gpgcompose.c $(gpg_sources)
gpgv_SOURCES = gpgv.c \
$(common_source) \
diff --git a/g10/call-dirmngr.h b/g10/call-dirmngr.h
index 285c4cb4d..7af328c2a 100644
--- a/g10/call-dirmngr.h
+++ b/g10/call-dirmngr.h
@@ -19,6 +19,8 @@
#ifndef GNUPG_G10_CALL_DIRMNGR_H
#define GNUPG_G10_CALL_DIRMNGR_H
+#include "options.h"
+
void gpg_dirmngr_deinit_session_data (ctrl_t ctrl);
gpg_error_t gpg_dirmngr_ks_list (ctrl_t ctrl, char **r_keyserver);
diff --git a/g10/compress-bz2.c b/g10/compress-bz2.c
index 45aa40dfc..5a59787f6 100644
--- a/g10/compress-bz2.c
+++ b/g10/compress-bz2.c
@@ -155,8 +155,11 @@ do_uncompress( compress_filter_context_t *zfx, bz_stream *bzs,
(unsigned)bzs->avail_in, (unsigned)bzs->avail_out, zrc);
if( zrc == BZ_STREAM_END )
rc = -1; /* eof */
- else if( zrc != BZ_OK && zrc != BZ_PARAM_ERROR )
- log_fatal("bz2lib inflate problem: rc=%d\n", zrc );
+ else if( zrc != BZ_OK && zrc != BZ_PARAM_ERROR ) {
+ log_error("bz2lib inflate problem: rc=%d\n", zrc );
+ rc = GPG_ERR_BAD_DATA;
+ break;
+ }
else if (zrc == BZ_OK && eofseen
&& !bzs->avail_in && bzs->avail_out > 0)
{
diff --git a/g10/compress.c b/g10/compress.c
index 61bb756f2..5d1f06102 100644
--- a/g10/compress.c
+++ b/g10/compress.c
@@ -204,10 +204,12 @@ do_uncompress( compress_filter_context_t *zfx, z_stream *zs,
if( zrc == Z_STREAM_END )
rc = -1; /* eof */
else if( zrc != Z_OK && zrc != Z_BUF_ERROR ) {
+ rc = -1;
+ zrc = Z_BUF_ERROR;
if( zs->msg )
- log_fatal("zlib inflate problem: %s\n", zs->msg );
+ log_error("zlib inflate problem: %s\n", zs->msg );
else
- log_fatal("zlib inflate problem: rc=%d\n", zrc );
+ log_error("zlib inflate problem: rc=%d\n", zrc );
}
} while (zs->avail_out && zrc != Z_STREAM_END && zrc != Z_BUF_ERROR
&& !leave);
diff --git a/g10/parse-packet.c b/g10/parse-packet.c
index e933abfa0..20ef8368a 100644
--- a/g10/parse-packet.c
+++ b/g10/parse-packet.c
@@ -709,7 +709,8 @@ parse (parse_packet_ctx_t ctx, PACKET *pkt, int onlykeypkts, off_t * retpos,
* the uncompressing layer - in some error cases it just loops
* and spits out 0xff bytes. */
log_error ("%s: garbled packet detected\n", iobuf_where (inp));
- g10_exit (2);
+ rc = gpg_error (GPG_ERR_INV_PACKET);
+ goto leave;
}
if (out && pkttype)
diff --git a/m4/iconv.m4 b/m4/iconv.m4
index 66bc76f48..2d6d6e423 100644
--- a/m4/iconv.m4
+++ b/m4/iconv.m4
@@ -83,6 +83,7 @@ int main ()
size_t res = iconv (cd_utf8_to_88591,
(char **) &inptr, &inbytesleft,
&outptr, &outbytesleft);
+ iconv_close(cd_utf8_to_88591);
if (res == 0)
return 1;
}
@@ -107,17 +108,19 @@ int main ()
}
}
#endif
+ iconv_t ic;
/* Test against HP-UX 11.11 bug: No converter from EUC-JP to UTF-8 is
provided. */
if (/* Try standardized names. */
- iconv_open ("UTF-8", "EUC-JP") == (iconv_t)(-1)
+ (ic = iconv_open ("UTF-8", "EUC-JP")) == (iconv_t)(-1)
/* Try IRIX, OSF/1 names. */
- && iconv_open ("UTF-8", "eucJP") == (iconv_t)(-1)
+ && (ic = iconv_open ("UTF-8", "eucJP")) == (iconv_t)(-1)
/* Try AIX names. */
- && iconv_open ("UTF-8", "IBM-eucJP") == (iconv_t)(-1)
+ && (ic = iconv_open ("UTF-8", "IBM-eucJP")) == (iconv_t)(-1)
/* Try HP-UX names. */
- && iconv_open ("utf8", "eucJP") == (iconv_t)(-1))
+ && (ic = iconv_open ("utf8", "eucJP")) == (iconv_t)(-1))
return 1;
+ iconv_close(ic);
return 0;
}], [am_cv_func_iconv_works=yes], [am_cv_func_iconv_works=no],
[case "$host_os" in
diff --git a/tests/Makefile.am b/tests/Makefile.am
index b9be6aaa6..f4085b824 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -18,7 +18,13 @@
## Process this file with automake to produce Makefile.in
-SUBDIRS = gpgscm openpgp migrations gpgsm gpgme pkits .
+SUBDIRS = gpgscm openpgp migrations gpgsm gpgme pkits
+
+if HAVE_LIB_FUZZING_ENGINE
+SUBDIRS += fuzz
+endif
+
+SUBDIRS += .
GPGSM = ../sm/gpgsm
diff --git a/tests/fuzz/Makefile.am b/tests/fuzz/Makefile.am
new file mode 100644
index 000000000..e2dee99a6
--- /dev/null
+++ b/tests/fuzz/Makefile.am
@@ -0,0 +1,50 @@
+# Makefile.am - For tests/fuzz
+# Copyright (C) 2018 Free Software Foundation, Inc.
+#
+# This file is part of GnuPG.
+#
+# GnuPG is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# GnuPG is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+# Process this file with automake to create Makefile.in
+
+
+# Programs required before we can run these tests.
+required_pgms = ../../g10/gpg$(EXEEXT)
+
+
+# Force linking with clang++ even if we have pure C fuzzing targets
+CCLD = clang++
+LDFLAGS += -stdlib=libc++
+
+AM_CPPFLAGS = -I$(top_srcdir)/common -I$(top_srcdir)/g10
+include $(top_srcdir)/am/cmacros.am
+
+noinst_PROGRAMS = fuzz_verify fuzz_import
+
+fuzz_verify_SOURCES = fuzz_verify.c
+
+fuzz_verify_LDADD = $(top_srcdir)/g10/libgpg.a ../../kbx/libkeybox.a ../../common/libcommon.a ../../common/libgpgrl.a $(LIB_FUZZING_ENGINE) \
+ $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \
+ $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBICONV) $(resource_objs) $(extra_sys_libs)
+
+fuzz_import_SOURCES = fuzz_import.c
+
+fuzz_import_LDADD = $(top_srcdir)/g10/libgpg.a ../../kbx/libkeybox.a ../../common/libcommon.a ../../common/libgpgrl.a $(LIB_FUZZING_ENGINE)\
+ $(ZLIBS) $(LIBINTL) $(CAPLIBS) $(NETLIBS) $(SQLITE3_LIBS) $(LIBGCRYPT_LIBS) $(LIBREADLINE) \
+ $(LIBASSUAN_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBICONV) $(resource_objs) $(extra_sys_libs)
+
+# We need to depend on a couple of programs so that the tests don't
+# start before all programs are built.
+all-local: $(required_pgms)
diff --git a/tests/fuzz/fuzz_import.c b/tests/fuzz/fuzz_import.c
new file mode 100644
index 000000000..c31a21605
--- /dev/null
+++ b/tests/fuzz/fuzz_import.c
@@ -0,0 +1,86 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "config.h"
+#include "gpg.h"
+#include "../common/types.h"
+#include "../common/iobuf.h"
+#include "keydb.h"
+#include "keyedit.h"
+#include "../common/util.h"
+#include "main.h"
+#include "call-dirmngr.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/mount.h>
+
+static bool initialized = false;
+ctrl_t ctrlGlobal;
+int fd;
+const char *filename = "/tmp/ramfuzz/fuzz.gpg";
+
+//hack not to include gpg.c which has main function
+int g10_errors_seen = 0;
+
+void
+g10_exit( int rc )
+{
+ gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
+ gcry_control (GCRYCTL_TERM_SECMEM );
+ exit (rc);
+}
+
+static void
+gpg_deinit_default_ctrl (ctrl_t ctrl)
+{
+#ifdef USE_TOFU
+ tofu_closedbs (ctrl);
+#endif
+ gpg_dirmngr_deinit_session_data (ctrl);
+
+ keydb_release (ctrl->cached_getkey_kdb);
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+ kbnode_t keyblock;
+
+ if (! initialized) {
+ ctrlGlobal = (ctrl_t) malloc(sizeof(*ctrlGlobal));
+ if (!ctrlGlobal) {
+ exit(1);
+ }
+ //creates a dir if it does not exist already
+ //TODO mount it as ramfs
+ mkdir("/tmp/ramfuzz/", 0777);
+ fd = open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1) {
+ free(ctrlGlobal);
+ return 0;
+ }
+ initialized = true;
+ }
+
+ memset(ctrlGlobal, 0, sizeof(*ctrlGlobal));
+ ctrlGlobal->magic = SERVER_CONTROL_MAGIC;
+
+ if (ftruncate(fd, Size) == -1) {
+ return 0;
+ }
+ if (lseek (fd, 0, SEEK_SET) < 0) {
+ return 0;
+ }
+ if (write (fd, Data, Size) != Size) {
+ return 0;
+ }
+
+ read_key_from_file (ctrlGlobal, filename, &keyblock);
+ gpg_deinit_default_ctrl (ctrlGlobal);
+
+ return 0;
+}
diff --git a/tests/fuzz/fuzz_import.options b/tests/fuzz/fuzz_import.options
new file mode 100644
index 000000000..678d526b1
--- /dev/null
+++ b/tests/fuzz/fuzz_import.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65536
diff --git a/tests/fuzz/fuzz_verify.c b/tests/fuzz/fuzz_verify.c
new file mode 100644
index 000000000..63f42ce2b
--- /dev/null
+++ b/tests/fuzz/fuzz_verify.c
@@ -0,0 +1,92 @@
+#include <stdint.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+
+#include "config.h"
+#include "gpg.h"
+#include "../common/types.h"
+#include "../common/iobuf.h"
+#include "keydb.h"
+#include "keyedit.h"
+#include "../common/util.h"
+#include "main.h"
+#include "call-dirmngr.h"
+
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/mount.h>
+
+static bool initialized = false;
+ctrl_t ctrlGlobal;
+int fd;
+char *filename;
+
+//hack not to include gpg.c which has main function
+int g10_errors_seen = 0;
+
+void
+g10_exit( int rc )
+{
+ gcry_control (GCRYCTL_UPDATE_RANDOM_SEED_FILE);
+ gcry_control (GCRYCTL_TERM_SECMEM );
+ exit (rc);
+}
+
+static void
+gpg_deinit_default_ctrl (ctrl_t ctrl)
+{
+#ifdef USE_TOFU
+ tofu_closedbs (ctrl);
+#endif
+ gpg_dirmngr_deinit_session_data (ctrl);
+
+ keydb_release (ctrl->cached_getkey_kdb);
+}
+
+
+int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
+
+ if (! initialized) {
+ ctrlGlobal = (ctrl_t) malloc(sizeof(*ctrlGlobal));
+ if (!ctrlGlobal) {
+ exit(1);
+ }
+ //creates a dir if it does not exist already
+ //TODO mount it as ramfs
+ mkdir("/tmp/ramfuzz/", 0777);
+ filename=strdup("/tmp/ramfuzz/fuzz.gpg");
+ if (!filename) {
+ free(ctrlGlobal);
+ return 0;
+ }
+ fd = open("/tmp/ramfuzz/fuzz.gpg", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
+ if (fd == -1) {
+ free(ctrlGlobal);
+ free(filename);
+ return 0;
+ }
+ initialized = true;
+ }
+
+ memset(ctrlGlobal, 0, sizeof(*ctrlGlobal));
+ ctrlGlobal->magic = SERVER_CONTROL_MAGIC;
+
+ if (ftruncate(fd, Size) == -1) {
+ return 0;
+ }
+ if (lseek (fd, 0, SEEK_SET) < 0) {
+ return 0;
+ }
+ if (write (fd, Data, Size) != Size) {
+ return 0;
+ }
+
+ verify_signatures(ctrlGlobal, 1, &filename);
+ gpg_deinit_default_ctrl (ctrlGlobal);
+
+ return 0;
+}
diff --git a/tests/fuzz/fuzz_verify.options b/tests/fuzz/fuzz_verify.options
new file mode 100644
index 000000000..678d526b1
--- /dev/null
+++ b/tests/fuzz/fuzz_verify.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 65536

File Metadata

Mime Type
text/x-diff
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
153085

Event Timeline