• 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/file.h>
30 #include <android-base/logging.h>
31 #include <android-base/strings.h>
32 #include <android-base/stringprintf.h>
33 #include <android-base/unique_fd.h>
34 #include <cutils/fs.h>
35 #include <cutils/properties.h>
36 #include <log/log.h>
37 #include <private/android_filesystem_config.h>
38 #include <private/android_projectid_config.h>
39 
40 #include "dexopt_return_codes.h"
41 #include "globals.h"  // extern variables.
42 #include "QuotaUtils.h"
43 
44 #ifndef LOG_TAG
45 #define LOG_TAG "installd"
46 #endif
47 
48 #define DEBUG_XATTRS 0
49 
50 using android::base::EndsWith;
51 using android::base::Fdopendir;
52 using android::base::StringPrintf;
53 using android::base::unique_fd;
54 
55 namespace android {
56 namespace installd {
57 
58 /**
59  * Check that given string is valid filename, and that it attempts no
60  * parent or child directory traversal.
61  */
is_valid_filename(const std::string & name)62 bool is_valid_filename(const std::string& name) {
63     if (name.empty() || (name == ".") || (name == "..")
64             || (name.find('/') != std::string::npos)) {
65         return false;
66     } else {
67         return true;
68     }
69 }
70 
check_package_name(const char * package_name)71 static void check_package_name(const char* package_name) {
72     CHECK(is_valid_filename(package_name));
73     CHECK(is_valid_package_name(package_name));
74 }
75 
resolve_ce_path_by_inode_or_fallback(const std::string & root_path,ino_t ce_data_inode,const std::string & fallback)76 static std::string resolve_ce_path_by_inode_or_fallback(const std::string& root_path,
77         ino_t ce_data_inode, const std::string& fallback) {
78     if (ce_data_inode != 0) {
79         DIR* dir = opendir(root_path.c_str());
80         if (dir == nullptr) {
81             PLOG(ERROR) << "Failed to opendir " << root_path;
82             return fallback;
83         }
84 
85         struct dirent* ent;
86         while ((ent = readdir(dir))) {
87             if (ent->d_ino == ce_data_inode) {
88                 auto resolved = StringPrintf("%s/%s", root_path.c_str(), ent->d_name);
89                 if (resolved != fallback) {
90                     LOG(DEBUG) << "Resolved path " << resolved << " for inode " << ce_data_inode
91                             << " instead of " << fallback;
92                 }
93                 closedir(dir);
94                 return resolved;
95             }
96         }
97         LOG(WARNING) << "Failed to resolve inode " << ce_data_inode << "; using " << fallback;
98         closedir(dir);
99         return fallback;
100     } else {
101         return fallback;
102     }
103 }
104 
105 /**
106  * Create the path name where package data should be stored for the given
107  * volume UUID, package name, and user ID. An empty UUID is assumed to be
108  * internal storage.
109  */
create_data_user_ce_package_path(const char * volume_uuid,userid_t user,const char * package_name)110 std::string create_data_user_ce_package_path(const char* volume_uuid,
111         userid_t user, const char* package_name) {
112     check_package_name(package_name);
113     return StringPrintf("%s/%s",
114             create_data_user_ce_path(volume_uuid, user).c_str(), package_name);
115 }
116 
117 /**
118  * Create the path name where package data should be stored for the given
119  * volume UUID, package name, and user ID. An empty UUID is assumed to be
120  * internal storage.
121  * Compared to create_data_user_ce_package_path this method always return the
122  * ".../user/..." directory.
123  */
create_data_user_ce_package_path_as_user_link(const char * volume_uuid,userid_t userid,const char * package_name)124 std::string create_data_user_ce_package_path_as_user_link(
125         const char* volume_uuid, userid_t userid, const char* package_name) {
126     check_package_name(package_name);
127     std::string data(create_data_path(volume_uuid));
128     return StringPrintf("%s/user/%u/%s", data.c_str(), userid, package_name);
129 }
130 
create_data_user_ce_package_path(const char * volume_uuid,userid_t user,const char * package_name,ino_t ce_data_inode)131 std::string create_data_user_ce_package_path(const char* volume_uuid, userid_t user,
132         const char* package_name, ino_t ce_data_inode) {
133     // For testing purposes, rely on the inode when defined; this could be
134     // optimized to use access() in the future.
135     auto fallback = create_data_user_ce_package_path(volume_uuid, user, package_name);
136     auto user_path = create_data_user_ce_path(volume_uuid, user);
137     return resolve_ce_path_by_inode_or_fallback(user_path, ce_data_inode, fallback);
138 }
139 
create_data_user_de_package_path(const char * volume_uuid,userid_t user,const char * package_name)140 std::string create_data_user_de_package_path(const char* volume_uuid,
141         userid_t user, const char* package_name) {
142     check_package_name(package_name);
143     return StringPrintf("%s/%s",
144             create_data_user_de_path(volume_uuid, user).c_str(), package_name);
145 }
146 
create_data_path(const char * volume_uuid)147 std::string create_data_path(const char* volume_uuid) {
148     if (volume_uuid == nullptr) {
149         return "/data";
150     } else if (!strcmp(volume_uuid, "TEST")) {
151         CHECK(property_get_bool("ro.debuggable", false));
152         return "/data/local/tmp";
153     } else {
154         CHECK(is_valid_filename(volume_uuid));
155         return StringPrintf("/mnt/expand/%s", volume_uuid);
156     }
157 }
158 
159 /**
160  * Create the path name for app data.
161  */
create_data_app_path(const char * volume_uuid)162 std::string create_data_app_path(const char* volume_uuid) {
163     return StringPrintf("%s/app", create_data_path(volume_uuid).c_str());
164 }
165 
166 /**
167  * Create the path name for user data for a certain userid.
168  * Keep same implementation as vold to minimize path walking overhead
169  */
create_data_user_ce_path(const char * volume_uuid,userid_t userid)170 std::string create_data_user_ce_path(const char* volume_uuid, userid_t userid) {
171     std::string data(create_data_path(volume_uuid));
172     if (volume_uuid == nullptr && userid == 0) {
173         std::string legacy = StringPrintf("%s/data", data.c_str());
174         struct stat sb;
175         if (lstat(legacy.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
176             /* /data/data is dir, return /data/data for legacy system */
177             return legacy;
178         }
179     }
180     return StringPrintf("%s/user/%u", data.c_str(), userid);
181 }
182 
183 /**
184  * Create the path name for device encrypted user data for a certain userid.
185  */
create_data_user_de_path(const char * volume_uuid,userid_t userid)186 std::string create_data_user_de_path(const char* volume_uuid, userid_t userid) {
187     std::string data(create_data_path(volume_uuid));
188     return StringPrintf("%s/user_de/%u", data.c_str(), userid);
189 }
190 
create_data_misc_ce_rollback_base_path(const char * volume_uuid,userid_t user)191 std::string create_data_misc_ce_rollback_base_path(const char* volume_uuid, userid_t user) {
192     return StringPrintf("%s/misc_ce/%u/rollback", create_data_path(volume_uuid).c_str(), user);
193 }
194 
create_data_misc_de_rollback_base_path(const char * volume_uuid,userid_t user)195 std::string create_data_misc_de_rollback_base_path(const char* volume_uuid, userid_t user) {
196     return StringPrintf("%s/misc_de/%u/rollback", create_data_path(volume_uuid).c_str(), user);
197 }
198 
create_data_misc_ce_rollback_path(const char * volume_uuid,userid_t user,int32_t snapshot_id)199 std::string create_data_misc_ce_rollback_path(const char* volume_uuid, userid_t user,
200         int32_t snapshot_id) {
201     return StringPrintf("%s/%d", create_data_misc_ce_rollback_base_path(volume_uuid, user).c_str(),
202           snapshot_id);
203 }
204 
create_data_misc_de_rollback_path(const char * volume_uuid,userid_t user,int32_t snapshot_id)205 std::string create_data_misc_de_rollback_path(const char* volume_uuid, userid_t user,
206         int32_t snapshot_id) {
207     return StringPrintf("%s/%d", create_data_misc_de_rollback_base_path(volume_uuid, user).c_str(),
208           snapshot_id);
209 }
210 
create_data_misc_ce_rollback_package_path(const char * volume_uuid,userid_t user,int32_t snapshot_id,const char * package_name)211 std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
212         userid_t user, int32_t snapshot_id, const char* package_name) {
213     return StringPrintf("%s/%s",
214            create_data_misc_ce_rollback_path(volume_uuid, user, snapshot_id).c_str(), package_name);
215 }
216 
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)217 std::string create_data_misc_ce_rollback_package_path(const char* volume_uuid,
218         userid_t user, int32_t snapshot_id, const char* package_name, ino_t ce_rollback_inode) {
219     auto fallback = create_data_misc_ce_rollback_package_path(volume_uuid, user, snapshot_id,
220             package_name);
221     auto user_path = create_data_misc_ce_rollback_path(volume_uuid, user, snapshot_id);
222     return resolve_ce_path_by_inode_or_fallback(user_path, ce_rollback_inode, fallback);
223 }
224 
create_data_misc_de_rollback_package_path(const char * volume_uuid,userid_t user,int32_t snapshot_id,const char * package_name)225 std::string create_data_misc_de_rollback_package_path(const char* volume_uuid,
226         userid_t user, int32_t snapshot_id, const char* package_name) {
227     return StringPrintf("%s/%s",
228            create_data_misc_de_rollback_path(volume_uuid, user, snapshot_id).c_str(), package_name);
229 }
230 
231 /**
232  * Create the path name for media for a certain userid.
233  */
create_data_media_path(const char * volume_uuid,userid_t userid)234 std::string create_data_media_path(const char* volume_uuid, userid_t userid) {
235     return StringPrintf("%s/media/%u", create_data_path(volume_uuid).c_str(), userid);
236 }
237 
create_data_media_package_path(const char * volume_uuid,userid_t userid,const char * data_type,const char * package_name)238 std::string create_data_media_package_path(const char* volume_uuid, userid_t userid,
239         const char* data_type, const char* package_name) {
240     return StringPrintf("%s/Android/%s/%s", create_data_media_path(volume_uuid, userid).c_str(),
241             data_type, package_name);
242 }
243 
create_data_misc_legacy_path(userid_t userid)244 std::string create_data_misc_legacy_path(userid_t userid) {
245     return StringPrintf("%s/misc/user/%u", create_data_path(nullptr).c_str(), userid);
246 }
247 
create_primary_cur_profile_dir_path(userid_t userid)248 std::string create_primary_cur_profile_dir_path(userid_t userid) {
249     return StringPrintf("%s/cur/%u", android_profiles_dir.c_str(), userid);
250 }
251 
create_primary_current_profile_package_dir_path(userid_t user,const std::string & package_name)252 std::string create_primary_current_profile_package_dir_path(userid_t user,
253         const std::string& package_name) {
254     check_package_name(package_name.c_str());
255     return StringPrintf("%s/%s",
256             create_primary_cur_profile_dir_path(user).c_str(), package_name.c_str());
257 }
258 
create_primary_ref_profile_dir_path()259 std::string create_primary_ref_profile_dir_path() {
260     return StringPrintf("%s/ref", android_profiles_dir.c_str());
261 }
262 
create_primary_reference_profile_package_dir_path(const std::string & package_name)263 std::string create_primary_reference_profile_package_dir_path(const std::string& package_name) {
264     check_package_name(package_name.c_str());
265     return StringPrintf("%s/ref/%s", android_profiles_dir.c_str(), package_name.c_str());
266 }
267 
create_data_dalvik_cache_path()268 std::string create_data_dalvik_cache_path() {
269     return "/data/dalvik-cache";
270 }
271 
create_system_user_ce_path(userid_t userId)272 std::string create_system_user_ce_path(userid_t userId) {
273     return StringPrintf("%s/system_ce/%u", create_data_path(nullptr).c_str(), userId);
274 }
275 
create_system_user_ce_package_path(userid_t userId,const char * package_name)276 std::string create_system_user_ce_package_path(userid_t userId, const char* package_name) {
277     check_package_name(package_name);
278     return StringPrintf("%s/%s", create_system_user_ce_path(userId).c_str(), package_name);
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, 2 /* 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, 4 /* 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 static const char* kProcFilesystems = "/proc/filesystems";
supports_sdcardfs()1064 bool supports_sdcardfs() {
1065     if (!property_get_bool("external_storage.sdcardfs.enabled", true))
1066         return false;
1067     std::string supported;
1068     if (!android::base::ReadFileToString(kProcFilesystems, &supported)) {
1069         PLOG(ERROR) << "Failed to read supported filesystems";
1070         return false;
1071     }
1072     return supported.find("sdcardfs\n") != std::string::npos;
1073 }
1074 
get_occupied_app_space_external(const std::string & uuid,int32_t userId,int32_t appId)1075 int64_t get_occupied_app_space_external(const std::string& uuid, int32_t userId, int32_t appId) {
1076     static const bool supportsSdcardFs = supports_sdcardfs();
1077 
1078     if (supportsSdcardFs) {
1079         int extGid = multiuser_get_ext_gid(userId, appId);
1080 
1081         if (extGid == -1) {
1082             return -1;
1083         }
1084 
1085         return GetOccupiedSpaceForGid(uuid, extGid);
1086     } else {
1087         uid_t uid = multiuser_get_uid(userId, appId);
1088         long projectId = uid - AID_APP_START + PROJECT_ID_EXT_DATA_START;
1089         return GetOccupiedSpaceForProjectId(uuid, projectId);
1090     }
1091 }
get_occupied_app_cache_space_external(const std::string & uuid,int32_t userId,int32_t appId)1092 int64_t get_occupied_app_cache_space_external(const std::string& uuid, int32_t userId, int32_t appId) {
1093     static const bool supportsSdcardFs = supports_sdcardfs();
1094 
1095     if (supportsSdcardFs) {
1096         int extCacheGid = multiuser_get_ext_cache_gid(userId, appId);
1097 
1098         if (extCacheGid == -1) {
1099             return -1;
1100         }
1101 
1102         return GetOccupiedSpaceForGid(uuid, extCacheGid);
1103     } else {
1104         uid_t uid = multiuser_get_uid(userId, appId);
1105         long projectId = uid - AID_APP_START + PROJECT_ID_EXT_CACHE_START;
1106         return GetOccupiedSpaceForProjectId(uuid, projectId);
1107     }
1108 }
1109 
1110 // Collect all non empty profiles from the given directory and puts then into profile_paths.
1111 // The profiles are identified based on PROFILE_EXT extension.
1112 // If a subdirectory or profile file cannot be opened the method logs a warning and moves on.
1113 // 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)1114 static bool collect_profiles(DIR* d,
1115                              const std::string& current_path,
1116                              std::vector<std::string>* profiles_paths) {
1117     int32_t dir_fd = dirfd(d);
1118     if (dir_fd < 0) {
1119         return false;
1120     }
1121 
1122     bool result = true;
1123     struct dirent* dir_entry;
1124     while ((dir_entry = readdir(d))) {
1125         std::string name = dir_entry->d_name;
1126         std::string local_path = current_path + "/" + name;
1127 
1128         if (dir_entry->d_type == DT_REG) {
1129             // Check if this is a non empty profile file.
1130             if (EndsWith(name, PROFILE_EXT)) {
1131                 struct stat st;
1132                 if (stat(local_path.c_str(), &st) != 0) {
1133                     PLOG(WARNING) << "Cannot stat local path " << local_path;
1134                     result = false;
1135                     continue;
1136                 } else if (st.st_size > 0) {
1137                     profiles_paths->push_back(local_path);
1138                 }
1139             }
1140         } else if (dir_entry->d_type == DT_DIR) {
1141             // always skip "." and ".."
1142             if (name == "." || name == "..") {
1143                 continue;
1144             }
1145 
1146             unique_fd subdir_fd(openat(dir_fd, name.c_str(),
1147                     O_RDONLY | O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC));
1148             if (subdir_fd < 0) {
1149                 PLOG(WARNING) << "Could not open dir path " << local_path;
1150                 result = false;
1151                 continue;
1152             }
1153 
1154             DIR* subdir = Fdopendir(std::move(subdir_fd));
1155             if (subdir == nullptr) {
1156                 PLOG(WARNING) << "Could not open dir path " << local_path;
1157                 result = false;
1158                 continue;
1159             }
1160             bool new_result = collect_profiles(subdir, local_path, profiles_paths);
1161             result = result && new_result;
1162             if (closedir(subdir) != 0) {
1163                 PLOG(WARNING) << "Could not close dir path " << local_path;
1164             }
1165         }
1166     }
1167 
1168     return result;
1169 }
1170 
collect_profiles(std::vector<std::string> * profiles_paths)1171 bool collect_profiles(std::vector<std::string>* profiles_paths) {
1172     DIR* d = opendir(android_profiles_dir.c_str());
1173     if (d == nullptr) {
1174         return false;
1175     } else {
1176         return collect_profiles(d, android_profiles_dir, profiles_paths);
1177     }
1178 }
1179 
drop_capabilities(uid_t uid)1180 void drop_capabilities(uid_t uid) {
1181     if (setgid(uid) != 0) {
1182         PLOG(ERROR) << "setgid(" << uid << ") failed in installd during dexopt";
1183         exit(DexoptReturnCodes::kSetGid);
1184     }
1185     if (setuid(uid) != 0) {
1186         PLOG(ERROR) << "setuid(" << uid << ") failed in installd during dexopt";
1187         exit(DexoptReturnCodes::kSetUid);
1188     }
1189     // drop capabilities
1190     struct __user_cap_header_struct capheader;
1191     struct __user_cap_data_struct capdata[2];
1192     memset(&capheader, 0, sizeof(capheader));
1193     memset(&capdata, 0, sizeof(capdata));
1194     capheader.version = _LINUX_CAPABILITY_VERSION_3;
1195     if (capset(&capheader, &capdata[0]) < 0) {
1196         PLOG(ERROR) << "capset failed";
1197         exit(DexoptReturnCodes::kCapSet);
1198     }
1199 }
1200 
1201 }  // namespace installd
1202 }  // namespace android
1203