1 /*
2 * Copyright (C) 2024 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 "src/trace_redaction/verify_integrity.h"
18 #include "src/base/test/status_matchers.h"
19 #include "test/gtest_and_gmock.h"
20
21 #include "protos/perfetto/common/trace_stats.gen.h"
22 #include "protos/perfetto/trace/ftrace/ftrace_event.gen.h"
23 #include "protos/perfetto/trace/ftrace/ftrace_event_bundle.gen.h"
24 #include "protos/perfetto/trace/trace_packet.gen.h"
25
26 namespace perfetto::trace_redaction {
27
28 namespace {
29 // The trace packet uid must be less than or equal to 9999 (nobody). If it is
30 // anything else, the packet is invalid.
31 int32_t kValid = 1000;
32 int32_t kLastValid = Context::kMaxTrustedUid;
33 int32_t kInvalidUid = 12000;
34
35 uint64_t kSomeTime = 1234;
36 uint32_t kSomePid = 7;
37
38 uint32_t kSomeCpu = 3;
39 } // namespace
40
41 class VerifyIntegrityUnitTest : public testing::Test {
42 protected:
Verify(const protos::gen::TracePacket & packet)43 base::Status Verify(const protos::gen::TracePacket& packet) {
44 auto packet_buffer = packet.SerializeAsString();
45 protos::pbzero::TracePacket::Decoder packer_decoder(packet_buffer);
46
47 VerifyIntegrity verify;
48 Context context;
49 return verify.Collect(packer_decoder, &context);
50 }
51 };
52
TEST_F(VerifyIntegrityUnitTest,InvalidPacketNoUid)53 TEST_F(VerifyIntegrityUnitTest, InvalidPacketNoUid) {
54 protos::gen::TracePacket packet;
55 ASSERT_FALSE(Verify(packet).ok());
56 }
57
TEST_F(VerifyIntegrityUnitTest,InvalidPacketInvalidUid)58 TEST_F(VerifyIntegrityUnitTest, InvalidPacketInvalidUid) {
59 protos::gen::TracePacket packet;
60
61 packet.set_trusted_uid(kInvalidUid);
62
63 ASSERT_FALSE(Verify(packet).ok());
64 }
65
TEST_F(VerifyIntegrityUnitTest,ValidPacketSystemUid)66 TEST_F(VerifyIntegrityUnitTest, ValidPacketSystemUid) {
67 protos::gen::TracePacket packet;
68
69 packet.set_trusted_uid(kValid);
70
71 ASSERT_OK(Verify(packet));
72 }
73
TEST_F(VerifyIntegrityUnitTest,InclusiveEnd)74 TEST_F(VerifyIntegrityUnitTest, InclusiveEnd) {
75 protos::gen::TracePacket packet;
76
77 packet.set_trusted_uid(kLastValid);
78
79 ASSERT_OK(Verify(packet));
80 }
81
TEST_F(VerifyIntegrityUnitTest,InvalidPacketFtraceBundleHasLostEvents)82 TEST_F(VerifyIntegrityUnitTest, InvalidPacketFtraceBundleHasLostEvents) {
83 protos::gen::TracePacket packet;
84
85 packet.set_trusted_uid(kValid);
86
87 packet.mutable_ftrace_events()->set_lost_events(true);
88
89 ASSERT_FALSE(Verify(packet).ok());
90 }
91
TEST_F(VerifyIntegrityUnitTest,ValidPacketFtraceBundleHasNoLostEvents)92 TEST_F(VerifyIntegrityUnitTest, ValidPacketFtraceBundleHasNoLostEvents) {
93 protos::gen::TracePacket packet;
94
95 packet.set_trusted_uid(kValid);
96
97 packet.mutable_ftrace_events()->set_lost_events(false);
98
99 ASSERT_FALSE(Verify(packet).ok());
100 }
101
TEST_F(VerifyIntegrityUnitTest,InvalidPacketFtraceBundleMissingCpu)102 TEST_F(VerifyIntegrityUnitTest, InvalidPacketFtraceBundleMissingCpu) {
103 protos::gen::TracePacket packet;
104
105 packet.set_trusted_uid(kValid);
106
107 packet.mutable_ftrace_events();
108
109 ASSERT_FALSE(Verify(packet).ok());
110 }
111
TEST_F(VerifyIntegrityUnitTest,InvalidPacketFtraceBundleHasErrors)112 TEST_F(VerifyIntegrityUnitTest, InvalidPacketFtraceBundleHasErrors) {
113 protos::gen::TracePacket packet;
114
115 packet.set_trusted_uid(kValid);
116
117 packet.mutable_ftrace_events()->add_error();
118
119 ASSERT_FALSE(Verify(packet).ok());
120 }
121
TEST_F(VerifyIntegrityUnitTest,ValidPacketFtraceBundle)122 TEST_F(VerifyIntegrityUnitTest, ValidPacketFtraceBundle) {
123 protos::gen::TracePacket packet;
124
125 packet.set_trusted_uid(kValid);
126
127 // A bundle doesn't need to have anything in it (other than cpu).
128 auto* ftrace_events = packet.mutable_ftrace_events();
129 ftrace_events->set_cpu(kSomeCpu);
130
131 ASSERT_OK(Verify(packet));
132 }
133
TEST_F(VerifyIntegrityUnitTest,InvalidPacketFtraceEventMissingPid)134 TEST_F(VerifyIntegrityUnitTest, InvalidPacketFtraceEventMissingPid) {
135 protos::gen::TracePacket packet;
136
137 packet.set_trusted_uid(kValid);
138
139 auto* ftrace_events = packet.mutable_ftrace_events();
140 ftrace_events->set_cpu(kSomeCpu);
141
142 // A valid event has a pid and timestamp. Add the time (but not the pid) to
143 // ensure the pid caused the error.
144 auto* event = ftrace_events->add_event();
145 event->set_timestamp(kSomeTime);
146
147 ASSERT_FALSE(Verify(packet).ok());
148 }
149
TEST_F(VerifyIntegrityUnitTest,InvalidPacketFtraceEventMissingTime)150 TEST_F(VerifyIntegrityUnitTest, InvalidPacketFtraceEventMissingTime) {
151 protos::gen::TracePacket packet;
152
153 packet.set_trusted_uid(kValid);
154
155 auto* ftrace_events = packet.mutable_ftrace_events();
156 ftrace_events->set_cpu(kSomeCpu);
157
158 // A valid event has a pid and timestamp. Add the pid (but not the time) to
159 // ensure the time caused the error.
160 auto* event = ftrace_events->add_event();
161 event->set_pid(kSomePid);
162
163 ASSERT_FALSE(Verify(packet).ok());
164 }
165
TEST_F(VerifyIntegrityUnitTest,ValidPacketFtraceEvent)166 TEST_F(VerifyIntegrityUnitTest, ValidPacketFtraceEvent) {
167 protos::gen::TracePacket packet;
168
169 packet.set_trusted_uid(kValid);
170
171 auto* ftrace_events = packet.mutable_ftrace_events();
172 ftrace_events->set_cpu(kSomeCpu);
173
174 auto* event = ftrace_events->add_event();
175 event->set_pid(kSomePid);
176 event->set_timestamp(kSomeTime);
177
178 ASSERT_OK(Verify(packet));
179 }
180
TEST_F(VerifyIntegrityUnitTest,InvalidPacketProcessTreeMissingTime)181 TEST_F(VerifyIntegrityUnitTest, InvalidPacketProcessTreeMissingTime) {
182 protos::gen::TracePacket packet;
183
184 packet.set_trusted_uid(kValid);
185
186 // When the packet has a process tree, the packet must have a timestamp.
187 packet.mutable_process_tree();
188
189 ASSERT_FALSE(Verify(packet).ok());
190 }
191
TEST_F(VerifyIntegrityUnitTest,ValidPacketProcessTree)192 TEST_F(VerifyIntegrityUnitTest, ValidPacketProcessTree) {
193 protos::gen::TracePacket packet;
194
195 packet.set_trusted_uid(kValid);
196
197 // When the packet has a process tree, the packet must have a timestamp.
198 packet.mutable_process_tree();
199 packet.set_timestamp(kSomeTime);
200
201 ASSERT_OK(Verify(packet));
202 }
203
TEST_F(VerifyIntegrityUnitTest,InvalidPacketProcessStatsMissingTime)204 TEST_F(VerifyIntegrityUnitTest, InvalidPacketProcessStatsMissingTime) {
205 protos::gen::TracePacket packet;
206
207 packet.set_trusted_uid(kValid);
208
209 // When the packet has process stats, the packet must have a timestamp.
210 packet.mutable_process_stats();
211
212 ASSERT_FALSE(Verify(packet).ok());
213 }
214
TEST_F(VerifyIntegrityUnitTest,InvalidPacketTraceStatsFlushFailed)215 TEST_F(VerifyIntegrityUnitTest, InvalidPacketTraceStatsFlushFailed) {
216 protos::gen::TracePacket packet;
217
218 packet.set_trusted_uid(kValid);
219
220 packet.mutable_trace_stats()->set_flushes_failed(true);
221
222 ASSERT_FALSE(Verify(packet).ok());
223 }
224
TEST_F(VerifyIntegrityUnitTest,InvalidPacketTraceStatsNoFlushFailed)225 TEST_F(VerifyIntegrityUnitTest, InvalidPacketTraceStatsNoFlushFailed) {
226 protos::gen::TracePacket packet;
227
228 packet.set_trusted_uid(kValid);
229
230 packet.mutable_trace_stats()->set_flushes_failed(false);
231
232 ASSERT_OK(Verify(packet));
233 }
234
TEST_F(VerifyIntegrityUnitTest,ValidPacketFinalFlushSucceeded)235 TEST_F(VerifyIntegrityUnitTest, ValidPacketFinalFlushSucceeded) {
236 protos::gen::TracePacket packet;
237
238 packet.set_trusted_uid(kValid);
239
240 packet.mutable_trace_stats()->set_final_flush_outcome(
241 protos::gen::TraceStats::FINAL_FLUSH_SUCCEEDED);
242
243 ASSERT_OK(Verify(packet));
244 }
245
TEST_F(VerifyIntegrityUnitTest,ValidPacketFinalFlushUnspecified)246 TEST_F(VerifyIntegrityUnitTest, ValidPacketFinalFlushUnspecified) {
247 protos::gen::TracePacket packet;
248
249 packet.set_trusted_uid(kValid);
250
251 packet.mutable_trace_stats()->set_final_flush_outcome(
252 protos::gen::TraceStats::FINAL_FLUSH_UNSPECIFIED);
253
254 ASSERT_OK(Verify(packet));
255 }
256
TEST_F(VerifyIntegrityUnitTest,InvalidPacketFinalFlushFailed)257 TEST_F(VerifyIntegrityUnitTest, InvalidPacketFinalFlushFailed) {
258 protos::gen::TracePacket packet;
259
260 packet.set_trusted_uid(kValid);
261
262 packet.mutable_trace_stats()->set_final_flush_outcome(
263 protos::gen::TraceStats::FINAL_FLUSH_FAILED);
264
265 ASSERT_FALSE(Verify(packet).ok());
266 }
267
TEST_F(VerifyIntegrityUnitTest,InvalidPacketBufferStatsPatchesFailed)268 TEST_F(VerifyIntegrityUnitTest, InvalidPacketBufferStatsPatchesFailed) {
269 protos::gen::TracePacket packet;
270
271 packet.set_trusted_uid(kValid);
272
273 packet.mutable_trace_stats()->add_buffer_stats()->set_patches_failed(3);
274
275 ASSERT_FALSE(Verify(packet).ok());
276 }
277
TEST_F(VerifyIntegrityUnitTest,ValidPacketBufferStatsNoPatchesFailed)278 TEST_F(VerifyIntegrityUnitTest, ValidPacketBufferStatsNoPatchesFailed) {
279 protos::gen::TracePacket packet;
280
281 packet.set_trusted_uid(kValid);
282
283 packet.mutable_trace_stats()->add_buffer_stats()->set_patches_failed(0);
284
285 ASSERT_OK(Verify(packet));
286 }
287
TEST_F(VerifyIntegrityUnitTest,InvalidPacketBufferStatsAbiViolation)288 TEST_F(VerifyIntegrityUnitTest, InvalidPacketBufferStatsAbiViolation) {
289 protos::gen::TracePacket packet;
290
291 packet.set_trusted_uid(kValid);
292
293 packet.mutable_trace_stats()->add_buffer_stats()->set_abi_violations(3);
294
295 ASSERT_FALSE(Verify(packet).ok());
296 }
297
TEST_F(VerifyIntegrityUnitTest,InvalidPacketBufferStatsNoAbiViolation)298 TEST_F(VerifyIntegrityUnitTest, InvalidPacketBufferStatsNoAbiViolation) {
299 protos::gen::TracePacket packet;
300
301 packet.set_trusted_uid(kValid);
302
303 packet.mutable_trace_stats()->add_buffer_stats()->set_abi_violations(0);
304
305 ASSERT_OK(Verify(packet));
306 }
307
TEST_F(VerifyIntegrityUnitTest,InvalidPacketBufferStatsTraceWriterPacketLoss)308 TEST_F(VerifyIntegrityUnitTest, InvalidPacketBufferStatsTraceWriterPacketLoss) {
309 protos::gen::TracePacket packet;
310
311 packet.set_trusted_uid(kValid);
312
313 packet.mutable_trace_stats()
314 ->add_buffer_stats()
315 ->set_trace_writer_packet_loss(3);
316
317 ASSERT_EQ(packet.trace_stats().buffer_stats_size(), 1);
318
319 ASSERT_FALSE(Verify(packet).ok());
320 }
321
TEST_F(VerifyIntegrityUnitTest,InvalidPacketBufferStatsNoTraceWriterPacketLoss)322 TEST_F(VerifyIntegrityUnitTest,
323 InvalidPacketBufferStatsNoTraceWriterPacketLoss) {
324 protos::gen::TracePacket packet;
325
326 packet.set_trusted_uid(kValid);
327
328 packet.mutable_trace_stats()
329 ->add_buffer_stats()
330 ->set_trace_writer_packet_loss(0);
331
332 ASSERT_OK(Verify(packet));
333 }
334
TEST_F(VerifyIntegrityUnitTest,ValidPacketProcessStats)335 TEST_F(VerifyIntegrityUnitTest, ValidPacketProcessStats) {
336 protos::gen::TracePacket packet;
337
338 packet.set_trusted_uid(kValid);
339
340 // When the packet has a process tree, the packet must have a timestamp.
341 packet.mutable_process_stats();
342 packet.set_timestamp(kSomeTime);
343
344 ASSERT_OK(Verify(packet));
345 }
346
347 } // namespace perfetto::trace_redaction
348