blob: 18f28aa45daa03fddd9308839b6ca6325bb52793 [file] [log] [blame]
// Copyright 2021 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 "patchpanel/broadcast_forwarder.h"
#include <net/if.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <algorithm>
#include <memory>
#include <string>
#include <vector>
#include <base/files/scoped_file.h>
#include <base/logging.h>
#include <fuzzer/FuzzedDataProvider.h>
#include <shill/net/byte_string.h>
#include <shill/net/rtnl_message.h>
namespace patchpanel {
namespace {
// Test class that overrides BroadcastForwader's sending and receive functions
// with stubs.
class TestBroadcastForwarder : public BroadcastForwarder {
public:
TestBroadcastForwarder(const std::string& lan_ifname)
: BroadcastForwarder(lan_ifname) {}
TestBroadcastForwarder(const TestBroadcastForwarder&) = delete;
TestBroadcastForwarder& operator=(const TestBroadcastForwarder&) = delete;
~TestBroadcastForwarder() = default;
base::ScopedFD Bind(const std::string& ifname, uint16_t port) override {
// Make a real socket to satisfy ScopedFD's checks.
int fd = socket(AF_INET, SOCK_DGRAM, 0);
fds.push_back(fd);
return base::ScopedFD(fd);
}
virtual base::ScopedFD BindRaw(const std::string& ifname) override {
// Make a real socket to satisfy ScopedFD's checks.
return Bind(ifname, 0);
}
std::unique_ptr<Socket> CreateSocket(base::ScopedFD fd,
uint32_t addr,
uint32_t broadaddr,
uint32_t netmask) override {
auto socket = std::make_unique<Socket>();
socket->fd = std::move(fd);
return socket;
}
ssize_t ReceiveMessage(int fd, struct msghdr* msg) override {
ssize_t msg_len = std::min(payload.size(), msg->msg_iov->iov_len);
if (msg_len > 0) {
memcpy(msg->msg_iov->iov_base, payload.data(), msg_len);
}
return msg_len;
}
ssize_t SendTo(int fd,
const void* buffer,
size_t buffer_len,
const struct sockaddr_in* dst_addr) override {
return buffer_len;
}
std::vector<int> fds;
std::vector<uint8_t> payload;
};
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// Turn off logging.
logging::SetMinLogLevel(logging::LOGGING_FATAL);
FuzzedDataProvider provider(data, size);
std::string lan_ifname = provider.ConsumeRandomLengthString(IFNAMSIZ - 1);
std::string guest_ifname1 = provider.ConsumeRandomLengthString(IFNAMSIZ - 1);
std::string guest_ifname2 = provider.ConsumeRandomLengthString(IFNAMSIZ - 1);
TestBroadcastForwarder bcast_forwarder(lan_ifname);
bcast_forwarder.AddGuest(guest_ifname1);
bcast_forwarder.AddGuest(guest_ifname2);
int fd_index =
provider.ConsumeIntegralInRange<int>(0, bcast_forwarder.fds.size() - 1);
int fd = bcast_forwarder.fds[fd_index];
bcast_forwarder.payload = provider.ConsumeRemainingBytes<uint8_t>();
bcast_forwarder.OnFileCanReadWithoutBlocking(fd);
shill::RTNLMessage rtnl_msg;
shill::ByteString bytes(bcast_forwarder.payload);
rtnl_msg.Decode(bytes);
bcast_forwarder.AddrMsgHandler(rtnl_msg);
return 0;
}
} // namespace
} // namespace patchpanel