blob: 0200112241f9e4a40aabed88c6a02b0096ce1829 [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,
Richard Uhlerc92fb622015-03-26 15:47:38 -0700991 const char *pkgname, const char *instruction_set, int dexopt_needed,
992 bool vm_safe_mode, 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
Richard Uhlerc92fb622015-03-26 15:47:38 -07001024 switch (dexopt_needed) {
1025 case DEXOPT_DEX2OAT_NEEDED:
1026 input_file = apk_path;
1027 break;
1028
1029 case DEXOPT_PATCHOAT_NEEDED:
1030 if (!calculate_odex_file_path(in_odex_path, apk_path, instruction_set)) {
1031 return -1;
1032 }
1033 input_file = in_odex_path;
1034 break;
1035
1036 case DEXOPT_SELF_PATCHOAT_NEEDED:
1037 input_file = out_path;
1038 break;
1039
1040 default:
1041 ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
1042 exit(72);
Alex Light7365a102014-07-21 12:23:48 -07001043 }
Mike Lockwood94afecf2012-10-24 10:45:23 -07001044
Alex Light7365a102014-07-21 12:23:48 -07001045 memset(&input_stat, 0, sizeof(input_stat));
1046 stat(input_file, &input_stat);
1047
1048 input_fd = open(input_file, O_RDONLY, 0);
1049 if (input_fd < 0) {
1050 ALOGE("installd cannot open '%s' for input during dexopt\n", input_file);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001051 return -1;
1052 }
1053
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001054 unlink(out_path);
1055 out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644);
1056 if (out_fd < 0) {
1057 ALOGE("installd cannot open '%s' for output during dexopt\n", out_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001058 goto fail;
1059 }
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001060 if (fchmod(out_fd,
Mike Lockwood94afecf2012-10-24 10:45:23 -07001061 S_IRUSR|S_IWUSR|S_IRGRP |
1062 (is_public ? S_IROTH : 0)) < 0) {
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001063 ALOGE("installd cannot chmod '%s' during dexopt\n", out_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001064 goto fail;
1065 }
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001066 if (fchown(out_fd, AID_SYSTEM, uid) < 0) {
1067 ALOGE("installd cannot chown '%s' during dexopt\n", out_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001068 goto fail;
1069 }
1070
Dave Allisond9370732014-01-30 14:19:23 -08001071 // Create profile file if there is a package name present.
1072 if (strcmp(pkgname, "*") != 0) {
1073 create_profile_file(pkgname, uid);
1074 }
1075
Andreas Gampee1c01352014-12-10 16:41:11 -08001076 // Create a swap file if necessary.
Richard Uhlerc92fb622015-03-26 15:47:38 -07001077 if (ShouldUseSwapFileForDexopt()) {
Andreas Gampee1c01352014-12-10 16:41:11 -08001078 // Make sure there really is enough space.
1079 size_t out_len = strlen(out_path);
1080 if (out_len + strlen(".swap") + 1 <= PKG_PATH_MAX) {
1081 strcpy(swap_file_name, out_path);
1082 strcpy(swap_file_name + strlen(out_path), ".swap");
1083 unlink(swap_file_name);
1084 swap_fd = open(swap_file_name, O_RDWR | O_CREAT | O_EXCL, 0600);
1085 if (swap_fd < 0) {
1086 // Could not create swap file. Optimistically go on and hope that we can compile
1087 // without it.
1088 ALOGE("installd could not create '%s' for swap during dexopt\n", swap_file_name);
1089 } else {
1090 // Immediately unlink. We don't really want to hit flash.
1091 unlink(swap_file_name);
1092 }
1093 } else {
1094 // Swap file path is too long. Try to run without.
1095 ALOGE("installd could not create swap file for path %s during dexopt\n", out_path);
1096 }
1097 }
Dave Allisond9370732014-01-30 14:19:23 -08001098
Alex Light7365a102014-07-21 12:23:48 -07001099 ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001100
1101 pid_t pid;
1102 pid = fork();
1103 if (pid == 0) {
1104 /* child -- drop privileges before continuing */
1105 if (setgid(uid) != 0) {
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001106 ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001107 exit(64);
1108 }
1109 if (setuid(uid) != 0) {
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001110 ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001111 exit(65);
1112 }
1113 // drop capabilities
1114 struct __user_cap_header_struct capheader;
1115 struct __user_cap_data_struct capdata[2];
1116 memset(&capheader, 0, sizeof(capheader));
1117 memset(&capdata, 0, sizeof(capdata));
1118 capheader.version = _LINUX_CAPABILITY_VERSION_3;
1119 if (capset(&capheader, &capdata[0]) < 0) {
1120 ALOGE("capset failed: %s\n", strerror(errno));
1121 exit(66);
1122 }
Brian Carlstrom0378aaf2014-08-08 00:52:22 -07001123 if (set_sched_policy(0, SP_BACKGROUND) < 0) {
1124 ALOGE("set_sched_policy failed: %s\n", strerror(errno));
1125 exit(70);
1126 }
Igor Murashkin9e87a802014-11-05 15:21:12 -08001127 if (setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND) < 0) {
1128 ALOGE("setpriority failed: %s\n", strerror(errno));
1129 exit(71);
1130 }
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001131 if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
1132 ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
Mike Lockwood94afecf2012-10-24 10:45:23 -07001133 exit(67);
1134 }
1135
Richard Uhlerc92fb622015-03-26 15:47:38 -07001136 if (dexopt_needed == DEXOPT_PATCHOAT_NEEDED
1137 || dexopt_needed == DEXOPT_SELF_PATCHOAT_NEEDED) {
Andreas Gampebd872e42014-12-15 11:41:11 -08001138 run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
Richard Uhlerc92fb622015-03-26 15:47:38 -07001139 } else if (dexopt_needed == DEXOPT_DEX2OAT_NEEDED) {
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001140 const char *input_file_name = strrchr(input_file, '/');
1141 if (input_file_name == NULL) {
1142 input_file_name = input_file;
1143 } else {
1144 input_file_name++;
1145 }
1146 run_dex2oat(input_fd, out_fd, input_file_name, out_path, swap_fd, pkgname,
1147 instruction_set, vm_safe_mode, debuggable);
Richard Uhlerc92fb622015-03-26 15:47:38 -07001148 } else {
1149 ALOGE("Invalid dexopt needed: %d\n", dexopt_needed);
1150 exit(73);
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001151 }
Mike Lockwood94afecf2012-10-24 10:45:23 -07001152 exit(68); /* only get here on exec failure */
1153 } else {
MÃ¥rten Kongstad63568b12014-01-31 14:42:59 +01001154 res = wait_child(pid);
1155 if (res == 0) {
Alex Light7365a102014-07-21 12:23:48 -07001156 ALOGV("DexInv: --- END '%s' (success) ---\n", input_file);
MÃ¥rten Kongstad63568b12014-01-31 14:42:59 +01001157 } else {
Alex Light7365a102014-07-21 12:23:48 -07001158 ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", input_file, res);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001159 goto fail;
1160 }
1161 }
1162
Alex Light7365a102014-07-21 12:23:48 -07001163 ut.actime = input_stat.st_atime;
1164 ut.modtime = input_stat.st_mtime;
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001165 utime(out_path, &ut);
1166
1167 close(out_fd);
Alex Light7365a102014-07-21 12:23:48 -07001168 close(input_fd);
Andreas Gampee1c01352014-12-10 16:41:11 -08001169 if (swap_fd != -1) {
1170 close(swap_fd);
1171 }
Mike Lockwood94afecf2012-10-24 10:45:23 -07001172 return 0;
1173
1174fail:
Brian Carlstrom1705fc42013-03-21 18:20:22 -07001175 if (out_fd >= 0) {
1176 close(out_fd);
1177 unlink(out_path);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001178 }
Alex Light7365a102014-07-21 12:23:48 -07001179 if (input_fd >= 0) {
1180 close(input_fd);
Mike Lockwood94afecf2012-10-24 10:45:23 -07001181 }
1182 return -1;
1183}
1184
Narayan Kamath091ea772014-11-10 15:03:46 +00001185int mark_boot_complete(const char* instruction_set)
1186{
1187 char boot_marker_path[PKG_PATH_MAX];
1188 sprintf(boot_marker_path,"%s%s/.booting", DALVIK_CACHE_PREFIX, instruction_set);
1189
1190 ALOGV("mark_boot_complete : %s", boot_marker_path);
1191 if (unlink(boot_marker_path) != 0) {
1192 ALOGE("Unable to unlink boot marker at %s, error=%s", boot_marker_path,
1193 strerror(errno));
1194 return -1;
1195 }
1196
1197 return 0;
1198}
1199
Mike Lockwood94afecf2012-10-24 10:45:23 -07001200void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
1201 struct stat* statbuf)
1202{
1203 while (path[basepos] != 0) {
1204 if (path[basepos] == '/') {
1205 path[basepos] = 0;
1206 if (lstat(path, statbuf) < 0) {
1207 ALOGV("Making directory: %s\n", path);
1208 if (mkdir(path, mode) == 0) {
1209 chown(path, uid, gid);
1210 } else {
1211 ALOGW("Unable to make directory %s: %s\n", path, strerror(errno));
1212 }
1213 }
1214 path[basepos] = '/';
1215 basepos++;
1216 }
1217 basepos++;
1218 }
1219}
1220
1221int movefileordir(char* srcpath, char* dstpath, int dstbasepos,
1222 int dstuid, int dstgid, struct stat* statbuf)
1223{
1224 DIR *d;
1225 struct dirent *de;
1226 int res;
1227
1228 int srcend = strlen(srcpath);
1229 int dstend = strlen(dstpath);
Dave Allisond9370732014-01-30 14:19:23 -08001230
Mike Lockwood94afecf2012-10-24 10:45:23 -07001231 if (lstat(srcpath, statbuf) < 0) {
1232 ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno));
1233 return 1;
1234 }
Dave Allisond9370732014-01-30 14:19:23 -08001235
Mike Lockwood94afecf2012-10-24 10:45:23 -07001236 if ((statbuf->st_mode&S_IFDIR) == 0) {
1237 mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH,
1238 dstuid, dstgid, statbuf);
1239 ALOGV("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
1240 if (rename(srcpath, dstpath) >= 0) {
1241 if (chown(dstpath, dstuid, dstgid) < 0) {
1242 ALOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
1243 unlink(dstpath);
1244 return 1;
1245 }
1246 } else {
1247 ALOGW("Unable to rename %s to %s: %s\n",
1248 srcpath, dstpath, strerror(errno));
1249 return 1;
1250 }
1251 return 0;
1252 }
1253
1254 d = opendir(srcpath);
1255 if (d == NULL) {
1256 ALOGW("Unable to opendir %s: %s\n", srcpath, strerror(errno));
1257 return 1;
1258 }
1259
1260 res = 0;
Dave Allisond9370732014-01-30 14:19:23 -08001261
Mike Lockwood94afecf2012-10-24 10:45:23 -07001262 while ((de = readdir(d))) {
1263 const char *name = de->d_name;
1264 /* always skip "." and ".." */
1265 if (name[0] == '.') {
1266 if (name[1] == 0) continue;
1267 if ((name[1] == '.') && (name[2] == 0)) continue;
1268 }
Dave Allisond9370732014-01-30 14:19:23 -08001269
Mike Lockwood94afecf2012-10-24 10:45:23 -07001270 if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) {
1271 ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name);
1272 continue;
1273 }
Dave Allisond9370732014-01-30 14:19:23 -08001274
Mike Lockwood94afecf2012-10-24 10:45:23 -07001275 if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) {
1276 ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name);
1277 continue;
1278 }
Dave Allisond9370732014-01-30 14:19:23 -08001279
Mike Lockwood94afecf2012-10-24 10:45:23 -07001280 srcpath[srcend] = dstpath[dstend] = '/';
1281 strcpy(srcpath+srcend+1, name);
1282 strcpy(dstpath+dstend+1, name);
Dave Allisond9370732014-01-30 14:19:23 -08001283
Mike Lockwood94afecf2012-10-24 10:45:23 -07001284 if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) {
1285 res = 1;
1286 }
Dave Allisond9370732014-01-30 14:19:23 -08001287
Mike Lockwood94afecf2012-10-24 10:45:23 -07001288 // Note: we will be leaving empty directories behind in srcpath,
1289 // but that is okay, the package manager will be erasing all of the
1290 // data associated with .apks that disappear.
Dave Allisond9370732014-01-30 14:19:23 -08001291
Mike Lockwood94afecf2012-10-24 10:45:23 -07001292 srcpath[srcend] = dstpath[dstend] = 0;
1293 }
Dave Allisond9370732014-01-30 14:19:23 -08001294
Mike Lockwood94afecf2012-10-24 10:45:23 -07001295 closedir(d);
1296 return res;
1297}
1298
1299int movefiles()
1300{
1301 DIR *d;
1302 int dfd, subfd;
1303 struct dirent *de;
1304 struct stat s;
1305 char buf[PKG_PATH_MAX+1];
1306 int bufp, bufe, bufi, readlen;
1307
1308 char srcpkg[PKG_NAME_MAX];
1309 char dstpkg[PKG_NAME_MAX];
1310 char srcpath[PKG_PATH_MAX];
1311 char dstpath[PKG_PATH_MAX];
1312 int dstuid=-1, dstgid=-1;
1313 int hasspace;
1314
1315 d = opendir(UPDATE_COMMANDS_DIR_PREFIX);
1316 if (d == NULL) {
1317 goto done;
1318 }
1319 dfd = dirfd(d);
1320
1321 /* Iterate through all files in the directory, executing the
1322 * file movements requested there-in.
1323 */
1324 while ((de = readdir(d))) {
1325 const char *name = de->d_name;
1326
1327 if (de->d_type == DT_DIR) {
1328 continue;
1329 } else {
1330 subfd = openat(dfd, name, O_RDONLY);
1331 if (subfd < 0) {
1332 ALOGW("Unable to open update commands at %s%s\n",
1333 UPDATE_COMMANDS_DIR_PREFIX, name);
1334 continue;
1335 }
Dave Allisond9370732014-01-30 14:19:23 -08001336
Mike Lockwood94afecf2012-10-24 10:45:23 -07001337 bufp = 0;
1338 bufe = 0;
1339 buf[PKG_PATH_MAX] = 0;
1340 srcpkg[0] = dstpkg[0] = 0;
1341 while (1) {
1342 bufi = bufp;
1343 while (bufi < bufe && buf[bufi] != '\n') {
1344 bufi++;
1345 }
1346 if (bufi < bufe) {
1347 buf[bufi] = 0;
1348 ALOGV("Processing line: %s\n", buf+bufp);
1349 hasspace = 0;
1350 while (bufp < bufi && isspace(buf[bufp])) {
1351 hasspace = 1;
1352 bufp++;
1353 }
1354 if (buf[bufp] == '#' || bufp == bufi) {
1355 // skip comments and empty lines.
1356 } else if (hasspace) {
1357 if (dstpkg[0] == 0) {
1358 ALOGW("Path before package line in %s%s: %s\n",
1359 UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
1360 } else if (srcpkg[0] == 0) {
1361 // Skip -- source package no longer exists.
1362 } else {
1363 ALOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg);
1364 if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) &&
1365 !create_move_path(dstpath, dstpkg, buf+bufp, 0)) {
1366 movefileordir(srcpath, dstpath,
1367 strlen(dstpath)-strlen(buf+bufp),
1368 dstuid, dstgid, &s);
1369 }
1370 }
1371 } else {
1372 char* div = strchr(buf+bufp, ':');
1373 if (div == NULL) {
1374 ALOGW("Bad package spec in %s%s; no ':' sep: %s\n",
1375 UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
1376 } else {
1377 *div = 0;
1378 div++;
1379 if (strlen(buf+bufp) < PKG_NAME_MAX) {
1380 strcpy(dstpkg, buf+bufp);
1381 } else {
1382 srcpkg[0] = dstpkg[0] = 0;
1383 ALOGW("Package name too long in %s%s: %s\n",
1384 UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
1385 }
1386 if (strlen(div) < PKG_NAME_MAX) {
1387 strcpy(srcpkg, div);
1388 } else {
1389 srcpkg[0] = dstpkg[0] = 0;
1390 ALOGW("Package name too long in %s%s: %s\n",
1391 UPDATE_COMMANDS_DIR_PREFIX, name, div);
1392 }
1393 if (srcpkg[0] != 0) {
1394 if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) {
1395 if (lstat(srcpath, &s) < 0) {
1396 // Package no longer exists -- skip.
1397 srcpkg[0] = 0;
1398 }
1399 } else {
1400 srcpkg[0] = 0;
1401 ALOGW("Can't create path %s in %s%s\n",
1402 div, UPDATE_COMMANDS_DIR_PREFIX, name);
1403 }
1404 if (srcpkg[0] != 0) {
1405 if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) {
1406 if (lstat(dstpath, &s) == 0) {
1407 dstuid = s.st_uid;
1408 dstgid = s.st_gid;
1409 } else {
1410 // Destination package doesn't
1411 // exist... due to original-package,
1412 // this is normal, so don't be
1413 // noisy about it.
1414 srcpkg[0] = 0;
1415 }
1416 } else {
1417 srcpkg[0] = 0;
1418 ALOGW("Can't create path %s in %s%s\n",
1419 div, UPDATE_COMMANDS_DIR_PREFIX, name);
1420 }
1421 }
1422 ALOGV("Transfering from %s to %s: uid=%d\n",
1423 srcpkg, dstpkg, dstuid);
1424 }
1425 }
1426 }
1427 bufp = bufi+1;
1428 } else {
1429 if (bufp == 0) {
1430 if (bufp < bufe) {
1431 ALOGW("Line too long in %s%s, skipping: %s\n",
1432 UPDATE_COMMANDS_DIR_PREFIX, name, buf);
1433 }
1434 } else if (bufp < bufe) {
1435 memcpy(buf, buf+bufp, bufe-bufp);
1436 bufe -= bufp;
1437 bufp = 0;
1438 }
1439 readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe);
1440 if (readlen < 0) {
1441 ALOGW("Failure reading update commands in %s%s: %s\n",
1442 UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno));
1443 break;
1444 } else if (readlen == 0) {
1445 break;
1446 }
1447 bufe += readlen;
1448 buf[bufe] = 0;
1449 ALOGV("Read buf: %s\n", buf);
1450 }
1451 }
1452 close(subfd);
1453 }
1454 }
1455 closedir(d);
1456done:
1457 return 0;
1458}
1459
1460int linklib(const char* pkgname, const char* asecLibDir, int userId)
1461{
1462 char pkgdir[PKG_PATH_MAX];
1463 char libsymlink[PKG_PATH_MAX];
1464 struct stat s, libStat;
1465 int rc = 0;
1466
1467 if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) {
1468 ALOGE("cannot create package path\n");
1469 return -1;
1470 }
1471 if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) {
1472 ALOGE("cannot create package lib symlink origin path\n");
1473 return -1;
1474 }
1475
1476 if (stat(pkgdir, &s) < 0) return -1;
1477
1478 if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
1479 ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
1480 return -1;
1481 }
1482
1483 if (chmod(pkgdir, 0700) < 0) {
1484 ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
1485 rc = -1;
1486 goto out;
1487 }
1488
1489 if (lstat(libsymlink, &libStat) < 0) {
1490 if (errno != ENOENT) {
1491 ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
1492 rc = -1;
1493 goto out;
1494 }
1495 } else {
1496 if (S_ISDIR(libStat.st_mode)) {
Narayan Kamath3aee2c52014-06-10 13:16:47 +01001497 if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
Mike Lockwood94afecf2012-10-24 10:45:23 -07001498 rc = -1;
1499 goto out;
1500 }
1501 } else if (S_ISLNK(libStat.st_mode)) {
1502 if (unlink(libsymlink) < 0) {
1503 ALOGE("couldn't unlink lib dir: %s\n", strerror(errno));
1504 rc = -1;
1505 goto out;
1506 }
1507 }
1508 }
1509
1510 if (symlink(asecLibDir, libsymlink) < 0) {
1511 ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir,
1512 strerror(errno));
1513 rc = -errno;
1514 goto out;
1515 }
1516
1517out:
1518 if (chmod(pkgdir, s.st_mode) < 0) {
1519 ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
1520 rc = -errno;
1521 }
1522
1523 if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
1524 ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
1525 return -errno;
1526 }
1527
1528 return rc;
1529}
MÃ¥rten Kongstad63568b12014-01-31 14:42:59 +01001530
1531static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd)
1532{
1533 static const char *IDMAP_BIN = "/system/bin/idmap";
1534 static const size_t MAX_INT_LEN = 32;
1535 char idmap_str[MAX_INT_LEN];
1536
1537 snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd);
1538
1539 execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL);
1540 ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno));
1541}
1542
1543// Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix)
1544// eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap
1545static int flatten_path(const char *prefix, const char *suffix,
1546 const char *overlay_path, char *idmap_path, size_t N)
1547{
1548 if (overlay_path == NULL || idmap_path == NULL) {
1549 return -1;
1550 }
1551 const size_t len_overlay_path = strlen(overlay_path);
1552 // will access overlay_path + 1 further below; requires absolute path
1553 if (len_overlay_path < 2 || *overlay_path != '/') {
1554 return -1;
1555 }
1556 const size_t len_idmap_root = strlen(prefix);
1557 const size_t len_suffix = strlen(suffix);
1558 if (SIZE_MAX - len_idmap_root < len_overlay_path ||
1559 SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) {
1560 // additions below would cause overflow
1561 return -1;
1562 }
1563 if (N < len_idmap_root + len_overlay_path + len_suffix) {
1564 return -1;
1565 }
1566 memset(idmap_path, 0, N);
1567 snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix);
1568 char *ch = idmap_path + len_idmap_root;
1569 while (*ch != '\0') {
1570 if (*ch == '/') {
1571 *ch = '@';
1572 }
1573 ++ch;
1574 }
1575 return 0;
1576}
1577
1578int idmap(const char *target_apk, const char *overlay_apk, uid_t uid)
1579{
1580 ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid);
1581
1582 int idmap_fd = -1;
1583 char idmap_path[PATH_MAX];
1584
1585 if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
1586 idmap_path, sizeof(idmap_path)) == -1) {
1587 ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk);
1588 goto fail;
1589 }
1590
1591 unlink(idmap_path);
1592 idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644);
1593 if (idmap_fd < 0) {
1594 ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno));
1595 goto fail;
1596 }
1597 if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) {
1598 ALOGE("idmap cannot chown '%s'\n", idmap_path);
1599 goto fail;
1600 }
1601 if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
1602 ALOGE("idmap cannot chmod '%s'\n", idmap_path);
1603 goto fail;
1604 }
1605
1606 pid_t pid;
1607 pid = fork();
1608 if (pid == 0) {
1609 /* child -- drop privileges before continuing */
1610 if (setgid(uid) != 0) {
1611 ALOGE("setgid(%d) failed during idmap\n", uid);
1612 exit(1);
1613 }
1614 if (setuid(uid) != 0) {
1615 ALOGE("setuid(%d) failed during idmap\n", uid);
1616 exit(1);
1617 }
1618 if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) {
1619 ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno));
1620 exit(1);
1621 }
1622
1623 run_idmap(target_apk, overlay_apk, idmap_fd);
1624 exit(1); /* only if exec call to idmap failed */
1625 } else {
1626 int status = wait_child(pid);
1627 if (status != 0) {
1628 ALOGE("idmap failed, status=0x%04x\n", status);
1629 goto fail;
1630 }
1631 }
1632
1633 close(idmap_fd);
1634 return 0;
1635fail:
1636 if (idmap_fd >= 0) {
1637 close(idmap_fd);
1638 unlink(idmap_path);
1639 }
1640 return -1;
1641}
Robert Craige9887e42014-02-20 10:25:56 -05001642
Robert Craigda30dc72014-03-27 10:21:12 -04001643int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid)
Robert Craige9887e42014-02-20 10:25:56 -05001644{
Robert Craigda30dc72014-03-27 10:21:12 -04001645 struct dirent *entry;
1646 DIR *d;
1647 struct stat s;
1648 char *userdir;
1649 char *primarydir;
1650 char *pkgdir;
Robert Craige9887e42014-02-20 10:25:56 -05001651 int ret = 0;
1652
Robert Craigda30dc72014-03-27 10:21:12 -04001653 // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
1654 unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
1655
1656 if (!pkgName || !seinfo) {
1657 ALOGE("Package name or seinfo tag is null when trying to restorecon.");
Robert Craige9887e42014-02-20 10:25:56 -05001658 return -1;
1659 }
1660
Robert Craigda30dc72014-03-27 10:21:12 -04001661 if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) {
1662 return -1;
1663 }
1664
1665 // Relabel for primary user.
1666 if (selinux_android_restorecon_pkgdir(primarydir, seinfo, uid, flags) < 0) {
1667 ALOGE("restorecon failed for %s: %s\n", primarydir, strerror(errno));
Robert Craige9887e42014-02-20 10:25:56 -05001668 ret |= -1;
1669 }
1670
Robert Craigda30dc72014-03-27 10:21:12 -04001671 if (asprintf(&userdir, "%s%s", android_data_dir.path, SECONDARY_USER_PREFIX) < 0) {
1672 free(primarydir);
1673 return -1;
Robert Craige9887e42014-02-20 10:25:56 -05001674 }
1675
Robert Craigda30dc72014-03-27 10:21:12 -04001676 // Relabel package directory for all secondary users.
1677 d = opendir(userdir);
1678 if (d == NULL) {
1679 free(primarydir);
1680 free(userdir);
1681 return -1;
1682 }
1683
1684 while ((entry = readdir(d))) {
1685 if (entry->d_type != DT_DIR) {
1686 continue;
1687 }
1688
1689 const char *user = entry->d_name;
1690 // Ignore "." and ".."
1691 if (!strcmp(user, ".") || !strcmp(user, "..")) {
1692 continue;
1693 }
1694
1695 // user directories start with a number
1696 if (user[0] < '0' || user[0] > '9') {
1697 ALOGE("Expecting numbered directory during restorecon. Instead got '%s'.", user);
1698 continue;
1699 }
1700
1701 if (asprintf(&pkgdir, "%s%s/%s", userdir, user, pkgName) < 0) {
1702 continue;
1703 }
1704
1705 if (stat(pkgdir, &s) < 0) {
1706 free(pkgdir);
1707 continue;
1708 }
1709
Stephen Smalley8ac2a642014-09-08 15:51:55 -04001710 if (selinux_android_restorecon_pkgdir(pkgdir, seinfo, s.st_uid, flags) < 0) {
Robert Craigda30dc72014-03-27 10:21:12 -04001711 ALOGE("restorecon failed for %s: %s\n", pkgdir, strerror(errno));
1712 ret |= -1;
1713 }
1714 free(pkgdir);
1715 }
1716
1717 closedir(d);
1718 free(primarydir);
1719 free(userdir);
Robert Craige9887e42014-02-20 10:25:56 -05001720 return ret;
1721}
Narayan Kamath3aee2c52014-06-10 13:16:47 +01001722
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001723int create_oat_dir(const char* oat_dir, const char* instruction_set)
1724{
1725 char oat_instr_dir[PKG_PATH_MAX];
1726
1727 if (validate_apk_path(oat_dir)) {
1728 ALOGE("invalid apk path '%s' (bad prefix)\n", oat_dir);
1729 return -1;
1730 }
Fyodor Kupolov8eed7e62015-04-06 19:09:02 -07001731 if (fs_prepare_dir(oat_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001732 return -1;
1733 }
1734 if (selinux_android_restorecon(oat_dir, 0)) {
1735 ALOGE("cannot restorecon dir '%s': %s\n", oat_dir, strerror(errno));
1736 return -1;
1737 }
1738 snprintf(oat_instr_dir, PKG_PATH_MAX, "%s/%s", oat_dir, instruction_set);
Fyodor Kupolov8eed7e62015-04-06 19:09:02 -07001739 if (fs_prepare_dir(oat_instr_dir, S_IRWXU | S_IRWXG | S_IXOTH, AID_SYSTEM, AID_INSTALL)) {
Fyodor Kupolov88ce4ff2015-03-03 12:25:29 -08001740 return -1;
1741 }
1742 return 0;
1743}
1744
1745int rm_package_dir(const char* apk_path)
1746{
1747 if (validate_apk_path(apk_path)) {
1748 ALOGE("invalid apk path '%s' (bad prefix)\n", apk_path);
1749 return -1;
1750 }
1751 return delete_dir_contents(apk_path, 1 /* also_delete_dir */ , NULL /* exclusion_predicate */);
1752}
1753
1754int calculate_oat_file_path(char path[PKG_PATH_MAX], const char *oat_dir, const char *apk_path,
1755 const char *instruction_set) {
1756 char *file_name_start;
1757 char *file_name_end;
1758
1759 file_name_start = strrchr(apk_path, '/');
1760 if (file_name_start == NULL) {
1761 ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
1762 return -1;
1763 }
1764 file_name_end = strrchr(apk_path, '.');
1765 if (file_name_end < file_name_start) {
1766 ALOGE("apk_path '%s' has no extension\n", apk_path);
1767 return -1;
1768 }
1769
1770 // Calculate file_name
1771 int file_name_len = file_name_end - file_name_start - 1;
1772 char file_name[file_name_len + 1];
1773 memcpy(file_name, file_name_start + 1, file_name_len);
1774 file_name[file_name_len] = '\0';
1775
1776 // <apk_parent_dir>/oat/<isa>/<file_name>.odex
1777 snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
1778 return 0;
1779}