def test_fuzz_args(): fuzzing_time_seconds = 45 * 60 iotrace: IotracePlugin = TestRun.plugins['iotrace'] repo_path: str = f"{iotrace.working_dir}/slit-afl" disk = TestRun.dut.disks[0].system_path # Make sure AFL is installed if not is_afl_installed(): install_afl() # Install iotrace locally with AFL support # Patch so that we redirect fuzzed stdin to argv install_iotrace_with_afl_support( repo_path + "/tests/security/fuzzy/redirect-fuzz-to-argv.patch") # Instruct the system to output coredumps as files instead of sending them # to a specific crash handler app TestRun.LOGGER.info('Setting up system for fuzzing') TestRun.executor.run_expect_success( 'echo core > /proc/sys/kernel/core_pattern') TestRun.executor.run_expect_success( f'cd {repo_path} && mkdir -p afl-i afl-o') # Add input seeds which shall be mutated - try list-traces, version, help, # start-tracing and remove-trace commands to guide the fuzzer. TestRun.executor.run_expect_success(f'cd {repo_path} && echo "-L"' f' > afl-i/case0') TestRun.executor.run_expect_success(f'cd {repo_path} && echo "-L -p k*"' f' > afl-i/case1') TestRun.executor.run_expect_success(f'cd {repo_path} && echo "-V"' f' > afl-i/case2') TestRun.executor.run_expect_success(f'cd {repo_path} && echo "-H"' f' > afl-i/case3') TestRun.executor.run_expect_success( f'cd {repo_path} && echo "-S -d {disk}"' f' > afl-i/case4') TestRun.executor.run_expect_success(f'cd {repo_path} && echo "-R -p k*"' f' > afl-i/case5') # Run script which will launch parallel fuzzers in separate 'screen' # windows in the background TestRun.LOGGER.info('Starting fuzzing argv. This should take ' + str(fuzzing_time_seconds / 60) + ' minutes') TestRun.executor.run(f'cd {repo_path} && ./tests/security/fuzzy/fuzz.sh ' 'rootfs/bin/iotrace') # Wait for fuzzing completion and output logs output = wait_for_completion(fuzzing_time_seconds, repo_path) TestRun.LOGGER.info('Killing fuzzers') TestRun.executor.run( f'cd {repo_path} && ./tests/security/fuzzy/fuzz.sh clean') TestRun.executor.run_expect_success(f'rm -rf {repo_path}/afl-i') detect_crashes(output, "argv")
def test_fuzz_trace_file(): fuzzing_time_seconds = 10 * 60 iotrace: IotracePlugin = TestRun.plugins['iotrace'] repo_path: str = f"{iotrace.working_dir}/slit-afl" # Make sure AFL is installed if not is_afl_installed(): install_afl() # Create trace files iotrace.start_tracing() iotrace.stop_tracing() trace_repo_path = iotrace.parse_json( iotrace.get_trace_repository_path())[0]['path'] trace_path = trace_repo_path + "/" + iotrace.get_latest_trace_path() tracefile_path = f'{trace_path}/octf.trace.0' copied_tracefile_path = f'{repo_path}/rootfs/var/lib/octf/trace/' + \ f'{iotrace.get_latest_trace_path()}/octf.trace.0' # Create patch file for redirecting fuzzed stdin to trace file new_patch_path: str = f'{iotrace.working_dir}/redirect_to_tracefile.patch' create_patch_redirect_fuzz_to_file(f'{copied_tracefile_path}', new_patch_path) # Install iotrace locally with AFL support and redirect patch install_iotrace_with_afl_support(new_patch_path) # Copy trace files to local instalation of iotrace TestRun.executor.run_expect_success( f'cp -r {trace_repo_path}/kernel ' f'{repo_path}/rootfs/var/lib/octf/trace/') # Instruct the system to output coredumps as files instead of sending them # to a specific crash handler app TestRun.LOGGER.info('Setting up system for fuzzing') TestRun.executor.run_expect_success( 'echo core > /proc/sys/kernel/core_pattern') TestRun.executor.run_expect_success( f'cd {repo_path} && mkdir -p afl-i afl-o') # Add input seed which shall be mutated TestRun.executor.run_expect_success( f'cd {repo_path} && echo "0" > afl-i/case0') TestRun.LOGGER.info( f'Starting fuzzing {tracefile_path} This should take ' + str(fuzzing_time_seconds / 60) + ' minutes') TestRun.executor.run(f'cd {repo_path} && ./tests/security/fuzzy/fuzz.sh ' '"rootfs/bin/iotrace --get-trace-statistics -p ' f'{iotrace.get_latest_trace_path()}" --one-job') output = wait_for_completion(fuzzing_time_seconds, repo_path) TestRun.executor.run( f'cd {repo_path} && ./tests/security/fuzzy/fuzz.sh clean') detect_crashes(output.stdout)
def test_fuzz_config(): fuzzing_time_seconds = 10 * 60 iotrace: IotracePlugin = TestRun.plugins['iotrace'] repo_path: str = f"{iotrace.working_dir}/slit-afl" # Make sure AFL is installed if not is_afl_installed(): install_afl() # Create patch file for redirecting fuzzed stdin to config file path new_patch_path: str = f'{iotrace.working_dir}/redirect_to_config.patch' create_patch_redirect_fuzz_to_file( f'{repo_path}/rootfs/etc/octf/octf.conf', new_patch_path) # Install iotrace locally with AFL support and redirect patch install_iotrace_with_afl_support(new_patch_path) # Instruct the system to output coredumps as files instead of sending them # to a specific crash handler app TestRun.LOGGER.info('Setting up system for fuzzing') TestRun.executor.run_expect_success( 'echo core > /proc/sys/kernel/core_pattern') TestRun.executor.run_expect_success( f'cd {repo_path} && mkdir -p afl-i afl-o') # Use config as seed to be mutated TestRun.executor.run_expect_success( f'cp {repo_path}/rootfs/etc/octf/octf.conf' f' {repo_path}/afl-i/case0') TestRun.LOGGER.info('Starting fuzzing octf.conf. This should take ' + str(fuzzing_time_seconds / 60) + ' minutes') TestRun.LOGGER.info("Trying 'list-traces' command") TestRun.executor.run(f'cd {repo_path} && ./tests/security/fuzzy/fuzz.sh ' '"rootfs/bin/iotrace -L" --one-job') output = wait_for_completion(fuzzing_time_seconds / 2, repo_path) TestRun.executor.run( f'cd {repo_path} && ./tests/security/fuzzy/fuzz.sh clean') detect_crashes(output.stdout) TestRun.LOGGER.info("Trying 'get-trace-repository-path' command") TestRun.executor.run( f'cd {repo_path} && ./tests/security/fuzzy/fuzz.sh ' '"rootfs/bin/iotrace --get-trace-repository" --one-job') output = wait_for_completion(fuzzing_time_seconds / 2, repo_path) TestRun.executor.run( f'cd {repo_path} && ./tests/security/fuzzy/fuzz.sh clean') detect_crashes(output.stdout)
def test_fuzz_procfs(): # For simplicity we start one non-instrumented iotrace instance # and fuzz proc files using afl with -n flag (dumb fuzzing) fuzzing_time_seconds = 15 * 60 iotrace: IotracePlugin = TestRun.plugins['iotrace'] repo_path: str = f"{iotrace.working_dir}/slit-afl" # Make sure AFL is installed if not is_afl_installed(): install_afl() # Instruct the system to output coredumps as files instead of sending them # to a specific crash handler app TestRun.LOGGER.info('Setting up system for fuzzing') TestRun.executor.run_expect_success( 'echo core > /proc/sys/kernel/core_pattern') TestRun.executor.run_expect_success( f'cd {repo_path} && mkdir -p afl-i afl-o') # Procfs files and their initial seed fuzzed_files = { "/proc/iotrace/add_device": "/dev/sdb", "/proc/iotrace/remove_device": "/dev/sdb", "/proc/iotrace/size": "1024" } # Start tracing, we start it using procfs interface by putting traced # device path, buffer size, and mmaping (using fio with mmap engine) # consumer header procfile. This is because procfiles may have a limit # on applications which mmap them, and iotrace -S may block other mmaps disk = TestRun.dut.disks[0].system_path TestRun.executor.run_expect_success( f'echo {disk} > /proc/iotrace/add_device') TestRun.executor.run_expect_success(f'echo 1024 > /proc/iotrace/size') fio_pid = TestRun.executor.run_in_background( f'fio --name=job --direct=0 --ioengine=mmap ' f'--filename=/proc/iotrace/consumer_hdr.0 ' f"--buffer_pattern=\\'/dev/urandom\\' " f'--time_based --runtime=30s --bs=4k ' f'--iodepth=128 --rw=randwrite') # Also start some workload on traced device to generate trace traffic workload_pid = TestRun.executor.run_in_background( f'fio --direct=1' f'--filename={disk} ' f'--time_based --runtime=24h --bs=4k ' f'--iodepth=1 --rw=randwrite') for procfile, seed in fuzzed_files.items(): # Create patch file for redirecting fuzzed stdin to proc file new_patch_path: str = f'{iotrace.working_dir}/redirect_to_procfile.patch' create_patch_redirect_fuzz_to_file(f'{procfile}', new_patch_path) # Install iotrace locally with AFL support and redirect patch install_iotrace_with_afl_support(new_patch_path) # Add input seed which shall be mutated TestRun.executor.run_expect_success( f'cd {repo_path} && echo {seed} > afl-i/case0') TestRun.LOGGER.info(f'Starting fuzzing {procfile} This should take ' + str(fuzzing_time_seconds / 60 / len(fuzzed_files)) + ' minutes') TestRun.executor.run_in_background( f'cd {repo_path} && screen -S master -d -m &&' f'screen -S master -X stuff "afl-fuzz -n -i ' f'afl-i -o afl-o {repo_path}/rootfs/bin/iotrace -H\n"') elapsed = 0 start_time = time.time() while elapsed < fuzzing_time_seconds / len(fuzzed_files): output = TestRun.executor.run(f'dmesg | grep -A 20 "Call Trace"') if output.exit_code == 0: save_fuzzing_output(f'{repo_path}/afl-o') TestRun.executor.run_expect_success('dmesg -c') TestRun.fail('Kernel BUGs during fuzzing procfs were found:\n' f'{output.stdout}') time.sleep(5) current_time = time.time() elapsed = current_time - start_time TestRun.executor.run_expect_success( 'killall afl-fuzz && screen -X -S master kill') # Stop tracing TestRun.executor.run_expect_success(f'kill {fio_pid}') TestRun.executor.run_expect_success(f'kill {workload_pid}')