blob: cca7023b69931042de13bbf663044f799f95a1e3 [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"
25#include "perfetto/trace/trace_packet.pb.h"
26#include "perfetto/trace/trace_packet.pbzero.h"
27#include "perfetto/tracing/core/data_source_config.h"
28#include "perfetto/tracing/core/data_source_descriptor.h"
29#include "perfetto/tracing/core/producer.h"
30#include "perfetto/tracing/core/trace_writer.h"
31#include "perfetto/tracing/ipc/producer_ipc_client.h"
32#include "perfetto/tracing/ipc/service_ipc_host.h"
33#include "src/base/test/test_task_runner.h"
34#include "test/fake_consumer.h"
35#include "test/task_runner_thread.h"
36
37#define PRODUCER_SOCKET "/tmp/perfetto-producer"
38#define CONSUMER_SOCKET "/tmp/perfetto-consumer"
39
40namespace perfetto {
41namespace shm_fuzz {
42
43// Fake producer writing a protozero message of data into shared memory
44// buffer, followed by a sentinel message to signal completion to the
45// consumer.
46class FakeProducer : public Producer {
47 public:
48 FakeProducer(std::string name, const uint8_t* data, size_t size)
49 : name_(std::move(name)), data_(data), size_(size) {}
50
51 void Connect(const char* socket_name, base::TaskRunner* task_runner) {
52 endpoint_ = ProducerIPCClient::Connect(socket_name, this, task_runner);
53 }
54
55 void OnConnect() override {
56 DataSourceDescriptor descriptor;
57 descriptor.set_name(name_);
58 endpoint_->RegisterDataSource(descriptor,
59 [this](DataSourceID id) { id_ = id; });
60 }
61
62 void OnDisconnect() override {}
63
64 void CreateDataSourceInstance(
65 DataSourceInstanceID,
66 const DataSourceConfig& source_config) override {
67 auto trace_writer = endpoint_->CreateTraceWriter(
68 static_cast<BufferID>(source_config.target_buffer()));
69
70 auto packet = trace_writer->NewTracePacket();
71 packet->stream_writer_->WriteBytes(data_, size_);
72 packet->Finalize();
73
74 auto end_packet = trace_writer->NewTracePacket();
75 end_packet->set_test("end");
76 end_packet->Finalize();
77
78 // Temporarily create a new packet to flush the final packet to the
79 // consumer.
80 // TODO(primiano): remove this hack once flushing the final packet is fixed.
81 trace_writer->NewTracePacket();
82 }
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_;
92};
93
94class FakeProducerDelegate : public ThreadDelegate {
95 public:
96 FakeProducerDelegate(const uint8_t* data, size_t size)
97 : data_(data), size_(size) {}
98 ~FakeProducerDelegate() override = default;
99
100 void Initialize(base::TaskRunner* task_runner) override {
101 producer_.reset(
102 new FakeProducer("android.perfetto.FakeProducer", data_, size_));
103 producer_->Connect(PRODUCER_SOCKET, task_runner);
104 }
105
106 private:
107 std::unique_ptr<FakeProducer> producer_;
108 const uint8_t* data_;
109 const size_t size_;
110};
111
112class ServiceDelegate : public ThreadDelegate {
113 public:
114 ServiceDelegate() = default;
115 ~ServiceDelegate() override = default;
116 void Initialize(base::TaskRunner* task_runner) override {
117 svc_ = ServiceIPCHost::CreateInstance(task_runner);
118 unlink(PRODUCER_SOCKET);
119 unlink(CONSUMER_SOCKET);
120 svc_->Start(PRODUCER_SOCKET, CONSUMER_SOCKET);
121 }
122
123 private:
124 std::unique_ptr<ServiceIPCHost> svc_;
125 base::ScopedFile producer_fd_;
126 base::ScopedFile consumer_fd_;
127};
128
129int FuzzSharedMemory(const uint8_t* data, size_t size);
130
131int FuzzSharedMemory(const uint8_t* data, size_t size) {
132 TaskRunnerThread service_thread;
133 service_thread.Start(std::unique_ptr<ServiceDelegate>(new ServiceDelegate()));
134
135 TaskRunnerThread producer_thread;
136 producer_thread.Start(std::unique_ptr<FakeProducerDelegate>(
137 new FakeProducerDelegate(data, size)));
138
139 // Setup the TraceConfig for the consumer.
140 TraceConfig trace_config;
141 trace_config.add_buffers()->set_size_kb(4096 * 10);
142 trace_config.set_duration_ms(200);
143
144 // Create the buffer for ftrace.
145 auto* ds_config = trace_config.add_data_sources()->mutable_config();
146 ds_config->set_name("android.perfetto.FakeProducer");
147 ds_config->set_target_buffer(0);
148
149 base::TestTaskRunner task_runner;
150 auto finish = task_runner.CreateCheckpoint("no.more.packets");
151 // Wait for sentinel message from Producer, then signal no.more.packets.
152 auto function = [&finish](std::vector<TracePacket> packets, bool has_more) {
153 for (auto& p : packets) {
154 p.Decode();
155 if (p->test() == "end")
156 finish();
157 }
158 };
159 FakeConsumer consumer(trace_config, std::move(function), &task_runner);
160 consumer.Connect(CONSUMER_SOCKET);
161 task_runner.RunUntilCheckpoint("no.more.packets");
162 return 0;
163}
164
165} // namespace shm_fuzz
166} // namespace perfetto
167
168extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
169
170extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
171 return perfetto::shm_fuzz::FuzzSharedMemory(data, size);
172}