| // Copyright 2019 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifdef UNSAFE_BUFFERS_BUILD |
| // TODO(crbug.com/40285824): Remove this and convert code to safer constructs. |
| #pragma allow_unsafe_buffers |
| #endif |
| |
| #include <stddef.h> |
| #include <stdint.h> |
| |
| #include <fuzzer/FuzzedDataProvider.h> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "sandbox/win/src/broker_services.h" |
| #include "sandbox/win/src/ipc_tags.h" |
| #include "sandbox/win/src/policy_engine_params.h" |
| #include "sandbox/win/src/sandbox_policy.h" |
| #include "sandbox/win/src/sandbox_policy_base.h" |
| #include "sandbox/win/src/sandbox_types.h" |
| |
| // We only use the first two params so don't need more. |
| constexpr size_t maxParams = 2; |
| |
| // This fills policies with rules based on the current renderer sandbox in |
| // Chrome - the point isn't to test the /sandbox/ but to fuzz the rule matching. |
| std::unique_ptr<sandbox::PolicyBase> InitPolicy() { |
| auto policy = std::make_unique<sandbox::PolicyBase>(""); |
| auto* config = policy->GetConfig(); |
| CHECK(config); |
| |
| auto result = config->SetFakeGdiInit(); |
| CHECK_EQ(result, sandbox::SBOX_ALL_OK); |
| |
| result = config->AllowFileAccess(sandbox::FileSemantics::kAllowAny, |
| L"\\??\\pipe\\chrome.*"); |
| CHECK_EQ(result, sandbox::SBOX_ALL_OK); |
| |
| result = config->AllowFileAccess(sandbox::FileSemantics::kAllowReadonly, |
| L"\\??\\pipe\\chrome.unused.*"); |
| CHECK_EQ(result, sandbox::SBOX_ALL_OK); |
| |
| result = config->AllowFileAccess(sandbox::FileSemantics::kAllowAny, |
| L"\\??\\*.log"); |
| CHECK_EQ(result, sandbox::SBOX_ALL_OK); |
| |
| sandbox::BrokerServicesBase::FreezeTargetConfigForTesting( |
| policy->GetConfig()); |
| return policy; |
| } |
| |
| struct FakeParameterSet { |
| sandbox::ArgType real_type_; |
| raw_ptr<void> address_; |
| }; |
| |
| static_assert(sizeof(FakeParameterSet) == sizeof(sandbox::ParameterSet)); |
| |
| struct FakeCountedParameterSetBase { |
| size_t count; |
| struct FakeParameterSet params[maxParams]; |
| }; |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| FakeCountedParameterSetBase params; |
| |
| static std::unique_ptr<sandbox::PolicyBase> policy = InitPolicy(); |
| |
| if (size < 20) { |
| return 0; |
| } |
| // We will take a sizeof(pointer) and a wchar_t string so need an even number. |
| if (size % sizeof(wchar_t)) { |
| return 0; |
| } |
| |
| // As parameters are created by Chromium code the format of the variables must |
| // be correct, and any wstrings will be validly null-terminated. |
| |
| FuzzedDataProvider data_provider(data, size); |
| params.count = maxParams; |
| // The rules expect a string in param[0] so we construct that last with the |
| // remaining bytes. |
| params.params[1].real_type_ = static_cast<sandbox::ArgType>( |
| data_provider.ConsumeIntegralInRange<uint8_t>( |
| sandbox::ArgType::WCHAR_TYPE, sandbox::ArgType::LAST_TYPE)); |
| auto pointed_at_bytes = data_provider.ConsumeBytes<uint8_t>(sizeof(void*)); |
| // These variables must remain in scope past the EvalPolicy call later. |
| std::wstring param_1_wstring; |
| const unsigned char* param_data = nullptr; |
| if (params.params[1].real_type_ == sandbox::ArgType::WCHAR_TYPE) { |
| param_1_wstring = |
| std::wstring(reinterpret_cast<wchar_t*>(pointed_at_bytes.data()), |
| pointed_at_bytes.size() / sizeof(wchar_t)); |
| |
| param_data = |
| reinterpret_cast<const unsigned char*>(param_1_wstring.c_str()); |
| } else { |
| param_data = pointed_at_bytes.data(); |
| } |
| params.params[1].address_ = static_cast<void*>(¶m_data); |
| |
| // param[0] is usually the filename. It must be a valid terminated wstring. |
| params.params[0].real_type_ = sandbox::ArgType::WCHAR_TYPE; |
| auto string_bytes = |
| data_provider.ConsumeBytes<uint8_t>(data_provider.remaining_bytes()); |
| std::wstring valid_wstr(reinterpret_cast<wchar_t*>(string_bytes.data()), |
| string_bytes.size() / sizeof(wchar_t)); |
| const wchar_t* wcharstar_variable = valid_wstr.c_str(); |
| params.params[0].address_ = static_cast<void*>(&wcharstar_variable); |
| |
| // Overlay the real type. |
| sandbox::CountedParameterSetBase* real_params = |
| (sandbox::CountedParameterSetBase*)¶ms; |
| |
| // We send the fuzzer generated data to every available policy rule. |
| // Only some of the services will be registered, but it will |
| // quickly skip those that have nothing registered. |
| for (size_t i = 0; i < sandbox::kSandboxIpcCount; i++) { |
| policy->EvalPolicy(static_cast<sandbox::IpcTag>(i), real_params); |
| } |
| |
| return 0; |
| } |