Skip to content
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

Add bpf2c fuzzer and execution context fuzzer to CI/CD #1164

Merged
merged 7 commits into from
Jun 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,33 @@ jobs:
code_coverage: false
gather_dumps: true

bpf2c_fuzzer:
needs: libfuzzer
# Always run this job.
if: github.event_name == 'schedule' || github.event_name == 'pull_request'
uses: ./.github/workflows/reusable-test.yml
with:
name: bpf2c_fuzzer
test_command: bpf2c_fuzzer.exe bpf2c_fuzzer_corpus -use_value_profile=1 -max_total_time=900 -artifact_prefix=Artifacts\
build_artifact: Build-x64-fuzzer
environment: windows-2019
code_coverage: false
gather_dumps: true

execution_context_fuzzer:
needs: libfuzzer
# Always run this job.
if: github.event_name == 'schedule' || github.event_name == 'pull_request'
uses: ./.github/workflows/reusable-test.yml
with:
name: execution_context_fuzzer
pre_test: powershell Expand-Archive -Path .\corpus.zip -DestinationPath execution_context_fuzzer_corpus -Force
test_command: execution_context_fuzzer.exe execution_context_fuzzer_corpus -use_value_profile=1 -runs=3000 -artifact_prefix=Artifacts\
build_artifact: Build-x64-fuzzer
environment: windows-2019
code_coverage: false
gather_dumps: true

# Run Cilium regression tests in GitHub.
cilium_tests:
needs: regular
Expand Down
20 changes: 20 additions & 0 deletions .github/workflows/reusable-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ jobs:
name: ${{inputs.build_artifact}} ${{matrix.configurations}}
path: ${{github.workspace}}/${{env.BUILD_PLATFORM}}/${{env.BUILD_CONFIGURATION}}

- name: Create generated artifact folder
run: |
mkdir ${{github.workspace}}\${{env.BUILD_PLATFORM}}\${{env.BUILD_CONFIGURATION}}\Artifacts

- name: Start ETW tracing
id: start_etw_tracing
if: inputs.capture_etw == true
Expand Down Expand Up @@ -242,6 +246,22 @@ jobs:
path: ./${{env.BUILD_PLATFORM}}/${{env.BUILD_CONFIGURATION}}/TestLogs
retention-days: 5

- name: Check for generated artifacts
if: always()
uses: andstor/file-existence-action@f02338908d150e00a4b8bebc2dad18bd9e5229b0
id: check_artifacts
with:
files: ${{github.workspace}}\${{env.BUILD_PLATFORM}}\${{env.BUILD_CONFIGURATION}}\Artifacts\*

- name: Upload generated artifacts
if: always() && steps.check_artifacts.outputs.files_exists == 'true'
id: upload_artifacts
uses: actions/upload-artifact@3cea5372237819ed00197afe530f5a7ea3e805c8
with:
name: Artifacts-${{env.NAME}}-${{env.BUILD_PLATFORM}}-${{env.BUILD_CONFIGURATION}}
path: ${{github.workspace}}\${{env.BUILD_PLATFORM}}\${{env.BUILD_CONFIGURATION}}\Artifacts
retention-days: 5

