• 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/BnArtd.h"
24 #include "android-base/errors.h"
25 #include "android-base/result.h"
26 #include "android-base/strings.h"
27 #include "arch/instruction_set.h"
28 #include "base/file_utils.h"
29 #include "file_utils.h"
30 #include "fmt/format.h"
31 #include "oat_file_assistant.h"
32 #include "tools/tools.h"
33 
34 namespace art {
35 namespace artd {
36 
37 namespace {
38 
39 using ::aidl::com::android::server::art::ArtifactsPath;
40 using ::aidl::com::android::server::art::DexMetadataPath;
41 using ::aidl::com::android::server::art::ProfilePath;
42 using ::aidl::com::android::server::art::VdexPath;
43 using ::android::base::Error;
44 using ::android::base::Result;
45 
46 using ::fmt::literals::operator""_format;  // NOLINT
47 
48 using PrebuiltProfilePath = ProfilePath::PrebuiltProfilePath;
49 using PrimaryCurProfilePath = ProfilePath::PrimaryCurProfilePath;
50 using PrimaryRefProfilePath = ProfilePath::PrimaryRefProfilePath;
51 using SecondaryCurProfilePath = ProfilePath::SecondaryCurProfilePath;
52 using SecondaryRefProfilePath = ProfilePath::SecondaryRefProfilePath;
53 using TmpProfilePath = ProfilePath::TmpProfilePath;
54 using WritableProfilePath = ProfilePath::WritableProfilePath;
55 
ValidateAbsoluteNormalPath(const std::string & path_str)56 Result<void> ValidateAbsoluteNormalPath(const std::string& path_str) {
57   if (path_str.empty()) {
58     return Errorf("Path is empty");
59   }
60   if (path_str.find('\0') != std::string::npos) {
61     return Errorf("Path '{}' has invalid character '\\0'", path_str);
62   }
63   std::filesystem::path path(path_str);
64   if (!path.is_absolute()) {
65     return Errorf("Path '{}' is not an absolute path", path_str);
66   }
67   if (path.lexically_normal() != path_str) {
68     return Errorf("Path '{}' is not in normal form", path_str);
69   }
70   return {};
71 }
72 
ValidatePathElementSubstring(const std::string & path_element_substring,const std::string & name)73 Result<void> ValidatePathElementSubstring(const std::string& path_element_substring,
74                                           const std::string& name) {
75   if (path_element_substring.empty()) {
76     return Errorf("{} is empty", name);
77   }
78   if (path_element_substring.find('/') != std::string::npos) {
79     return Errorf("{} '{}' has invalid character '/'", name, path_element_substring);
80   }
81   if (path_element_substring.find('\0') != std::string::npos) {
82     return Errorf("{} '{}' has invalid character '\\0'", name, path_element_substring);
83   }
84   return {};
85 }
86 
ValidatePathElement(const std::string & path_element,const std::string & name)87 Result<void> ValidatePathElement(const std::string& path_element, const std::string& name) {
88   OR_RETURN(ValidatePathElementSubstring(path_element, name));
89   if (path_element == "." || path_element == "..") {
90     return Errorf("Invalid {} '{}'", name, path_element);
91   }
92   return {};
93 }
94 
GetAndroidDataOrError()95 Result<std::string> GetAndroidDataOrError() {
96   std::string error_msg;
97   std::string result = GetAndroidDataSafe(&error_msg);
98   if (!error_msg.empty()) {
99     return Error() << error_msg;
100   }
101   return result;
102 }
103 
GetAndroidExpandOrError()104 Result<std::string> GetAndroidExpandOrError() {
105   std::string error_msg;
106   std::string result = GetAndroidExpandSafe(&error_msg);
107   if (!error_msg.empty()) {
108     return Error() << error_msg;
109   }
110   return result;
111 }
112 
GetArtRootOrError()113 Result<std::string> GetArtRootOrError() {
114   std::string error_msg;
115   std::string result = GetArtRootSafe(&error_msg);
116   if (!error_msg.empty()) {
117     return Error() << error_msg;
118   }
119   return result;
120 }
121 
122 }  // namespace
123 
ListManagedFiles()124 Result<std::vector<std::string>> ListManagedFiles() {
125   std::string android_data = OR_RETURN(GetAndroidDataOrError());
126   std::string android_expand = OR_RETURN(GetAndroidExpandOrError());
127 
128   // See `art::tools::Glob` for the syntax.
129   std::vector<std::string> patterns = {
130       // Profiles for primary dex files.
131       android_data + "/misc/profiles/**",
132       // Artifacts for primary dex files.
133       android_data + "/dalvik-cache/**",
134   };
135 
136   for (const std::string& data_root : {android_data, android_expand + "/*"}) {
137     // Artifacts for primary dex files.
138     patterns.push_back(data_root + "/app/*/*/oat/**");
139     // Profiles and artifacts for secondary dex files. Those files are in app data directories, so
140     // we use more granular patterns to avoid accidentally deleting apps' files.
141     for (const char* user_dir : {"/user", "/user_de"}) {
142       std::string secondary_oat_dir = data_root + user_dir + "/*/*/**/oat";
143       for (const char* maybe_tmp_suffix : {"", ".*.tmp"}) {
144         patterns.push_back(secondary_oat_dir + "/*.prof" + maybe_tmp_suffix);
145         patterns.push_back(secondary_oat_dir + "/*/*.odex" + maybe_tmp_suffix);
146         patterns.push_back(secondary_oat_dir + "/*/*.vdex" + maybe_tmp_suffix);
147         patterns.push_back(secondary_oat_dir + "/*/*.art" + maybe_tmp_suffix);
148       }
149     }
150   }
151 
152   return tools::Glob(patterns);
153 }
154 
ValidateDexPath(const std::string & dex_path)155 Result<void> ValidateDexPath(const std::string& dex_path) {
156   OR_RETURN(ValidateAbsoluteNormalPath(dex_path));
157   return {};
158 }
159 
BuildArtBinPath(const std::string & binary_name)160 Result<std::string> BuildArtBinPath(const std::string& binary_name) {
161   return "{}/bin/{}"_format(OR_RETURN(GetArtRootOrError()), binary_name);
162 }
163 
BuildOatPath(const ArtifactsPath & artifacts_path)164 Result<std::string> BuildOatPath(const ArtifactsPath& artifacts_path) {
165   OR_RETURN(ValidateDexPath(artifacts_path.dexPath));
166 
167   InstructionSet isa = GetInstructionSetFromString(artifacts_path.isa.c_str());
168   if (isa == InstructionSet::kNone) {
169     return Errorf("Instruction set '{}' is invalid", artifacts_path.isa);
170   }
171 
172   std::string error_msg;
173   std::string path;
174   if (artifacts_path.isInDalvikCache) {
175     // Apps' OAT files are never in ART APEX data.
176     if (!OatFileAssistant::DexLocationToOatFilename(
177             artifacts_path.dexPath, isa, /*deny_art_apex_data_files=*/true, &path, &error_msg)) {
178       return Error() << error_msg;
179     }
180     return path;
181   } else {
182     if (!OatFileAssistant::DexLocationToOdexFilename(
183             artifacts_path.dexPath, isa, &path, &error_msg)) {
184       return Error() << error_msg;
185     }
186     return path;
187   }
188 }
189 
BuildPrimaryRefProfilePath(const PrimaryRefProfilePath & primary_ref_profile_path)190 Result<std::string> BuildPrimaryRefProfilePath(
191     const PrimaryRefProfilePath& primary_ref_profile_path) {
192   OR_RETURN(ValidatePathElement(primary_ref_profile_path.packageName, "packageName"));
193   OR_RETURN(ValidatePathElementSubstring(primary_ref_profile_path.profileName, "profileName"));
194   return "{}/misc/profiles/ref/{}/{}.prof"_format(OR_RETURN(GetAndroidDataOrError()),
195                                                   primary_ref_profile_path.packageName,
196                                                   primary_ref_profile_path.profileName);
197 }
198 
BuildPrebuiltProfilePath(const PrebuiltProfilePath & prebuilt_profile_path)199 Result<std::string> BuildPrebuiltProfilePath(const PrebuiltProfilePath& prebuilt_profile_path) {
200   OR_RETURN(ValidateDexPath(prebuilt_profile_path.dexPath));
201   return prebuilt_profile_path.dexPath + ".prof";
202 }
203 
BuildPrimaryCurProfilePath(const PrimaryCurProfilePath & primary_cur_profile_path)204 Result<std::string> BuildPrimaryCurProfilePath(
205     const PrimaryCurProfilePath& primary_cur_profile_path) {
206   OR_RETURN(ValidatePathElement(primary_cur_profile_path.packageName, "packageName"));
207   OR_RETURN(ValidatePathElementSubstring(primary_cur_profile_path.profileName, "profileName"));
208   return "{}/misc/profiles/cur/{}/{}/{}.prof"_format(OR_RETURN(GetAndroidDataOrError()),
209                                                      primary_cur_profile_path.userId,
210                                                      primary_cur_profile_path.packageName,
211                                                      primary_cur_profile_path.profileName);
212 }
213 
BuildSecondaryRefProfilePath(const SecondaryRefProfilePath & secondary_ref_profile_path)214 Result<std::string> BuildSecondaryRefProfilePath(
215     const SecondaryRefProfilePath& secondary_ref_profile_path) {
216   OR_RETURN(ValidateDexPath(secondary_ref_profile_path.dexPath));
217   std::filesystem::path dex_path(secondary_ref_profile_path.dexPath);
218   return "{}/oat/{}.prof"_format(dex_path.parent_path().string(), dex_path.filename().string());
219 }
220 
BuildSecondaryCurProfilePath(const SecondaryCurProfilePath & secondary_cur_profile_path)221 Result<std::string> BuildSecondaryCurProfilePath(
222     const SecondaryCurProfilePath& secondary_cur_profile_path) {
223   OR_RETURN(ValidateDexPath(secondary_cur_profile_path.dexPath));
224   std::filesystem::path dex_path(secondary_cur_profile_path.dexPath);
225   return "{}/oat/{}.cur.prof"_format(dex_path.parent_path().string(), dex_path.filename().string());
226 }
227 
BuildFinalProfilePath(const TmpProfilePath & tmp_profile_path)228 Result<std::string> BuildFinalProfilePath(const TmpProfilePath& tmp_profile_path) {
229   const WritableProfilePath& final_path = tmp_profile_path.finalPath;
230   switch (final_path.getTag()) {
231     case WritableProfilePath::forPrimary:
232       return BuildPrimaryRefProfilePath(final_path.get<WritableProfilePath::forPrimary>());
233     case WritableProfilePath::forSecondary:
234       return BuildSecondaryRefProfilePath(final_path.get<WritableProfilePath::forSecondary>());
235       // No default. All cases should be explicitly handled, or the compilation will fail.
236   }
237   // This should never happen. Just in case we get a non-enumerator value.
238   LOG(FATAL) << "Unexpected writable profile path type {}"_format(final_path.getTag());
239 }
240 
BuildTmpProfilePath(const TmpProfilePath & tmp_profile_path)241 Result<std::string> BuildTmpProfilePath(const TmpProfilePath& tmp_profile_path) {
242   OR_RETURN(ValidatePathElementSubstring(tmp_profile_path.id, "id"));
243   return NewFile::BuildTempPath(OR_RETURN(BuildFinalProfilePath(tmp_profile_path)),
244                                 tmp_profile_path.id);
245 }
246 
BuildDexMetadataPath(const DexMetadataPath & dex_metadata_path)247 Result<std::string> BuildDexMetadataPath(const DexMetadataPath& dex_metadata_path) {
248   OR_RETURN(ValidateDexPath(dex_metadata_path.dexPath));
249   return ReplaceFileExtension(dex_metadata_path.dexPath, "dm");
250 }
251 
BuildProfileOrDmPath(const ProfilePath & profile_path)252 Result<std::string> BuildProfileOrDmPath(const ProfilePath& profile_path) {
253   switch (profile_path.getTag()) {
254     case ProfilePath::primaryRefProfilePath:
255       return BuildPrimaryRefProfilePath(profile_path.get<ProfilePath::primaryRefProfilePath>());
256     case ProfilePath::prebuiltProfilePath:
257       return BuildPrebuiltProfilePath(profile_path.get<ProfilePath::prebuiltProfilePath>());
258     case ProfilePath::primaryCurProfilePath:
259       return BuildPrimaryCurProfilePath(profile_path.get<ProfilePath::primaryCurProfilePath>());
260     case ProfilePath::secondaryRefProfilePath:
261       return BuildSecondaryRefProfilePath(profile_path.get<ProfilePath::secondaryRefProfilePath>());
262     case ProfilePath::secondaryCurProfilePath:
263       return BuildSecondaryCurProfilePath(profile_path.get<ProfilePath::secondaryCurProfilePath>());
264     case ProfilePath::tmpProfilePath:
265       return BuildTmpProfilePath(profile_path.get<ProfilePath::tmpProfilePath>());
266     case ProfilePath::dexMetadataPath:
267       return BuildDexMetadataPath(profile_path.get<ProfilePath::dexMetadataPath>());
268       // No default. All cases should be explicitly handled, or the compilation will fail.
269   }
270   // This should never happen. Just in case we get a non-enumerator value.
271   LOG(FATAL) << "Unexpected profile path type {}"_format(profile_path.getTag());
272 }
273 
BuildVdexPath(const VdexPath & vdex_path)274 Result<std::string> BuildVdexPath(const VdexPath& vdex_path) {
275   DCHECK(vdex_path.getTag() == VdexPath::artifactsPath);
276   return OatPathToVdexPath(OR_RETURN(BuildOatPath(vdex_path.get<VdexPath::artifactsPath>())));
277 }
278 
279 }  // namespace artd
280 }  // namespace art
281