Home | History | Annotate | Download | only in test
      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