Added fastboot_fuzzer
Test: ./fastboot_fuzzer Bug: 189053436 Change-Id: Idf9be2f86238eb2c7090402adc54bbb9c0b43582
This commit is contained in:
parent
74646e8774
commit
ce5c033e2b
6 changed files with 589 additions and 0 deletions
|
@ -408,3 +408,9 @@ cc_test_host {
|
|||
":fastboot_test_vendor_boot_v4_with_frag"
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
name: "fastboot_headers",
|
||||
host_supported: true,
|
||||
export_include_dirs: ["."],
|
||||
}
|
||||
|
|
57
fastboot/fuzzer/Android.bp
Normal file
57
fastboot/fuzzer/Android.bp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
cc_fuzz {
|
||||
name: "fastboot_fuzzer",
|
||||
host_supported: true,
|
||||
device_supported: false,
|
||||
srcs: [
|
||||
"fastboot_fuzzer.cpp",
|
||||
"socket_mock_fuzz.cpp",
|
||||
],
|
||||
header_libs: [
|
||||
"bootimg_headers",
|
||||
"fastboot_headers",
|
||||
],
|
||||
static_libs: [
|
||||
"libext4_utils",
|
||||
"libcrypto",
|
||||
"libfastboot",
|
||||
"libbuildversion",
|
||||
"libbase",
|
||||
"libziparchive",
|
||||
"libsparse",
|
||||
"libutils",
|
||||
"liblog",
|
||||
"libz",
|
||||
"libdiagnose_usb",
|
||||
"libbase",
|
||||
"libcutils",
|
||||
"libgtest",
|
||||
"libgtest_main",
|
||||
"libbase",
|
||||
"libadb_host",
|
||||
"liblp",
|
||||
"liblog",
|
||||
],
|
||||
fuzz_config: {
|
||||
cc: [
|
||||
"android-media-fuzzing-reports@google.com",
|
||||
],
|
||||
componentid: 533764,
|
||||
},
|
||||
}
|
51
fastboot/fuzzer/README.md
Normal file
51
fastboot/fuzzer/README.md
Normal file
|
@ -0,0 +1,51 @@
|
|||
# Fuzzer for libfastboot
|
||||
|
||||
## Plugin Design Considerations
|
||||
The fuzzer plugin for libfastboot is designed based on the understanding of the
|
||||
source code and tries to achieve the following:
|
||||
|
||||
##### Maximize code coverage
|
||||
The configuration parameters are not hardcoded, but instead selected based on
|
||||
incoming data. This ensures more code paths are reached by the fuzzer.
|
||||
|
||||
libfastboot supports the following parameters:
|
||||
1. Year (parameter name: `year`)
|
||||
2. Month (parameter name: `month`)
|
||||
3. Day (parameter name: `day`)
|
||||
4. Version (parameter name: `version`)
|
||||
5. Fs Option (parameter name: `fsOption`)
|
||||
|
||||
| Parameter| Valid Values| Configured Value|
|
||||
|------------- |-------------| ----- |
|
||||
| `year` | `2000` to `2127` | Value obtained from FuzzedDataProvider|
|
||||
| `month` | `1` to `12` | Value obtained from FuzzedDataProvider|
|
||||
| `day` | `1` to `31` | Value obtained from FuzzedDataProvider|
|
||||
| `version` | `0` to `127` | Value obtained from FuzzedDataProvider|
|
||||
| `fsOption` | 0. `casefold` 1. `projid` 2. `compress` | Value obtained from FuzzedDataProvider|
|
||||
|
||||
##### Maximize utilization of input data
|
||||
The plugin feeds the entire input data to the module.
|
||||
This ensures that the plugin tolerates any kind of input (empty, huge,
|
||||
malformed, etc) and doesnt `exit()` on any input and thereby increasing the
|
||||
chance of identifying vulnerabilities.
|
||||
|
||||
## Build
|
||||
|
||||
This describes steps to build fastboot_fuzzer binary.
|
||||
|
||||
### Android
|
||||
|
||||
#### Steps to build
|
||||
Build the fuzzer
|
||||
```
|
||||
$ mm -j$(nproc) fastboot_fuzzer_fuzzer
|
||||
```
|
||||
#### Steps to run
|
||||
To run on host
|
||||
```
|
||||
$ $ANDROID_HOST_OUT/fuzz/${TARGET_ARCH}/fastboot_fuzzer/fastboot_fuzzer CORPUS_DIR
|
||||
```
|
||||
|
||||
## References:
|
||||
* http://llvm.org/docs/LibFuzzer.html
|
||||
* https://github.com/google/oss-fuzz
|
276
fastboot/fuzzer/fastboot_fuzzer.cpp
Normal file
276
fastboot/fuzzer/fastboot_fuzzer.cpp
Normal file
|
@ -0,0 +1,276 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
#include <android-base/file.h>
|
||||
#include "fastboot.h"
|
||||
#include "socket.h"
|
||||
#include "socket_mock_fuzz.h"
|
||||
#include "tcp.h"
|
||||
#include "udp.h"
|
||||
#include "vendor_boot_img_utils.h"
|
||||
|
||||
#include <fuzzer/FuzzedDataProvider.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const size_t kYearMin = 2000;
|
||||
const size_t kYearMax = 2127;
|
||||
const size_t kMonthMin = 1;
|
||||
const size_t kMonthMax = 12;
|
||||
const size_t kDayMin = 1;
|
||||
const size_t kDayMax = 31;
|
||||
const size_t kVersionMin = 0;
|
||||
const size_t kVersionMax = 127;
|
||||
const size_t kMaxStringSize = 100;
|
||||
const size_t kMinTimeout = 10;
|
||||
const size_t kMaxTimeout = 3000;
|
||||
const uint16_t kValidUdpPacketSize = 512;
|
||||
const uint16_t kMinUdpPackets = 1;
|
||||
const uint16_t kMaxUdpPackets = 10;
|
||||
|
||||
const string kValidTcpHandshakeString = "FB01";
|
||||
const string kInvalidTcpHandshakeString = "FB00";
|
||||
const string kValidRamdiskName = "default";
|
||||
const string kVendorBootFile = "/tmp/vendorBootFile";
|
||||
const string kRamdiskFile = "/tmp/ramdiskFile";
|
||||
const char* kFsOptionsArray[] = {"casefold", "projid", "compress"};
|
||||
|
||||
class FastbootFuzzer {
|
||||
public:
|
||||
void Process(const uint8_t* data, size_t size);
|
||||
|
||||
private:
|
||||
void InvokeParseApi();
|
||||
void InvokeSocket();
|
||||
void InvokeTcp();
|
||||
void InvokeUdp();
|
||||
void InvokeVendorBootImgUtils(const uint8_t* data, size_t size);
|
||||
bool MakeConnectedSockets(Socket::Protocol protocol, unique_ptr<Socket>* server,
|
||||
unique_ptr<Socket>* client, const string& hostname);
|
||||
unique_ptr<FuzzedDataProvider> fdp_ = nullptr;
|
||||
};
|
||||
|
||||
void FastbootFuzzer::InvokeParseApi() {
|
||||
boot_img_hdr_v1 hdr = {};
|
||||
FastBootTool fastBoot;
|
||||
|
||||
int32_t year = fdp_->ConsumeIntegralInRange<int32_t>(kYearMin, kYearMax);
|
||||
int32_t month = fdp_->ConsumeIntegralInRange<int32_t>(kMonthMin, kMonthMax);
|
||||
int32_t day = fdp_->ConsumeIntegralInRange<int32_t>(kDayMin, kDayMax);
|
||||
string date = to_string(year) + "-" + to_string(month) + "-" + to_string(day);
|
||||
fastBoot.ParseOsPatchLevel(&hdr, date.c_str());
|
||||
|
||||
int32_t major = fdp_->ConsumeIntegralInRange<int32_t>(kVersionMin, kVersionMax);
|
||||
int32_t minor = fdp_->ConsumeIntegralInRange<int32_t>(kVersionMin, kVersionMax);
|
||||
int32_t patch = fdp_->ConsumeIntegralInRange<int32_t>(kVersionMin, kVersionMax);
|
||||
string version = to_string(major) + "." + to_string(minor) + "." + to_string(patch);
|
||||
fastBoot.ParseOsVersion(&hdr, version.c_str());
|
||||
|
||||
fastBoot.ParseFsOption(fdp_->PickValueInArray(kFsOptionsArray));
|
||||
}
|
||||
|
||||
bool FastbootFuzzer::MakeConnectedSockets(Socket::Protocol protocol, unique_ptr<Socket>* server,
|
||||
unique_ptr<Socket>* client,
|
||||
const string& hostname = "localhost") {
|
||||
*server = Socket::NewServer(protocol, 0);
|
||||
if (*server == nullptr) {
|
||||
return false;
|
||||
}
|
||||
*client = Socket::NewClient(protocol, hostname, (*server)->GetLocalPort(), nullptr);
|
||||
if (*client == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (protocol == Socket::Protocol::kTcp) {
|
||||
*server = (*server)->Accept();
|
||||
if (*server == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FastbootFuzzer::InvokeSocket() {
|
||||
unique_ptr<Socket> server, client;
|
||||
|
||||
for (Socket::Protocol protocol : {Socket::Protocol::kUdp, Socket::Protocol::kTcp}) {
|
||||
if (MakeConnectedSockets(protocol, &server, &client)) {
|
||||
string message = fdp_->ConsumeRandomLengthString(kMaxStringSize);
|
||||
client->Send(message.c_str(), message.length());
|
||||
string received(message.length(), '\0');
|
||||
if (fdp_->ConsumeBool()) {
|
||||
client->Close();
|
||||
}
|
||||
if (fdp_->ConsumeBool()) {
|
||||
server->Close();
|
||||
}
|
||||
server->ReceiveAll(&received[0], received.length(),
|
||||
/* timeout_ms */
|
||||
fdp_->ConsumeIntegralInRange<size_t>(kMinTimeout, kMaxTimeout));
|
||||
server->Close();
|
||||
client->Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FastbootFuzzer::InvokeTcp() {
|
||||
/* Using a raw SocketMockFuzz* here because ownership shall be passed to the Transport object */
|
||||
SocketMockFuzz* tcp_mock = new SocketMockFuzz;
|
||||
tcp_mock->ExpectSend(fdp_->ConsumeBool() ? kValidTcpHandshakeString
|
||||
: kInvalidTcpHandshakeString);
|
||||
tcp_mock->AddReceive(fdp_->ConsumeBool() ? kValidTcpHandshakeString
|
||||
: kInvalidTcpHandshakeString);
|
||||
|
||||
string error;
|
||||
unique_ptr<Transport> transport = tcp::internal::Connect(unique_ptr<Socket>(tcp_mock), &error);
|
||||
|
||||
if (transport.get()) {
|
||||
string write_message = fdp_->ConsumeRandomLengthString(kMaxStringSize);
|
||||
if (fdp_->ConsumeBool()) {
|
||||
tcp_mock->ExpectSend(write_message);
|
||||
} else {
|
||||
tcp_mock->ExpectSendFailure(write_message);
|
||||
}
|
||||
string read_message = fdp_->ConsumeRandomLengthString(kMaxStringSize);
|
||||
if (fdp_->ConsumeBool()) {
|
||||
tcp_mock->AddReceive(read_message);
|
||||
} else {
|
||||
tcp_mock->AddReceiveFailure();
|
||||
}
|
||||
|
||||
transport->Write(write_message.data(), write_message.length());
|
||||
|
||||
string buffer(read_message.length(), '\0');
|
||||
transport->Read(&buffer[0], buffer.length());
|
||||
|
||||
transport->Close();
|
||||
}
|
||||
}
|
||||
|
||||
static string PacketValue(uint16_t value) {
|
||||
return string{static_cast<char>(value >> 8), static_cast<char>(value)};
|
||||
}
|
||||
|
||||
static string ErrorPacket(uint16_t sequence, const string& message = "",
|
||||
char flags = udp::internal::kFlagNone) {
|
||||
return string{udp::internal::kIdError, flags} + PacketValue(sequence) + message;
|
||||
}
|
||||
|
||||
static string InitPacket(uint16_t sequence, uint16_t version, uint16_t max_packet_size) {
|
||||
return string{udp::internal::kIdInitialization, udp::internal::kFlagNone} +
|
||||
PacketValue(sequence) + PacketValue(version) + PacketValue(max_packet_size);
|
||||
}
|
||||
|
||||
static string QueryPacket(uint16_t sequence, uint16_t new_sequence) {
|
||||
return string{udp::internal::kIdDeviceQuery, udp::internal::kFlagNone} + PacketValue(sequence) +
|
||||
PacketValue(new_sequence);
|
||||
}
|
||||
|
||||
static string QueryPacket(uint16_t sequence) {
|
||||
return string{udp::internal::kIdDeviceQuery, udp::internal::kFlagNone} + PacketValue(sequence);
|
||||
}
|
||||
|
||||
static string FastbootPacket(uint16_t sequence, const string& data = "",
|
||||
char flags = udp::internal::kFlagNone) {
|
||||
return string{udp::internal::kIdFastboot, flags} + PacketValue(sequence) + data;
|
||||
}
|
||||
|
||||
void FastbootFuzzer::InvokeUdp() {
|
||||
/* Using a raw SocketMockFuzz* here because ownership shall be passed to the Transport object */
|
||||
SocketMockFuzz* udp_mock = new SocketMockFuzz;
|
||||
uint16_t starting_sequence = fdp_->ConsumeIntegral<uint16_t>();
|
||||
int32_t device_max_packet_size = fdp_->ConsumeBool() ? kValidUdpPacketSize
|
||||
: fdp_->ConsumeIntegralInRange<uint16_t>(
|
||||
0, kValidUdpPacketSize - 1);
|
||||
udp_mock->ExpectSend(QueryPacket(0));
|
||||
udp_mock->AddReceive(QueryPacket(0, starting_sequence));
|
||||
udp_mock->ExpectSend(InitPacket(starting_sequence, udp::internal::kProtocolVersion,
|
||||
udp::internal::kHostMaxPacketSize));
|
||||
udp_mock->AddReceive(
|
||||
InitPacket(starting_sequence, udp::internal::kProtocolVersion, device_max_packet_size));
|
||||
|
||||
string error;
|
||||
unique_ptr<Transport> transport = udp::internal::Connect(unique_ptr<Socket>(udp_mock), &error);
|
||||
bool is_transport_initialized = transport != nullptr && error.empty();
|
||||
|
||||
if (is_transport_initialized) {
|
||||
uint16_t num_packets =
|
||||
fdp_->ConsumeIntegralInRange<uint16_t>(kMinUdpPackets, kMaxUdpPackets);
|
||||
|
||||
for (uint16_t i = 0; i < num_packets; ++i) {
|
||||
string write_message = fdp_->ConsumeRandomLengthString(kMaxStringSize);
|
||||
string read_message = fdp_->ConsumeRandomLengthString(kMaxStringSize);
|
||||
if (fdp_->ConsumeBool()) {
|
||||
udp_mock->ExpectSend(FastbootPacket(i, write_message));
|
||||
} else {
|
||||
udp_mock->ExpectSend(ErrorPacket(i, write_message));
|
||||
}
|
||||
|
||||
if (fdp_->ConsumeBool()) {
|
||||
udp_mock->AddReceive(FastbootPacket(i, read_message));
|
||||
} else {
|
||||
udp_mock->AddReceive(ErrorPacket(i, read_message));
|
||||
}
|
||||
transport->Write(write_message.data(), write_message.length());
|
||||
string buffer(read_message.length(), '\0');
|
||||
transport->Read(&buffer[0], buffer.length());
|
||||
}
|
||||
transport->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void FastbootFuzzer::InvokeVendorBootImgUtils(const uint8_t* data, size_t size) {
|
||||
int32_t vendor_boot_fd = open(kVendorBootFile.c_str(), O_CREAT | O_RDWR, 0644);
|
||||
if (vendor_boot_fd < 0) {
|
||||
return;
|
||||
}
|
||||
int32_t ramdisk_fd = open(kRamdiskFile.c_str(), O_CREAT | O_RDWR, 0644);
|
||||
if (ramdisk_fd < 0) {
|
||||
return;
|
||||
}
|
||||
write(vendor_boot_fd, data, size);
|
||||
write(ramdisk_fd, data, size);
|
||||
string ramdisk_name = fdp_->ConsumeBool() ? kValidRamdiskName
|
||||
: fdp_->ConsumeRandomLengthString(kMaxStringSize);
|
||||
string content_vendor_boot_fd = {};
|
||||
string content_ramdisk_fd = {};
|
||||
lseek(vendor_boot_fd, 0, SEEK_SET);
|
||||
lseek(ramdisk_fd, 0, SEEK_SET);
|
||||
android::base::ReadFdToString(vendor_boot_fd, &content_vendor_boot_fd);
|
||||
android::base::ReadFdToString(ramdisk_fd, &content_ramdisk_fd);
|
||||
uint64_t vendor_boot_size =
|
||||
fdp_->ConsumeBool() ? content_vendor_boot_fd.size() : fdp_->ConsumeIntegral<uint64_t>();
|
||||
uint64_t ramdisk_size =
|
||||
fdp_->ConsumeBool() ? content_ramdisk_fd.size() : fdp_->ConsumeIntegral<uint64_t>();
|
||||
(void)replace_vendor_ramdisk(vendor_boot_fd, vendor_boot_size, ramdisk_name, ramdisk_fd,
|
||||
ramdisk_size);
|
||||
close(vendor_boot_fd);
|
||||
close(ramdisk_fd);
|
||||
}
|
||||
|
||||
void FastbootFuzzer::Process(const uint8_t* data, size_t size) {
|
||||
fdp_ = make_unique<FuzzedDataProvider>(data, size);
|
||||
InvokeParseApi();
|
||||
InvokeSocket();
|
||||
InvokeTcp();
|
||||
InvokeUdp();
|
||||
InvokeVendorBootImgUtils(data, size);
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
FastbootFuzzer fastbootFuzzer;
|
||||
fastbootFuzzer.Process(data, size);
|
||||
return 0;
|
||||
}
|
126
fastboot/fuzzer/socket_mock_fuzz.cpp
Normal file
126
fastboot/fuzzer/socket_mock_fuzz.cpp
Normal file
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "socket_mock_fuzz.h"
|
||||
|
||||
SocketMockFuzz::SocketMockFuzz() : Socket(INVALID_SOCKET) {}
|
||||
|
||||
SocketMockFuzz::~SocketMockFuzz() {}
|
||||
|
||||
bool SocketMockFuzz::Send(const void* data, size_t length) {
|
||||
if (events_.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (events_.front().type != EventType::kSend) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string message(reinterpret_cast<const char*>(data), length);
|
||||
if (events_.front().message != message) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool return_value = events_.front().status;
|
||||
events_.pop();
|
||||
return return_value;
|
||||
}
|
||||
|
||||
// Mock out multi-buffer send to be one large send, since that's what it should looks like from
|
||||
// the user's perspective.
|
||||
bool SocketMockFuzz::Send(std::vector<cutils_socket_buffer_t> buffers) {
|
||||
std::string data;
|
||||
for (const auto& buffer : buffers) {
|
||||
data.append(reinterpret_cast<const char*>(buffer.data), buffer.length);
|
||||
}
|
||||
return Send(data.data(), data.size());
|
||||
}
|
||||
|
||||
ssize_t SocketMockFuzz::Receive(void* data, size_t length, int /*timeout_ms*/) {
|
||||
if (events_.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const Event& event = events_.front();
|
||||
if (event.type != EventType::kReceive) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::string& message = event.message;
|
||||
if (message.length() > length) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
receive_timed_out_ = event.status;
|
||||
ssize_t return_value = message.length();
|
||||
|
||||
// Empty message indicates failure.
|
||||
if (message.empty()) {
|
||||
return_value = -1;
|
||||
} else {
|
||||
memcpy(data, message.data(), message.length());
|
||||
}
|
||||
|
||||
events_.pop();
|
||||
return return_value;
|
||||
}
|
||||
|
||||
int SocketMockFuzz::Close() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<Socket> SocketMockFuzz::Accept() {
|
||||
if (events_.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (events_.front().type != EventType::kAccept) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::unique_ptr<Socket> sock = std::move(events_.front().sock);
|
||||
events_.pop();
|
||||
return sock;
|
||||
}
|
||||
|
||||
void SocketMockFuzz::ExpectSend(std::string message) {
|
||||
events_.push(Event(EventType::kSend, std::move(message), true, nullptr));
|
||||
}
|
||||
|
||||
void SocketMockFuzz::ExpectSendFailure(std::string message) {
|
||||
events_.push(Event(EventType::kSend, std::move(message), false, nullptr));
|
||||
}
|
||||
|
||||
void SocketMockFuzz::AddReceive(std::string message) {
|
||||
events_.push(Event(EventType::kReceive, std::move(message), false, nullptr));
|
||||
}
|
||||
|
||||
void SocketMockFuzz::AddReceiveTimeout() {
|
||||
events_.push(Event(EventType::kReceive, "", true, nullptr));
|
||||
}
|
||||
|
||||
void SocketMockFuzz::AddReceiveFailure() {
|
||||
events_.push(Event(EventType::kReceive, "", false, nullptr));
|
||||
}
|
||||
|
||||
void SocketMockFuzz::AddAccept(std::unique_ptr<Socket> sock) {
|
||||
events_.push(Event(EventType::kAccept, "", false, std::move(sock)));
|
||||
}
|
||||
|
||||
SocketMockFuzz::Event::Event(EventType _type, std::string _message, ssize_t _status,
|
||||
std::unique_ptr<Socket> _sock)
|
||||
: type(_type), message(_message), status(_status), sock(std::move(_sock)) {}
|
73
fastboot/fuzzer/socket_mock_fuzz.h
Normal file
73
fastboot/fuzzer/socket_mock_fuzz.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
#include <android-base/macros.h>
|
||||
|
||||
#include "socket.h"
|
||||
|
||||
class SocketMockFuzz : public Socket {
|
||||
public:
|
||||
SocketMockFuzz();
|
||||
~SocketMockFuzz() override;
|
||||
|
||||
bool Send(const void* data, size_t length) override;
|
||||
bool Send(std::vector<cutils_socket_buffer_t> buffers) override;
|
||||
ssize_t Receive(void* data, size_t length, int timeout_ms) override;
|
||||
int Close() override;
|
||||
virtual std::unique_ptr<Socket> Accept();
|
||||
|
||||
// Adds an expectation for Send().
|
||||
void ExpectSend(std::string message);
|
||||
|
||||
// Adds an expectation for Send() that returns false.
|
||||
void ExpectSendFailure(std::string message);
|
||||
|
||||
// Adds data to provide for Receive().
|
||||
void AddReceive(std::string message);
|
||||
|
||||
// Adds a Receive() timeout after which ReceiveTimedOut() will return true.
|
||||
void AddReceiveTimeout();
|
||||
|
||||
// Adds a Receive() failure after which ReceiveTimedOut() will return false.
|
||||
void AddReceiveFailure();
|
||||
|
||||
// Adds a Socket to return from Accept().
|
||||
void AddAccept(std::unique_ptr<Socket> sock);
|
||||
|
||||
private:
|
||||
enum class EventType { kSend, kReceive, kAccept };
|
||||
|
||||
struct Event {
|
||||
Event(EventType _type, std::string _message, ssize_t _status,
|
||||
std::unique_ptr<Socket> _sock);
|
||||
|
||||
EventType type;
|
||||
std::string message;
|
||||
bool status; // Return value for Send() or timeout status for Receive().
|
||||
std::unique_ptr<Socket> sock;
|
||||
};
|
||||
|
||||
std::queue<Event> events_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SocketMockFuzz);
|
||||
};
|
Loading…
Reference in a new issue