• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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