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: 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 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 71 void OnConnect() override { 72 DataSourceDescriptor descriptor; 73 descriptor.set_name(name_); 74 endpoint_->RegisterDataSource(descriptor); 75 } 76 77 void OnDisconnect() override {} 78 79 void SetupDataSource(DataSourceInstanceID, const DataSourceConfig&) override { 80 } 81 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 99 void StopDataSource(DataSourceInstanceID) override {} 100 void OnTracingSetup() override {} 101 void Flush(FlushRequestID, const DataSourceInstanceID*, size_t) override {} 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: 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 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 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 173 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { 174 return perfetto::shm_fuzz::FuzzSharedMemory(data, size); 175 } 176