- name: Mark run as failed if crash dumps are found
if: steps.check_dumps.outputs.files_exists == 'true'
run: exit 1
8 changes: 7 additions & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@
<PropertyGroup Condition="'$(AddressSanitizer)'=='True'">
<EnableASAN>true</EnableASAN>
</PropertyGroup>
<PropertyGroup Condition="'$(Fuzzer)'=='True'">
<PropertyGroup Condition="'$(Configuration)|$(Fuzzer)'=='Release|True'">
<EnableASAN>true</EnableASAN>
<AdditionalOptions>/fsanitize-coverage=inline-bool-flag /fsanitize-coverage=edge /fsanitize-coverage=trace-cmp /fsanitize-coverage=trace-div %(AdditionalOptions)</AdditionalOptions>
<SanitizerLibs>libsancov.lib;clang_rt.fuzzer_MD-x86_64.lib</SanitizerLibs>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Fuzzer)'=='Debug|True'">
<EnableASAN>true</EnableASAN>
<AdditionalOptions>/fsanitize-coverage=inline-bool-flag /fsanitize-coverage=edge /fsanitize-coverage=trace-cmp /fsanitize-coverage=trace-div %(AdditionalOptions)</AdditionalOptions>
<SanitizerLibs>libsancov.lib;clang_rt.fuzzer_MDd-x86_64.lib</SanitizerLibs>
</PropertyGroup>
<PropertyGroup Condition="'$(Fuzzer)'!='True'">
<SpectreMitigation>Spectre</SpectreMitigation>
Expand Down
3 changes: 3 additions & 0 deletions ebpf-for-windows.sln
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "execution_context_fuzzer", "tests\libfuzzer\execution_context\execution_context_fuzzer.vcxproj", "{6116AE11-5296-4DE9-8A8E-5380B789907E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bpf2c_fuzzer", "tests\libfuzzer\bpf2c\bpf2c_fuzzer.vcxproj", "{A0A0D663-DCF7-4BB1-9DDB-7964C3C31603}"
ProjectSection(ProjectDependencies) = postProject
{B4AD72E3-754E-40CA-9CEA-D3F2C9170E51} = {B4AD72E3-754E-40CA-9CEA-D3F2C9170E51}
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "verifier_fuzzer", "tests\libfuzzer\verifier\verifier_fuzzer.vcxproj", "{DCF12929-B975-4874-A80F-9EAF1CC5A5A0}"
EndProject
Expand Down
5 changes: 2 additions & 3 deletions ebpfapi/ebpfapi.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@
<EnableUAC>false</EnableUAC>
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
<AdditionalLibraryDirectories>$(OutDir)</AdditionalLibraryDirectories>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>mincore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(SanitizerLibs);mincore.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<ResourceCompile>
<AdditionalIncludeDirectories>$(SolutionDir)include</AdditionalIncludeDirectories>
Expand All @@ -101,7 +100,7 @@
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
<EnableUAC>false</EnableUAC>
<ModuleDefinitionFile>Source.def</ModuleDefinitionFile>
<AdditionalDependencies>mincore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>$(SanitizerLibs);mincore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(OutDir)</AdditionalLibraryDirectories>
</Link>
<ResourceCompile>
Expand Down
11 changes: 11 additions & 0 deletions libs/platform/user/ebpf_platform_user.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ bool _ebpf_platform_code_integrity_enabled = false;
bool _ebpf_platform_is_preemptible = true;

extern "C" bool ebpf_fuzzing_enabled = false;
extern "C" size_t ebfp_fuzzing_memory_limit = MAXSIZE_T;

