1 /*
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/trace/test_event.pbzero.h"
25 #include "perfetto/tracing/core/data_source_config.h"
26 #include "perfetto/tracing/core/data_source_descriptor.h"
27 #include "perfetto/tracing/core/producer.h"
28 #include "perfetto/tracing/core/trace_writer.h"
29 #include "perfetto/tracing/ipc/producer_ipc_client.h"
30 #include "perfetto/tracing/ipc/service_ipc_host.h"
31 #include "src/base/test/test_task_runner.h"
32 #include "src/tracing/ipc/default_socket.h"
33 #include "test/task_runner_thread.h"
34 #include "test/task_runner_thread_delegates.h"
35 #include "test/test_helper.h"
36
37 #include "perfetto/trace/trace_packet.pb.h"
38 #include "perfetto/trace/trace_packet.pbzero.h"
39
40 namespace perfetto {
41 namespace shm_fuzz {
42
43 // If we're building on Android and starting the daemons ourselves,
44 // create the sockets in a world-writable location.
45 #if PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID) && \
46 PERFETTO_BUILDFLAG(PERFETTO_START_DAEMONS)
47 #define TEST_PRODUCER_SOCK_NAME "/data/local/tmp/traced_producer"
48 #else
49 #define TEST_PRODUCER_SOCK_NAME ::perfetto::GetProducerSocket()
50 #endif
51
52 // Fake producer writing a protozero message of data into shared memory
53 // buffer, followed by a sentinel message to signal completion to the
54 // consumer.
55 class FakeProducer : public Producer {
56 public:
FakeProducer(std::string name,const uint8_t * data,size_t size,std::function<void ()> on_produced_and_committed)57 FakeProducer(std::string name,
58 const uint8_t* data,
59 size_t size,
60 std::function<void()> on_produced_and_committed)
61 : name_(std::move(name)),
62 data_(data),
63 size_(size),
64 on_produced_and_committed_(on_produced_and_committed) {}
65
Connect(const char * socket_name,base::TaskRunner * task_runner)66 void Connect(const char* socket_name, base::TaskRunner* task_runner) {
67 endpoint_ = ProducerIPCClient::Connect(
68 socket_name, this, "android.perfetto.FakeProducer", task_runner);
69 }
70
OnConnect()71 void OnConnect() override {
72 DataSourceDescriptor descriptor;
73 descriptor.set_name(name_);
74 endpoint_->RegisterDataSource(descriptor);
75 }
76
OnDisconnect()77 void OnDisconnect() override {}
78
SetupDataSource(DataSourceInstanceID,const DataSourceConfig &)79 void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&) override {
80 }
81
StartDataSource(DataSourceInstanceID,const DataSourceConfig & source_config)82 void StartDataSource(DataSourceInstanceID,
83 const DataSourceConfig& source_config) override {
84 auto trace_writer = endpoint_->CreateTraceWriter(
85 static_cast<BufferID>(source_config.target_buffer()));
86 {
87 auto packet = trace_writer->NewTracePacket();
88 packet->stream_writer_->WriteBytes(data_, size_);
89 }
90 trace_writer->Flush();
91
92 {
93 auto end_packet = trace_writer->NewTracePacket();
94 end_packet->set_for_testing()->set_str("end");
95 }
96 trace_writer->Flush(on_produced_and_committed_);
97 }
98
StopDataSource(DataSourceInstanceID)99 void StopDataSource(DataSourceInstanceID) override {}
OnTracingSetup()100 void OnTracingSetup() override {}
Flush(FlushRequestID,const DataSourceInstanceID *,size_t)101 void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override {}
ClearIncrementalState(const DataSourceInstanceID *,size_t)102 void ClearIncrementalState(const DataSourceInstanceID*, size_t) {}
103
104 private:
105 const std::string name_;
106 const uint8_t* data_;
107 const size_t size_;
108 std::unique_ptr<TracingService::ProducerEndpoint> endpoint_;
109 std::function<void()> on_produced_and_committed_;
110 };
111
112 class FakeProducerDelegate : public ThreadDelegate {
113 public:
FakeProducerDelegate(const uint8_t * data,size_t size,std::function<void ()> on_produced_and_committed)114 FakeProducerDelegate(const uint8_t* data,
115 size_t size,
116 std::function<void()> on_produced_and_committed)
117 : data_(data),
118 size_(size),
119 on_produced_and_committed_(on_produced_and_committed) {}
120 ~FakeProducerDelegate() override = default;
121
Initialize(base::TaskRunner * task_runner)122 void Initialize(base::TaskRunner* task_runner) override {
123 producer_.reset(new FakeProducer("android.perfetto.FakeProducer", data_,
124 size_, on_produced_and_committed_));
125 producer_->Connect(TEST_PRODUCER_SOCK_NAME, task_runner);
126 }
127
128 private:
129 std::unique_ptr<FakeProducer> producer_;
130 const uint8_t* data_;
131 const size_t size_;
132 std::function<void()> on_produced_and_committed_;
133 };
134
135 int FuzzSharedMemory(const uint8_t* data, size_t size);
136
FuzzSharedMemory(const uint8_t * data,size_t size)137 int FuzzSharedMemory(const uint8_t* data, size_t size) {
138 base::TestTaskRunner task_runner;
139
140 TestHelper helper(&task_runner);
141 helper.StartServiceIfRequired();
142
143 TaskRunnerThread producer_thread("perfetto.prd");
144 producer_thread.Start(std::unique_ptr<FakeProducerDelegate>(
145 new FakeProducerDelegate(data, size,
146 helper.WrapTask(task_runner.CreateCheckpoint(
147 "produced.and.committed")))));
148
149 helper.ConnectConsumer();
150 helper.WaitForConsumerConnect();
151
152 TraceConfig trace_config;
153 trace_config.add_buffers()->set_size_kb(8);
154
155 auto* ds_config = trace_config.add_data_sources()->mutable_config();
156 ds_config->set_name("android.perfetto.FakeProducer");
157 ds_config->set_target_buffer(0);
158
159 helper.StartTracing(trace_config);
160 task_runner.RunUntilCheckpoint("produced.and.committed");
161
162 helper.ReadData();
163 helper.WaitForReadData();
164
165 return 0;
166 }
167
168 } // namespace shm_fuzz
169 } // namespace perfetto
170
171 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
172
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)173 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
174 return perfetto::shm_fuzz::FuzzSharedMemory(data, size);
175 }
176