From patchwork Thu Dec 19 21:58:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Petr_=C5=A0tetiar?= X-Patchwork-Id: 1213726 X-Patchwork-Delegate: ynezz@true.cz Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.openwrt.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=true.cz Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="Gmh8FMiL"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47f5R70bnzz9sPL for ; Fri, 20 Dec 2019 09:00:35 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:Subject:MIME-Version:References: In-Reply-To:Message-Id:Date:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=QKI7/jPJDoH2+Sj5+NcNmjUDo8UvJOmyK7/X6eiaZGA=; b=Gmh8FMiLjX1dXh llUTDgyvflfMjdP48JZ4MCh9nQG25Tk10TM5bPsVbhrgEvm6l6oy6/I/LgiaddeSyVLyO4/l1HqYf IG/f9c/TvYiSHOX9c9Crn3rfWjh8f2aqGT6epzXrJobxeKJQBviW5Qk2qNgcZ8QEoVlGMGEeIXFsB y/6uq/ZmHh2+GXOoRZ8T141ezxtRp3h3Uim+XXt9QHnQIbluH1Mmlprll4OfIqIzoJx5q8gzPL5AU 02OKTaKmJCLQzKHnTnbGtqwoxLvirlFNTqcNk61F5iZcgE6minCUC5A0rQ4ewDpVQP/CGpuSe2xOi tj2cohcN9VWtdfcuS8jg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1ii3qL-0004Gu-JO; Thu, 19 Dec 2019 22:00:25 +0000 Received: from smtp-out.xnet.cz ([178.217.244.18]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1ii3op-0000sz-ND for openwrt-devel@lists.openwrt.org; Thu, 19 Dec 2019 21:58:54 +0000 Received: from meh.true.cz (meh.true.cz [108.61.167.218]) (Authenticated sender: petr@true.cz) by smtp-out.xnet.cz (Postfix) with ESMTPSA id CF53C4B47; Thu, 19 Dec 2019 22:58:46 +0100 (CET) Received: by meh.true.cz (OpenSMTPD) with ESMTP id b2715cf5; Thu, 19 Dec 2019 22:58:34 +0100 (CET) From: =?utf-8?q?Petr_=C5=A0tetiar?= To: openwrt-devel@lists.openwrt.org Date: Thu, 19 Dec 2019 22:58:21 +0100 Message-Id: <20191219215836.21773-6-ynezz@true.cz> In-Reply-To: <20191219215836.21773-1-ynezz@true.cz> References: <20191219215836.21773-1-ynezz@true.cz> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20191219_135851_926004_9B28BED9 X-CRM114-Status: GOOD ( 12.35 ) X-Spam-Score: 0.0 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (0.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [178.217.244.18 listed in list.dnswl.org] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.0 SPF_NONE SPF: sender does not publish an SPF Record Subject: [OpenWrt-Devel] [PATCH libubox 05/20] tests: add libFuzzer based tests X-BeenThere: openwrt-devel@lists.openwrt.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?utf-8?q?Petr_=C5=A0tetiar?= Sender: "openwrt-devel" Errors-To: openwrt-devel-bounces+incoming=patchwork.ozlabs.org@lists.openwrt.org LibFuzzer is in-process, coverage-guided, evolutionary fuzzing engine. LibFuzzer is linked with the library under test, and feeds fuzzed inputs to the library via a specific fuzzing entrypoint (aka "target function"); the fuzzer then tracks which areas of the code are reached, and generates mutations on the corpus of input data in order to maximize the code coverage. Lets use libFuzzer to fuzz blob and blobmsg parsing for the start. Ref: https://llvm.org/docs/LibFuzzer.html Signed-off-by: Petr Štetiar --- tests/CMakeLists.txt | 4 + tests/fuzz/CMakeLists.txt | 18 +++++ .../71520a5c4b5ca73903216857abbad54a8002d44a | Bin 0 -> 2 bytes .../c1dfd96eea8cc2b62785275bca38ac261256e278 | 1 + .../c42ac1c46f1d4e211c735cc7dfad4ff8391110e9 | Bin 0 -> 3 bytes tests/fuzz/corpus/valid-blobmsg.bin | Bin 0 -> 176 bytes tests/fuzz/test-fuzz.c | 76 ++++++++++++++++++ 7 files changed, 99 insertions(+) create mode 100644 tests/fuzz/CMakeLists.txt create mode 100644 tests/fuzz/corpus/71520a5c4b5ca73903216857abbad54a8002d44a create mode 100644 tests/fuzz/corpus/c1dfd96eea8cc2b62785275bca38ac261256e278 create mode 100644 tests/fuzz/corpus/c42ac1c46f1d4e211c735cc7dfad4ff8391110e9 create mode 100644 tests/fuzz/corpus/valid-blobmsg.bin create mode 100644 tests/fuzz/test-fuzz.c diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index bd2205743318..0cb33427e45a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,3 +12,7 @@ FOREACH(test_case ${test_cases}) ADD_UNIT_TEST(${test_case}) ADD_UNIT_TEST_SAN(${test_case}) ENDFOREACH(test_case) + +IF(CMAKE_C_COMPILER_ID STREQUAL "Clang") + ADD_SUBDIRECTORY(fuzz) +ENDIF() diff --git a/tests/fuzz/CMakeLists.txt b/tests/fuzz/CMakeLists.txt new file mode 100644 index 000000000000..cca74fd6ca12 --- /dev/null +++ b/tests/fuzz/CMakeLists.txt @@ -0,0 +1,18 @@ +FILE(GLOB test_cases "test-*.c") + +MACRO(ADD_FUZZER_TEST name) + ADD_EXECUTABLE(${name} ${name}.c) + TARGET_COMPILE_OPTIONS(${name} PRIVATE -g -O1 -fno-omit-frame-pointer -fsanitize=fuzzer,address,leak,undefined) + TARGET_INCLUDE_DIRECTORIES(${name} PRIVATE ${PROJECT_SOURCE_DIR}) + TARGET_LINK_OPTIONS(${name} PRIVATE -stdlib=libc++ -fsanitize=fuzzer,address,leak,undefined) + TARGET_LINK_LIBRARIES(${name} ubox blobmsg_json json_script ${json}) + ADD_TEST( + NAME ${name} + COMMAND ${name} -max_len=256 -timeout=10 -max_total_time=300 ${CMAKE_CURRENT_SOURCE_DIR}/corpus + ) +ENDMACRO(ADD_FUZZER_TEST) + +FOREACH(test_case ${test_cases}) + GET_FILENAME_COMPONENT(test_case ${test_case} NAME_WE) + ADD_FUZZER_TEST(${test_case}) +ENDFOREACH(test_case) diff --git a/tests/fuzz/corpus/71520a5c4b5ca73903216857abbad54a8002d44a b/tests/fuzz/corpus/71520a5c4b5ca73903216857abbad54a8002d44a new file mode 100644 index 0000000000000000000000000000000000000000..b4e009dd6d7e91ff56595a84010db2eb81e41622 GIT binary patch literal 2 Jcmcb}0004`0MY;e literal 0 HcmV?d00001 diff --git a/tests/fuzz/corpus/c1dfd96eea8cc2b62785275bca38ac261256e278 b/tests/fuzz/corpus/c1dfd96eea8cc2b62785275bca38ac261256e278 new file mode 100644 index 000000000000..62f9457511f8 --- /dev/null +++ b/tests/fuzz/corpus/c1dfd96eea8cc2b62785275bca38ac261256e278 @@ -0,0 +1 @@ +6 \ No newline at end of file diff --git a/tests/fuzz/corpus/c42ac1c46f1d4e211c735cc7dfad4ff8391110e9 b/tests/fuzz/corpus/c42ac1c46f1d4e211c735cc7dfad4ff8391110e9 new file mode 100644 index 0000000000000000000000000000000000000000..3d70d85eba81360f757bc71859316667610c5339 GIT binary patch literal 3 KcmZQ%U<3dF2LJ;A literal 0 HcmV?d00001 diff --git a/tests/fuzz/corpus/valid-blobmsg.bin b/tests/fuzz/corpus/valid-blobmsg.bin new file mode 100644 index 0000000000000000000000000000000000000000..2d0c68e8a1273ae12ac6d4401c7471927809a926 GIT binary patch literal 176 zcmZo>V31>A&rK~ZPE1c_U|{e_&B@8vQ7F$Z%1KcK@*9Cd3@kaB#U%_3tqcr2Kp`+d zVlyJKnK~F4BpBFI@=KF)K*ljRBy39qfhLeS93`p6B`Jv|i3|+5)B(*BU|`JvxdNn} Rv6+E^kAW5J90ntx007e$BMSfk literal 0 HcmV?d00001 diff --git a/tests/fuzz/test-fuzz.c b/tests/fuzz/test-fuzz.c new file mode 100644 index 000000000000..7153847e0825 --- /dev/null +++ b/tests/fuzz/test-fuzz.c @@ -0,0 +1,76 @@ +#include +#include +#include + +#include "blob.h" +#include "blobmsg.h" + +static void fuzz_blobmsg_parse(const uint8_t *data, size_t size) +{ + enum { + FOO_MESSAGE, + FOO_LIST, + FOO_TESTDATA, + __FOO_MAX + }; + + static const struct blobmsg_policy foo_policy[] = { + [FOO_MESSAGE] = { + .name = "message", + .type = BLOBMSG_TYPE_STRING, + }, + [FOO_LIST] = { + .name = "list", + .type = BLOBMSG_TYPE_ARRAY, + }, + [FOO_TESTDATA] = { + .name = "testdata", + .type = BLOBMSG_TYPE_TABLE, + }, + }; + + struct blob_attr *tb[__FOO_MAX]; + + blobmsg_parse(foo_policy, __FOO_MAX, tb, (uint8_t *)data, size); + blobmsg_parse_array(foo_policy, __FOO_MAX, tb, (uint8_t *)data, size); +} + +static void fuzz_blob_parse(const uint8_t *data, size_t size) +{ + enum { + FOO_ATTR_NESTED, + FOO_ATTR_BINARY, + FOO_ATTR_STRING, + FOO_ATTR_INT8, + FOO_ATTR_INT16, + FOO_ATTR_INT32, + FOO_ATTR_INT64, + FOO_ATTR_DOUBLE, + __FOO_ATTR_MAX + }; + + + static const struct blob_attr_info foo_policy[__FOO_ATTR_MAX] = { + [FOO_ATTR_NESTED] = { .type = BLOB_ATTR_NESTED }, + [FOO_ATTR_BINARY] = { .type = BLOB_ATTR_BINARY }, + [FOO_ATTR_STRING] = { .type = BLOB_ATTR_STRING }, + [FOO_ATTR_INT8] = { .type = BLOB_ATTR_INT8 }, + [FOO_ATTR_INT16] = { .type = BLOB_ATTR_INT16 }, + [FOO_ATTR_INT32] = { .type = BLOB_ATTR_INT32 }, + [FOO_ATTR_INT64] = { .type = BLOB_ATTR_INT64 }, + [FOO_ATTR_DOUBLE] = { .type = BLOB_ATTR_DOUBLE }, + }; + + struct blob_attr *foo[__FOO_ATTR_MAX]; + struct blob_attr *buf = (struct blob_attr *)data; + + blob_parse(buf, foo, foo_policy, __FOO_ATTR_MAX); +} + +int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + fuzz_blob_parse(data, size); + fuzz_blobmsg_parse(data, size); + + return 0; +}