• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright 2008, 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 "utils.h"
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <fts.h>
22 #include <stdlib.h>
23 #include <sys/capability.h>
24 #include <sys/stat.h>
25 #include <sys/wait.h>
26 #include <sys/xattr.h>
27 #include <sys/statvfs.h>
28 
29 #include <android-base/logging.h>
30 #include <android-base/strings.h>
31 #include <android-base/stringprintf.h>
32 #include <android-base/unique_fd.h>
33 #include <cutils/fs.h>
34 #include <cutils/properties.h>
35 #include <log/log.h>
36 #include <private/android_filesystem_config.h>
37 
38 #include "dexopt_return_codes.h"
39 #include "globals.h"  // extern variables.
40 
41 #ifndef LOG_TAG
42 #define LOG_TAG "installd"
43 #endif
44 
45 #define DEBUG_XATTRS 0
46 
47 using android::base::EndsWith;
48 using android::base::Fdopendir;
49 using android::base::StringPrintf;
50 using android::base::unique_fd;
51 
52 namespace android {
53 namespace installd {
54 
55 /**
56  * Check that given string is valid filename, and that it attempts no
57  * parent or child directory traversal.
58  */
is_valid_filename(const std::string & name)59 bool is_valid_filename(const std::string& name) {
60     if (name.empty() || (name == ".") || (name == "..")
61             || (name.find('/') != std::string::npos)) {
62         return false;
63     } else {
64         return true;
65     }
66 }
67 
check_package_name(const char * package_name)68 static void check_package_name(const char* package_name) {
69     CHECK(is_valid_filename(package_name));
70     CHECK(is_valid_package_name(package_name));
71 }
72 
resolve_ce_path_by_inode_or_fallback(const std::string & root_path,ino_t ce_data_inode,const std::string & fallback)73 static std::string resolve_ce_path_by_inode_or_fallback(const std::string& root_path,
74         ino_t ce_data_inode, const std::string& fallback) {
75     if (ce_data_inode != 0) {
76         DIR* dir = opendir(root_path.c_str());
77         if (dir == nullptr) {
78             PLOG(ERROR) << "Failed to opendir " << root_path;
79             return fallback;
80         }
81 
82         struct dirent* ent;
83         while ((ent = readdir(dir))) {
84             if (ent->d_ino == ce_data_inode) {
85                 auto resolved = StringPrintf("%s/%s", root_path.c_str(), ent->d_name);
86                 if (resolved != fallback) {
87                     LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
88                             << " instead of " << fallback;
89                 }
90                 closedir(dir);
91                 return resolved;
92             }
93         }
94         LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback;
95         closedir(dir);
96         return fallback;
97     } else {
98         return fallback;
99     }
100 }
101 
102 /**
103  * Create the path name where package app contents should be stored for
104  * the given volume UUID and package name.  An empty UUID is assumed to
105  * be internal storage.
106  */
create_data_app_package_path(const char * volume_uuid,const char * package_name)107 std::string create_data_app_package_path(const char* volume_uuid,
108         const char* package_name) {
109     check_package_name(package_name);
110     return StringPrintf("%s/%s",
111             create_data_app_path(volume_uuid).c_str(), package_name);
112 }
113 
114 /**
115  * Create the path name where package data should be stored for the given
116  * volume UUID, package name, and user ID. An empty UUID is assumed to be
117  * internal storage.
118  */
create_data_user_ce_package_path(const char * volume_uuid,userid_t user,const char * package_name)119 std::string create_data_user_ce_package_path(const char* volume_uuid,
120         userid_t user, const char* package_name) {
121     check_package_name(package_name);
122     return StringPrintf("%s/%s",
123             create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
124 }
125 
126 /**
127  * Create the path name where package data should be stored for the given
128  * volume UUID, package name, and user ID. An empty UUID is assumed to be
129  * internal storage.
130  * Compared to create_data_user_ce_package_path this method always return the
131  * ".../user/..." directory.
132  */
create_data_user_ce_package_path_as_user_link(const char * volume_uuid,userid_t userid,const char * package_name)133 std::string create_data_user_ce_package_path_as_user_link(
134         const char* volume_uuid, userid_t userid, const char* package_name) {
135     check_package_name(package_name);
136     std::string data(create_data_path(volume_uuid));
137     return StringPrintf("%s/user/%u/%s", data.c_str(), userid, package_name);
138 }
139 
create_data_user_ce_package_path(const char * volume_uuid,userid_t user,const char * package_name,ino_t ce_data_inode)140 std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user,
141         const char* package_name, ino_t ce_data_inode) {
142     // For testing purposes, rely on the inode when defined; this could be
143     // optimized to use access() in the future.
144     auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
145     auto user_path = create_data_user_ce_path(volume_uuid, user);
146     return resolve_ce_path_by_inode_or_fallback(user_path, ce_data_inode, fallback);
147 }
148 
create_data_user_de_package_path(const char * volume_uuid,userid_t user,const char * package_name)149 std::string create_data_user_de_package_path(const char* volume_uuid,
150         userid_t user, const char* package_name) {
151     check_package_name(package_name);
152     return StringPrintf("%s/%s",
153             create_data_user_de_path(volume_uuid, user).c_str(), package_name);
154 }
155 
create_data_path(const char * volume_uuid)156 std::string create_data_path(const char* volume_uuid) {
157     if (volume_uuid == nullptr) {
158         return "/data";
159     } else if (!strcmp(volume_uuid, "TEST")) {
160         CHECK(property_get_bool("ro.debuggable", false));
161         return "/data/local/tmp";
162     } else {
163         CHECK(is_valid_filename(volume_uuid));
164         return StringPrintf("/mnt/expand/%s", volume_uuid);
165     }
166 }
167 
168 /**
169  * Create the path name for app data.
170  */
create_data_app_path(const char * volume_uuid)171 std::string create_data_app_path(const char* volume_uuid) {
172     return StringPrintf("%s/app", create_data_path(volume_uuid).c_str());
173 }
174 
175 /**
176  * Create the path name for user data for a certain userid.
177  * Keep same implementation as vold to minimize path walking overhead
178  */
create_data_user_ce_path(const char * volume_uuid,userid_t userid)179 std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
180     std::string data(create_data_path(volume_uuid));
181     if (volume_uuid == nullptr && userid == 0) {
182         std::string legacy = StringPrintf("%s/data", data.c_str());
183         struct stat sb;
184         if (lstat(legacy.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
185             /* /data/data is dir, return /data/data for legacy system */
186             return legacy;
187         }
188     }
189     return StringPrintf("%s/user/%u", data.c_str(), userid);
190 }
191 
192 /**
193  * Create the path name for device encrypted user data for a certain userid.
194  */
create_data_user_de_path(const char * volume_uuid,userid_t userid)195 std::string create_data_user_de_path(const char* volume_uuid, userid_t userid) {
196     std::string data(create_data_path(volume_uuid));
197     return StringPrintf("%s/user_de/%u", data.c_str(), userid);
198 }
199 
create_data_misc_ce_rollback_base_path(const char * volume_uuid,userid_t user)200 std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user) {
201     return StringPrintf("%s/misc_ce/%u/rollback", create_data_path(volume_uuid).c_str(), user);
202 }
203 
create_data_misc_de_rollback_base_path(const char * volume_uuid,userid_t user)204 std::string create_data_misc_de_rollback_base_path(const char* volume_uuid, userid_t user) {
205     return StringPrintf("%s/misc_de/%u/rollback", create_data_path(volume_uuid).c_str(), user);
206 }
207 
create_data_misc_ce_rollback_path(const char * volume_uuid,userid_t user,int32_t snapshot_id)208 std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user,
209         int32_t snapshot_id) {
210     return StringPrintf("%s/%d", create_data_misc_ce_rollback_base_path(volume_uuid, user).c_str(),
211           snapshot_id);
212 }
213 
create_data_misc_de_rollback_path(const char * volume_uuid,userid_t user,int32_t snapshot_id)214 std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user,
215         int32_t snapshot_id) {
216     return StringPrintf("%s/%d", create_data_misc_de_rollback_base_path(volume_uuid, user).c_str(),
217           snapshot_id);
218 }
219 
create_data_misc_ce_rollback_package_path(const char * volume_uuid,userid_t user,int32_t snapshot_id,const char * package_name)220 std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
221         userid_t user, int32_t snapshot_id, const char* package_name) {
222     return StringPrintf("%s/%s",
223            create_data_misc_ce_rollback_path(volume_uuid, user, snapshot_id).c_str(), package_name);
224 }
225 
create_data_misc_ce_rollback_package_path(const char * volume_uuid,userid_t user,int32_t snapshot_id,const char * package_name,ino_t ce_rollback_inode)226 std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
227         userid_t user, int32_t snapshot_id, const char* package_name, ino_t ce_rollback_inode) {
228     auto fallback = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshot_id,
229             package_name);
230     auto user_path = create_data_misc_ce_rollback_path(volume_uuid, user, snapshot_id);
231     return resolve_ce_path_by_inode_or_fallback(user_path, ce_rollback_inode, fallback);
232 }
233 
create_data_misc_de_rollback_package_path(const char * volume_uuid,userid_t user,int32_t snapshot_id,const char * package_name)234 std::string create_data_misc_de_rollback_package_path(const char* volume_uuid,
235         userid_t user, int32_t snapshot_id, const char* package_name) {
236     return StringPrintf("%s/%s",
237            create_data_misc_de_rollback_path(volume_uuid, user, snapshot_id).c_str(), package_name);
238 }
239 
240 /**
241  * Create the path name for media for a certain userid.
242  */
create_data_media_path(const char * volume_uuid,userid_t userid)243 std::string create_data_media_path(const char* volume_uuid, userid_t userid) {
244     return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
245 }
246 
create_data_media_package_path(const char * volume_uuid,userid_t userid,const char * data_type,const char * package_name)247 std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
248         const char* data_type, const char* package_name) {
249     return StringPrintf("%s/Android/%s/%s", create_data_media_path(volume_uuid, userid).c_str(),
250             data_type, package_name);
251 }
252 
create_data_misc_legacy_path(userid_t userid)253 std::string create_data_misc_legacy_path(userid_t userid) {
254     return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
255 }
256 
create_primary_cur_profile_dir_path(userid_t userid)257 std::string create_primary_cur_profile_dir_path(userid_t userid) {
258     return StringPrintf("%s/cur/%u", android_profiles_dir.c_str(), userid);
259 }
260 
create_primary_current_profile_package_dir_path(userid_t user,const std::string & package_name)261 std::string create_primary_current_profile_package_dir_path(userid_t user,
262         const std::string& package_name) {
263     check_package_name(package_name.c_str());
264     return StringPrintf("%s/%s",
265             create_primary_cur_profile_dir_path(user).c_str(), package_name.c_str());
266 }
267 
create_primary_ref_profile_dir_path()268 std::string create_primary_ref_profile_dir_path() {
269     return StringPrintf("%s/ref", android_profiles_dir.c_str());
270 }
271 
create_primary_reference_profile_package_dir_path(const std::string & package_name)272 std::string create_primary_reference_profile_package_dir_path(const std::string& package_name) {
273     check_package_name(package_name.c_str());
274     return StringPrintf("%s/ref/%s", android_profiles_dir.c_str(), package_name.c_str());
275 }
276 
create_data_dalvik_cache_path()277 std::string create_data_dalvik_cache_path() {
278     return "/data/dalvik-cache";
279 }
280 
281 // Keep profile paths in sync with ActivityThread and LoadedApk.
282 const std::string PROFILE_EXT = ".prof";
283 const std::string CURRENT_PROFILE_EXT = ".cur";
284 const std::string SNAPSHOT_PROFILE_EXT = ".snapshot";
285 
286 // Gets the parent directory and the file name for the given secondary dex path.
287 // Returns true on success, false on failure (if the dex_path does not have the expected
288 // structure).
get_secondary_dex_location(const std::string & dex_path,std::string * out_dir_name,std::string * out_file_name)289 static bool get_secondary_dex_location(const std::string& dex_path,
290         std::string* out_dir_name, std::string* out_file_name) {
291    size_t dirIndex = dex_path.rfind('/');
292    if (dirIndex == std::string::npos) {
293         return false;
294    }
295    if (dirIndex == dex_path.size() - 1) {
296         return false;
297    }
298    *out_dir_name = dex_path.substr(0, dirIndex);
299    *out_file_name = dex_path.substr(dirIndex + 1);
300 
301    return true;
302 }
303 
create_current_profile_path(userid_t user,const std::string & package_name,const std::string & location,bool is_secondary_dex)304 std::string create_current_profile_path(userid_t user, const std::string& package_name,
305         const std::string& location, bool is_secondary_dex) {
306     if (is_secondary_dex) {
307         // Secondary dex current profiles are stored next to the dex files under the oat folder.
308         std::string dex_dir;
309         std::string dex_name;
310         CHECK(get_secondary_dex_location(location, &dex_dir, &dex_name))
311                 << "Unexpected dir structure for secondary dex " << location;
312         return StringPrintf("%s/oat/%s%s%s",
313                 dex_dir.c_str(), dex_name.c_str(), CURRENT_PROFILE_EXT.c_str(),
314                 PROFILE_EXT.c_str());
315     } else {
316         // Profiles for primary apks are under /data/misc/profiles/cur.
317         std::string profile_dir = create_primary_current_profile_package_dir_path(
318                 user, package_name);
319         return StringPrintf("%s/%s", profile_dir.c_str(), location.c_str());
320     }
321 }
322 
create_reference_profile_path(const std::string & package_name,const std::string & location,bool is_secondary_dex)323 std::string create_reference_profile_path(const std::string& package_name,
324         const std::string& location, bool is_secondary_dex) {
325     if (is_secondary_dex) {
326         // Secondary dex reference profiles are stored next to the dex files under the oat folder.
327         std::string dex_dir;
328         std::string dex_name;
329         CHECK(get_secondary_dex_location(location, &dex_dir, &dex_name))
330                 << "Unexpected dir structure for secondary dex " << location;
331         return StringPrintf("%s/oat/%s%s",
332                 dex_dir.c_str(), dex_name.c_str(), PROFILE_EXT.c_str());
333     } else {
334         // Reference profiles for primary apks are stored in /data/misc/profile/ref.
335         std::string profile_dir = create_primary_reference_profile_package_dir_path(package_name);
336         return StringPrintf("%s/%s", profile_dir.c_str(), location.c_str());
337     }
338 }
339 
create_snapshot_profile_path(const std::string & package,const std::string & profile_name)340 std::string create_snapshot_profile_path(const std::string& package,
341         const std::string& profile_name) {
342     std::string ref_profile = create_reference_profile_path(package, profile_name,
343             /*is_secondary_dex*/ false);
344     return ref_profile + SNAPSHOT_PROFILE_EXT;
345 }
346 
get_known_users(const char * volume_uuid)347 std::vector<userid_t> get_known_users(const char* volume_uuid) {
348     std::vector<userid_t> users;
349 
350     // We always have an owner
351     users.push_back(0);
352 
353     std::string path(create_data_path(volume_uuid) + "/" + SECONDARY_USER_PREFIX);
354     DIR* dir = opendir(path.c_str());
355     if (dir == nullptr) {
356         // Unable to discover other users, but at least return owner
357         PLOG(ERROR) << "Failed to opendir " << path;
358         return users;
359     }
360 
361     struct dirent* ent;
362     while ((ent = readdir(dir))) {
363         if (ent->d_type != DT_DIR) {
364             continue;
365         }
366 
367         char* end;
368         userid_t user = strtol(ent->d_name, &end, 10);
369         if (*end == '\0' && user != 0) {
370             LOG(DEBUG) << "Found valid user " << user;
371             users.push_back(user);
372         }
373     }
374     closedir(dir);
375 
376     return users;
377 }
378 
calculate_tree_size(const std::string & path,int64_t * size,int32_t include_gid,int32_t exclude_gid,bool exclude_apps)379 int calculate_tree_size(const std::string& path, int64_t* size,
380         int32_t include_gid, int32_t exclude_gid, bool exclude_apps) {
381     FTS *fts;
382     FTSENT *p;
383     int64_t matchedSize = 0;
384     char *argv[] = { (char*) path.c_str(), nullptr };
385     if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
386         if (errno != ENOENT) {
387             PLOG(ERROR) << "Failed to fts_open " << path;
388         }
389         return -1;
390     }
391     while ((p = fts_read(fts)) != nullptr) {
392         switch (p->fts_info) {
393         case FTS_D:
394         case FTS_DEFAULT:
395         case FTS_F:
396         case FTS_SL:
397         case FTS_SLNONE:
398             int32_t uid = p->fts_statp->st_uid;
399             int32_t gid = p->fts_statp->st_gid;
400             int32_t user_uid = multiuser_get_app_id(uid);
401             int32_t user_gid = multiuser_get_app_id(gid);
402             if (exclude_apps && ((user_uid >= AID_APP_START && user_uid <= AID_APP_END)
403                     || (user_gid >= AID_CACHE_GID_START && user_gid <= AID_CACHE_GID_END)
404                     || (user_gid >= AID_SHARED_GID_START && user_gid <= AID_SHARED_GID_END))) {
405                 // Don't traverse inside or measure
406                 fts_set(fts, p, FTS_SKIP);
407                 break;
408             }
409             if (include_gid != -1 && gid != include_gid) {
410                 break;
411             }
412             if (exclude_gid != -1 && gid == exclude_gid) {
413                 break;
414             }
415             matchedSize += (p->fts_statp->st_blocks * 512);
416             break;
417         }
418     }
419     fts_close(fts);
420 #if MEASURE_DEBUG
421     if ((include_gid == -1) && (exclude_gid == -1)) {
422         LOG(DEBUG) << "Measured " << path << " size " << matchedSize;
423     } else {
424         LOG(DEBUG) << "Measured " << path << " size " << matchedSize << "; include " << include_gid
425                 << " exclude " << exclude_gid;
426     }
427 #endif
428     *size += matchedSize;
429     return 0;
430 }
431 
432 /**
433  * Checks whether the package name is valid. Returns -1 on error and
434  * 0 on success.
435  */
is_valid_package_name(const std::string & packageName)436 bool is_valid_package_name(const std::string& packageName) {
437     // This logic is borrowed from PackageParser.java
438     bool hasSep = false;
439     bool front = true;
440 
441     auto it = packageName.begin();
442     for (; it != packageName.end() && *it != '-'; it++) {
443         char c = *it;
444         if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
445             front = false;
446             continue;
447         }
448         if (!front) {
449             if ((c >= '0' && c <= '9') || c == '_') {
450                 continue;
451             }
452         }
453         if (c == '.') {
454             hasSep = true;
455             front = true;
456             continue;
457         }
458         LOG(WARNING) << "Bad package character " << c << " in " << packageName;
459         return false;
460     }
461 
462     if (front) {
463         LOG(WARNING) << "Missing separator in " << packageName;
464         return false;
465     }
466 
467     for (; it != packageName.end(); it++) {
468         char c = *it;
469         if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) continue;
470         if ((c >= '0' && c <= '9') || c == '_' || c == '-' || c == '=') continue;
471         LOG(WARNING) << "Bad suffix character " << c << " in " << packageName;
472         return false;
473     }
474 
475     return true;
476 }
477 
_delete_dir_contents(DIR * d,int (* exclusion_predicate)(const char * name,const int is_dir))478 static int _delete_dir_contents(DIR *d,
479                                 int (*exclusion_predicate)(const char *name, const int is_dir))
480 {
481     int result = 0;
482     struct dirent *de;
483     int dfd;
484 
485     dfd = dirfd(d);
486 
487     if (dfd < 0) return -1;
488 
489     while ((de = readdir(d))) {
490         const char *name = de->d_name;
491 
492             /* check using the exclusion predicate, if provided */
493         if (exclusion_predicate && exclusion_predicate(name, (de->d_type == DT_DIR))) {
494             continue;
495         }
496 
497         if (de->d_type == DT_DIR) {
498             int subfd;
499             DIR *subdir;
500 
501                 /* always skip "." and ".." */
502             if (name[0] == '.') {
503                 if (name[1] == 0) continue;
504                 if ((name[1] == '.') && (name[2] == 0)) continue;
505             }
506 
507             subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
508             if (subfd < 0) {
509                 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
510                 result = -1;
511                 continue;
512             }
513             subdir = fdopendir(subfd);
514             if (subdir == nullptr) {
515                 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
516                 close(subfd);
517                 result = -1;
518                 continue;
519             }
520             if (_delete_dir_contents(subdir, exclusion_predicate)) {
521                 result = -1;
522             }
523             closedir(subdir);
524             if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
525                 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
526                 result = -1;
527             }
528         } else {
529             if (unlinkat(dfd, name, 0) < 0) {
530                 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
531                 result = -1;
532             }
533         }
534     }
535 
536     return result;
537 }
538 
create_dir_if_needed(const std::string & pathname,mode_t perms)539 int create_dir_if_needed(const std::string& pathname, mode_t perms) {
540     struct stat st;
541 
542     int rc;
543     if ((rc = stat(pathname.c_str(), &st)) != 0) {
544         if (errno == ENOENT) {
545             return mkdir(pathname.c_str(), perms);
546         } else {
547             return rc;
548         }
549     } else if (!S_ISDIR(st.st_mode)) {
550         LOG(DEBUG) << pathname << " is not a folder";
551         return -1;
552     }
553 
554     mode_t actual_perms = st.st_mode & ALLPERMS;
555     if (actual_perms != perms) {
556         LOG(WARNING) << pathname << " permissions " << actual_perms << " expected " << perms;
557         return -1;
558     }
559 
560     return 0;
561 }
562 
delete_dir_contents(const std::string & pathname,bool ignore_if_missing)563 int delete_dir_contents(const std::string& pathname, bool ignore_if_missing) {
564     return delete_dir_contents(pathname.c_str(), 0, nullptr, ignore_if_missing);
565 }
566 
delete_dir_contents_and_dir(const std::string & pathname,bool ignore_if_missing)567 int delete_dir_contents_and_dir(const std::string& pathname, bool ignore_if_missing) {
568     return delete_dir_contents(pathname.c_str(), 1, nullptr, ignore_if_missing);
569 }
570 
delete_dir_contents(const char * pathname,int also_delete_dir,int (* exclusion_predicate)(const char *,const int),bool ignore_if_missing)571 int delete_dir_contents(const char *pathname,
572                         int also_delete_dir,
573                         int (*exclusion_predicate)(const char*, const int),
574                         bool ignore_if_missing)
575 {
576     int res = 0;
577     DIR *d;
578 
579     d = opendir(pathname);
580     if (d == nullptr) {
581         if (ignore_if_missing && (errno == ENOENT)) {
582             return 0;
583         }
584         ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno));
585         return -errno;
586     }
587     res = _delete_dir_contents(d, exclusion_predicate);
588     closedir(d);
589     if (also_delete_dir) {
590         if (rmdir(pathname)) {
591             ALOGE("Couldn't rmdir %s: %s\n", pathname, strerror(errno));
592             res = -1;
593         }
594     }
595     return res;
596 }
597 
delete_dir_contents_fd(int dfd,const char * name)598 int delete_dir_contents_fd(int dfd, const char *name)
599 {
600     int fd, res;
601     DIR *d;
602 
603     fd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
604     if (fd < 0) {
605         ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
606         return -1;
607     }
608     d = fdopendir(fd);
609     if (d == nullptr) {
610         ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
611         close(fd);
612         return -1;
613     }
614     res = _delete_dir_contents(d, nullptr);
615     closedir(d);
616     return res;
617 }
618 
_copy_owner_permissions(int srcfd,int dstfd)619 static int _copy_owner_permissions(int srcfd, int dstfd)
620 {
621     struct stat st;
622     if (fstat(srcfd, &st) != 0) {
623         return -1;
624     }
625     if (fchmod(dstfd, st.st_mode) != 0) {
626         return -1;
627     }
628     return 0;
629 }
630 
_copy_dir_files(int sdfd,int ddfd,uid_t owner,gid_t group)631 static int _copy_dir_files(int sdfd, int ddfd, uid_t owner, gid_t group)
632 {
633     int result = 0;
634     if (_copy_owner_permissions(sdfd, ddfd) != 0) {
635         ALOGE("_copy_dir_files failed to copy dir permissions\n");
636     }
637     if (fchown(ddfd, owner, group) != 0) {
638         ALOGE("_copy_dir_files failed to change dir owner\n");
639     }
640 
641     DIR *ds = fdopendir(sdfd);
642     if (ds == nullptr) {
643         ALOGE("Couldn't fdopendir: %s\n", strerror(errno));
644         return -1;
645     }
646     struct dirent *de;
647     while ((de = readdir(ds))) {
648         if (de->d_type != DT_REG) {
649             continue;
650         }
651 
652         const char *name = de->d_name;
653         int fsfd = openat(sdfd, name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
654         int fdfd = openat(ddfd, name, O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_CREAT, 0600);
655         if (fsfd == -1 || fdfd == -1) {
656             ALOGW("Couldn't copy %s: %s\n", name, strerror(errno));
657         } else {
658             if (_copy_owner_permissions(fsfd, fdfd) != 0) {
659                 ALOGE("Failed to change file permissions\n");
660             }
661             if (fchown(fdfd, owner, group) != 0) {
662                 ALOGE("Failed to change file owner\n");
663             }
664 
665             char buf[8192];
666             ssize_t size;
667             while ((size = read(fsfd, buf, sizeof(buf))) > 0) {
668                 write(fdfd, buf, size);
669             }
670             if (size < 0) {
671                 ALOGW("Couldn't copy %s: %s\n", name, strerror(errno));
672                 result = -1;
673             }
674         }
675         close(fdfd);
676         close(fsfd);
677     }
678 
679     return result;
680 }
681 
copy_dir_files(const char * srcname,const char * dstname,uid_t owner,uid_t group)682 int copy_dir_files(const char *srcname,
683                    const char *dstname,
684                    uid_t owner,
685                    uid_t group)
686 {
687     int res = 0;
688     DIR *ds = nullptr;
689     DIR *dd = nullptr;
690 
691     ds = opendir(srcname);
692     if (ds == nullptr) {
693         ALOGE("Couldn't opendir %s: %s\n", srcname, strerror(errno));
694         return -errno;
695     }
696 
697     mkdir(dstname, 0600);
698     dd = opendir(dstname);
699     if (dd == nullptr) {
700         ALOGE("Couldn't opendir %s: %s\n", dstname, strerror(errno));
701         closedir(ds);
702         return -errno;
703     }
704 
705     int sdfd = dirfd(ds);
706     int ddfd = dirfd(dd);
707     if (sdfd != -1 && ddfd != -1) {
708         res = _copy_dir_files(sdfd, ddfd, owner, group);
709     } else {
710         res = -errno;
711     }
712     closedir(dd);
713     closedir(ds);
714     return res;
715 }
716 
data_disk_free(const std::string & data_path)717 int64_t data_disk_free(const std::string& data_path) {
718     struct statvfs sfs;
719     if (statvfs(data_path.c_str(), &sfs) == 0) {
720         return static_cast<int64_t>(sfs.f_bavail) * sfs.f_frsize;
721     } else {
722         PLOG(ERROR) << "Couldn't statvfs " << data_path;
723         return -1;
724     }
725 }
726 
get_path_inode(const std::string & path,ino_t * inode)727 int get_path_inode(const std::string& path, ino_t *inode) {
728     struct stat buf;
729     memset(&buf, 0, sizeof(buf));
730     if (stat(path.c_str(), &buf) != 0) {
731         PLOG(WARNING) << "Failed to stat " << path;
732         return -1;
733     } else {
734         *inode = buf.st_ino;
735         return 0;
736     }
737 }
738 
739 /**
740  * Write the inode of a specific child file into the given xattr on the
741  * parent directory. This allows you to find the child later, even if its
742  * name is encrypted.
743  */
write_path_inode(const std::string & parent,const char * name,const char * inode_xattr)744 int write_path_inode(const std::string& parent, const char* name, const char* inode_xattr) {
745     ino_t inode = 0;
746     uint64_t inode_raw = 0;
747     auto path = StringPrintf("%s/%s", parent.c_str(), name);
748 
749     if (get_path_inode(path, &inode) != 0) {
750         // Path probably doesn't exist yet; ignore
751         return 0;
752     }
753 
754     // Check to see if already set correctly
755     if (getxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw)) == sizeof(inode_raw)) {
756         if (inode_raw == inode) {
757             // Already set correctly; skip writing
758             return 0;
759         } else {
760             PLOG(WARNING) << "Mismatched inode value; found " << inode
761                     << " on disk but marked value was " << inode_raw << "; overwriting";
762         }
763     }
764 
765     inode_raw = inode;
766     if (setxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw), 0) != 0 && errno != EOPNOTSUPP) {
767         PLOG(ERROR) << "Failed to write xattr " << inode_xattr << " at " << parent;
768         return -1;
769     } else {
770         return 0;
771     }
772 }
773 
774 /**
775  * Read the inode of a specific child file from the given xattr on the
776  * parent directory. Returns a currently valid path for that child, which
777  * might have an encrypted name.
778  */
read_path_inode(const std::string & parent,const char * name,const char * inode_xattr)779 std::string read_path_inode(const std::string& parent, const char* name, const char* inode_xattr) {
780     ino_t inode = 0;
781     uint64_t inode_raw = 0;
782     auto fallback = StringPrintf("%s/%s", parent.c_str(), name);
783 
784     // Lookup the inode value written earlier
785     if (getxattr(parent.c_str(), inode_xattr, &inode_raw, sizeof(inode_raw)) == sizeof(inode_raw)) {
786         inode = inode_raw;
787     }
788 
789     // For testing purposes, rely on the inode when defined; this could be
790     // optimized to use access() in the future.
791     if (inode != 0) {
792         DIR* dir = opendir(parent.c_str());
793         if (dir == nullptr) {
794             PLOG(ERROR) << "Failed to opendir " << parent;
795             return fallback;
796         }
797 
798         struct dirent* ent;
799         while ((ent = readdir(dir))) {
800             if (ent->d_ino == inode) {
801                 auto resolved = StringPrintf("%s/%s", parent.c_str(), ent->d_name);
802 #if DEBUG_XATTRS
803                 if (resolved != fallback) {
804                     LOG(DEBUG) << "Resolved path " << resolved << " for inode " << inode
805                             << " instead of " << fallback;
806                 }
807 #endif
808                 closedir(dir);
809                 return resolved;
810             }
811         }
812         LOG(WARNING) << "Failed to resolve inode " << inode << "; using " << fallback;
813         closedir(dir);
814         return fallback;
815     } else {
816         return fallback;
817     }
818 }
819 
remove_path_xattr(const std::string & path,const char * inode_xattr)820 void remove_path_xattr(const std::string& path, const char* inode_xattr) {
821     if (removexattr(path.c_str(), inode_xattr) && errno != ENODATA) {
822         PLOG(ERROR) << "Failed to remove xattr " << inode_xattr << " at " << path;
823     }
824 }
825 
826 /**
827  * Validate that the path is valid in the context of the provided directory.
828  * The path is allowed to have at most one subdirectory and no indirections
829  * to top level directories (i.e. have "..").
830  */
validate_path(const std::string & dir,const std::string & path,int maxSubdirs)831 static int validate_path(const std::string& dir, const std::string& path, int maxSubdirs) {
832     // Argument sanity checking
833     if (dir.find('/') != 0 || dir.rfind('/') != dir.size() - 1
834             || dir.find("..") != std::string::npos) {
835         LOG(ERROR) << "Invalid directory " << dir;
836         return -1;
837     }
838     if (path.find("..") != std::string::npos) {
839         LOG(ERROR) << "Invalid path " << path;
840         return -1;
841     }
842 
843     if (path.compare(0, dir.size(), dir) != 0) {
844         // Common case, path isn't under directory
845         return -1;
846     }
847 
848     // Count number of subdirectories
849     auto pos = path.find('/', dir.size());
850     int count = 0;
851     while (pos != std::string::npos) {
852         auto next = path.find('/', pos + 1);
853         if (next > pos + 1) {
854             count++;
855         }
856         pos = next;
857     }
858 
859     if (count > maxSubdirs) {
860         LOG(ERROR) << "Invalid path depth " << path << " when tested against " << dir;
861         return -1;
862     }
863 
864     return 0;
865 }
866 
867 /**
868  * Checks whether a path points to a system app (.apk file). Returns 0
869  * if it is a system app or -1 if it is not.
870  */
validate_system_app_path(const char * path)871 int validate_system_app_path(const char* path) {
872     std::string path_ = path;
873     for (const auto& dir : android_system_dirs) {
874         if (validate_path(dir, path, 1) == 0) {
875             return 0;
876         }
877     }
878     return -1;
879 }
880 
validate_secondary_dex_path(const std::string & pkgname,const std::string & dex_path,const char * volume_uuid,int uid,int storage_flag)881 bool validate_secondary_dex_path(const std::string& pkgname, const std::string& dex_path,
882         const char* volume_uuid, int uid, int storage_flag) {
883     CHECK(storage_flag == FLAG_STORAGE_CE || storage_flag == FLAG_STORAGE_DE);
884 
885     // Empty paths are not allowed.
886     if (dex_path.empty()) { return false; }
887     // First character should always be '/'. No relative paths.
888     if (dex_path[0] != '/') { return false; }
889     // The last character should not be '/'.
890     if (dex_path[dex_path.size() - 1] == '/') { return false; }
891     // There should be no '.' after the directory marker.
892     if (dex_path.find("/.") != std::string::npos) { return false; }
893     // The path should be at most PKG_PATH_MAX long.
894     if (dex_path.size() > PKG_PATH_MAX) { return false; }
895 
896     // The dex_path should be under the app data directory.
897     std::string app_private_dir = storage_flag == FLAG_STORAGE_CE
898             ? create_data_user_ce_package_path(
899                     volume_uuid, multiuser_get_user_id(uid), pkgname.c_str())
900             : create_data_user_de_package_path(
901                     volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
902 
903     if (strncmp(dex_path.c_str(), app_private_dir.c_str(), app_private_dir.size()) != 0) {
904         // The check above might fail if the dex file is accessed via the /data/user/0 symlink.
905         // If that's the case, attempt to validate against the user data link.
906         std::string app_private_dir_symlink = create_data_user_ce_package_path_as_user_link(
907                 volume_uuid, multiuser_get_user_id(uid), pkgname.c_str());
908         if (strncmp(dex_path.c_str(), app_private_dir_symlink.c_str(),
909                 app_private_dir_symlink.size()) != 0) {
910             return false;
911         }
912     }
913 
914     // If we got here we have a valid path.
915     return true;
916 }
917 
918 /**
919  * Check whether path points to a valid path for an APK file. The path must
920  * begin with a whitelisted prefix path and must be no deeper than |maxSubdirs| within
921  * that path. Returns -1 when an invalid path is encountered and 0 when a valid path
922  * is encountered.
923  */
validate_apk_path_internal(const std::string & path,int maxSubdirs)924 static int validate_apk_path_internal(const std::string& path, int maxSubdirs) {
925     if (validate_path(android_app_dir, path, maxSubdirs) == 0) {
926         return 0;
927     } else if (validate_path(android_staging_dir, path, maxSubdirs) == 0) {
928         return 0;
929     } else if (validate_path(android_app_private_dir, path, maxSubdirs) == 0) {
930         return 0;
931     } else if (validate_path(android_app_ephemeral_dir, path, maxSubdirs) == 0) {
932         return 0;
933     } else if (validate_path(android_asec_dir, path, maxSubdirs) == 0) {
934         return 0;
935     } else if (android::base::StartsWith(path, android_mnt_expand_dir)) {
936         // Rewrite the path as if it were on internal storage, and test that
937         size_t end = path.find('/', android_mnt_expand_dir.size() + 1);
938         if (end != std::string::npos) {
939             auto modified = path;
940             modified.replace(0, end + 1, android_data_dir);
941             return validate_apk_path_internal(modified, maxSubdirs);
942         }
943     }
944     return -1;
945 }
946 
validate_apk_path(const char * path)947 int validate_apk_path(const char* path) {
948     return validate_apk_path_internal(path, 1 /* maxSubdirs */);
949 }
950 
validate_apk_path_subdirs(const char * path)951 int validate_apk_path_subdirs(const char* path) {
952     return validate_apk_path_internal(path, 3 /* maxSubdirs */);
953 }
954 
ensure_config_user_dirs(userid_t userid)955 int ensure_config_user_dirs(userid_t userid) {
956     // writable by system, readable by any app within the same user
957     const int uid = multiuser_get_uid(userid, AID_SYSTEM);
958     const int gid = multiuser_get_uid(userid, AID_EVERYBODY);
959 
960     // Ensure /data/misc/user/<userid> exists
961     auto path = create_data_misc_legacy_path(userid);
962     return fs_prepare_dir(path.c_str(), 0750, uid, gid);
963 }
964 
wait_child(pid_t pid)965 int wait_child(pid_t pid)
966 {
967     int status;
968     pid_t got_pid;
969 
970     while (1) {
971         got_pid = waitpid(pid, &status, 0);
972         if (got_pid == -1 && errno == EINTR) {
973             printf("waitpid interrupted, retrying\n");
974         } else {
975             break;
976         }
977     }
978     if (got_pid != pid) {
979         ALOGW("waitpid failed: wanted %d, got %d: %s\n",
980             (int) pid, (int) got_pid, strerror(errno));
981         return 1;
982     }
983 
984     if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
985         return 0;
986     } else {
987         return status;      /* always nonzero */
988     }
989 }
990 
991 /**
992  * Prepare an app cache directory, which offers to fix-up the GID and
993  * directory mode flags during a platform upgrade.
994  * The app cache directory path will be 'parent'/'name'.
995  */
prepare_app_cache_dir(const std::string & parent,const char * name,mode_t target_mode,uid_t uid,gid_t gid)996 int prepare_app_cache_dir(const std::string& parent, const char* name, mode_t target_mode,
997         uid_t uid, gid_t gid) {
998     auto path = StringPrintf("%s/%s", parent.c_str(), name);
999     struct stat st;
1000     if (stat(path.c_str(), &st) != 0) {
1001         if (errno == ENOENT) {
1002             // This is fine, just create it
1003             if (fs_prepare_dir_strict(path.c_str(), target_mode, uid, gid) != 0) {
1004                 PLOG(ERROR) << "Failed to prepare " << path;
1005                 return -1;
1006             } else {
1007                 return 0;
1008             }
1009         } else {
1010             PLOG(ERROR) << "Failed to stat " << path;
1011             return -1;
1012         }
1013     }
1014 
1015     mode_t actual_mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO | S_ISGID);
1016     if (st.st_uid != uid) {
1017         // Mismatched UID is real trouble; we can't recover
1018         LOG(ERROR) << "Mismatched UID at " << path << ": found " << st.st_uid
1019                 << " but expected " << uid;
1020         return -1;
1021     } else if (st.st_gid == gid && actual_mode == target_mode) {
1022         // Everything looks good!
1023         return 0;
1024     } else {
1025         // Mismatched GID/mode is recoverable; fall through to update
1026         LOG(DEBUG) << "Mismatched cache GID/mode at " << path << ": found " << st.st_gid
1027                 << "/" << actual_mode << " but expected " << gid << "/" << target_mode;
1028     }
1029 
1030     // Directory is owned correctly, but GID or mode mismatch means it's
1031     // probably a platform upgrade so we need to fix them
1032     FTS *fts;
1033     FTSENT *p;
1034     char *argv[] = { (char*) path.c_str(), nullptr };
1035     if (!(fts = fts_open(argv, FTS_PHYSICAL | FTS_NOCHDIR | FTS_XDEV, nullptr))) {
1036         PLOG(ERROR) << "Failed to fts_open " << path;
1037         return -1;
1038     }
1039     while ((p = fts_read(fts)) != nullptr) {
1040         switch (p->fts_info) {
1041         case FTS_DP:
1042             if (chmod(p->fts_path, target_mode) != 0) {
1043                 PLOG(WARNING) << "Failed to chmod " << p->fts_path;
1044             }
1045             [[fallthrough]]; // to also set GID
1046         case FTS_F:
1047             if (chown(p->fts_path, -1, gid) != 0) {
1048                 PLOG(WARNING) << "Failed to chown " << p->fts_path;
1049             }
1050             break;
1051         case FTS_SL:
1052         case FTS_SLNONE:
1053             if (lchown(p->fts_path, -1, gid) != 0) {
1054                 PLOG(WARNING) << "Failed to chown " << p->fts_path;
1055             }
1056             break;
1057         }
1058     }
1059     fts_close(fts);
1060     return 0;
1061 }
1062 
1063 // Collect all non empty profiles from the given directory and puts then into profile_paths.
1064 // The profiles are identified based on PROFILE_EXT extension.
1065 // If a subdirectory or profile file cannot be opened the method logs a warning and moves on.
1066 // It returns true if there were no errors at all, and false otherwise.
collect_profiles(DIR * d,const std::string & current_path,std::vector<std::string> * profiles_paths)1067 static bool collect_profiles(DIR* d,
1068                              const std::string& current_path,
1069                              std::vector<std::string>* profiles_paths) {
1070     int32_t dir_fd = dirfd(d);
1071     if (dir_fd < 0) {
1072         return false;
1073     }
1074 
1075     bool result = true;
1076     struct dirent* dir_entry;
1077     while ((dir_entry = readdir(d))) {
1078         std::string name = dir_entry->d_name;
1079         std::string local_path = current_path + "/" + name;
1080 
1081         if (dir_entry->d_type == DT_REG) {
1082             // Check if this is a non empty profile file.
1083             if (EndsWith(name, PROFILE_EXT)) {
1084                 struct stat st;
1085                 if (stat(local_path.c_str(), &st) != 0) {
1086                     PLOG(WARNING) << "Cannot stat local path " << local_path;
1087                     result = false;
1088                     continue;
1089                 } else if (st.st_size > 0) {
1090                     profiles_paths->push_back(local_path);
1091                 }
1092             }
1093         } else if (dir_entry->d_type == DT_DIR) {
1094             // always skip "." and ".."
1095             if (name == "." || name == "..") {
1096                 continue;
1097             }
1098 
1099             unique_fd subdir_fd(openat(dir_fd, name.c_str(),
1100                     O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC));
1101             if (subdir_fd < 0) {
1102                 PLOG(WARNING) << "Could not open dir path " << local_path;
1103                 result = false;
1104                 continue;
1105             }
1106 
1107             DIR* subdir = Fdopendir(std::move(subdir_fd));
1108             if (subdir == nullptr) {
1109                 PLOG(WARNING) << "Could not open dir path " << local_path;
1110                 result = false;
1111                 continue;
1112             }
1113             bool new_result = collect_profiles(subdir, local_path, profiles_paths);
1114             result = result && new_result;
1115             if (closedir(subdir) != 0) {
1116                 PLOG(WARNING) << "Could not close dir path " << local_path;
1117             }
1118         }
1119     }
1120 
1121     return result;
1122 }
1123 
collect_profiles(std::vector<std::string> * profiles_paths)1124 bool collect_profiles(std::vector<std::string>* profiles_paths) {
1125     DIR* d = opendir(android_profiles_dir.c_str());
1126     if (d == nullptr) {
1127         return false;
1128     } else {
1129         return collect_profiles(d, android_profiles_dir, profiles_paths);
1130     }
1131 }
1132 
drop_capabilities(uid_t uid)1133 void drop_capabilities(uid_t uid) {
1134     if (setgid(uid) != 0) {
1135         PLOG(ERROR) << "setgid(" << uid << ") failed in installd during dexopt";
1136         exit(DexoptReturnCodes::kSetGid);
1137     }
1138     if (setuid(uid) != 0) {
1139         PLOG(ERROR) << "setuid(" << uid << ") failed in installd during dexopt";
1140         exit(DexoptReturnCodes::kSetUid);
1141     }
1142     // drop capabilities
1143     struct __user_cap_header_struct capheader;
1144     struct __user_cap_data_struct capdata[2];
1145     memset(&capheader, 0, sizeof(capheader));
1146     memset(&capdata, 0, sizeof(capdata));
1147     capheader.version = _LINUX_CAPABILITY_VERSION_3;
1148     if (capset(&capheader, &capdata[0]) < 0) {
1149         PLOG(ERROR) << "capset failed";
1150         exit(DexoptReturnCodes::kCapSet);
1151     }
1152 }
1153 
1154 }  // namespace installd
1155 }  // namespace android
1156