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