| // Copyright 2018 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <arpa/inet.h> |
| #include <net/if.h> |
| |
| #include <fuzzer/FuzzedDataProvider.h> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/logging.h" |
| |
| #include "patchpanel/firewall.h" |
| #include "patchpanel/minijailed_process_runner.h" |
| |
| using patchpanel::ModifyPortRuleRequest; |
| using Protocol = patchpanel::ModifyPortRuleRequest::Protocol; |
| |
| namespace patchpanel { |
| namespace { |
| |
| class FakeProcessRunner : public MinijailedProcessRunner { |
| public: |
| FakeProcessRunner() : MinijailedProcessRunner(nullptr, nullptr) {} |
| FakeProcessRunner(const FakeProcessRunner&) = delete; |
| FakeProcessRunner& operator=(const FakeProcessRunner&) = delete; |
| ~FakeProcessRunner() = default; |
| |
| int Run(const std::vector<std::string>& argv, bool log_failures) override { |
| return 0; |
| } |
| |
| int RunSync(const std::vector<std::string>& argv, |
| bool log_failures, |
| std::string* output) override { |
| return 0; |
| } |
| }; |
| } // namespace |
| |
| } // namespace patchpanel |
| |
| struct Environment { |
| Environment() { logging::SetMinLogLevel(logging::LOGGING_FATAL); } |
| }; |
| |
| void FuzzAcceptRules(patchpanel::Firewall* firewall, |
| const uint8_t* data, |
| size_t size) { |
| FuzzedDataProvider data_provider(data, size); |
| while (data_provider.remaining_bytes() > 0) { |
| ModifyPortRuleRequest::Protocol proto = data_provider.ConsumeBool() |
| ? ModifyPortRuleRequest::TCP |
| : ModifyPortRuleRequest::UDP; |
| uint16_t port = data_provider.ConsumeIntegral<uint16_t>(); |
| std::string iface = data_provider.ConsumeRandomLengthString(IFNAMSIZ - 1); |
| if (data_provider.ConsumeBool()) { |
| firewall->AddAcceptRules(proto, port, iface); |
| } else { |
| firewall->DeleteAcceptRules(proto, port, iface); |
| } |
| } |
| } |
| |
| void FuzzForwardRules(patchpanel::Firewall* firewall, |
| const uint8_t* data, |
| size_t size) { |
| FuzzedDataProvider data_provider(data, size); |
| while (data_provider.remaining_bytes() > 0) { |
| ModifyPortRuleRequest::Protocol proto = data_provider.ConsumeBool() |
| ? ModifyPortRuleRequest::TCP |
| : ModifyPortRuleRequest::UDP; |
| uint16_t forwarded_port = data_provider.ConsumeIntegral<uint16_t>(); |
| uint16_t dst_port = data_provider.ConsumeIntegral<uint16_t>(); |
| struct in_addr input_ip_addr = { |
| .s_addr = data_provider.ConsumeIntegral<uint32_t>()}; |
| struct in_addr dst_ip_addr = { |
| .s_addr = data_provider.ConsumeIntegral<uint32_t>()}; |
| char input_buffer[INET_ADDRSTRLEN]; |
| char dst_buffer[INET_ADDRSTRLEN]; |
| memset(input_buffer, 0, INET_ADDRSTRLEN); |
| memset(dst_buffer, 0, INET_ADDRSTRLEN); |
| inet_ntop(AF_INET, &input_ip_addr, input_buffer, INET_ADDRSTRLEN); |
| inet_ntop(AF_INET, &dst_ip_addr, dst_buffer, INET_ADDRSTRLEN); |
| std::string input_ip = input_buffer; |
| std::string dst_ip = dst_buffer; |
| std::string iface = data_provider.ConsumeRandomLengthString(IFNAMSIZ - 1); |
| if (data_provider.ConsumeBool()) { |
| firewall->AddIpv4ForwardRule(proto, input_ip, forwarded_port, iface, |
| dst_ip, dst_port); |
| } else { |
| firewall->DeleteIpv4ForwardRule(proto, input_ip, forwarded_port, iface, |
| dst_ip, dst_port); |
| } |
| } |
| } |
| |
| void FuzzLoopbackLockdownRules(patchpanel::Firewall* firewall, |
| const uint8_t* data, |
| size_t size) { |
| FuzzedDataProvider data_provider(data, size); |
| while (data_provider.remaining_bytes() > 0) { |
| ModifyPortRuleRequest::Protocol proto = data_provider.ConsumeBool() |
| ? ModifyPortRuleRequest::TCP |
| : ModifyPortRuleRequest::UDP; |
| uint16_t port = data_provider.ConsumeIntegral<uint16_t>(); |
| if (data_provider.ConsumeBool()) { |
| firewall->AddLoopbackLockdownRules(proto, port); |
| } else { |
| firewall->DeleteLoopbackLockdownRules(proto, port); |
| } |
| } |
| } |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| static Environment env; |
| |
| auto process_runner = new patchpanel::FakeProcessRunner(); |
| patchpanel::Firewall firewall(process_runner); |
| |
| FuzzAcceptRules(&firewall, data, size); |
| FuzzForwardRules(&firewall, data, size); |
| FuzzLoopbackLockdownRules(&firewall, data, size); |
| |
| return 0; |
| } |