1 /*
2 * Copyright (C) 2022 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 "path_utils.h"
18
19 #include <filesystem>
20 #include <string>
21 #include <vector>
22
23 #include "aidl/com/android/server/art/ArtConstants.h"
24 #include "aidl/com/android/server/art/BnArtd.h"
25 #include "android-base/errors.h"
26 #include "android-base/result.h"
27 #include "arch/instruction_set.h"
28 #include "base/file_utils.h"
29 #include "base/macros.h"
30 #include "file_utils.h"
31 #include "oat/oat_file_assistant.h"
32 #include "runtime_image.h"
33 #include "service.h"
34 #include "tools/tools.h"
35
36 namespace art {
37 namespace artd {
38
39 namespace {
40
41 using ::aidl::com::android::server::art::ArtConstants;
42 using ::aidl::com::android::server::art::ArtifactsPath;
43 using ::aidl::com::android::server::art::DexMetadataPath;
44 using ::aidl::com::android::server::art::OutputArtifacts;
45 using ::aidl::com::android::server::art::OutputProfile;
46 using ::aidl::com::android::server::art::ProfilePath;
47 using ::aidl::com::android::server::art::RuntimeArtifactsPath;
48 using ::aidl::com::android::server::art::SecureDexMetadataWithCompanionPaths;
49 using ::aidl::com::android::server::art::VdexPath;
50 using ::android::base::Error;
51 using ::android::base::Result;
52 using ::art::service::ValidateDexPath;
53 using ::art::service::ValidatePathElement;
54 using ::art::service::ValidatePathElementSubstring;
55
56 using PrebuiltProfilePath = ProfilePath::PrebuiltProfilePath;
57 using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath;
58 using PrimaryRefProfilePath = ProfilePath::PrimaryRefProfilePath;
59 using SecondaryCurProfilePath = ProfilePath::SecondaryCurProfilePath;
60 using SecondaryRefProfilePath = ProfilePath::SecondaryRefProfilePath;
61 using TmpProfilePath = ProfilePath::TmpProfilePath;
62 using WritableProfilePath = ProfilePath::WritableProfilePath;
63
64 constexpr const char* kPreRebootSuffix = ".staged";
65
66 // Only to be changed for testing.
67 std::string_view gListRootDir = "/";
68
69 } // namespace
70
GetAndroidDataOrError()71 Result<std::string> GetAndroidDataOrError() {
72 std::string error_msg;
73 std::string result = GetAndroidDataSafe(&error_msg);
74 if (!error_msg.empty()) {
75 return Error() << error_msg;
76 }
77 return result;
78 }
79
GetAndroidExpandOrError()80 Result<std::string> GetAndroidExpandOrError() {
81 std::string error_msg;
82 std::string result = GetAndroidExpandSafe(&error_msg);
83 if (!error_msg.empty()) {
84 return Error() << error_msg;
85 }
86 return result;
87 }
88
GetArtRootOrError()89 Result<std::string> GetArtRootOrError() {
90 std::string error_msg;
91 std::string result = GetArtRootSafe(&error_msg);
92 if (!error_msg.empty()) {
93 return Error() << error_msg;
94 }
95 return result;
96 }
97
ListManagedFiles(const std::string & android_data,const std::string & android_expand)98 std::vector<std::string> ListManagedFiles(const std::string& android_data,
99 const std::string& android_expand) {
100 // See `art::tools::Glob` for the syntax.
101 std::vector<std::string> patterns = {
102 // Profiles for primary dex files.
103 android_data + "/misc/profiles/**",
104 // Artifacts for primary dex files.
105 android_data + "/dalvik-cache/**",
106 };
107
108 for (const std::string& data_root : {android_data, android_expand + "/*"}) {
109 // Artifacts for primary dex files.
110 patterns.push_back(data_root + "/app/*/*/oat/**");
111 patterns.push_back(data_root + "/app/*/*/*.sdm");
112
113 for (const char* user_dir : {"/user", "/user_de"}) {
114 std::string data_dir = data_root + user_dir + "/*/*";
115 // Profiles and artifacts for secondary dex files. Those files are in app data directories, so
116 // we use more granular patterns to avoid accidentally deleting apps' files.
117 std::string secondary_oat_dir = data_dir + "/**/oat";
118 for (const char* suffix : {"", ".*.tmp", kPreRebootSuffix}) {
119 patterns.push_back(secondary_oat_dir + "/*" + ArtConstants::PROFILE_FILE_EXT + suffix);
120 patterns.push_back(secondary_oat_dir + "/*/*" + kOdexExtension + suffix);
121 patterns.push_back(secondary_oat_dir + "/*/*" + kVdexExtension + suffix);
122 patterns.push_back(secondary_oat_dir + "/*/*" + kArtExtension + suffix);
123 }
124 // Runtime image files.
125 patterns.push_back(RuntimeImage::GetRuntimeImageDir(data_dir) + "**");
126 }
127 }
128
129 return tools::Glob(patterns, gListRootDir);
130 }
131
ListRuntimeArtifactsFiles(const std::string & android_data,const std::string & android_expand,const RuntimeArtifactsPath & runtime_artifacts_path)132 std::vector<std::string> ListRuntimeArtifactsFiles(
133 const std::string& android_data,
134 const std::string& android_expand,
135 const RuntimeArtifactsPath& runtime_artifacts_path) {
136 // See `art::tools::Glob` for the syntax.
137 std::vector<std::string> patterns;
138
139 for (const std::string& data_root : {android_data, android_expand + "/*"}) {
140 for (const char* user_dir : {"/user", "/user_de"}) {
141 std::string data_dir =
142 data_root + user_dir + "/*/" + tools::EscapeGlob(runtime_artifacts_path.packageName);
143 patterns.push_back(
144 RuntimeImage::GetRuntimeImagePath(data_dir,
145 tools::EscapeGlob(runtime_artifacts_path.dexPath),
146 tools::EscapeGlob(runtime_artifacts_path.isa)));
147 }
148 }
149
150 return tools::Glob(patterns, gListRootDir);
151 }
152
ValidateAndGetIsa(const std::string & isa_str)153 static Result<InstructionSet> ValidateAndGetIsa(const std::string& isa_str) {
154 InstructionSet isa = GetInstructionSetFromString(isa_str.c_str());
155 if (isa == InstructionSet::kNone) {
156 return Errorf("Instruction set '{}' is invalid", isa_str);
157 }
158 return isa;
159 }
160
ValidateRuntimeArtifactsPath(const RuntimeArtifactsPath & runtime_artifacts_path)161 Result<void> ValidateRuntimeArtifactsPath(const RuntimeArtifactsPath& runtime_artifacts_path) {
162 OR_RETURN(ValidatePathElement(runtime_artifacts_path.packageName, "packageName"));
163 OR_RETURN(ValidateAndGetIsa(runtime_artifacts_path.isa));
164 OR_RETURN(ValidateDexPath(runtime_artifacts_path.dexPath));
165 return {};
166 }
167
BuildArtBinPath(const std::string & binary_name)168 Result<std::string> BuildArtBinPath(const std::string& binary_name) {
169 return ART_FORMAT("{}/bin/{}", OR_RETURN(GetArtRootOrError()), binary_name);
170 }
171
BuildOatPath(const std::string & dex_path,const std::string & isa_str,bool is_in_dalvik_cache)172 Result<std::string> BuildOatPath(const std::string& dex_path,
173 const std::string& isa_str,
174 bool is_in_dalvik_cache) {
175 OR_RETURN(ValidateDexPath(dex_path));
176 InstructionSet isa = OR_RETURN(ValidateAndGetIsa(isa_str));
177
178 std::string oat_path;
179 std::string error_msg;
180 if (is_in_dalvik_cache) {
181 // Apps' OAT files are never in ART APEX data.
182 if (!OatFileAssistant::DexLocationToOatFilename(dex_path,
183 isa,
184 /*deny_art_apex_data_files=*/true,
185 &oat_path,
186 &error_msg)) {
187 return Errorf("{}", error_msg);
188 }
189 } else {
190 if (!OatFileAssistant::DexLocationToOdexFilename(dex_path, isa, &oat_path, &error_msg)) {
191 return Errorf("{}", error_msg);
192 }
193 }
194
195 return oat_path;
196 }
197
BuildArtifactsPath(const ArtifactsPath & artifacts_path)198 Result<RawArtifactsPath> BuildArtifactsPath(const ArtifactsPath& artifacts_path) {
199 RawArtifactsPath path;
200 path.oat_path = OR_RETURN(
201 BuildOatPath(artifacts_path.dexPath, artifacts_path.isa, artifacts_path.isInDalvikCache));
202 path.vdex_path = ReplaceFileExtension(path.oat_path, kVdexExtension);
203 path.art_path = ReplaceFileExtension(path.oat_path, kArtExtension);
204
205 if (artifacts_path.isPreReboot) {
206 path.oat_path += kPreRebootSuffix;
207 path.vdex_path += kPreRebootSuffix;
208 path.art_path += kPreRebootSuffix;
209 }
210
211 return path;
212 }
213
BuildPrimaryRefProfilePath(const PrimaryRefProfilePath & primary_ref_profile_path)214 Result<std::string> BuildPrimaryRefProfilePath(
215 const PrimaryRefProfilePath& primary_ref_profile_path) {
216 OR_RETURN(ValidatePathElement(primary_ref_profile_path.packageName, "packageName"));
217 OR_RETURN(ValidatePathElementSubstring(primary_ref_profile_path.profileName, "profileName"));
218 return ART_FORMAT("{}/misc/profiles/ref/{}/{}{}{}",
219 OR_RETURN(GetAndroidDataOrError()),
220 primary_ref_profile_path.packageName,
221 primary_ref_profile_path.profileName,
222 ArtConstants::PROFILE_FILE_EXT,
223 primary_ref_profile_path.isPreReboot ? kPreRebootSuffix : "");
224 }
225
BuildPrebuiltProfilePath(const PrebuiltProfilePath & prebuilt_profile_path)226 Result<std::string> BuildPrebuiltProfilePath(const PrebuiltProfilePath& prebuilt_profile_path) {
227 OR_RETURN(ValidateDexPath(prebuilt_profile_path.dexPath));
228 return prebuilt_profile_path.dexPath + ArtConstants::PROFILE_FILE_EXT;
229 }
230
BuildPrimaryCurProfilePath(const PrimaryCurProfilePath & primary_cur_profile_path)231 Result<std::string> BuildPrimaryCurProfilePath(
232 const PrimaryCurProfilePath& primary_cur_profile_path) {
233 OR_RETURN(ValidatePathElement(primary_cur_profile_path.packageName, "packageName"));
234 OR_RETURN(ValidatePathElementSubstring(primary_cur_profile_path.profileName, "profileName"));
235 return ART_FORMAT("{}/misc/profiles/cur/{}/{}/{}{}",
236 OR_RETURN(GetAndroidDataOrError()),
237 primary_cur_profile_path.userId,
238 primary_cur_profile_path.packageName,
239 primary_cur_profile_path.profileName,
240 ArtConstants::PROFILE_FILE_EXT);
241 }
242
BuildSecondaryRefProfilePath(const SecondaryRefProfilePath & secondary_ref_profile_path)243 Result<std::string> BuildSecondaryRefProfilePath(
244 const SecondaryRefProfilePath& secondary_ref_profile_path) {
245 OR_RETURN(ValidateDexPath(secondary_ref_profile_path.dexPath));
246 std::filesystem::path dex_path(secondary_ref_profile_path.dexPath);
247 return ART_FORMAT("{}/oat/{}{}{}",
248 dex_path.parent_path().string(),
249 dex_path.filename().string(),
250 ArtConstants::PROFILE_FILE_EXT,
251 secondary_ref_profile_path.isPreReboot ? kPreRebootSuffix : "");
252 }
253
BuildSecondaryCurProfilePath(const SecondaryCurProfilePath & secondary_cur_profile_path)254 Result<std::string> BuildSecondaryCurProfilePath(
255 const SecondaryCurProfilePath& secondary_cur_profile_path) {
256 OR_RETURN(ValidateDexPath(secondary_cur_profile_path.dexPath));
257 std::filesystem::path dex_path(secondary_cur_profile_path.dexPath);
258 return ART_FORMAT("{}/oat/{}.cur{}",
259 dex_path.parent_path().string(),
260 dex_path.filename().string(),
261 ArtConstants::PROFILE_FILE_EXT);
262 }
263
BuildWritableProfilePath(const WritableProfilePath & profile_path)264 Result<std::string> BuildWritableProfilePath(const WritableProfilePath& profile_path) {
265 switch (profile_path.getTag()) {
266 case WritableProfilePath::forPrimary:
267 return BuildPrimaryRefProfilePath(profile_path.get<WritableProfilePath::forPrimary>());
268 case WritableProfilePath::forSecondary:
269 return BuildSecondaryRefProfilePath(profile_path.get<WritableProfilePath::forSecondary>());
270 // No default. All cases should be explicitly handled, or the compilation will fail.
271 }
272 // This should never happen. Just in case we get a non-enumerator value.
273 LOG(FATAL) << ART_FORMAT("Unexpected writable profile path type {}",
274 fmt::underlying(profile_path.getTag()));
275 }
276
BuildFinalProfilePath(const TmpProfilePath & tmp_profile_path)277 Result<std::string> BuildFinalProfilePath(const TmpProfilePath& tmp_profile_path) {
278 return BuildWritableProfilePath(tmp_profile_path.finalPath);
279 }
280
BuildTmpProfilePath(const TmpProfilePath & tmp_profile_path)281 Result<std::string> BuildTmpProfilePath(const TmpProfilePath& tmp_profile_path) {
282 OR_RETURN(ValidatePathElementSubstring(tmp_profile_path.id, "id"));
283 return NewFile::BuildTempPath(OR_RETURN(BuildFinalProfilePath(tmp_profile_path)),
284 tmp_profile_path.id);
285 }
286
BuildDexMetadataPath(const DexMetadataPath & dex_metadata_path)287 Result<std::string> BuildDexMetadataPath(const DexMetadataPath& dex_metadata_path) {
288 OR_RETURN(ValidateDexPath(dex_metadata_path.dexPath));
289 return ReplaceFileExtension(dex_metadata_path.dexPath, kDmExtension);
290 }
291
BuildProfileOrDmPath(const ProfilePath & profile_path)292 Result<std::string> BuildProfileOrDmPath(const ProfilePath& profile_path) {
293 switch (profile_path.getTag()) {
294 case ProfilePath::primaryRefProfilePath:
295 return BuildPrimaryRefProfilePath(profile_path.get<ProfilePath::primaryRefProfilePath>());
296 case ProfilePath::prebuiltProfilePath:
297 return BuildPrebuiltProfilePath(profile_path.get<ProfilePath::prebuiltProfilePath>());
298 case ProfilePath::primaryCurProfilePath:
299 return BuildPrimaryCurProfilePath(profile_path.get<ProfilePath::primaryCurProfilePath>());
300 case ProfilePath::secondaryRefProfilePath:
301 return BuildSecondaryRefProfilePath(profile_path.get<ProfilePath::secondaryRefProfilePath>());
302 case ProfilePath::secondaryCurProfilePath:
303 return BuildSecondaryCurProfilePath(profile_path.get<ProfilePath::secondaryCurProfilePath>());
304 case ProfilePath::tmpProfilePath:
305 return BuildTmpProfilePath(profile_path.get<ProfilePath::tmpProfilePath>());
306 case ProfilePath::dexMetadataPath:
307 return BuildDexMetadataPath(profile_path.get<ProfilePath::dexMetadataPath>());
308 // No default. All cases should be explicitly handled, or the compilation will fail.
309 }
310 // This should never happen. Just in case we get a non-enumerator value.
311 LOG(FATAL) << ART_FORMAT("Unexpected profile path type {}",
312 fmt::underlying(profile_path.getTag()));
313 }
314
BuildVdexPath(const VdexPath & vdex_path)315 Result<std::string> BuildVdexPath(const VdexPath& vdex_path) {
316 DCHECK(vdex_path.getTag() == VdexPath::artifactsPath);
317 return OR_RETURN(BuildArtifactsPath(vdex_path.get<VdexPath::artifactsPath>())).vdex_path;
318 }
319
BuildSdmPath(const SecureDexMetadataWithCompanionPaths & sdm_path)320 Result<std::string> BuildSdmPath(const SecureDexMetadataWithCompanionPaths& sdm_path) {
321 // `sdm_path.isInDalvikCache` is intentionally ignored because it's only applicable to SDC files.
322 OR_RETURN(ValidateDexPath(sdm_path.dexPath));
323 OR_RETURN(ValidateAndGetIsa(sdm_path.isa));
324 return ReplaceFileExtension(sdm_path.dexPath, ART_FORMAT(".{}{}", sdm_path.isa, kSdmExtension));
325 }
326
BuildSdcPath(const SecureDexMetadataWithCompanionPaths & sdc_path)327 Result<std::string> BuildSdcPath(const SecureDexMetadataWithCompanionPaths& sdc_path) {
328 std::string oat_path =
329 OR_RETURN(BuildOatPath(sdc_path.dexPath, sdc_path.isa, sdc_path.isInDalvikCache));
330 return ReplaceFileExtension(oat_path, ".sdc");
331 }
332
PreRebootFlag(const ProfilePath & profile_path)333 bool PreRebootFlag(const ProfilePath& profile_path) {
334 switch (profile_path.getTag()) {
335 case ProfilePath::primaryRefProfilePath:
336 return profile_path.get<ProfilePath::primaryRefProfilePath>().isPreReboot;
337 case ProfilePath::secondaryRefProfilePath:
338 return profile_path.get<ProfilePath::secondaryRefProfilePath>().isPreReboot;
339 case ProfilePath::tmpProfilePath:
340 return PreRebootFlag(profile_path.get<ProfilePath::tmpProfilePath>());
341 case ProfilePath::prebuiltProfilePath:
342 case ProfilePath::primaryCurProfilePath:
343 case ProfilePath::secondaryCurProfilePath:
344 case ProfilePath::dexMetadataPath:
345 return false;
346 // No default. All cases should be explicitly handled, or the compilation will fail.
347 }
348 // This should never happen. Just in case we get a non-enumerator value.
349 LOG(FATAL) << ART_FORMAT("Unexpected profile path type {}",
350 fmt::underlying(profile_path.getTag()));
351 }
352
PreRebootFlag(const TmpProfilePath & tmp_profile_path)353 bool PreRebootFlag(const TmpProfilePath& tmp_profile_path) {
354 return PreRebootFlag(tmp_profile_path.finalPath);
355 }
356
PreRebootFlag(const OutputProfile & profile)357 bool PreRebootFlag(const OutputProfile& profile) { return PreRebootFlag(profile.profilePath); }
358
PreRebootFlag(const ArtifactsPath & artifacts_path)359 bool PreRebootFlag(const ArtifactsPath& artifacts_path) { return artifacts_path.isPreReboot; }
360
PreRebootFlag(const OutputArtifacts & artifacts)361 bool PreRebootFlag(const OutputArtifacts& artifacts) {
362 return PreRebootFlag(artifacts.artifactsPath);
363 }
364
PreRebootFlag(const VdexPath & vdex_path)365 bool PreRebootFlag(const VdexPath& vdex_path) {
366 return PreRebootFlag(vdex_path.get<VdexPath::artifactsPath>());
367 }
368
IsPreRebootStagedFile(std::string_view filename)369 bool IsPreRebootStagedFile(std::string_view filename) {
370 return filename.ends_with(kPreRebootSuffix);
371 }
372
TestOnlySetListRootDir(std::string_view root_dir)373 void TestOnlySetListRootDir(std::string_view root_dir) { gListRootDir = root_dir; }
374
375 } // namespace artd
376 } // namespace art
377