blob: a75edd72fd0aea8d99d7b33b7db31d86b999abb4 [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:
49 FakeProducer(std::string name, const uint8_t* data, size_t size)
50 : name_(std::move(name)), data_(data), size_(size) {}
51
52 void Connect(const char* socket_name, base::TaskRunner* task_runner) {
53 endpoint_ = ProducerIPCClient::Connect(socket_name, this, task_runner);
54 }
55
56 void OnConnect() override {
57 DataSourceDescriptor descriptor;
58 descriptor.set_name(name_);
59 endpoint_->RegisterDataSource(descriptor,
60 [this](DataSourceID id) { id_ = id; });
61 }
62
63 void OnDisconnect() override {}
64
65 void CreateDataSourceInstance(
66 DataSourceInstanceID,
67 const DataSourceConfig& source_config) override {
68 auto trace_writer = endpoint_->CreateTraceWriter(
69 static_cast<BufferID>(source_config.target_buffer()));
70
71 auto packet = trace_writer->NewTracePacket();
72 packet->stream_writer_->WriteBytes(data_, size_);
73 packet->Finalize();
74
75 auto end_packet = trace_writer->NewTracePacket();
Hector Dearmanfaa22f82018-02-14 12:02:51 +000076 end_packet->set_for_testing()->set_str("end");
Florian Mayer60d1e132018-01-26 15:00:52 +000077 end_packet->Finalize();
Florian Mayer60d1e132018-01-26 15:00:52 +000078 }
79
80 void TearDownDataSourceInstance(DataSourceInstanceID) override {}
81
82 private:
83 const std::string name_;
84 const uint8_t* data_;
85 const size_t size_;
86 DataSourceID id_ = 0;
87 std::unique_ptr<Service::ProducerEndpoint> endpoint_;
88};
89
90class FakeProducerDelegate : public ThreadDelegate {
91 public:
92 FakeProducerDelegate(const uint8_t* data, size_t size)
93 : data_(data), size_(size) {}
94 ~FakeProducerDelegate() override = default;
95
96 void Initialize(base::TaskRunner* task_runner) override {
97 producer_.reset(
98 new FakeProducer("android.perfetto.FakeProducer", data_, size_));
99 producer_->Connect(PRODUCER_SOCKET, task_runner);
100 }
101
102 private:
103 std::unique_ptr<FakeProducer> producer_;
104 const uint8_t* data_;
105 const size_t size_;
106};
107
108class ServiceDelegate : public ThreadDelegate {
109 public:
110 ServiceDelegate() = default;
111 ~ServiceDelegate() override = default;
112 void Initialize(base::TaskRunner* task_runner) override {
113 svc_ = ServiceIPCHost::CreateInstance(task_runner);
114 unlink(PRODUCER_SOCKET);
115 unlink(CONSUMER_SOCKET);
116 svc_->Start(PRODUCER_SOCKET, CONSUMER_SOCKET);
117 }
118
119 private:
120 std::unique_ptr<ServiceIPCHost> svc_;
121 base::ScopedFile producer_fd_;
122 base::ScopedFile consumer_fd_;
123};
124
125int FuzzSharedMemory(const uint8_t* data, size_t size);
126
127int FuzzSharedMemory(const uint8_t* data, size_t size) {
128 TaskRunnerThread service_thread;
129 service_thread.Start(std::unique_ptr<ServiceDelegate>(new ServiceDelegate()));
130
131 TaskRunnerThread producer_thread;
132 producer_thread.Start(std::unique_ptr<FakeProducerDelegate>(
133 new FakeProducerDelegate(data, size)));
134
135 // Setup the TraceConfig for the consumer.
136 TraceConfig trace_config;
Florian Mayer4c3580f2018-02-12 15:59:55 +0000137 trace_config.add_buffers()->set_size_kb(8);
Florian Mayerf2a282f2018-01-30 10:55:56 +0000138 trace_config.set_duration_ms(10);
Florian Mayer60d1e132018-01-26 15:00:52 +0000139
140 // Create the buffer for ftrace.
141 auto* ds_config = trace_config.add_data_sources()->mutable_config();
142 ds_config->set_name("android.perfetto.FakeProducer");
143 ds_config->set_target_buffer(0);
144
145 base::TestTaskRunner task_runner;
146 auto finish = task_runner.CreateCheckpoint("no.more.packets");
147 // Wait for sentinel message from Producer, then signal no.more.packets.
148 auto function = [&finish](std::vector<TracePacket> packets, bool has_more) {
149 for (auto& p : packets) {
150 p.Decode();
Hector Dearmanfaa22f82018-02-14 12:02:51 +0000151 if (p->for_testing().str() == "end")
Florian Mayer60d1e132018-01-26 15:00:52 +0000152 finish();
153 }
154 };
155 FakeConsumer consumer(trace_config, std::move(function), &task_runner);
156 consumer.Connect(CONSUMER_SOCKET);
157 task_runner.RunUntilCheckpoint("no.more.packets");
158 return 0;
159}
160
161} // namespace shm_fuzz
162} // namespace perfetto
163
164extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
165
166extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
167 return perfetto::shm_fuzz::FuzzSharedMemory(data, size);
168}