1
2 /*
3 * Copyright (C) 2024 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <cstdint>
19 #include <string>
20
21 #include "src/base/test/status_matchers.h"
22 #include "src/trace_redaction/find_package_uid.h"
23 #include "test/gtest_and_gmock.h"
24
25 #include "protos/perfetto/trace/android/packages_list.gen.h"
26 #include "protos/perfetto/trace/ps/process_tree.gen.h"
27 #include "protos/perfetto/trace/trace_packet.gen.h"
28
29 namespace perfetto::trace_redaction {
30
31 namespace {
32
33 // packet {
34 // trusted_uid: 9999
35 // trusted_packet_sequence_id: 2
36 // previous_packet_dropped: true
37 // packages_list {
38 // packages {
39 // name: "com.shannon.qualifiednetworksservice"
40 // uid: 10201
41 // debuggable: false
42 // profileable_from_shell: false
43 // version_code: 131
44 // }
45 // packages {
46 // name: "com.google.android.uvexposurereporter"
47 // uid: 10205
48 // debuggable: false
49 // profileable_from_shell: false
50 // version_code: 34
51 // }
52 // packages {
53 // name: "com.android.internal.display.cutout.emulation.noCutout"
54 // uid: 10007
55 // debuggable: false
56 // profileable_from_shell: false
57 // version_code: 1
58 // }
59 // packages {
60 // name: "com.google.android.networkstack.tethering"
61 // uid: 1073
62 // debuggable: false
63 // profileable_from_shell: false
64 // version_code: 34
65 // }
66 // packages {
67 // name: "com.amazon.mShop.android.shopping"
68 // uid: 10303
69 // debuggable: false
70 // profileable_from_shell: false
71 // version_code: 1241261011
72 // }
73 // }
74 // trusted_pid: 1085
75 // first_packet_on_sequence: true
76 // }
77 //
78 // packet {
79 // process_tree {
80 // processes {
81 // pid: 23022
82 // ppid: 1
83 // cmdline: "/vendor/bin/hw/wpa_supplicant"
84 // cmdline: "-O/data/vendor/wifi/wpa/sockets"
85 // cmdline: "-dd"
86 // cmdline: "-g@android:wpa_wlan0"
87 // uid: 1010
88 // }
89 // threads {
90 // tid: 6382
91 // tgid: 18176
92 // }
93 // threads {
94 // tid: 18419
95 // tgid: 18176
96 // }
97 // threads {
98 // tid: 18434
99 // tgid: 18176
100 // }
101 // collection_end_timestamp: 333724398314653
102 // }
103 // trusted_uid: 9999
104 // timestamp: 333724396714922
105 // trusted_packet_sequence_id: 3
106 // trusted_pid: 1085
107 // }
108
AddPackage(const std::string & name,uint64_t uid,int version_code,protos::gen::PackagesList * list)109 void AddPackage(const std::string& name,
110 uint64_t uid,
111 int version_code,
112 protos::gen::PackagesList* list) {
113 auto* pkg = list->add_packages();
114 pkg->set_name(name);
115 pkg->set_uid(uid);
116 pkg->set_version_code(version_code);
117 }
118
AddProcess(protos::gen::ProcessTree * process_tree)119 void AddProcess(protos::gen::ProcessTree* process_tree) {
120 auto* p0 = process_tree->add_processes();
121 p0->set_pid(23022);
122 p0->set_ppid(1);
123 p0->add_cmdline("/vendor/bin/hw/wpa_supplicant");
124 p0->add_cmdline("-O/data/vendor/wifi/wpa/sockets");
125 p0->add_cmdline("-dd");
126 p0->add_cmdline("-g@android:wpa_wlan0");
127 p0->set_uid(1010);
128 }
129
AddThread(int32_t tid,int32_t ttid,protos::gen::ProcessTree * process_tree)130 void AddThread(int32_t tid,
131 int32_t ttid,
132 protos::gen::ProcessTree* process_tree) {
133 auto* thread = process_tree->add_threads();
134 thread->set_tid(tid);
135 thread->set_tgid(ttid);
136 }
137
CreatePackageListPacket()138 std::string CreatePackageListPacket() {
139 protos::gen::TracePacket packet;
140 packet.set_trusted_uid(9999);
141 packet.set_trusted_packet_sequence_id(2);
142 packet.set_previous_packet_dropped(true);
143 packet.set_trusted_pid(1085);
144 packet.set_first_packet_on_sequence(true);
145
146 auto* package_list = packet.mutable_packages_list();
147
148 AddPackage("com.shannon.qualifiednetworksservice", 10201, 131, package_list);
149 AddPackage("com.google.android.uvexposurereporter", 10205, 34, package_list);
150 AddPackage("com.android.internal.display.cutout.emulation.noCutout", 10007, 1,
151 package_list);
152 AddPackage("com.google.android.networkstack.tethering", 1073, 34,
153 package_list);
154 AddPackage("com.amazon.mShop.android.shopping", 10303, 1241261011,
155 package_list);
156
157 return packet.SerializeAsString();
158 }
159
CreateProcessTreePacket()160 std::string CreateProcessTreePacket() {
161 protos::gen::TracePacket packet;
162 packet.set_trusted_uid(9999);
163 packet.set_timestamp(333724396714922);
164 packet.set_trusted_packet_sequence_id(3);
165 packet.set_trusted_pid(1085);
166
167 auto* tree = packet.mutable_process_tree();
168 tree->set_collection_end_timestamp(333724398314653);
169
170 AddProcess(tree);
171 AddThread(6382, 18176, tree);
172 AddThread(18419, 18176, tree);
173 AddThread(18434, 18176, tree);
174
175 return packet.SerializeAsString();
176 }
177 } // namespace
178
TEST(FindPackageUidTest,FindsUidInPackageList)179 TEST(FindPackageUidTest, FindsUidInPackageList) {
180 const auto packet = CreatePackageListPacket();
181
182 Context context;
183 context.package_name = "com.google.android.uvexposurereporter";
184
185 const FindPackageUid find;
186
187 const auto decoder = protos::pbzero::TracePacket::Decoder(packet);
188
189 base::Status status = find.Begin(&context);
190 ASSERT_OK(status) << status.message();
191
192 status = find.Collect(decoder, &context);
193 ASSERT_OK(status) << status.message();
194
195 status = find.End(&context);
196 ASSERT_OK(status) << status.message();
197
198 ASSERT_TRUE(context.package_uid.has_value());
199
200 // context.package_uid should have been normalized already.
201 ASSERT_EQ(context.package_uid.value(), NormalizeUid(10205));
202 }
203
TEST(FindPackageUidTest,ContinuesOverNonPackageList)204 TEST(FindPackageUidTest, ContinuesOverNonPackageList) {
205 const auto packet = CreateProcessTreePacket();
206
207 Context context;
208 context.package_name = "com.google.android.uvexposurereporter";
209
210 const FindPackageUid find;
211
212 const auto decoder = protos::pbzero::TracePacket::Decoder(packet);
213
214 base::Status status = find.Begin(&context);
215 ASSERT_OK(status) << status.message();
216
217 status = find.Collect(decoder, &context);
218 ASSERT_OK(status) << status.message();
219
220 // The should not have been found; End() should return an error.
221 status = find.End(&context);
222 ASSERT_FALSE(status.ok()) << status.message();
223
224 ASSERT_FALSE(context.package_uid.has_value());
225 }
226
TEST(FindPackageUidTest,ContinuesOverPackageListWithOutPackageName)227 TEST(FindPackageUidTest, ContinuesOverPackageListWithOutPackageName) {
228 const auto packet = CreatePackageListPacket();
229
230 Context context;
231 context.package_name = "com.not.a.packagename";
232
233 const FindPackageUid find;
234
235 const auto decoder = protos::pbzero::TracePacket::Decoder(packet);
236
237 base::Status status = find.Begin(&context);
238 ASSERT_OK(status) << status.message();
239
240 status = find.Collect(decoder, &context);
241 ASSERT_OK(status) << status.message();
242
243 // The should not have been found; End() should return an error.
244 status = find.End(&context);
245 ASSERT_FALSE(status.ok()) << status.message();
246
247 ASSERT_FALSE(context.package_uid.has_value());
248 }
249
TEST(FindPackageUidTest,MissingPackageNameReturnsError)250 TEST(FindPackageUidTest, MissingPackageNameReturnsError) {
251 const auto packet = CreatePackageListPacket();
252
253 Context context;
254
255 const FindPackageUid find;
256
257 const auto decoder = protos::pbzero::TracePacket::Decoder(packet);
258
259 base::Status status = find.Begin(&context);
260 ASSERT_FALSE(status.ok()) << status.message();
261 }
262
TEST(FindPackageUidTest,FailsIfUidStartsInitialized)263 TEST(FindPackageUidTest, FailsIfUidStartsInitialized) {
264 const auto packet = CreatePackageListPacket();
265
266 Context context;
267 context.package_name = "com.google.android.uvexposurereporter";
268 context.package_uid = 1000;
269
270 const FindPackageUid find;
271
272 const auto decoder = protos::pbzero::TracePacket::Decoder(packet);
273
274 base::Status status = find.Begin(&context);
275 ASSERT_FALSE(status.ok()) << status.message();
276 }
277
278 } // namespace perfetto::trace_redaction
279