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