| // 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 "base/logging.h" |
| |
| #include "patchpanel/firewall.h" |
| |
| using patchpanel::ModifyPortRuleRequest; |
| using Protocol = patchpanel::ModifyPortRuleRequest::Protocol; |
| |
| namespace patchpanel { |
| |
| class FakeFirewall : public Firewall { |
| public: |
| FakeFirewall() = default; |
| ~FakeFirewall() = default; |
| |
| private: |
| // The fake's implementation always succeeds. |
| int RunInMinijail(const std::vector<std::string>& argv) override { |
| return 0; |
| } |
| |
| DISALLOW_COPY_AND_ASSIGN(FakeFirewall); |
| }; |
| |
| } // namespace patchpanel |
| |
| struct Environment { |
| Environment() { |
| logging::SetMinLogLevel(logging::LOG_FATAL); |
| } |
| }; |
| |
| void FuzzAcceptRules(patchpanel::FakeFirewall& fake_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()) { |
| fake_firewall.AddAcceptRules(proto, port, iface); |
| } else { |
| fake_firewall.DeleteAcceptRules(proto, port, iface); |
| } |
| } |
| } |
| |
| void FuzzForwardRules(patchpanel::FakeFirewall& fake_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()) { |
| fake_firewall.AddIpv4ForwardRule(proto, input_ip, forwarded_port, iface, |
| dst_ip, dst_port); |
| } else { |
| fake_firewall.DeleteIpv4ForwardRule(proto, input_ip, forwarded_port, |
| iface, dst_ip, dst_port); |
| } |
| } |
| } |
| |
| void FuzzLoopbackLockdownRules(patchpanel::FakeFirewall& fake_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()) { |
| fake_firewall.AddLoopbackLockdownRules(proto, port); |
| } else { |
| fake_firewall.DeleteLoopbackLockdownRules(proto, port); |
| } |
| } |
| } |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| static Environment env; |
| |
| patchpanel::FakeFirewall fake_firewall; |
| |
| FuzzAcceptRules(fake_firewall, data, size); |
| FuzzForwardRules(fake_firewall, data, size); |
| FuzzLoopbackLockdownRules(fake_firewall, data, size); |
| |
| return 0; |
| } |