diff --git a/ports/unix/main.c b/ports/unix/main.c index 530e20a386..dab521ef63 100644 --- a/ports/unix/main.c +++ b/ports/unix/main.c @@ -640,6 +640,10 @@ MP_NOINLINE int main_(int argc, char **argv) { sys_set_excecutable(argv[0]); #endif + #ifdef __AFL_HAVE_MANUAL_CONTROL + __AFL_INIT(); + #endif + const int NOTHING_EXECUTED = -2; int ret = NOTHING_EXECUTED; bool inspect = false; diff --git a/ports/unix/variants/aflplusplus/README.md b/ports/unix/variants/aflplusplus/README.md new file mode 100644 index 0000000000..3529d86a69 --- /dev/null +++ b/ports/unix/variants/aflplusplus/README.md @@ -0,0 +1,24 @@ +# Unix Fuzzing Variant + +This variant is for use with the [AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) +fuzzer. + + 1. Install AFLplusplus so that the program `afl-cc` is on $PATH + 1. `cd ports/unix && make VARIANT=aflplusplus -j$(nproc)` + 1. Gather your inputs (e.g., from test cases in `tests`) + 1. Optionally, minimize them e.g., with `afl-cmin` (see AFLplusplus docs) + 1. Run the fuzzer. The simplest single process way is: `afl-fuzz -i inputs -o findings -- ports/unix/build-aflfuzz/micropython @@` + +Eventually, if crashing test cases are found, the crashing program(s) are placed in +`findings/default/crashes` and invocations that were determined to hang go to +`findings/default/hangs`. + +There are many more advanced ways to run the fuzzer; see the AFLplusplus documentation for info. + +# Safety + +Functionality that is known to be unsafe (host filesystem write access via vfs_posix) +or is accepted as causing crashes when used improperly (ctypes, certain struct +& array typecodes) is build-time disabled. However, it's always possible that +the fuzzer will find a condition that can cause an unexpected modification to +the runtime environment. diff --git a/ports/unix/variants/aflplusplus/manifest.py b/ports/unix/variants/aflplusplus/manifest.py new file mode 100644 index 0000000000..d27bf3c47f --- /dev/null +++ b/ports/unix/variants/aflplusplus/manifest.py @@ -0,0 +1,3 @@ +include("$(PORT_DIR)/variants/manifest.py") + +include("$(MPY_DIR)/extmod/asyncio") diff --git a/ports/unix/variants/aflplusplus/mpconfigvariant.h b/ports/unix/variants/aflplusplus/mpconfigvariant.h new file mode 100644 index 0000000000..df848dcc82 --- /dev/null +++ b/ports/unix/variants/aflplusplus/mpconfigvariant.h @@ -0,0 +1,60 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +// Set base feature level. +#define MICROPY_CONFIG_ROM_LEVEL (MICROPY_CONFIG_ROM_LEVEL_EXTRA_FEATURES) + +#define MICROPY_LONGINT_IMPL (MICROPY_LONGINT_IMPL_LONGLONG) + +// Disable features known to affect host environment, access arbitrary addresses, or +// execute arbitrary code +#define MICROPY_VFS_POSIX_WRITABLE (0) +#define MICROPY_PY_STRUCT_UNSAFE_TYPECODES (0) +#define MICROPY_PY_UCTYPES (0) +#define MICROPY_PERSISTENT_CODE_LOAD (0) +// https://github.com/micropython/micropython/issues/17818 +#define MICROPY_PY_WEBSOCKET (0) +// https://github.com/micropython/micropython/issues/17714 +#define MICROPY_PY_MACHINE (0) + +#define MICROPY_EMIT_X64 (0) +#define MICROPY_EMIT_X86 (0) +#define MICROPY_EMIT_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB (0) +#define MICROPY_EMIT_INLINE_THUMB_FLOAT (0) +#define MICROPY_EMIT_ARM (0) +#define MICROPY_EMIT_XTENSA (0) +#define MICROPY_EMIT_INLINE_XTENSA (0) +#define MICROPY_EMIT_XTENSAWIN (0) +#define MICROPY_EMIT_RV32 (0) +#define MICROPY_EMIT_INLINE_RV32 (0) + +#define MICROPY_EMIT_NATIVE_DEBUG (1) +#define MICROPY_EMIT_NATIVE_DEBUG_PRINTER (&mp_stderr_print) + + +// Enable extra Unix features. +#include "../mpconfigvariant_common.h" diff --git a/ports/unix/variants/aflplusplus/mpconfigvariant.mk b/ports/unix/variants/aflplusplus/mpconfigvariant.mk new file mode 100644 index 0000000000..f1e8add6e9 --- /dev/null +++ b/ports/unix/variants/aflplusplus/mpconfigvariant.mk @@ -0,0 +1,15 @@ +# This is for fuzzing with AFLplusplus + +# Disable optimisations and enable assert() on coverage builds. +DEBUG ?= 1 + +CC=afl-cc + +CFLAGS += \ + -Wformat -Wmissing-declarations -Wmissing-prototypes \ + -Wold-style-definition -Wpointer-arith -Wshadow -Wuninitialized -Wunused-parameter \ + +MICROPY_PY_SSL = 0 +MICROPY_PY_FFI = 0 + +MPY_TOOL_FLAGS = -mlongint-impl longlong diff --git a/ports/unix/variants/mpconfigvariant_common.h b/ports/unix/variants/mpconfigvariant_common.h index 65c8743176..65be34bf45 100644 --- a/ports/unix/variants/mpconfigvariant_common.h +++ b/ports/unix/variants/mpconfigvariant_common.h @@ -70,7 +70,9 @@ #define MICROPY_EMERGENCY_EXCEPTION_BUF_SIZE (256) // Allow loading of .mpy files. +#ifndef MICROPY_PERSISTENT_CODE_LOAD #define MICROPY_PERSISTENT_CODE_LOAD (1) +#endif // Extra memory debugging. #define MICROPY_MALLOC_USES_ALLOCATED_SIZE (1) @@ -115,10 +117,14 @@ #define MICROPY_PY_SELECT_SELECT (0) // Enable the "websocket" module. +#ifndef MICROPY_PY_WEBSOCKET #define MICROPY_PY_WEBSOCKET (1) +#endif // Enable the "machine" module, mostly for machine.mem*. +#ifndef MICROPY_PY_MACHINE #define MICROPY_PY_MACHINE (1) +#endif #define MICROPY_PY_MACHINE_PULSE (1) #define MICROPY_PY_MACHINE_PIN_BASE (1)