| // Copyright 2019 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 <net/if.h> |
| #include <string.h> |
| #include <sys/ioctl.h> |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include <base/at_exit.h> |
| #include <base/bind.h> |
| #include <base/callback_helpers.h> |
| #include <base/logging.h> |
| #include <fuzzer/FuzzedDataProvider.h> |
| |
| #include "patchpanel/datapath.h" |
| #include "patchpanel/firewall.h" |
| #include "patchpanel/minijailed_process_runner.h" |
| #include "patchpanel/multicast_forwarder.h" |
| #include "patchpanel/net_util.h" |
| #include "patchpanel/subnet.h" |
| #include "patchpanel/system.h" |
| |
| namespace patchpanel { |
| namespace { |
| |
| // Always succeeds |
| class FakeProcessRunner : public MinijailedProcessRunner { |
| public: |
| FakeProcessRunner() = default; |
| 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; |
| } |
| }; |
| |
| // Always succeeds |
| class NoopSystem : public System { |
| public: |
| NoopSystem() = default; |
| NoopSystem(const NoopSystem&) = delete; |
| NoopSystem& operator=(const NoopSystem&) = delete; |
| virtual ~NoopSystem() = default; |
| |
| int Ioctl(int fd, ioctl_req_t request, const char* argp) override { |
| return 0; |
| } |
| }; |
| |
| class Environment { |
| public: |
| Environment() { |
| logging::SetMinLogLevel(logging::LOGGING_FATAL); // <- DISABLE LOGGING. |
| } |
| base::AtExitManager at_exit; |
| }; |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
| static Environment env; |
| FuzzedDataProvider provider(data, size); |
| |
| uint32_t pid = provider.ConsumeIntegral<uint32_t>(); |
| std::string netns_name = provider.ConsumeRandomLengthString(10); |
| std::string ifname = provider.ConsumeRandomLengthString(IFNAMSIZ - 1); |
| std::string ifname2 = provider.ConsumeRandomLengthString(IFNAMSIZ - 1); |
| std::string ifname3 = provider.ConsumeRandomLengthString(IFNAMSIZ - 1); |
| std::string bridge = provider.ConsumeRandomLengthString(IFNAMSIZ - 1); |
| uint32_t addr = provider.ConsumeIntegral<uint32_t>(); |
| std::string addr_str = IPv4AddressToString(addr); |
| uint32_t prefix_len = provider.ConsumeIntegralInRange<uint32_t>(0, 31); |
| SubnetAddress subnet_addr(provider.ConsumeIntegral<int32_t>(), prefix_len, |
| base::DoNothing()); |
| MacAddress mac; |
| std::vector<uint8_t> mac_addr_bytes = |
| provider.ConsumeBytes<uint8_t>(mac.size()); |
| std::copy(mac_addr_bytes.begin(), mac_addr_bytes.end(), mac.begin()); |
| |
| struct in6_addr ipv6_addr; |
| memset(&ipv6_addr, 0, sizeof(ipv6_addr)); |
| std::vector<uint8_t> ipv6_addr_bytes = |
| provider.ConsumeBytes<uint8_t>(sizeof(ipv6_addr.s6_addr)); |
| std::copy(ipv6_addr_bytes.begin(), ipv6_addr_bytes.end(), ipv6_addr.s6_addr); |
| std::string ipv6_addr_str = IPv6AddressToString(ipv6_addr); |
| bool route_on_vpn = provider.ConsumeBool(); |
| |
| ConnectedNamespace nsinfo = {}; |
| nsinfo.pid = pid; |
| nsinfo.netns_name = netns_name; |
| nsinfo.source = TrafficSource::USER; |
| nsinfo.outbound_ifname = ifname; |
| nsinfo.route_on_vpn = route_on_vpn; |
| nsinfo.host_ifname = ifname2; |
| nsinfo.peer_ifname = ifname3; |
| nsinfo.peer_subnet = |
| std::make_unique<Subnet>(addr, prefix_len, base::DoNothing()); |
| nsinfo.peer_mac_addr = mac; |
| |
| auto runner = new FakeProcessRunner(); |
| auto firewall = new Firewall(); |
| auto system = new NoopSystem(); |
| Datapath datapath(runner, firewall, system); |
| datapath.Start(); |
| datapath.Stop(); |
| datapath.NetnsAttachName(netns_name, pid); |
| datapath.NetnsDeleteName(netns_name); |
| datapath.AddBridge(ifname, addr, prefix_len); |
| datapath.RemoveBridge(ifname); |
| datapath.AddToBridge(ifname, ifname2); |
| datapath.StartRoutingDevice(ifname, ifname2, addr, TrafficSource::UNKNOWN, |
| route_on_vpn); |
| datapath.StopRoutingDevice(ifname, ifname2, addr, TrafficSource::UNKNOWN, |
| route_on_vpn); |
| datapath.StartRoutingNamespace(nsinfo); |
| datapath.StopRoutingNamespace(nsinfo); |
| datapath.ConnectVethPair(pid, netns_name, ifname, ifname2, mac, addr, |
| prefix_len, provider.ConsumeBool()); |
| datapath.RemoveInterface(ifname); |
| datapath.AddTAP(ifname, &mac, &subnet_addr, ""); |
| datapath.RemoveTAP(ifname); |
| datapath.AddIPv4Route(provider.ConsumeIntegral<uint32_t>(), |
| provider.ConsumeIntegral<uint32_t>(), |
| provider.ConsumeIntegral<uint32_t>()); |
| datapath.StartConnectionPinning(ifname); |
| datapath.StopConnectionPinning(ifname); |
| datapath.StartVpnRouting(ifname); |
| datapath.StopVpnRouting(ifname); |
| datapath.MaskInterfaceFlags(ifname, provider.ConsumeIntegral<uint16_t>(), |
| provider.ConsumeIntegral<uint16_t>()); |
| datapath.AddIPv6Forwarding(ifname, ifname2); |
| datapath.RemoveIPv6Forwarding(ifname, ifname2); |
| datapath.AddIPv6HostRoute(ifname, ipv6_addr_str, prefix_len); |
| datapath.RemoveIPv6HostRoute(ifname, ipv6_addr_str, prefix_len); |
| datapath.AddIPv6Address(ifname, ipv6_addr_str); |
| datapath.RemoveIPv6Address(ifname, ipv6_addr_str); |
| |
| return 0; |
| } |
| |
| } // namespace |
| } // namespace patchpanel |