1 /*
2 * Copyright 2019 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 #include <string>
17
18 #include <android-base/logging.h>
19
20 #include "../ChattyLogBuffer.h"
21 #include "../LogReaderList.h"
22 #include "../LogReaderThread.h"
23 #include "../LogStatistics.h"
24 #include "../SerializedLogBuffer.h"
25
26 // We don't want to waste a lot of entropy on messages
27 #define MAX_MSG_LENGTH 5
28
29 // Tag IDs usually start at 1000, we only want to try 1000 through 1009
30 #define MIN_TAG_ID 1000
31 #define TAG_MOD 10
32
uidToName(uid_t)33 char* android::uidToName(uid_t) {
34 return strdup("fake");
35 }
36
37 struct LogInput {
38 public:
39 log_id_t log_id;
40 log_time realtime;
41 uid_t uid;
42 pid_t pid;
43 pid_t tid;
44 unsigned int log_mask;
45 };
46
write_log_messages(const uint8_t ** pdata,size_t * data_left,LogBuffer * log_buffer,LogStatistics * stats)47 int write_log_messages(const uint8_t** pdata, size_t* data_left, LogBuffer* log_buffer,
48 LogStatistics* stats) {
49 const uint8_t* data = *pdata;
50 const LogInput* logInput = reinterpret_cast<const LogInput*>(data);
51 data += sizeof(LogInput);
52 *data_left -= sizeof(LogInput);
53
54 uint32_t tag = MIN_TAG_ID + data[0] % TAG_MOD;
55 uint8_t msg_length = data[1] % MAX_MSG_LENGTH;
56 if (msg_length < 2) {
57 // Not enough data for message
58 return 0;
59 }
60
61 data += 2 * sizeof(uint8_t);
62 *data_left -= 2 * sizeof(uint8_t);
63
64 if (*data_left < msg_length) {
65 // Not enough data for tag and message
66 *pdata = data;
67 return 0;
68 }
69
70 // We need nullterm'd strings
71 char msg[sizeof(uint32_t) + MAX_MSG_LENGTH + sizeof(char)];
72 char* msg_only = msg + sizeof(uint32_t);
73 memcpy(msg, &tag, sizeof(uint32_t));
74 memcpy(msg_only, data, msg_length);
75 msg_only[msg_length] = '\0';
76 data += msg_length;
77 *data_left -= msg_length;
78
79 // Other elements not in enum.
80 log_id_t log_id = static_cast<log_id_t>(unsigned(logInput->log_id) % (LOG_ID_MAX + 1));
81 log_buffer->Log(log_id, logInput->realtime, logInput->uid, logInput->pid, logInput->tid, msg,
82 sizeof(uint32_t) + msg_length + 1);
83 stats->Format(logInput->uid, logInput->pid, logInput->log_mask);
84 *pdata = data;
85 return 1;
86 }
87
88 class NoopWriter : public LogWriter {
89 public:
NoopWriter()90 NoopWriter() : LogWriter(0, true) {}
Write(const logger_entry &,const char *)91 bool Write(const logger_entry&, const char*) override { return true; }
92
name() const93 std::string name() const override { return "noop_writer"; }
94 };
95
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)96 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
97 // We want a random tag length and a random remaining message length
98 if (data == nullptr || size < sizeof(LogInput) + 2 * sizeof(uint8_t)) {
99 return 0;
100 }
101
102 android::base::SetMinimumLogSeverity(android::base::ERROR);
103
104 LogReaderList reader_list;
105 LogTags tags;
106 PruneList prune_list;
107 LogStatistics stats(true, true);
108 std::unique_ptr<LogBuffer> log_buffer;
109 #ifdef FUZZ_SERIALIZED
110 log_buffer.reset(new SerializedLogBuffer(&reader_list, &tags, &stats));
111 #else
112 log_buffer.reset(new ChattyLogBuffer(&reader_list, &tags, &prune_list, &stats));
113 #endif
114 size_t data_left = size;
115 const uint8_t** pdata = &data;
116
117 prune_list.Init(nullptr);
118 // We want to get pruning code to get called.
119 log_id_for_each(i) { log_buffer->SetSize(i, 10000); }
120
121 while (data_left >= sizeof(LogInput) + 2 * sizeof(uint8_t)) {
122 if (!write_log_messages(pdata, &data_left, log_buffer.get(), &stats)) {
123 return 0;
124 }
125 }
126
127 // Read out all of the logs.
128 {
129 auto lock = std::unique_lock{logd_lock};
130 std::unique_ptr<LogWriter> test_writer(new NoopWriter());
131 std::unique_ptr<LogReaderThread> log_reader(
132 new LogReaderThread(log_buffer.get(), &reader_list, std::move(test_writer), true, 0,
133 kLogMaskAll, 0, {}, 1, {}));
134 reader_list.reader_threads().emplace_back(std::move(log_reader));
135 }
136
137 // Wait until the reader has finished.
138 while (true) {
139 usleep(50);
140 auto lock = std::unique_lock{logd_lock};
141 if (reader_list.reader_threads().size() == 0) {
142 break;
143 }
144 }
145
146 log_id_for_each(i) { log_buffer->Clear(i, 0); }
147 return 0;
148 }
149