// Thread pool related globals.
static TP_CALLBACK_ENVIRON _callback_environment;
Expand Down Expand Up @@ -243,6 +244,9 @@ __drv_allocatesMem(Mem) _Must_inspect_result_ _Ret_maybenull_
_Post_writable_byte_size_(size) void* ebpf_allocate(size_t size)
{
ebpf_assert(size);
if (size > ebfp_fuzzing_memory_limit) {
return nullptr;
}
void* memory;
memory = calloc(size, 1);
if (memory != nullptr)
Expand All @@ -255,6 +259,9 @@ __drv_allocatesMem(Mem) _Must_inspect_result_ _Ret_maybenull_
_Post_writable_byte_size_(new_size) void* ebpf_reallocate(_In_ void* memory, size_t old_size, size_t new_size)
{
UNREFERENCED_PARAMETER(old_size);
if (new_size > ebfp_fuzzing_memory_limit) {
return nullptr;
}
void* p = realloc(memory, new_size);
if (p && (new_size > old_size))
memset(((char*)p) + old_size, 0, new_size - old_size);
Expand All @@ -270,6 +277,10 @@ ebpf_free(_Frees_ptr_opt_ void* memory)
__drv_allocatesMem(Mem) _Must_inspect_result_ _Ret_maybenull_
_Post_writable_byte_size_(size) void* ebpf_allocate_cache_aligned(size_t size)
{
if (size > ebfp_fuzzing_memory_limit) {
return nullptr;
}

void* memory = _aligned_malloc(size, EBPF_CACHE_LINE_SIZE);
if (memory) {
memset(memory, 0, size);
Expand Down
10 changes: 10 additions & 0 deletions scripts/create_bpf2c_corpus.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@echo off
rem Copyright (c) Microsoft Corporation
rem SPDX-License-Identifier: MIT
rem
rem Usage: create_bpf2c_corpus.bat <output_directory>
echo set OUTPUTPATH=%1
set OUTPUTPATH=%1
rem Strip the \ from the end of the path if present.
if %OUTPUTPATH:~-1% EQU \ set OUTPUTPATH=%OUTPUTPATH:~0,-1%
xcopy /d /i /y "%OUTPUTPATH%\*.o" "%OUTPUTPATH%\bpf2c_fuzzer_corpus"
9 changes: 9 additions & 0 deletions tests/libfuzzer/bpf2c/bpf2c_fuzzer.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@
<Project>{7d5b4e68-c0fa-3f86-9405-f6400219b440}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="$(SolutionDir)scripts\create_bpf2c_corpus.bat">
<FileType>Document</FileType>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(OutDir)bpf2c_fuzzer_corpus\bpf.o</Outputs>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(OutDir)bpf2c_fuzzer_corpus\bpf.o</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(SolutionDir)scripts\create_bpf2c_corpus.bat $(OutDir)</Command>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(SolutionDir)scripts\create_bpf2c_corpus.bat $(OutDir)</Command>
</CustomBuild>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
Expand Down
5 changes: 5 additions & 0 deletions tests/libfuzzer/bpf2c/bpf2c_fuzzer.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,9 @@
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\..\scripts\create_bpf2c_corpus.bat">
<Filter>Source Files</Filter>
</CustomBuild>
</ItemGroup>
</Project>
Binary file added tests/libfuzzer/execution_context/corpus.zip
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@
<ClInclude Include="..\..\libs\thunk\mock\mock.h" />
<ClInclude Include="..\end_to_end\test_helper.hpp" />
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="corpus.zip">
<FileType>Document</FileType>
</CopyFileToFolders>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,7 @@
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<CopyFileToFolders Include="corpus.zip" />
</ItemGroup>
</Project>
8 changes: 7 additions & 1 deletion tests/libfuzzer/execution_context/libfuzz_harness.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "libfuzzer.h"
#include "platform.h"

extern "C" size_t ebfp_fuzzing_memory_limit;

static std::vector<std::unique_ptr<_program_info_provider>> _program_information_providers;
static std::vector<GUID> _program_types = {
EBPF_PROGRAM_TYPE_XDP,
Expand Down Expand Up @@ -236,7 +238,11 @@ fuzz_ioctl(std::vector<uint8_t>& random_buffer)
}
}

FUZZ_EXPORT int __cdecl LLVMFuzzerInitialize(int*, char***) { return 0; }
FUZZ_EXPORT int __cdecl LLVMFuzzerInitialize(int*, char***)
{
ebfp_fuzzing_memory_limit = 1024 * 1024 * 10;
return 0;
}

FUZZ_EXPORT int __cdecl LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
{
Expand Down
2 changes: 2 additions & 0 deletions tools/bpf2c/bpf2c.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(SanitizerLibs);%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>powershell -NonInteractive -ExecutionPolicy Unrestricted $(SolutionDir)scripts\Process-File.ps1 -InputFile Convert-BpfToNative.ps1.template -OutputFile $(OutDir)Convert-BpfToNative.ps1 -ConfigFile replacements.json</Command>
Expand All @@ -137,6 +138,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>$(SanitizerLibs);%(AdditionalDependencies)</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>powershell -NonInteractive -ExecutionPolicy Unrestricted $(SolutionDir)scripts\Process-File.ps1 -InputFile Convert-BpfToNative.ps1.template -OutputFile $(OutDir)Convert-BpfToNative.ps1 -ConfigFile replacements.json</Command>
Expand Down
12 changes: 12 additions & 0 deletions tools/bpf2c/bpf_code_generator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ bpf_code_generator::parse()

if (map_section) {
size_t data_size = map_section->get_size();
size_t map_count = data_size / sizeof(ebpf_map_definition_in_file_t);

if (data_size % sizeof(ebpf_map_definition_in_file_t) != 0) {
throw std::runtime_error(
Expand Down Expand Up @@ -276,12 +277,23 @@ bpf_code_generator::parse()
if (symbol_size != sizeof(ebpf_map_definition_in_file_t)) {
throw std::runtime_error("invalid map size");
}
if (symbol_value > map_section->get_size()) {
throw std::runtime_error("invalid symbol value");
}
if ((symbol_value + symbol_size) > map_section->get_size()) {
throw std::runtime_error("invalid symbol value");
}

map_definitions[symbol_name].definition =
*reinterpret_cast<const ebpf_map_definition_in_file_t*>(map_section->get_data() + symbol_value);

map_definitions[symbol_name].index = symbol_value / sizeof(ebpf_map_definition_in_file_t);
}
}

if (map_definitions.size() != map_count) {
throw std::runtime_error(std::string("bad maps section, map must have associated symbol"));
}
}
}

Expand Down