blob: 39257525ed47f414cda1cfa1aaf16eb3a50946c6 [file] [log] [blame]
// Copyright 2019 The ChromiumOS Authors
// 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/functional/bind.h>
#include <base/functional/callback_helpers.h>
#include <base/logging.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <net-base/ipv4_address.h>
#include "patchpanel/datapath.h"
#include "patchpanel/fake_process_runner.h"
#include "patchpanel/firewall.h"
#include "patchpanel/multicast_forwarder.h"
#include "patchpanel/shill_client.h"
#include "patchpanel/subnet.h"
#include "patchpanel/system.h"
namespace patchpanel {
namespace {
// 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);
int32_t pid = provider.ConsumeIntegral<int32_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>();
int prefix_len = provider.ConsumeIntegralInRange<int>(0, 31);
const auto ipv4_addr = net_base::IPv4Address(addr);
const auto cidr =
*net_base::IPv4CIDR::CreateFromAddressAndPrefix(ipv4_addr, prefix_len);
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());
const std::vector<uint8_t> ipv6_addr_bytes =
provider.ConsumeBytes<uint8_t>(net_base::IPv6Address::kAddressLength);
const int ipv6_prefix_len = provider.ConsumeIntegralInRange<int>(0, 128);
const auto ipv6_addr = net_base::IPv6Address::CreateFromBytes(ipv6_addr_bytes)
.value_or(net_base::IPv6Address());
const auto ipv6_cidr = *net_base::IPv6CIDR::CreateFromAddressAndPrefix(
ipv6_addr, ipv6_prefix_len);
const std::string ipv6_addr_str = ipv6_addr.ToString();
bool route_on_vpn = provider.ConsumeBool();
ConnectedNamespace nsinfo = {};
nsinfo.pid = pid;
nsinfo.netns_name = netns_name;
nsinfo.source = TrafficSource::kUser;
nsinfo.outbound_ifname = ifname;
nsinfo.route_on_vpn = route_on_vpn;
nsinfo.host_ifname = ifname2;
nsinfo.peer_ifname = ifname3;
nsinfo.peer_ipv4_subnet = std::make_unique<Subnet>(cidr, base::DoNothing());
nsinfo.peer_mac_addr = mac;
ShillClient::Device shill_device;
shill_device.ifname = ifname;
shill_device.type = ShillClient::Device::Type::kWifi;
shill_device.service_path = provider.ConsumeRandomLengthString(10);
shill_device.ifindex = provider.ConsumeIntegral<int32_t>();
auto runner = new FakeProcessRunner();
auto firewall = new Firewall();
NoopSystem system;
Datapath datapath(runner, firewall, &system);
datapath.Start();
datapath.Stop();
datapath.NetnsAttachName(netns_name, pid);
datapath.NetnsDeleteName(netns_name);
datapath.AddBridge(ifname, cidr);
datapath.RemoveBridge(ifname);
datapath.AddToBridge(ifname, ifname2);
datapath.StartRoutingDevice(shill_device, ifname2, TrafficSource::kUnknown);
datapath.StartRoutingDeviceAsSystem(ifname2, TrafficSource::kUnknown);
datapath.StartRoutingDeviceAsUser(ifname2, TrafficSource::kUnknown,
ipv4_addr);
datapath.StopRoutingDevice(ifname2, TrafficSource::kUnknown);
datapath.StartRoutingNamespace(nsinfo);
datapath.StopRoutingNamespace(nsinfo);
datapath.ConnectVethPair(pid, netns_name, ifname, ifname2, mac, cidr,
ipv6_cidr, provider.ConsumeBool());
datapath.RemoveInterface(ifname);
datapath.AddTunTap(ifname, mac, cidr, "", DeviceMode::kTun);
datapath.RemoveTunTap(ifname, DeviceMode::kTun);
datapath.AddTunTap(ifname, mac, cidr, "", DeviceMode::kTap);
datapath.RemoveTunTap(ifname, DeviceMode::kTap);
datapath.AddIPv4Route(
net_base::IPv4Address(provider.ConsumeIntegral<uint32_t>()), cidr);
datapath.DeleteIPv4Route(
net_base::IPv4Address(provider.ConsumeIntegral<uint32_t>()), cidr);
datapath.StartConnectionPinning(shill_device);
datapath.StopConnectionPinning(shill_device);
datapath.StartVpnRouting(shill_device);
datapath.StopVpnRouting(shill_device);
datapath.MaskInterfaceFlags(ifname, provider.ConsumeIntegral<uint16_t>(),
provider.ConsumeIntegral<uint16_t>());
datapath.AddIPv6HostRoute(ifname, ipv6_cidr);
datapath.RemoveIPv6HostRoute(ipv6_cidr);
datapath.AddIPv6Address(ifname, ipv6_addr_str);
datapath.RemoveIPv6Address(ifname, ipv6_addr_str);
datapath.StartSourceIPv6PrefixEnforcement(shill_device);
datapath.StopSourceIPv6PrefixEnforcement(shill_device);
datapath.UpdateSourceEnforcementIPv6Prefix(shill_device, ipv6_cidr);
datapath.AddInboundIPv4DNAT(AutoDNATTarget::kArc, shill_device, ipv4_addr);
datapath.RemoveInboundIPv4DNAT(AutoDNATTarget::kArc, shill_device, ipv4_addr);
datapath.AddRedirectDnsRule(shill_device, ipv4_addr.ToString());
datapath.RemoveRedirectDnsRule(shill_device);
return 0;
}
} // namespace
} // namespace patchpanel