blob: 22902d3876268566b2fbd3f195916d1ca0004b72 [file] [log] [blame]
Florian Mayer60d1e132018-01-26 15:00:52 +00001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stddef.h>
18#include <stdint.h>
19#include <unistd.h>
20
21#include "perfetto/base/logging.h"
22#include "perfetto/base/task_runner.h"
23#include "perfetto/base/utils.h"
24#include "perfetto/ipc/host.h"
Hector Dearmanfaa22f82018-02-14 12:02:51 +000025#include "perfetto/trace/test_event.pbzero.h"
Florian Mayer60d1e132018-01-26 15:00:52 +000026#include "perfetto/trace/trace_packet.pb.h"
27#include "perfetto/trace/trace_packet.pbzero.h"
28#include "perfetto/tracing/core/data_source_config.h"
29#include "perfetto/tracing/core/data_source_descriptor.h"
30#include "perfetto/tracing/core/producer.h"
31#include "perfetto/tracing/core/trace_writer.h"
32#include "perfetto/tracing/ipc/producer_ipc_client.h"
33#include "perfetto/tracing/ipc/service_ipc_host.h"
34#include "src/base/test/test_task_runner.h"
35#include "test/fake_consumer.h"
36#include "test/task_runner_thread.h"
37
38#define PRODUCER_SOCKET "/tmp/perfetto-producer"
39#define CONSUMER_SOCKET "/tmp/perfetto-consumer"
40
41namespace perfetto {
42namespace shm_fuzz {
43
44// Fake producer writing a protozero message of data into shared memory
45// buffer, followed by a sentinel message to signal completion to the
46// consumer.
47class FakeProducer : public Producer {
48 public:
Florian Mayer20c2c722018-02-15 14:10:16 +000049 FakeProducer(std::string name,
50 const uint8_t* data,
51 size_t size,
52 FakeConsumer* consumer)
53 : name_(std::move(name)), data_(data), size_(size), consumer_(consumer) {}
Florian Mayer60d1e132018-01-26 15:00:52 +000054
55 void Connect(const char* socket_name, base::TaskRunner* task_runner) {
56 endpoint_ = ProducerIPCClient::Connect(socket_name, this, task_runner);
57 }
58
59 void OnConnect() override {
60 DataSourceDescriptor descriptor;
61 descriptor.set_name(name_);
62 endpoint_->RegisterDataSource(descriptor,
63 [this](DataSourceID id) { id_ = id; });
64 }
65
66 void OnDisconnect() override {}
67
68 void CreateDataSourceInstance(
69 DataSourceInstanceID,
70 const DataSourceConfig& source_config) override {
71 auto trace_writer = endpoint_->CreateTraceWriter(
72 static_cast<BufferID>(source_config.target_buffer()));
73
74 auto packet = trace_writer->NewTracePacket();
75 packet->stream_writer_->WriteBytes(data_, size_);
76 packet->Finalize();
77
78 auto end_packet = trace_writer->NewTracePacket();
Hector Dearmanfaa22f82018-02-14 12:02:51 +000079 end_packet->set_for_testing()->set_str("end");
Florian Mayer60d1e132018-01-26 15:00:52 +000080 end_packet->Finalize();
Florian Mayer20c2c722018-02-15 14:10:16 +000081 consumer_->BusyWaitReadBuffers();
Florian Mayer60d1e132018-01-26 15:00:52 +000082 }
83
84 void TearDownDataSourceInstance(DataSourceInstanceID) override {}
85
86 private:
87 const std::string name_;
88 const uint8_t* data_;
89 const size_t size_;
90 DataSourceID id_ = 0;
91 std::unique_ptr<Service::ProducerEndpoint> endpoint_;
Florian Mayer20c2c722018-02-15 14:10:16 +000092 FakeConsumer* consumer_;
Florian Mayer60d1e132018-01-26 15:00:52 +000093};
94
95class FakeProducerDelegate : public ThreadDelegate {
96 public:
Florian Mayer20c2c722018-02-15 14:10:16 +000097 FakeProducerDelegate(const uint8_t* data, size_t size, FakeConsumer* consumer)
98 : data_(data), size_(size), consumer_(consumer) {}
Florian Mayer60d1e132018-01-26 15:00:52 +000099 ~FakeProducerDelegate() override = default;
100
101 void Initialize(base::TaskRunner* task_runner) override {
Florian Mayer20c2c722018-02-15 14:10:16 +0000102 producer_.reset(new FakeProducer("android.perfetto.FakeProducer", data_,
103 size_, consumer_));
Florian Mayer60d1e132018-01-26 15:00:52 +0000104 producer_->Connect(PRODUCER_SOCKET, task_runner);
105 }
106
107 private:
108 std::unique_ptr<FakeProducer> producer_;
109 const uint8_t* data_;
110 const size_t size_;
Florian Mayer20c2c722018-02-15 14:10:16 +0000111 FakeConsumer* consumer_;
Florian Mayer60d1e132018-01-26 15:00:52 +0000112};
113
114class ServiceDelegate : public ThreadDelegate {
115 public:
116 ServiceDelegate() = default;
117 ~ServiceDelegate() override = default;
118 void Initialize(base::TaskRunner* task_runner) override {
119 svc_ = ServiceIPCHost::CreateInstance(task_runner);
120 unlink(PRODUCER_SOCKET);
121 unlink(CONSUMER_SOCKET);
122 svc_->Start(PRODUCER_SOCKET, CONSUMER_SOCKET);
123 }
124
125 private:
126 std::unique_ptr<ServiceIPCHost> svc_;
127 base::ScopedFile producer_fd_;
128 base::ScopedFile consumer_fd_;
129};
130
131int FuzzSharedMemory(const uint8_t* data, size_t size);
132
133int FuzzSharedMemory(const uint8_t* data, size_t size) {
134 TaskRunnerThread service_thread;
135 service_thread.Start(std::unique_ptr<ServiceDelegate>(new ServiceDelegate()));
136
Florian Mayer60d1e132018-01-26 15:00:52 +0000137 // Setup the TraceConfig for the consumer.
138 TraceConfig trace_config;
Florian Mayer4c3580f2018-02-12 15:59:55 +0000139 trace_config.add_buffers()->set_size_kb(8);
Florian Mayer20c2c722018-02-15 14:10:16 +0000140 trace_config.set_duration_ms(1000);
Florian Mayer60d1e132018-01-26 15:00:52 +0000141
142 // Create the buffer for ftrace.
143 auto* ds_config = trace_config.add_data_sources()->mutable_config();
144 ds_config->set_name("android.perfetto.FakeProducer");
145 ds_config->set_target_buffer(0);
146
147 base::TestTaskRunner task_runner;
148 auto finish = task_runner.CreateCheckpoint("no.more.packets");
149 // Wait for sentinel message from Producer, then signal no.more.packets.
150 auto function = [&finish](std::vector<TracePacket> packets, bool has_more) {
151 for (auto& p : packets) {
152 p.Decode();
Hector Dearmanfaa22f82018-02-14 12:02:51 +0000153 if (p->for_testing().str() == "end")
Florian Mayer60d1e132018-01-26 15:00:52 +0000154 finish();
155 }
156 };
157 FakeConsumer consumer(trace_config, std::move(function), &task_runner);
158 consumer.Connect(CONSUMER_SOCKET);
Florian Mayer20c2c722018-02-15 14:10:16 +0000159
160 TaskRunnerThread producer_thread;
161 producer_thread.Start(std::unique_ptr<FakeProducerDelegate>(
162 new FakeProducerDelegate(data, size, &consumer)));
163
Florian Mayer60d1e132018-01-26 15:00:52 +0000164 task_runner.RunUntilCheckpoint("no.more.packets");
165 return 0;
166}
167
168} // namespace shm_fuzz
169} // namespace perfetto
170
171extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
172
173extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
174 return perfetto::shm_fuzz::FuzzSharedMemory(data, size);
175}