blob: 5f72ae4cbfef5e5439e64a572f43c63723e51a53 [file] [log] [blame]
Mike Lockwood94afecf2012-10-24 10:45:23 -07001/*
2** Copyright 2008, The Android Open Source Project
3**
Dave Allisond9370732014-01-30 14:19:23 -08004** 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
Mike Lockwood94afecf2012-10-24 10:45:23 -07007**
Dave Allisond9370732014-01-30 14:19:23 -08008** http://www.apache.org/licenses/LICENSE-2.0
Mike Lockwood94afecf2012-10-24 10:45:23 -07009**
Dave Allisond9370732014-01-30 14:19:23 -080010** 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
Mike Lockwood94afecf2012-10-24 10:45:23 -070014** limitations under the License.
15*/
16
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -070017#include <inttypes.h>
Nick Kralevichd7471292013-02-28 16:59:13 -080018#include <sys/capability.h>
Elliott Hughes2ead70c2015-02-16 10:44:22 -080019#include <sys/file.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -070020#include "installd.h"
Brian Carlstrom0378aaf2014-08-08 00:52:22 -070021#include <cutils/sched_policy.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -070022#include <diskusage/dirsize.h>
23#include <selinux/android.h>
Igor Murashkin9e87a802014-11-05 15:21:12 -080024#include <system/thread_defs.h>
Mike Lockwood94afecf2012-10-24 10:45:23 -070025
26/* Directory records that are used in execution of commands. */
27dir_rec_t android_data_dir;
28dir_rec_t android_asec_dir;
29dir_rec_t android_app_dir;
30dir_rec_t android_app_private_dir;
31dir_rec_t android_app_lib_dir;
32dir_rec_t android_media_dir;
Jeff Sharkeye23a1322015-04-06 16:19:39 -070033dir_rec_t android_mnt_expand_dir;
Mike Lockwood94afecf2012-10-24 10:45:23 -070034dir_rec_array_t android_system_dirs;
35
Robert Craig4d3fd4e2013-03-25 06:33:03 -040036int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
Mike Lockwood94afecf2012-10-24 10:45:23 -070037{
38 char pkgdir[PKG_PATH_MAX];
39 char libsymlink[PKG_PATH_MAX];
40 char applibdir[PKG_PATH_MAX];
41 struct stat libStat;
42
43 if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
44 ALOGE("invalid uid/gid: %d %d\n", uid, gid);
45 return -1;
46 }
47
48 if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
49 ALOGE("cannot create package path\n");
50 return -1;
51 }
52
53 if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) {
54 ALOGE("cannot create package lib symlink origin path\n");
55 return -1;
56 }
57
58 if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
59 ALOGE("cannot create package lib symlink dest path\n");
60 return -1;
61 }
62
Nick Kralevicha2d838a2013-01-09 16:00:35 -080063 if (mkdir(pkgdir, 0751) < 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -070064 ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
65 return -1;
66 }
Nick Kralevicha2d838a2013-01-09 16:00:35 -080067 if (chmod(pkgdir, 0751) < 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -070068 ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
69 unlink(pkgdir);
70 return -1;
71 }
72
73 if (lstat(libsymlink, &libStat) < 0) {
74 if (errno != ENOENT) {
75 ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
76 return -1;
77 }
78 } else {
79 if (S_ISDIR(libStat.st_mode)) {
Narayan Kamath3aee2c52014-06-10 13:16:47 +010080 if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -070081 ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
82 return -1;
83 }
84 } else if (S_ISLNK(libStat.st_mode)) {
85 if (unlink(libsymlink) < 0) {
86 ALOGE("couldn't unlink lib directory during install for: %s", libsymlink);
87 return -1;
88 }
89 }
90 }
91
Stephen Smalley26288202014-02-07 09:16:46 -050092 if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -070093 ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
94 unlink(libsymlink);
95 unlink(pkgdir);
96 return -errno;
97 }
98
Stephen Smalley3a983892014-05-13 12:53:07 -040099 if (symlink(applibdir, libsymlink) < 0) {
100 ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
101 strerror(errno));
102 unlink(pkgdir);
103 return -1;
104 }
105
Mike Lockwood94afecf2012-10-24 10:45:23 -0700106 if (chown(pkgdir, uid, gid) < 0) {
107 ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
108 unlink(libsymlink);
109 unlink(pkgdir);
110 return -1;
111 }
112
113 return 0;
114}
115
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700116int uninstall(const char *pkgname, userid_t userid)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700117{
118 char pkgdir[PKG_PATH_MAX];
119
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700120 if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
Mike Lockwood94afecf2012-10-24 10:45:23 -0700121 return -1;
122
Dave Allisond9370732014-01-30 14:19:23 -0800123 remove_profile_file(pkgname);
124
Mike Lockwood94afecf2012-10-24 10:45:23 -0700125 /* delete contents AND directory, no exceptions */
126 return delete_dir_contents(pkgdir, 1, NULL);
127}
128
129int renamepkg(const char *oldpkgname, const char *newpkgname)
130{
131 char oldpkgdir[PKG_PATH_MAX];
132 char newpkgdir[PKG_PATH_MAX];
133
134 if (create_pkg_path(oldpkgdir, oldpkgname, PKG_DIR_POSTFIX, 0))
135 return -1;
136 if (create_pkg_path(newpkgdir, newpkgname, PKG_DIR_POSTFIX, 0))
137 return -1;
138
139 if (rename(oldpkgdir, newpkgdir) < 0) {
140 ALOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno));
141 return -errno;
142 }
143 return 0;
144}
145
146int fix_uid(const char *pkgname, uid_t uid, gid_t gid)
147{
148 char pkgdir[PKG_PATH_MAX];
149 struct stat s;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700150
151 if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
152 ALOGE("invalid uid/gid: %d %d\n", uid, gid);
153 return -1;
154 }
155
156 if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
157 ALOGE("cannot create package path\n");
158 return -1;
159 }
160
161 if (stat(pkgdir, &s) < 0) return -1;
162
163 if (s.st_uid != 0 || s.st_gid != 0) {
Mark Salyzyn92dc3fc2014-03-12 13:12:44 -0700164 ALOGE("fixing uid of non-root pkg: %s %" PRIu32 " %" PRIu32 "\n", pkgdir, s.st_uid, s.st_gid);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700165 return -1;
166 }
167
168 if (chmod(pkgdir, 0751) < 0) {
169 ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
170 unlink(pkgdir);
171 return -errno;
172 }
173 if (chown(pkgdir, uid, gid) < 0) {
174 ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
175 unlink(pkgdir);
176 return -errno;
177 }
178
179 return 0;
180}
181
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700182int delete_user_data(const char *pkgname, userid_t userid)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700183{
184 char pkgdir[PKG_PATH_MAX];
185
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700186 if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
Mike Lockwood94afecf2012-10-24 10:45:23 -0700187 return -1;
188
Jeff Sharkey3316fe42014-08-27 10:46:25 -0700189 return delete_dir_contents(pkgdir, 0, NULL);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700190}
191
Nick Kraleviche4e91c42013-09-20 12:45:20 -0700192int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700193{
194 char pkgdir[PKG_PATH_MAX];
195 char applibdir[PKG_PATH_MAX];
196 char libsymlink[PKG_PATH_MAX];
197 struct stat libStat;
198
199 // Create the data dir for the package
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700200 if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700201 return -1;
202 }
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700203 if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userid)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700204 ALOGE("cannot create package lib symlink origin path\n");
205 return -1;
206 }
207 if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
208 ALOGE("cannot create package lib symlink dest path\n");
209 return -1;
210 }
211
Nick Kralevicha2d838a2013-01-09 16:00:35 -0800212 if (mkdir(pkgdir, 0751) < 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700213 ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
214 return -errno;
215 }
Nick Kralevicha2d838a2013-01-09 16:00:35 -0800216 if (chmod(pkgdir, 0751) < 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700217 ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
218 unlink(pkgdir);
219 return -errno;
220 }
221
222 if (lstat(libsymlink, &libStat) < 0) {
223 if (errno != ENOENT) {
224 ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno));
225 unlink(pkgdir);
226 return -1;
227 }
228 } else {
229 if (S_ISDIR(libStat.st_mode)) {
Narayan Kamath3aee2c52014-06-10 13:16:47 +0100230 if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700231 ALOGE("couldn't delete lib directory during install for non-primary: %s",
232 libsymlink);
233 unlink(pkgdir);
234 return -1;
235 }
236 } else if (S_ISLNK(libStat.st_mode)) {
237 if (unlink(libsymlink) < 0) {
238 ALOGE("couldn't unlink lib directory during install for non-primary: %s",
239 libsymlink);
240 unlink(pkgdir);
241 return -1;
242 }
243 }
244 }
245
Stephen Smalley26288202014-02-07 09:16:46 -0500246 if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700247 ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
248 unlink(libsymlink);
249 unlink(pkgdir);
250 return -errno;
251 }
252
Stephen Smalley3a983892014-05-13 12:53:07 -0400253 if (symlink(applibdir, libsymlink) < 0) {
254 ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink,
255 applibdir, strerror(errno));
256 unlink(pkgdir);
257 return -1;
258 }
259
Mike Lockwood94afecf2012-10-24 10:45:23 -0700260 if (chown(pkgdir, uid, uid) < 0) {
261 ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
262 unlink(libsymlink);
263 unlink(pkgdir);
264 return -errno;
265 }
266
267 return 0;
268}
269
Robin Lee7c8bec02014-06-10 18:46:26 +0100270int make_user_config(userid_t userid)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700271{
Robin Lee095c7632014-04-25 15:05:19 +0100272 if (ensure_config_user_dirs(userid) == -1) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700273 return -1;
274 }
275
276 return 0;
277}
278
Robin Lee095c7632014-04-25 15:05:19 +0100279int delete_user(userid_t userid)
280{
281 int status = 0;
282
283 char data_path[PKG_PATH_MAX];
284 if ((create_user_path(data_path, userid) != 0)
285 || (delete_dir_contents(data_path, 1, NULL) != 0)) {
286 status = -1;
287 }
288
289 char media_path[PATH_MAX];
290 if ((create_user_media_path(media_path, userid) != 0)
291 || (delete_dir_contents(media_path, 1, NULL) != 0)) {
292 status = -1;
293 }
294
295 char config_path[PATH_MAX];
296 if ((create_user_config_path(config_path, userid) != 0)
297 || (delete_dir_contents(config_path, 1, NULL) != 0)) {
298 status = -1;
299 }
300
301 return status;
302}
303
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700304int delete_cache(const char *pkgname, userid_t userid)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700305{
306 char cachedir[PKG_PATH_MAX];
307
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700308 if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, userid))
Mike Lockwood94afecf2012-10-24 10:45:23 -0700309 return -1;
310
Jeff Sharkeyc796b682014-07-15 21:49:51 -0700311 /* delete contents, not the directory, no exceptions */
Narayan Kamath3aee2c52014-06-10 13:16:47 +0100312 return delete_dir_contents(cachedir, 0, NULL);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700313}
314
Jeff Sharkeyc796b682014-07-15 21:49:51 -0700315int delete_code_cache(const char *pkgname, userid_t userid)
316{
317 char codecachedir[PKG_PATH_MAX];
Jeff Sharkey770180a2014-09-08 17:14:26 -0700318 struct stat s;
Jeff Sharkeyc796b682014-07-15 21:49:51 -0700319
320 if (create_pkg_path(codecachedir, pkgname, CODE_CACHE_DIR_POSTFIX, userid))
321 return -1;
322
Jeff Sharkey770180a2014-09-08 17:14:26 -0700323 /* it's okay if code cache is missing */
324 if (lstat(codecachedir, &s) == -1 && errno == ENOENT) {
325 return 0;
326 }
327
Jeff Sharkeyc796b682014-07-15 21:49:51 -0700328 /* delete contents, not the directory, no exceptions */
329 return delete_dir_contents(codecachedir, 0, NULL);
330}
331
Mike Lockwood94afecf2012-10-24 10:45:23 -0700332/* Try to ensure free_size bytes of storage are available.
333 * Returns 0 on success.
334 * This is rather simple-minded because doing a full LRU would
335 * be potentially memory-intensive, and without atime it would
336 * also require that apps constantly modify file metadata even
337 * when just reading from the cache, which is pretty awful.
338 */
339int free_cache(int64_t free_size)
340{
341 cache_t* cache;
342 int64_t avail;
343 DIR *d;
344 struct dirent *de;
345 char tmpdir[PATH_MAX];
346 char *dirpos;
347
348 avail = data_disk_free();
349 if (avail < 0) return -1;
350
351 ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
352 if (avail >= free_size) return 0;
353
354 cache = start_cache_collection();
355
356 // Collect cache files for primary user.
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700357 if (create_user_path(tmpdir, 0) == 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700358 //ALOGI("adding cache files from %s\n", tmpdir);
359 add_cache_files(cache, tmpdir, "cache");
360 }
361
362 // Search for other users and add any cache files from them.
363 snprintf(tmpdir, sizeof(tmpdir), "%s%s", android_data_dir.path,
364 SECONDARY_USER_PREFIX);
365 dirpos = tmpdir + strlen(tmpdir);
366 d = opendir(tmpdir);
367 if (d != NULL) {
368 while ((de = readdir(d))) {
369 if (de->d_type == DT_DIR) {
370 const char *name = de->d_name;
371 /* always skip "." and ".." */
372 if (name[0] == '.') {
373 if (name[1] == 0) continue;
374 if ((name[1] == '.') && (name[2] == 0)) continue;
375 }
376 if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
377 strcpy(dirpos, name);
378 //ALOGI("adding cache files from %s\n", tmpdir);
379 add_cache_files(cache, tmpdir, "cache");
380 } else {
381 ALOGW("Path exceeds limit: %s%s", tmpdir, name);
382 }
383 }
384 }
385 closedir(d);
386 }
387
388 // Collect cache files on external storage for all users (if it is mounted as part
389 // of the internal storage).
390 strcpy(tmpdir, android_media_dir.path);
391 dirpos = tmpdir + strlen(tmpdir);
392 d = opendir(tmpdir);
393 if (d != NULL) {
394 while ((de = readdir(d))) {
395 if (de->d_type == DT_DIR) {
396 const char *name = de->d_name;
397 /* skip any dir that doesn't start with a number, so not a user */
398 if (name[0] < '0' || name[0] > '9') {
399 continue;
400 }
401 if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
402 strcpy(dirpos, name);
403 if (lookup_media_dir(tmpdir, "Android") == 0
404 && lookup_media_dir(tmpdir, "data") == 0) {
405 //ALOGI("adding cache files from %s\n", tmpdir);
406 add_cache_files(cache, tmpdir, "cache");
407 }
408 } else {
409 ALOGW("Path exceeds limit: %s%s", tmpdir, name);
410 }
411 }
412 }
413 closedir(d);
414 }
415
416 clear_cache_files(cache, free_size);
417 finish_cache_collection(cache);
418
419 return data_disk_free() >= free_size ? 0 : -1;
420}
421
Narayan Kamath1b400322014-04-11 13:17:00 +0100422int move_dex(const char *src, const char *dst, const char *instruction_set)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700423{
424 char src_dex[PKG_PATH_MAX];
425 char dst_dex[PKG_PATH_MAX];
426
Jeff Sharkey770180a2014-09-08 17:14:26 -0700427 if (validate_apk_path(src)) {
428 ALOGE("invalid apk path '%s' (bad prefix)\n", src);
429 return -1;
430 }
431 if (validate_apk_path(dst)) {
432 ALOGE("invalid apk path '%s' (bad prefix)\n", dst);
433 return -1;
434 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700435
Narayan Kamath1b400322014-04-11 13:17:00 +0100436 if (create_cache_path(src_dex, src, instruction_set)) return -1;
437 if (create_cache_path(dst_dex, dst, instruction_set)) return -1;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700438
439 ALOGV("move %s -> %s\n", src_dex, dst_dex);
440 if (rename(src_dex, dst_dex) < 0) {
441 ALOGE("Couldn't move %s: %s\n", src_dex, strerror(errno));
442 return -1;
443 } else {
444 return 0;
445 }
446}
447
Narayan Kamath1b400322014-04-11 13:17:00 +0100448int rm_dex(const char *path, const char *instruction_set)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700449{
450 char dex_path[PKG_PATH_MAX];
451
Jeff Sharkey770180a2014-09-08 17:14:26 -0700452 if (validate_apk_path(path) && validate_system_app_path(path)) {
453 ALOGE("invalid apk path '%s' (bad prefix)\n", path);
454 return -1;
455 }
456
Narayan Kamath1b400322014-04-11 13:17:00 +0100457 if (create_cache_path(dex_path, path, instruction_set)) return -1;
Mike Lockwood94afecf2012-10-24 10:45:23 -0700458
459 ALOGV("unlink %s\n", dex_path);
460 if (unlink(dex_path) < 0) {
Jeff Sharkey770180a2014-09-08 17:14:26 -0700461 if (errno != ENOENT) {
462 ALOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno));
463 }
Mike Lockwood94afecf2012-10-24 10:45:23 -0700464 return -1;
465 } else {
466 return 0;
467 }
468}
469
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700470int get_size(const char *pkgname, userid_t userid, const char *apkpath,
Dianne Hackborn8b417802013-05-01 18:55:10 -0700471 const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath,
Narayan Kamath1b400322014-04-11 13:17:00 +0100472 const char *instruction_set, int64_t *_codesize, int64_t *_datasize,
473 int64_t *_cachesize, int64_t* _asecsize)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700474{
475 DIR *d;
476 int dfd;
477 struct dirent *de;
478 struct stat s;
479 char path[PKG_PATH_MAX];
480
481 int64_t codesize = 0;
482 int64_t datasize = 0;
483 int64_t cachesize = 0;
484 int64_t asecsize = 0;
485
486 /* count the source apk as code -- but only if it's not
487 * on the /system partition and its not on the sdcard.
488 */
489 if (validate_system_app_path(apkpath) &&
490 strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
491 if (stat(apkpath, &s) == 0) {
492 codesize += stat_size(&s);
493 }
494 }
495 /* count the forward locked apk as code if it is given
496 */
497 if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
498 if (stat(fwdlock_apkpath, &s) == 0) {
499 codesize += stat_size(&s);
500 }
501 }
502 /* count the cached dexfile as code */
Narayan Kamath1b400322014-04-11 13:17:00 +0100503 if (!create_cache_path(path, apkpath, instruction_set)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700504 if (stat(path, &s) == 0) {
505 codesize += stat_size(&s);
506 }
507 }
508
509 /* add in size of any libraries */
Dianne Hackborn8b417802013-05-01 18:55:10 -0700510 if (libdirpath != NULL && libdirpath[0] != '!') {
511 d = opendir(libdirpath);
Mike Lockwood94afecf2012-10-24 10:45:23 -0700512 if (d != NULL) {
513 dfd = dirfd(d);
514 codesize += calculate_dir_size(dfd);
515 closedir(d);
516 }
517 }
518
519 /* compute asec size if it is given
520 */
521 if (asecpath != NULL && asecpath[0] != '!') {
522 if (stat(asecpath, &s) == 0) {
523 asecsize += stat_size(&s);
524 }
525 }
526
Jeff Sharkeyabe4fe52013-07-10 16:55:46 -0700527 if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, userid)) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700528 goto done;
529 }
530
531 d = opendir(path);
532 if (d == NULL) {
533 goto done;
534 }
535 dfd = dirfd(d);
536
537 /* most stuff in the pkgdir is data, except for the "cache"
538 * directory and below, which is cache, and the "lib" directory
539 * and below, which is code...
540 */
541 while ((de = readdir(d))) {
542 const char *name = de->d_name;
543
544 if (de->d_type == DT_DIR) {
545 int subfd;
546 int64_t statsize = 0;
547 int64_t dirsize = 0;
548 /* always skip "." and ".." */
549 if (name[0] == '.') {
550 if (name[1] == 0) continue;
551 if ((name[1] == '.') && (name[2] == 0)) continue;
552 }
553 if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
554 statsize = stat_size(&s);
555 }
556 subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
557 if (subfd >= 0) {
558 dirsize = calculate_dir_size(subfd);
559 }
560 if(!strcmp(name,"lib")) {
561 codesize += dirsize + statsize;
562 } else if(!strcmp(name,"cache")) {
563 cachesize += dirsize + statsize;
564 } else {
565 datasize += dirsize + statsize;
566 }
567 } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
568 // This is the symbolic link to the application's library
569 // code. We'll count this as code instead of data, since
570 // it is not something that the app creates.
571 if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
572 codesize += stat_size(&s);
573 }
574 } else {
575 if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
576 datasize += stat_size(&s);
577 }
578 }
579 }
580 closedir(d);
581done:
582 *_codesize = codesize;
583 *_datasize = datasize;
584 *_cachesize = cachesize;
585 *_asecsize = asecsize;
586 return 0;
587}
588
Narayan Kamath1b400322014-04-11 13:17:00 +0100589int create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700590{
591 char *tmp;
592 int srclen;
593 int dstlen;
594
595 srclen = strlen(src);
596
597 /* demand that we are an absolute path */
598 if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
599 return -1;
600 }
601
602 if (srclen > PKG_PATH_MAX) { // XXX: PKG_NAME_MAX?
603 return -1;
604 }
605
Dave Allisond9370732014-01-30 14:19:23 -0800606 dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
Narayan Kamath1b400322014-04-11 13:17:00 +0100607 strlen(instruction_set) +
608 strlen(DALVIK_CACHE_POSTFIX) + 2;
Dave Allisond9370732014-01-30 14:19:23 -0800609
Mike Lockwood94afecf2012-10-24 10:45:23 -0700610 if (dstlen > PKG_PATH_MAX) {
611 return -1;
612 }
613
Narayan Kamath1b400322014-04-11 13:17:00 +0100614 sprintf(path,"%s%s/%s%s",
Mike Lockwood94afecf2012-10-24 10:45:23 -0700615 DALVIK_CACHE_PREFIX,
Narayan Kamath1b400322014-04-11 13:17:00 +0100616 instruction_set,
Mike Lockwood94afecf2012-10-24 10:45:23 -0700617 src + 1, /* skip the leading / */
618 DALVIK_CACHE_POSTFIX);
Dave Allisond9370732014-01-30 14:19:23 -0800619
Narayan Kamath1b400322014-04-11 13:17:00 +0100620 for(tmp = path + strlen(DALVIK_CACHE_PREFIX) + strlen(instruction_set) + 1; *tmp; tmp++) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700621 if (*tmp == '/') {
622 *tmp = '@';
623 }
624 }
625
626 return 0;
627}
628
Yevgeny Roubanb0d8d002014-09-08 17:02:10 +0700629static int split_count(const char *str)
630{
631 char *ctx;
632 int count = 0;
633 char buf[PROPERTY_VALUE_MAX];
634
635 strncpy(buf, str, sizeof(buf));
636 char *pBuf = buf;
637
638 while(strtok_r(pBuf, " ", &ctx) != NULL) {
639 count++;
640 pBuf = NULL;
641 }
642
643 return count;
644}
645
neo.chae14e084d2015-01-07 18:46:13 +0900646static int split(char *buf, const char **argv)
Yevgeny Roubanb0d8d002014-09-08 17:02:10 +0700647{
648 char *ctx;
649 int count = 0;
650 char *tok;
651 char *pBuf = buf;
652
653 while((tok = strtok_r(pBuf, " ", &ctx)) != NULL) {
654 argv[count++] = tok;
655 pBuf = NULL;
656 }
657
658 return count;
659}
660
Alex Light7365a102014-07-21 12:23:48 -0700661static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name,
Chih-Hung Hsieh99d9fb12014-09-11 14:44:46 -0700662 const char* output_file_name, const char *pkgname __unused, const char *instruction_set)
Alex Light7365a102014-07-21 12:23:48 -0700663{
664 static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
Calin Juravle8fc73152014-08-19 18:48:50 +0100665 static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
Alex Light7365a102014-07-21 12:23:48 -0700666
667 static const char* PATCHOAT_BIN = "/system/bin/patchoat";
668 if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
669 ALOGE("Instruction set %s longer than max length of %d",
670 instruction_set, MAX_INSTRUCTION_SET_LEN);
671 return;
672 }
673
674 /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/
675 char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
676 char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN];
677 char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN];
678 const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art";
679 // The caller has already gotten all the locks we need.
680 const char* no_lock_arg = "--no-lock-output";
681 sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
682 sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd);
683 sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd);
Alex Lighta7915d42014-08-11 10:07:02 -0700684 ALOGV("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n",
Alex Light7365a102014-07-21 12:23:48 -0700685 PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name);
686
687 /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */
688 char* argv[7];
689 argv[0] = (char*) PATCHOAT_BIN;
690 argv[1] = (char*) patched_image_location_arg;
691 argv[2] = (char*) no_lock_arg;
692 argv[3] = instruction_set_arg;
693 argv[4] = output_oat_fd_arg;
694 argv[5] = input_oat_fd_arg;
695 argv[6] = NULL;
696
697 execv(PATCHOAT_BIN, (char* const *)argv);
698 ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
699}
700
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700701static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
Andreas Gampee1c01352014-12-10 16:41:11 -0800702 const char* output_file_name, int swap_fd, const char *pkgname, const char *instruction_set,
Andreas Gampe598c25e2015-03-03 09:15:06 -0800703 bool vm_safe_mode, bool debuggable)
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700704{
Calin Juravle8fc73152014-08-19 18:48:50 +0100705 static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
706
707 if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
708 ALOGE("Instruction set %s longer than max length of %d",
709 instruction_set, MAX_INSTRUCTION_SET_LEN);
710 return;
711 }
712
Brian Carlstrome46a75a2014-06-27 16:03:06 -0700713 char prop_buf[PROPERTY_VALUE_MAX];
714 bool profiler = (property_get("dalvik.vm.profiler", prop_buf, "0") > 0) && (prop_buf[0] == '1');
715
716 char dex2oat_Xms_flag[PROPERTY_VALUE_MAX];
717 bool have_dex2oat_Xms_flag = property_get("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
718
719 char dex2oat_Xmx_flag[PROPERTY_VALUE_MAX];
720 bool have_dex2oat_Xmx_flag = property_get("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
721
Brian Carlstromcf51ba12014-07-28 19:13:28 -0700722 char dex2oat_compiler_filter_flag[PROPERTY_VALUE_MAX];
723 bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter",
724 dex2oat_compiler_filter_flag, NULL) > 0;
725
Andreas Gampe8d7af8b2015-03-30 18:45:03 -0700726 char dex2oat_threads_buf[PROPERTY_VALUE_MAX];
727 bool have_dex2oat_threads_flag = property_get("dalvik.vm.dex2oat-threads", dex2oat_threads_buf,
728 NULL) > 0;
729 char dex2oat_threads_arg[PROPERTY_VALUE_MAX + 2];
730 if (have_dex2oat_threads_flag) {
731 sprintf(dex2oat_threads_arg, "-j%s", dex2oat_threads_buf);
732 }
733
Calin Juravle8fc73152014-08-19 18:48:50 +0100734 char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
735 sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
736 char dex2oat_isa_features[PROPERTY_VALUE_MAX];
737 bool have_dex2oat_isa_features = property_get(dex2oat_isa_features_key,
738 dex2oat_isa_features, NULL) > 0;
739
Ian Rogers16a95b22014-11-08 16:58:13 -0800740 char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
741 sprintf(dex2oat_isa_variant_key, "dalvik.vm.isa.%s.variant", instruction_set);
742 char dex2oat_isa_variant[PROPERTY_VALUE_MAX];
743 bool have_dex2oat_isa_variant = property_get(dex2oat_isa_variant_key,
744 dex2oat_isa_variant, NULL) > 0;
745
neo.chae14e084d2015-01-07 18:46:13 +0900746 const char *dex2oat_norelocation = "-Xnorelocate";
747 bool have_dex2oat_relocation_skip_flag = false;
748
Brian Carlstrom0ae8e392014-02-10 16:42:52 -0800749 char dex2oat_flags[PROPERTY_VALUE_MAX];
Yevgeny Roubanb0d8d002014-09-08 17:02:10 +0700750 int dex2oat_flags_count = property_get("dalvik.vm.dex2oat-flags",
751 dex2oat_flags, NULL) <= 0 ? 0 : split_count(dex2oat_flags);
Brian Carlstrom0ae8e392014-02-10 16:42:52 -0800752 ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
753
Brian Carlstrom538998f2014-07-30 14:37:11 -0700754 // If we booting without the real /data, don't spend time compiling.
755 char vold_decrypt[PROPERTY_VALUE_MAX];
756 bool have_vold_decrypt = property_get("vold.decrypt", vold_decrypt, "") > 0;
757 bool skip_compilation = (have_vold_decrypt &&
758 (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
759 (strcmp(vold_decrypt, "1") == 0)));
760
Mathieu Chartierd4a7b452015-03-20 15:39:47 -0700761 char use_jit_property[PROPERTY_VALUE_MAX];
762 bool have_jit_property = property_get("debug.usejit", use_jit_property, NULL) > 0;
763 bool use_jit = have_jit_property && strcmp(use_jit_property, "true") == 0;
764
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700765 static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
Brian Carlstrom53e07762014-06-27 14:15:19 -0700766
Brian Carlstrom53e07762014-06-27 14:15:19 -0700767 static const char* RUNTIME_ARG = "--runtime-arg";
Brian Carlstrom53e07762014-06-27 14:15:19 -0700768
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700769 static const int MAX_INT_LEN = 12; // '-'+10dig+'\0' -OR- 0x+8dig
Narayan Kamath1b400322014-04-11 13:17:00 +0100770
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700771 char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];
772 char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
773 char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
Brian Carlstrom7195fcc2014-06-16 13:28:03 -0700774 char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX];
Narayan Kamath1b400322014-04-11 13:17:00 +0100775 char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
Ian Rogers16a95b22014-11-08 16:58:13 -0800776 char instruction_set_variant_arg[strlen("--instruction-set-variant=") + PROPERTY_VALUE_MAX];
Calin Juravle8fc73152014-08-19 18:48:50 +0100777 char instruction_set_features_arg[strlen("--instruction-set-features=") + PROPERTY_VALUE_MAX];
Calin Juravle4fdff462014-06-06 16:58:43 +0100778 char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX];
779 char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX];
Brian Carlstrome46a75a2014-06-27 16:03:06 -0700780 char dex2oat_Xms_arg[strlen("-Xms") + PROPERTY_VALUE_MAX];
781 char dex2oat_Xmx_arg[strlen("-Xmx") + PROPERTY_VALUE_MAX];
Brian Carlstromcf51ba12014-07-28 19:13:28 -0700782 char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + PROPERTY_VALUE_MAX];
Andreas Gampee1c01352014-12-10 16:41:11 -0800783 bool have_dex2oat_swap_fd = false;
784 char dex2oat_swap_fd[strlen("--swap-fd=") + MAX_INT_LEN];
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700785
786 sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
787 sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
788 sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
789 sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
Narayan Kamath1b400322014-04-11 13:17:00 +0100790 sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
Ian Rogers16a95b22014-11-08 16:58:13 -0800791 sprintf(instruction_set_variant_arg, "--instruction-set-variant=%s", dex2oat_isa_variant);
Calin Juravle8fc73152014-08-19 18:48:50 +0100792 sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features);
Andreas Gampee1c01352014-12-10 16:41:11 -0800793 if (swap_fd >= 0) {
794 have_dex2oat_swap_fd = true;
795 sprintf(dex2oat_swap_fd, "--swap-fd=%d", swap_fd);
796 }
Calin Juravle57c69c32014-06-06 14:42:16 +0100797
Calin Juravle4fdff462014-06-06 16:58:43 +0100798 bool have_profile_file = false;
799 bool have_top_k_profile_threshold = false;
Calin Juravle57c69c32014-06-06 14:42:16 +0100800 if (profiler && (strcmp(pkgname, "*") != 0)) {
801 char profile_file[PKG_PATH_MAX];
802 snprintf(profile_file, sizeof(profile_file), "%s/%s",
Dave Allisond9370732014-01-30 14:19:23 -0800803 DALVIK_CACHE_PREFIX "profiles", pkgname);
Calin Juravle57c69c32014-06-06 14:42:16 +0100804 struct stat st;
Calin Juravle4fdff462014-06-06 16:58:43 +0100805 if ((stat(profile_file, &st) == 0) && (st.st_size > 0)) {
Calin Juravle57c69c32014-06-06 14:42:16 +0100806 sprintf(profile_file_arg, "--profile-file=%s", profile_file);
Calin Juravle4fdff462014-06-06 16:58:43 +0100807 have_profile_file = true;
808 if (property_get("dalvik.vm.profile.top-k-thr", prop_buf, NULL) > 0) {
809 snprintf(top_k_profile_threshold_arg, sizeof(top_k_profile_threshold_arg),
810 "--top-k-profile-threshold=%s", prop_buf);
811 have_top_k_profile_threshold = true;
812 }
Calin Juravle57c69c32014-06-06 14:42:16 +0100813 }
Dave Allisond9370732014-01-30 14:19:23 -0800814 }
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700815
Brian Carlstrome46a75a2014-06-27 16:03:06 -0700816 if (have_dex2oat_Xms_flag) {
817 sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag);
818 }
819 if (have_dex2oat_Xmx_flag) {
820 sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
821 }
Brian Carlstrom538998f2014-07-30 14:37:11 -0700822 if (skip_compilation) {
Brian Carlstrome18987e2014-08-15 09:55:50 -0700823 strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
Brian Carlstrom538998f2014-07-30 14:37:11 -0700824 have_dex2oat_compiler_filter_flag = true;
neo.chae14e084d2015-01-07 18:46:13 +0900825 have_dex2oat_relocation_skip_flag = true;
Calin Juravleb1efac12014-08-21 19:05:20 +0100826 } else if (vm_safe_mode) {
827 strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
Calin Juravle97477d22014-08-27 16:10:03 +0100828 have_dex2oat_compiler_filter_flag = true;
Mathieu Chartierd4a7b452015-03-20 15:39:47 -0700829 } else if (use_jit) {
830 strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-at-runtime");
831 have_dex2oat_compiler_filter_flag = true;
Brian Carlstrom538998f2014-07-30 14:37:11 -0700832 } else if (have_dex2oat_compiler_filter_flag) {
Brian Carlstromcf51ba12014-07-28 19:13:28 -0700833 sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag);
834 }
Brian Carlstrome46a75a2014-06-27 16:03:06 -0700835
Andreas Gampe598c25e2015-03-03 09:15:06 -0800836 // Check whether all apps should be compiled debuggable.
837 if (!debuggable) {
838 debuggable =
839 (property_get("dalvik.vm.always_debuggable", prop_buf, "0") > 0) &&
840 (prop_buf[0] == '1');
841 }
842
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700843 ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
Calin Juravle4fdff462014-06-06 16:58:43 +0100844
neo.chae14e084d2015-01-07 18:46:13 +0900845 const char* argv[7 // program name, mandatory arguments and the final NULL
846 + (have_dex2oat_isa_variant ? 1 : 0)
847 + (have_dex2oat_isa_features ? 1 : 0)
848 + (have_profile_file ? 1 : 0)
849 + (have_top_k_profile_threshold ? 1 : 0)
850 + (have_dex2oat_Xms_flag ? 2 : 0)
851 + (have_dex2oat_Xmx_flag ? 2 : 0)
852 + (have_dex2oat_compiler_filter_flag ? 1 : 0)
Andreas Gampe8d7af8b2015-03-30 18:45:03 -0700853 + (have_dex2oat_threads_flag ? 1 : 0)
neo.chae14e084d2015-01-07 18:46:13 +0900854 + (have_dex2oat_swap_fd ? 1 : 0)
855 + (have_dex2oat_relocation_skip_flag ? 2 : 0)
Andreas Gampe598c25e2015-03-03 09:15:06 -0800856 + (debuggable ? 1 : 0)
neo.chae14e084d2015-01-07 18:46:13 +0900857 + dex2oat_flags_count];
Calin Juravle4fdff462014-06-06 16:58:43 +0100858 int i = 0;
neo.chae14e084d2015-01-07 18:46:13 +0900859 argv[i++] = DEX2OAT_BIN;
Calin Juravle4fdff462014-06-06 16:58:43 +0100860 argv[i++] = zip_fd_arg;
861 argv[i++] = zip_location_arg;
862 argv[i++] = oat_fd_arg;
863 argv[i++] = oat_location_arg;
864 argv[i++] = instruction_set_arg;
Ian Rogers16a95b22014-11-08 16:58:13 -0800865 if (have_dex2oat_isa_variant) {
866 argv[i++] = instruction_set_variant_arg;
867 }
Calin Juravle8fc73152014-08-19 18:48:50 +0100868 if (have_dex2oat_isa_features) {
869 argv[i++] = instruction_set_features_arg;
870 }
Calin Juravle4fdff462014-06-06 16:58:43 +0100871 if (have_profile_file) {
872 argv[i++] = profile_file_arg;
873 }
874 if (have_top_k_profile_threshold) {
875 argv[i++] = top_k_profile_threshold_arg;
876 }
Brian Carlstrome46a75a2014-06-27 16:03:06 -0700877 if (have_dex2oat_Xms_flag) {
neo.chae14e084d2015-01-07 18:46:13 +0900878 argv[i++] = RUNTIME_ARG;
Brian Carlstrome46a75a2014-06-27 16:03:06 -0700879 argv[i++] = dex2oat_Xms_arg;
880 }
881 if (have_dex2oat_Xmx_flag) {
neo.chae14e084d2015-01-07 18:46:13 +0900882 argv[i++] = RUNTIME_ARG;
Brian Carlstrome46a75a2014-06-27 16:03:06 -0700883 argv[i++] = dex2oat_Xmx_arg;
884 }
Brian Carlstromcf51ba12014-07-28 19:13:28 -0700885 if (have_dex2oat_compiler_filter_flag) {
886 argv[i++] = dex2oat_compiler_filter_arg;
887 }
Andreas Gampe8d7af8b2015-03-30 18:45:03 -0700888 if (have_dex2oat_threads_flag) {
889 argv[i++] = dex2oat_threads_arg;
890 }
Andreas Gampee1c01352014-12-10 16:41:11 -0800891 if (have_dex2oat_swap_fd) {
892 argv[i++] = dex2oat_swap_fd;
893 }
Andreas Gampe598c25e2015-03-03 09:15:06 -0800894 if (debuggable) {
895 argv[i++] = "--debuggable";
896 }
Yevgeny Roubanb0d8d002014-09-08 17:02:10 +0700897 if (dex2oat_flags_count) {
898 i += split(dex2oat_flags, argv + i);
Calin Juravle4fdff462014-06-06 16:58:43 +0100899 }
neo.chae14e084d2015-01-07 18:46:13 +0900900 if (have_dex2oat_relocation_skip_flag) {
901 argv[i++] = RUNTIME_ARG;
902 argv[i++] = dex2oat_norelocation;
903 }
Brian Carlstrome46a75a2014-06-27 16:03:06 -0700904 // Do not add after dex2oat_flags, they should override others for debugging.
Calin Juravle4fdff462014-06-06 16:58:43 +0100905 argv[i] = NULL;
906
neo.chae14e084d2015-01-07 18:46:13 +0900907 execv(DEX2OAT_BIN, (char * const *)argv);
Yevgeny Roubanb0d8d002014-09-08 17:02:10 +0700908 ALOGE("execv(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700909}
910
MÃ¥rten Kongstad63568b12014-01-31 14:42:59 +0100911static int wait_child(pid_t pid)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700912{
913 int status;
914 pid_t got_pid;
915
Mike Lockwood94afecf2012-10-24 10:45:23 -0700916 while (1) {
917 got_pid = waitpid(pid, &status, 0);
918 if (got_pid == -1 && errno == EINTR) {
919 printf("waitpid interrupted, retrying\n");
920 } else {
921 break;
922 }
923 }
924 if (got_pid != pid) {
925 ALOGW("waitpid failed: wanted %d, got %d: %s\n",
926 (int) pid, (int) got_pid, strerror(errno));
927 return 1;
928 }
929
930 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700931 return 0;
932 } else {
Mike Lockwood94afecf2012-10-24 10:45:23 -0700933 return status; /* always nonzero */
934 }
935}
936
Andreas Gampee1c01352014-12-10 16:41:11 -0800937/*
938 * Whether dexopt should use a swap file when compiling an APK. If kAlwaysProvideSwapFile, do this
939 * on all devices (dex2oat will make a more informed decision itself, anyways). Otherwise, only do
940 * this on a low-mem device.
941 */
942static bool kAlwaysProvideSwapFile = true;
943
944static bool ShouldUseSwapFileForDexopt() {
945 if (kAlwaysProvideSwapFile) {
946 return true;
947 }
948
949 char low_mem_buf[PROPERTY_VALUE_MAX];
950 property_get("ro.config.low_ram", low_mem_buf, "");
951 return (strcmp(low_mem_buf, "true") == 0);
952}
953
Richard Uhler009b8772015-03-18 12:39:09 -0700954/*
955 * Computes the odex file for the given apk_path and instruction_set.
956 * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
957 *
958 * Returns false if it failed to determine the odex file path.
959 */
960static bool calculate_odex_file_path(char path[PKG_PATH_MAX],
961 const char *apk_path,
962 const char *instruction_set)
963{
964 if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
965 + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
966 ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
967 return false;
968 }
969
970 strcpy(path, apk_path);
971 char *end = strrchr(path, '/');
972 if (end == NULL) {
973 ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
974 return false;
975 }
976 const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
977
978 strcpy(end + 1, "oat/"); // path = /system/framework/oat/\0
979 strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0
980 strcat(path, apk_end); // path = /system/framework/oat/<isa>/whatever.jar\0
981 end = strrchr(path, '.');
982 if (end == NULL) {
983 ALOGE("apk_path '%s' has no extension.\n", apk_path);
984 return false;
985 }
986 strcpy(end + 1, "odex");
987 return true;
988}
989
Calin Juravleb1efac12014-08-21 19:05:20 +0100990int dexopt(const char *apk_path, uid_t uid, bool is_public,
Alex Light7365a102014-07-21 12:23:48 -0700991 const char *pkgname, const char *instruction_set,
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -0800992 bool vm_safe_mode, bool is_patchoat, bool debuggable, const char* oat_dir)
Mike Lockwood94afecf2012-10-24 10:45:23 -0700993{
994 struct utimbuf ut;
Fyodor Kupolov26ff93c2015-04-02 16:59:10 -0700995 struct stat input_stat;
Brian Carlstrom1705fc42013-03-21 18:20:22 -0700996 char out_path[PKG_PATH_MAX];
Andreas Gampee1c01352014-12-10 16:41:11 -0800997 char swap_file_name[PKG_PATH_MAX];
Alex Light7365a102014-07-21 12:23:48 -0700998 const char *input_file;
999 char in_odex_path[PKG_PATH_MAX];
Andreas Gampee1c01352014-12-10 16:41:11 -08001000 int res, input_fd=-1, out_fd=-1, swap_fd=-1;
Mike Lockwood94afecf2012-10-24 10:45:23 -07001001
Andreas Gampee1c01352014-12-10 16:41:11 -08001002 // Early best-effort check whether we can fit the the path into our buffers.
1003 // Note: the cache path will require an additional 5 bytes for ".swap", but we'll try to run
1004 // without a swap file, if necessary.
Mike Lockwood94afecf2012-10-24 10:45:23 -07001005 if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001006 ALOGE("apk_path too long '%s'\n", apk_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001007 return -1;
1008 }
1009
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001010 if (oat_dir != NULL && oat_dir[0] != '!') {
1011 if (validate_apk_path(oat_dir)) {
1012 ALOGE("invalid oat_dir '%s'\n", oat_dir);
1013 return -1;
Chih-Wei Huang0e8ae162014-04-28 15:47:45 +08001014 }
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001015 if (calculate_oat_file_path(out_path, oat_dir, apk_path, instruction_set)) {
1016 return -1;
1017 }
1018 } else {
1019 if (create_cache_path(out_path, apk_path, instruction_set)) {
1020 return -1;
1021 }
Mike Lockwood94afecf2012-10-24 10:45:23 -07001022 }
1023
Alex Light7365a102014-07-21 12:23:48 -07001024 if (is_patchoat) {
Richard Uhler009b8772015-03-18 12:39:09 -07001025 if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
1026 return -1;
Alex Light7365a102014-07-21 12:23:48 -07001027 }
Alex Light7365a102014-07-21 12:23:48 -07001028 input_file = in_odex_path;
1029 } else {
1030 input_file = apk_path;
1031 }
Mike Lockwood94afecf2012-10-24 10:45:23 -07001032
Alex Light7365a102014-07-21 12:23:48 -07001033 memset(&input_stat, 0, sizeof(input_stat));
1034 stat(input_file, &input_stat);
1035
1036 input_fd = open(input_file, O_RDONLY, 0);
1037 if (input_fd < 0) {
1038 ALOGE("installd cannot open '%s' for input during dexopt\n", input_file);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001039 return -1;
1040 }
1041
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001042 unlink(out_path);
1043 out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644);
1044 if (out_fd < 0) {
1045 ALOGE("installd cannot open '%s' for output during dexopt\n", out_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001046 goto fail;
1047 }
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001048 if (fchmod(out_fd,
Mike Lockwood94afecf2012-10-24 10:45:23 -07001049 S_IRUSR|S_IWUSR|S_IRGRP |
1050 (is_public ? S_IROTH : 0)) < 0) {
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001051 ALOGE("installd cannot chmod '%s' during dexopt\n", out_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001052 goto fail;
1053 }
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001054 if (fchown(out_fd, AID_SYSTEM, uid) < 0) {
1055 ALOGE("installd cannot chown '%s' during dexopt\n", out_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001056 goto fail;
1057 }
1058
Dave Allisond9370732014-01-30 14:19:23 -08001059 // Create profile file if there is a package name present.
1060 if (strcmp(pkgname, "*") != 0) {
1061 create_profile_file(pkgname, uid);
1062 }
1063
Andreas Gampee1c01352014-12-10 16:41:11 -08001064 // Create a swap file if necessary.
1065 if (!is_patchoat && ShouldUseSwapFileForDexopt()) {
1066 // Make sure there really is enough space.
1067 size_t out_len = strlen(out_path);
1068 if (out_len + strlen(".swap") + 1 <= PKG_PATH_MAX) {
1069 strcpy(swap_file_name, out_path);
1070 strcpy(swap_file_name + strlen(out_path), ".swap");
1071 unlink(swap_file_name);
1072 swap_fd = open(swap_file_name, O_RDWR | O_CREAT | O_EXCL, 0600);
1073 if (swap_fd < 0) {
1074 // Could not create swap file. Optimistically go on and hope that we can compile
1075 // without it.
1076 ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
1077 } else {
1078 // Immediately unlink. We don't really want to hit flash.
1079 unlink(swap_file_name);
1080 }
1081 } else {
1082 // Swap file path is too long. Try to run without.
1083 ALOGE("installd could not create swap file for path %s during dexopt\n", out_path);
1084 }
1085 }
Dave Allisond9370732014-01-30 14:19:23 -08001086
Alex Light7365a102014-07-21 12:23:48 -07001087 ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001088
1089 pid_t pid;
1090 pid = fork();
1091 if (pid == 0) {
1092 /* child -- drop privileges before continuing */
1093 if (setgid(uid) != 0) {
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001094 ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001095 exit(64);
1096 }
1097 if (setuid(uid) != 0) {
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001098 ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001099 exit(65);
1100 }
1101 // drop capabilities
1102 struct __user_cap_header_struct capheader;
1103 struct __user_cap_data_struct capdata[2];
1104 memset(&capheader, 0, sizeof(capheader));
1105 memset(&capdata, 0, sizeof(capdata));
1106 capheader.version = _LINUX_CAPABILITY_VERSION_3;
1107 if (capset(&capheader, &capdata[0]) < 0) {
1108 ALOGE("capset failed: %s\n", strerror(errno));
1109 exit(66);
1110 }
Brian Carlstrom0378aaf2014-08-08 00:52:22 -07001111 if (set_sched_policy(0, SP_BACKGROUND) < 0) {
1112 ALOGE("set_sched_policy failed: %s\n", strerror(errno));
1113 exit(70);
1114 }
Igor Murashkin9e87a802014-11-05 15:21:12 -08001115 if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
1116 ALOGE("setpriority failed: %s\n", strerror(errno));
1117 exit(71);
1118 }
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001119 if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
1120 ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
Mike Lockwood94afecf2012-10-24 10:45:23 -07001121 exit(67);
1122 }
1123
Andreas Gampebd872e42014-12-15 11:41:11 -08001124 if (is_patchoat) {
1125 run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001126 } else {
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001127 const char *input_file_name = strrchr(input_file, '/');
1128 if (input_file_name == NULL) {
1129 input_file_name = input_file;
1130 } else {
1131 input_file_name++;
1132 }
1133 run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname,
1134 instruction_set, vm_safe_mode, debuggable);
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001135 }
Mike Lockwood94afecf2012-10-24 10:45:23 -07001136 exit(68); /* only get here on exec failure */
1137 } else {
MÃ¥rten Kongstad63568b12014-01-31 14:42:59 +01001138 res = wait_child(pid);
1139 if (res == 0) {
Alex Light7365a102014-07-21 12:23:48 -07001140 ALOGV("DexInv: --- END '%s' (success) ---\n", input_file);
MÃ¥rten Kongstad63568b12014-01-31 14:42:59 +01001141 } else {
Alex Light7365a102014-07-21 12:23:48 -07001142 ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", input_file, res);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001143 goto fail;
1144 }
1145 }
1146
Alex Light7365a102014-07-21 12:23:48 -07001147 ut.actime = input_stat.st_atime;
1148 ut.modtime = input_stat.st_mtime;
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001149 utime(out_path, &ut);
1150
1151 close(out_fd);
Alex Light7365a102014-07-21 12:23:48 -07001152 close(input_fd);
Andreas Gampee1c01352014-12-10 16:41:11 -08001153 if (swap_fd != -1) {
1154 close(swap_fd);
1155 }
Mike Lockwood94afecf2012-10-24 10:45:23 -07001156 return 0;
1157
1158fail:
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001159 if (out_fd >= 0) {
1160 close(out_fd);
1161 unlink(out_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001162 }
Alex Light7365a102014-07-21 12:23:48 -07001163 if (input_fd >= 0) {
1164 close(input_fd);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001165 }
1166 return -1;
1167}
1168
Narayan Kamath091ea772014-11-10 15:03:46 +00001169int mark_boot_complete(const char* instruction_set)
1170{
1171 char boot_marker_path[PKG_PATH_MAX];
1172 sprintf(boot_marker_path,"%s%s/.booting", DALVIK_CACHE_PREFIX, instruction_set);
1173
1174 ALOGV("mark_boot_complete : %s", boot_marker_path);
1175 if (unlink(boot_marker_path) != 0) {
1176 ALOGE("Unable to unlink boot marker at %s, error=%s", boot_marker_path,
1177 strerror(errno));
1178 return -1;
1179 }
1180
1181 return 0;
1182}
1183
Mike Lockwood94afecf2012-10-24 10:45:23 -07001184void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
1185 struct stat* statbuf)
1186{
1187 while (path[basepos] != 0) {
1188 if (path[basepos] == '/') {
1189 path[basepos] = 0;
1190 if (lstat(path, statbuf) < 0) {
1191 ALOGV("Making directory: %s\n", path);
1192 if (mkdir(path, mode) == 0) {
1193 chown(path, uid, gid);
1194 } else {
1195 ALOGW("Unable to make directory %s: %s\n", path, strerror(errno));
1196 }
1197 }
1198 path[basepos] = '/';
1199 basepos++;
1200 }
1201 basepos++;
1202 }
1203}
1204
1205int movefileordir(char* srcpath, char* dstpath, int dstbasepos,
1206 int dstuid, int dstgid, struct stat* statbuf)
1207{
1208 DIR *d;
1209 struct dirent *de;
1210 int res;
1211
1212 int srcend = strlen(srcpath);
1213 int dstend = strlen(dstpath);
Dave Allisond9370732014-01-30 14:19:23 -08001214
Mike Lockwood94afecf2012-10-24 10:45:23 -07001215 if (lstat(srcpath, statbuf) < 0) {
1216 ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno));
1217 return 1;
1218 }
Dave Allisond9370732014-01-30 14:19:23 -08001219
Mike Lockwood94afecf2012-10-24 10:45:23 -07001220 if ((statbuf->st_mode&S_IFDIR) == 0) {
1221 mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH,
1222 dstuid, dstgid, statbuf);
1223 ALOGV("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
1224 if (rename(srcpath, dstpath) >= 0) {
1225 if (chown(dstpath, dstuid, dstgid) < 0) {
1226 ALOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
1227 unlink(dstpath);
1228 return 1;
1229 }
1230 } else {
1231 ALOGW("Unable to rename %s to %s: %s\n",
1232 srcpath, dstpath, strerror(errno));
1233 return 1;
1234 }
1235 return 0;
1236 }
1237
1238 d = opendir(srcpath);
1239 if (d == NULL) {
1240 ALOGW("Unable to opendir %s: %s\n", srcpath, strerror(errno));
1241 return 1;
1242 }
1243
1244 res = 0;
Dave Allisond9370732014-01-30 14:19:23 -08001245
Mike Lockwood94afecf2012-10-24 10:45:23 -07001246 while ((de = readdir(d))) {
1247 const char *name = de->d_name;
1248 /* always skip "." and ".." */
1249 if (name[0] == '.') {
1250 if (name[1] == 0) continue;
1251 if ((name[1] == '.') && (name[2] == 0)) continue;
1252 }
Dave Allisond9370732014-01-30 14:19:23 -08001253
Mike Lockwood94afecf2012-10-24 10:45:23 -07001254 if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) {
1255 ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name);
1256 continue;
1257 }
Dave Allisond9370732014-01-30 14:19:23 -08001258
Mike Lockwood94afecf2012-10-24 10:45:23 -07001259 if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) {
1260 ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name);
1261 continue;
1262 }
Dave Allisond9370732014-01-30 14:19:23 -08001263
Mike Lockwood94afecf2012-10-24 10:45:23 -07001264 srcpath[srcend] = dstpath[dstend] = '/';
1265 strcpy(srcpath+srcend+1, name);
1266 strcpy(dstpath+dstend+1, name);
Dave Allisond9370732014-01-30 14:19:23 -08001267
Mike Lockwood94afecf2012-10-24 10:45:23 -07001268 if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) {
1269 res = 1;
1270 }
Dave Allisond9370732014-01-30 14:19:23 -08001271
Mike Lockwood94afecf2012-10-24 10:45:23 -07001272 // Note: we will be leaving empty directories behind in srcpath,
1273 // but that is okay, the package manager will be erasing all of the
1274 // data associated with .apks that disappear.
Dave Allisond9370732014-01-30 14:19:23 -08001275
Mike Lockwood94afecf2012-10-24 10:45:23 -07001276 srcpath[srcend] = dstpath[dstend] = 0;
1277 }
Dave Allisond9370732014-01-30 14:19:23 -08001278
Mike Lockwood94afecf2012-10-24 10:45:23 -07001279 closedir(d);
1280 return res;
1281}
1282
1283int movefiles()
1284{
1285 DIR *d;
1286 int dfd, subfd;
1287 struct dirent *de;
1288 struct stat s;
1289 char buf[PKG_PATH_MAX+1];
1290 int bufp, bufe, bufi, readlen;
1291
1292 char srcpkg[PKG_NAME_MAX];
1293 char dstpkg[PKG_NAME_MAX];
1294 char srcpath[PKG_PATH_MAX];
1295 char dstpath[PKG_PATH_MAX];
1296 int dstuid=-1, dstgid=-1;
1297 int hasspace;
1298
1299 d = opendir(UPDATE_COMMANDS_DIR_PREFIX);
1300 if (d == NULL) {
1301 goto done;
1302 }
1303 dfd = dirfd(d);
1304
1305 /* Iterate through all files in the directory, executing the
1306 * file movements requested there-in.
1307 */
1308 while ((de = readdir(d))) {
1309 const char *name = de->d_name;
1310
1311 if (de->d_type == DT_DIR) {
1312 continue;
1313 } else {
1314 subfd = openat(dfd, name, O_RDONLY);
1315 if (subfd < 0) {
1316 ALOGW("Unable to open update commands at %s%s\n",
1317 UPDATE_COMMANDS_DIR_PREFIX, name);
1318 continue;
1319 }
Dave Allisond9370732014-01-30 14:19:23 -08001320
Mike Lockwood94afecf2012-10-24 10:45:23 -07001321 bufp = 0;
1322 bufe = 0;
1323 buf[PKG_PATH_MAX] = 0;
1324 srcpkg[0] = dstpkg[0] = 0;
1325 while (1) {
1326 bufi = bufp;
1327 while (bufi < bufe && buf[bufi] != '\n') {
1328 bufi++;
1329 }
1330 if (bufi < bufe) {
1331 buf[bufi] = 0;
1332 ALOGV("Processing line: %s\n", buf+bufp);
1333 hasspace = 0;
1334 while (bufp < bufi && isspace(buf[bufp])) {
1335 hasspace = 1;
1336 bufp++;
1337 }
1338 if (buf[bufp] == '#' || bufp == bufi) {
1339 // skip comments and empty lines.
1340 } else if (hasspace) {
1341 if (dstpkg[0] == 0) {
1342 ALOGW("Path before package line in %s%s: %s\n",
1343 UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
1344 } else if (srcpkg[0] == 0) {
1345 // Skip -- source package no longer exists.
1346 } else {
1347 ALOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg);
1348 if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) &&
1349 !create_move_path(dstpath, dstpkg, buf+bufp, 0)) {
1350 movefileordir(srcpath, dstpath,
1351 strlen(dstpath)-strlen(buf+bufp),
1352 dstuid, dstgid, &s);
1353 }
1354 }
1355 } else {
1356 char* div = strchr(buf+bufp, ':');
1357 if (div == NULL) {
1358 ALOGW("Bad package spec in %s%s; no ':' sep: %s\n",
1359 UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
1360 } else {
1361 *div = 0;
1362 div++;
1363 if (strlen(buf+bufp) < PKG_NAME_MAX) {
1364 strcpy(dstpkg, buf+bufp);
1365 } else {
1366 srcpkg[0] = dstpkg[0] = 0;
1367 ALOGW("Package name too long in %s%s: %s\n",
1368 UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
1369 }
1370 if (strlen(div) < PKG_NAME_MAX) {
1371 strcpy(srcpkg, div);
1372 } else {
1373 srcpkg[0] = dstpkg[0] = 0;
1374 ALOGW("Package name too long in %s%s: %s\n",
1375 UPDATE_COMMANDS_DIR_PREFIX, name, div);
1376 }
1377 if (srcpkg[0] != 0) {
1378 if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) {
1379 if (lstat(srcpath, &s) < 0) {
1380 // Package no longer exists -- skip.
1381 srcpkg[0] = 0;
1382 }
1383 } else {
1384 srcpkg[0] = 0;
1385 ALOGW("Can't create path %s in %s%s\n",
1386 div, UPDATE_COMMANDS_DIR_PREFIX, name);
1387 }
1388 if (srcpkg[0] != 0) {
1389 if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) {
1390 if (lstat(dstpath, &s) == 0) {
1391 dstuid = s.st_uid;
1392 dstgid = s.st_gid;
1393 } else {
1394 // Destination package doesn't
1395 // exist... due to original-package,
1396 // this is normal, so don't be
1397 // noisy about it.
1398 srcpkg[0] = 0;
1399 }
1400 } else {
1401 srcpkg[0] = 0;
1402 ALOGW("Can't create path %s in %s%s\n",
1403 div, UPDATE_COMMANDS_DIR_PREFIX, name);
1404 }
1405 }
1406 ALOGV("Transfering from %s to %s: uid=%d\n",
1407 srcpkg, dstpkg, dstuid);
1408 }
1409 }
1410 }
1411 bufp = bufi+1;
1412 } else {
1413 if (bufp == 0) {
1414 if (bufp < bufe) {
1415 ALOGW("Line too long in %s%s, skipping: %s\n",
1416 UPDATE_COMMANDS_DIR_PREFIX, name, buf);
1417 }
1418 } else if (bufp < bufe) {
1419 memcpy(buf, buf+bufp, bufe-bufp);
1420 bufe -= bufp;
1421 bufp = 0;
1422 }
1423 readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe);
1424 if (readlen < 0) {
1425 ALOGW("Failure reading update commands in %s%s: %s\n",
1426 UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno));
1427 break;
1428 } else if (readlen == 0) {
1429 break;
1430 }
1431 bufe += readlen;
1432 buf[bufe] = 0;
1433 ALOGV("Read buf: %s\n", buf);
1434 }
1435 }
1436 close(subfd);
1437 }
1438 }
1439 closedir(d);
1440done:
1441 return 0;
1442}
1443
1444int linklib(const char* pkgname, const char* asecLibDir, int userId)
1445{
1446 char pkgdir[PKG_PATH_MAX];
1447 char libsymlink[PKG_PATH_MAX];
1448 struct stat s, libStat;
1449 int rc = 0;
1450
1451 if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) {
1452 ALOGE("cannot create package path\n");
1453 return -1;
1454 }
1455 if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) {
1456 ALOGE("cannot create package lib symlink origin path\n");
1457 return -1;
1458 }
1459
1460 if (stat(pkgdir, &s) < 0) return -1;
1461
1462 if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
1463 ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
1464 return -1;
1465 }
1466
1467 if (chmod(pkgdir, 0700) < 0) {
1468 ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
1469 rc = -1;
1470 goto out;
1471 }
1472
1473 if (lstat(libsymlink, &libStat) < 0) {
1474 if (errno != ENOENT) {
1475 ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
1476 rc = -1;
1477 goto out;
1478 }
1479 } else {
1480 if (S_ISDIR(libStat.st_mode)) {
Narayan Kamath3aee2c52014-06-10 13:16:47 +01001481 if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -07001482 rc = -1;
1483 goto out;
1484 }
1485 } else if (S_ISLNK(libStat.st_mode)) {
1486 if (unlink(libsymlink) < 0) {
1487 ALOGE("couldn't unlink lib dir: %s\n", strerror(errno));
1488 rc = -1;
1489 goto out;
1490 }
1491 }
1492 }
1493
1494 if (symlink(asecLibDir, libsymlink) < 0) {
1495 ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir,
1496 strerror(errno));
1497 rc = -errno;
1498 goto out;
1499 }
1500
1501out:
1502 if (chmod(pkgdir, s.st_mode) < 0) {
1503 ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
1504 rc = -errno;
1505 }
1506
1507 if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
1508 ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
1509 return -errno;
1510 }
1511
1512 return rc;
1513}
MÃ¥rten Kongstad63568b12014-01-31 14:42:59 +01001514
1515static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd)
1516{
1517 static const char *IDMAP_BIN = "/system/bin/idmap";
1518 static const size_t MAX_INT_LEN = 32;
1519 char idmap_str[MAX_INT_LEN];
1520
1521 snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd);
1522
1523 execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL);
1524 ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno));
1525}
1526
1527// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix)
1528// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap
1529static int flatten_path(const char *prefix, const char *suffix,
1530 const char *overlay_path, char *idmap_path, size_t N)
1531{
1532 if (overlay_path == NULL || idmap_path == NULL) {
1533 return -1;
1534 }
1535 const size_t len_overlay_path = strlen(overlay_path);
1536 // will access overlay_path + 1 further below; requires absolute path
1537 if (len_overlay_path < 2 || *overlay_path != '/') {
1538 return -1;
1539 }
1540 const size_t len_idmap_root = strlen(prefix);
1541 const size_t len_suffix = strlen(suffix);
1542 if (SIZE_MAX - len_idmap_root < len_overlay_path ||
1543 SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) {
1544 // additions below would cause overflow
1545 return -1;
1546 }
1547 if (N < len_idmap_root + len_overlay_path + len_suffix) {
1548 return -1;
1549 }
1550 memset(idmap_path, 0, N);
1551 snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix);
1552 char *ch = idmap_path + len_idmap_root;
1553 while (*ch != '\0') {
1554 if (*ch == '/') {
1555 *ch = '@';
1556 }
1557 ++ch;
1558 }
1559 return 0;
1560}
1561
1562int idmap(const char *target_apk, const char *overlay_apk, uid_t uid)
1563{
1564 ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid);
1565
1566 int idmap_fd = -1;
1567 char idmap_path[PATH_MAX];
1568
1569 if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
1570 idmap_path, sizeof(idmap_path)) == -1) {
1571 ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk);
1572 goto fail;
1573 }
1574
1575 unlink(idmap_path);
1576 idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644);
1577 if (idmap_fd < 0) {
1578 ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno));
1579 goto fail;
1580 }
1581 if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) {
1582 ALOGE("idmap cannot chown '%s'\n", idmap_path);
1583 goto fail;
1584 }
1585 if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
1586 ALOGE("idmap cannot chmod '%s'\n", idmap_path);
1587 goto fail;
1588 }
1589
1590 pid_t pid;
1591 pid = fork();
1592 if (pid == 0) {
1593 /* child -- drop privileges before continuing */
1594 if (setgid(uid) != 0) {
1595 ALOGE("setgid(%d) failed during idmap\n", uid);
1596 exit(1);
1597 }
1598 if (setuid(uid) != 0) {
1599 ALOGE("setuid(%d) failed during idmap\n", uid);
1600 exit(1);
1601 }
1602 if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) {
1603 ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno));
1604 exit(1);
1605 }
1606
1607 run_idmap(target_apk, overlay_apk, idmap_fd);
1608 exit(1); /* only if exec call to idmap failed */
1609 } else {
1610 int status = wait_child(pid);
1611 if (status != 0) {
1612 ALOGE("idmap failed, status=0x%04x\n", status);
1613 goto fail;
1614 }
1615 }
1616
1617 close(idmap_fd);
1618 return 0;
1619fail:
1620 if (idmap_fd >= 0) {
1621 close(idmap_fd);
1622 unlink(idmap_path);
1623 }
1624 return -1;
1625}
Robert Craige9887e42014-02-20 10:25:56 -05001626
Robert Craigda30dc72014-03-27 10:21:12 -04001627int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid)
Robert Craige9887e42014-02-20 10:25:56 -05001628{
Robert Craigda30dc72014-03-27 10:21:12 -04001629 struct dirent *entry;
1630 DIR *d;
1631 struct stat s;
1632 char *userdir;
1633 char *primarydir;
1634 char *pkgdir;
Robert Craige9887e42014-02-20 10:25:56 -05001635 int ret = 0;
1636
Robert Craigda30dc72014-03-27 10:21:12 -04001637 // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
1638 unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
1639
1640 if (!pkgName || !seinfo) {
1641 ALOGE("Package name or seinfo tag is null when trying to restorecon.");
Robert Craige9887e42014-02-20 10:25:56 -05001642 return -1;
1643 }
1644
Robert Craigda30dc72014-03-27 10:21:12 -04001645 if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) {
1646 return -1;
1647 }
1648
1649 // Relabel for primary user.
1650 if (selinux_android_restorecon_pkgdir(primarydir, seinfo, uid, flags) < 0) {
1651 ALOGE("restorecon failed for %s: %s\n", primarydir, strerror(errno));
Robert Craige9887e42014-02-20 10:25:56 -05001652 ret |= -1;
1653 }
1654
Robert Craigda30dc72014-03-27 10:21:12 -04001655 if (asprintf(&userdir, "%s%s", android_data_dir.path, SECONDARY_USER_PREFIX) < 0) {
1656 free(primarydir);
1657 return -1;
Robert Craige9887e42014-02-20 10:25:56 -05001658 }
1659
Robert Craigda30dc72014-03-27 10:21:12 -04001660 // Relabel package directory for all secondary users.
1661 d = opendir(userdir);
1662 if (d == NULL) {
1663 free(primarydir);
1664 free(userdir);
1665 return -1;
1666 }
1667
1668 while ((entry = readdir(d))) {
1669 if (entry->d_type != DT_DIR) {
1670 continue;
1671 }
1672
1673 const char *user = entry->d_name;
1674 // Ignore "." and ".."
1675 if (!strcmp(user, ".") || !strcmp(user, "..")) {
1676 continue;
1677 }
1678
1679 // user directories start with a number
1680 if (user[0] < '0' || user[0] > '9') {
1681 ALOGE("Expecting numbered directory during restorecon. Instead got '%s'.", user);
1682 continue;
1683 }
1684
1685 if (asprintf(&pkgdir, "%s%s/%s", userdir, user, pkgName) < 0) {
1686 continue;
1687 }
1688
1689 if (stat(pkgdir, &s) < 0) {
1690 free(pkgdir);
1691 continue;
1692 }
1693
Stephen Smalley8ac2a642014-09-08 15:51:55 -04001694 if (selinux_android_restorecon_pkgdir(pkgdir, seinfo, s.st_uid, flags) < 0) {
Robert Craigda30dc72014-03-27 10:21:12 -04001695 ALOGE("restorecon failed for %s: %s\n", pkgdir, strerror(errno));
1696 ret |= -1;
1697 }
1698 free(pkgdir);
1699 }
1700
1701 closedir(d);
1702 free(primarydir);
1703 free(userdir);
Robert Craige9887e42014-02-20 10:25:56 -05001704 return ret;
1705}
Narayan Kamath3aee2c52014-06-10 13:16:47 +01001706
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001707int create_oat_dir(const char* oat_dir, const char* instruction_set)
1708{
1709 char oat_instr_dir[PKG_PATH_MAX];
1710
1711 if (validate_apk_path(oat_dir)) {
1712 ALOGE("invalid apk path '%s' (bad prefix)\n", oat_dir);
1713 return -1;
1714 }
Fyodor Kupolov8eed7e62015-04-06 19:09:02 -07001715 if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001716 return -1;
1717 }
1718 if (selinux_android_restorecon(oat_dir, 0)) {
1719 ALOGE("cannot restorecon dir '%s': %s\n", oat_dir, strerror(errno));
1720 return -1;
1721 }
1722 snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set);
Fyodor Kupolov8eed7e62015-04-06 19:09:02 -07001723 if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001724 return -1;
1725 }
1726 return 0;
1727}
1728
1729int rm_package_dir(const char* apk_path)
1730{
1731 if (validate_apk_path(apk_path)) {
1732 ALOGE("invalid apk path '%s' (bad prefix)\n", apk_path);
1733 return -1;
1734 }
1735 return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */);
1736}
1737
1738int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
1739 const char *instruction_set) {
1740 char *file_name_start;
1741 char *file_name_end;
1742
1743 file_name_start = strrchr(apk_path, '/');
1744 if (file_name_start == NULL) {
1745 ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
1746 return -1;
1747 }
1748 file_name_end = strrchr(apk_path, '.');
1749 if (file_name_end < file_name_start) {
1750 ALOGE("apk_path '%s' has no extension\n", apk_path);
1751 return -1;
1752 }
1753
1754 // Calculate file_name
1755 int file_name_len = file_name_end - file_name_start - 1;
1756 char file_name[file_name_len + 1];
1757 memcpy(file_name, file_name_start + 1, file_name_len);
1758 file_name[file_name_len] = '\0';
1759
1760 // <apk_parent_dir>/oat/<isa>/<file_name>.odex
1761 snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
1762 return 0;
1763}