| // Copyright 2018 The ChromiumOS Authors | |
| // 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/fake_process_runner.h" | |
| #include "patchpanel/firewall.h" | |
| using patchpanel::ModifyPortRuleRequest; | |
| using Protocol = patchpanel::ModifyPortRuleRequest::Protocol; | |
| namespace patchpanel { | |
| namespace { | |
| net_base::IPv4Address ConsumeIPv4Address(FuzzedDataProvider& provider) { | |
| const auto bytes = | |
| provider.ConsumeBytes<uint8_t>(net_base::IPv4Address::kAddressLength); | |
| return net_base::IPv4Address::CreateFromBytes(bytes).value_or( | |
| net_base::IPv4Address()); | |
| } | |
| 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>(); | |
| const auto input_ip = ConsumeIPv4Address(data_provider); | |
| const auto dst_ip = ConsumeIPv4Address(data_provider); | |
| 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; | |
| patchpanel::FakeProcessRunner process_runner; | |
| patchpanel::Firewall firewall(&process_runner); | |
| FuzzAcceptRules(&firewall, data, size); | |
| FuzzForwardRules(&firewall, data, size); | |
| FuzzLoopbackLockdownRules(&firewall, data, size); | |
| return 0; | |
| } | |
| } // namespace | |
| } // namespace patchpanel |