• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright 2008, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 **     http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16 
17 #include <inttypes.h>
18 #include <sys/capability.h>
19 #include "installd.h"
20 #include <cutils/sched_policy.h>
21 #include <diskusage/dirsize.h>
22 #include <selinux/android.h>
23 
24 /* Directory records that are used in execution of commands. */
25 dir_rec_t android_data_dir;
26 dir_rec_t android_asec_dir;
27 dir_rec_t android_app_dir;
28 dir_rec_t android_app_private_dir;
29 dir_rec_t android_app_lib_dir;
30 dir_rec_t android_media_dir;
31 dir_rec_array_t android_system_dirs;
32 
install(const char * pkgname,uid_t uid,gid_t gid,const char * seinfo)33 int install(const char *pkgname, uid_t uid, gid_t gid, const char *seinfo)
34 {
35     char pkgdir[PKG_PATH_MAX];
36     char libsymlink[PKG_PATH_MAX];
37     char applibdir[PKG_PATH_MAX];
38     struct stat libStat;
39 
40     if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
41         ALOGE("invalid uid/gid: %d %d\n", uid, gid);
42         return -1;
43     }
44 
45     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
46         ALOGE("cannot create package path\n");
47         return -1;
48     }
49 
50     if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, 0)) {
51         ALOGE("cannot create package lib symlink origin path\n");
52         return -1;
53     }
54 
55     if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
56         ALOGE("cannot create package lib symlink dest path\n");
57         return -1;
58     }
59 
60     if (mkdir(pkgdir, 0751) < 0) {
61         ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
62         return -1;
63     }
64     if (chmod(pkgdir, 0751) < 0) {
65         ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
66         unlink(pkgdir);
67         return -1;
68     }
69 
70     if (lstat(libsymlink, &libStat) < 0) {
71         if (errno != ENOENT) {
72             ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
73             return -1;
74         }
75     } else {
76         if (S_ISDIR(libStat.st_mode)) {
77             if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
78                 ALOGE("couldn't delete lib directory during install for: %s", libsymlink);
79                 return -1;
80             }
81         } else if (S_ISLNK(libStat.st_mode)) {
82             if (unlink(libsymlink) < 0) {
83                 ALOGE("couldn't unlink lib directory during install for: %s", libsymlink);
84                 return -1;
85             }
86         }
87     }
88 
89     if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) {
90         ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
91         unlink(libsymlink);
92         unlink(pkgdir);
93         return -errno;
94     }
95 
96     if (symlink(applibdir, libsymlink) < 0) {
97         ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, applibdir,
98                 strerror(errno));
99         unlink(pkgdir);
100         return -1;
101     }
102 
103     if (chown(pkgdir, uid, gid) < 0) {
104         ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
105         unlink(libsymlink);
106         unlink(pkgdir);
107         return -1;
108     }
109 
110     return 0;
111 }
112 
uninstall(const char * pkgname,userid_t userid)113 int uninstall(const char *pkgname, userid_t userid)
114 {
115     char pkgdir[PKG_PATH_MAX];
116 
117     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
118         return -1;
119 
120     remove_profile_file(pkgname);
121 
122     /* delete contents AND directory, no exceptions */
123     return delete_dir_contents(pkgdir, 1, NULL);
124 }
125 
renamepkg(const char * oldpkgname,const char * newpkgname)126 int renamepkg(const char *oldpkgname, const char *newpkgname)
127 {
128     char oldpkgdir[PKG_PATH_MAX];
129     char newpkgdir[PKG_PATH_MAX];
130 
131     if (create_pkg_path(oldpkgdir, oldpkgname, PKG_DIR_POSTFIX, 0))
132         return -1;
133     if (create_pkg_path(newpkgdir, newpkgname, PKG_DIR_POSTFIX, 0))
134         return -1;
135 
136     if (rename(oldpkgdir, newpkgdir) < 0) {
137         ALOGE("cannot rename dir '%s' to '%s': %s\n", oldpkgdir, newpkgdir, strerror(errno));
138         return -errno;
139     }
140     return 0;
141 }
142 
fix_uid(const char * pkgname,uid_t uid,gid_t gid)143 int fix_uid(const char *pkgname, uid_t uid, gid_t gid)
144 {
145     char pkgdir[PKG_PATH_MAX];
146     struct stat s;
147     int rc = 0;
148 
149     if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
150         ALOGE("invalid uid/gid: %d %d\n", uid, gid);
151         return -1;
152     }
153 
154     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, 0)) {
155         ALOGE("cannot create package path\n");
156         return -1;
157     }
158 
159     if (stat(pkgdir, &s) < 0) return -1;
160 
161     if (s.st_uid != 0 || s.st_gid != 0) {
162         ALOGE("fixing uid of non-root pkg: %s %" PRIu32 " %" PRIu32 "\n", pkgdir, s.st_uid, s.st_gid);
163         return -1;
164     }
165 
166     if (chmod(pkgdir, 0751) < 0) {
167         ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
168         unlink(pkgdir);
169         return -errno;
170     }
171     if (chown(pkgdir, uid, gid) < 0) {
172         ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
173         unlink(pkgdir);
174         return -errno;
175     }
176 
177     return 0;
178 }
179 
delete_user_data(const char * pkgname,userid_t userid)180 int delete_user_data(const char *pkgname, userid_t userid)
181 {
182     char pkgdir[PKG_PATH_MAX];
183 
184     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid))
185         return -1;
186 
187     return delete_dir_contents(pkgdir, 0, NULL);
188 }
189 
make_user_data(const char * pkgname,uid_t uid,userid_t userid,const char * seinfo)190 int make_user_data(const char *pkgname, uid_t uid, userid_t userid, const char* seinfo)
191 {
192     char pkgdir[PKG_PATH_MAX];
193     char applibdir[PKG_PATH_MAX];
194     char libsymlink[PKG_PATH_MAX];
195     struct stat libStat;
196 
197     // Create the data dir for the package
198     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userid)) {
199         return -1;
200     }
201     if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userid)) {
202         ALOGE("cannot create package lib symlink origin path\n");
203         return -1;
204     }
205     if (create_pkg_path_in_dir(applibdir, &android_app_lib_dir, pkgname, PKG_DIR_POSTFIX)) {
206         ALOGE("cannot create package lib symlink dest path\n");
207         return -1;
208     }
209 
210     if (mkdir(pkgdir, 0751) < 0) {
211         ALOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
212         return -errno;
213     }
214     if (chmod(pkgdir, 0751) < 0) {
215         ALOGE("cannot chmod dir '%s': %s\n", pkgdir, strerror(errno));
216         unlink(pkgdir);
217         return -errno;
218     }
219 
220     if (lstat(libsymlink, &libStat) < 0) {
221         if (errno != ENOENT) {
222             ALOGE("couldn't stat lib dir for non-primary: %s\n", strerror(errno));
223             unlink(pkgdir);
224             return -1;
225         }
226     } else {
227         if (S_ISDIR(libStat.st_mode)) {
228             if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
229                 ALOGE("couldn't delete lib directory during install for non-primary: %s",
230                         libsymlink);
231                 unlink(pkgdir);
232                 return -1;
233             }
234         } else if (S_ISLNK(libStat.st_mode)) {
235             if (unlink(libsymlink) < 0) {
236                 ALOGE("couldn't unlink lib directory during install for non-primary: %s",
237                         libsymlink);
238                 unlink(pkgdir);
239                 return -1;
240             }
241         }
242     }
243 
244     if (selinux_android_setfilecon(pkgdir, pkgname, seinfo, uid) < 0) {
245         ALOGE("cannot setfilecon dir '%s': %s\n", pkgdir, strerror(errno));
246         unlink(libsymlink);
247         unlink(pkgdir);
248         return -errno;
249     }
250 
251     if (symlink(applibdir, libsymlink) < 0) {
252         ALOGE("couldn't symlink directory for non-primary '%s' -> '%s': %s\n", libsymlink,
253                 applibdir, strerror(errno));
254         unlink(pkgdir);
255         return -1;
256     }
257 
258     if (chown(pkgdir, uid, uid) < 0) {
259         ALOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
260         unlink(libsymlink);
261         unlink(pkgdir);
262         return -errno;
263     }
264 
265     return 0;
266 }
267 
make_user_config(userid_t userid)268 int make_user_config(userid_t userid)
269 {
270     if (ensure_config_user_dirs(userid) == -1) {
271         return -1;
272     }
273 
274     return 0;
275 }
276 
delete_user(userid_t userid)277 int delete_user(userid_t userid)
278 {
279     int status = 0;
280 
281     char data_path[PKG_PATH_MAX];
282     if ((create_user_path(data_path, userid) != 0)
283             || (delete_dir_contents(data_path, 1, NULL) != 0)) {
284         status = -1;
285     }
286 
287     char media_path[PATH_MAX];
288     if ((create_user_media_path(media_path, userid) != 0)
289             || (delete_dir_contents(media_path, 1, NULL) != 0)) {
290         status = -1;
291     }
292 
293     char config_path[PATH_MAX];
294     if ((create_user_config_path(config_path, userid) != 0)
295             || (delete_dir_contents(config_path, 1, NULL) != 0)) {
296         status = -1;
297     }
298 
299     return status;
300 }
301 
delete_cache(const char * pkgname,userid_t userid)302 int delete_cache(const char *pkgname, userid_t userid)
303 {
304     char cachedir[PKG_PATH_MAX];
305 
306     if (create_pkg_path(cachedir, pkgname, CACHE_DIR_POSTFIX, userid))
307         return -1;
308 
309     /* delete contents, not the directory, no exceptions */
310     return delete_dir_contents(cachedir, 0, NULL);
311 }
312 
delete_code_cache(const char * pkgname,userid_t userid)313 int delete_code_cache(const char *pkgname, userid_t userid)
314 {
315     char codecachedir[PKG_PATH_MAX];
316     struct stat s;
317 
318     if (create_pkg_path(codecachedir, pkgname, CODE_CACHE_DIR_POSTFIX, userid))
319         return -1;
320 
321     /* it's okay if code cache is missing */
322     if (lstat(codecachedir, &s) == -1 && errno == ENOENT) {
323         return 0;
324     }
325 
326     /* delete contents, not the directory, no exceptions */
327     return delete_dir_contents(codecachedir, 0, NULL);
328 }
329 
330 /* Try to ensure free_size bytes of storage are available.
331  * Returns 0 on success.
332  * This is rather simple-minded because doing a full LRU would
333  * be potentially memory-intensive, and without atime it would
334  * also require that apps constantly modify file metadata even
335  * when just reading from the cache, which is pretty awful.
336  */
free_cache(int64_t free_size)337 int free_cache(int64_t free_size)
338 {
339     cache_t* cache;
340     int64_t avail;
341     DIR *d;
342     struct dirent *de;
343     char tmpdir[PATH_MAX];
344     char *dirpos;
345 
346     avail = data_disk_free();
347     if (avail < 0) return -1;
348 
349     ALOGI("free_cache(%" PRId64 ") avail %" PRId64 "\n", free_size, avail);
350     if (avail >= free_size) return 0;
351 
352     cache = start_cache_collection();
353 
354     // Collect cache files for primary user.
355     if (create_user_path(tmpdir, 0) == 0) {
356         //ALOGI("adding cache files from %s\n", tmpdir);
357         add_cache_files(cache, tmpdir, "cache");
358     }
359 
360     // Search for other users and add any cache files from them.
361     snprintf(tmpdir, sizeof(tmpdir), "%s%s", android_data_dir.path,
362             SECONDARY_USER_PREFIX);
363     dirpos = tmpdir + strlen(tmpdir);
364     d = opendir(tmpdir);
365     if (d != NULL) {
366         while ((de = readdir(d))) {
367             if (de->d_type == DT_DIR) {
368                 const char *name = de->d_name;
369                     /* always skip "." and ".." */
370                 if (name[0] == '.') {
371                     if (name[1] == 0) continue;
372                     if ((name[1] == '.') && (name[2] == 0)) continue;
373                 }
374                 if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
375                     strcpy(dirpos, name);
376                     //ALOGI("adding cache files from %s\n", tmpdir);
377                     add_cache_files(cache, tmpdir, "cache");
378                 } else {
379                     ALOGW("Path exceeds limit: %s%s", tmpdir, name);
380                 }
381             }
382         }
383         closedir(d);
384     }
385 
386     // Collect cache files on external storage for all users (if it is mounted as part
387     // of the internal storage).
388     strcpy(tmpdir, android_media_dir.path);
389     dirpos = tmpdir + strlen(tmpdir);
390     d = opendir(tmpdir);
391     if (d != NULL) {
392         while ((de = readdir(d))) {
393             if (de->d_type == DT_DIR) {
394                 const char *name = de->d_name;
395                     /* skip any dir that doesn't start with a number, so not a user */
396                 if (name[0] < '0' || name[0] > '9') {
397                     continue;
398                 }
399                 if ((strlen(name)+(dirpos-tmpdir)) < (sizeof(tmpdir)-1)) {
400                     strcpy(dirpos, name);
401                     if (lookup_media_dir(tmpdir, "Android") == 0
402                             && lookup_media_dir(tmpdir, "data") == 0) {
403                         //ALOGI("adding cache files from %s\n", tmpdir);
404                         add_cache_files(cache, tmpdir, "cache");
405                     }
406                 } else {
407                     ALOGW("Path exceeds limit: %s%s", tmpdir, name);
408                 }
409             }
410         }
411         closedir(d);
412     }
413 
414     clear_cache_files(cache, free_size);
415     finish_cache_collection(cache);
416 
417     return data_disk_free() >= free_size ? 0 : -1;
418 }
419 
move_dex(const char * src,const char * dst,const char * instruction_set)420 int move_dex(const char *src, const char *dst, const char *instruction_set)
421 {
422     char src_dex[PKG_PATH_MAX];
423     char dst_dex[PKG_PATH_MAX];
424 
425     if (validate_apk_path(src)) {
426         ALOGE("invalid apk path '%s' (bad prefix)\n", src);
427         return -1;
428     }
429     if (validate_apk_path(dst)) {
430         ALOGE("invalid apk path '%s' (bad prefix)\n", dst);
431         return -1;
432     }
433 
434     if (create_cache_path(src_dex, src, instruction_set)) return -1;
435     if (create_cache_path(dst_dex, dst, instruction_set)) return -1;
436 
437     ALOGV("move %s -> %s\n", src_dex, dst_dex);
438     if (rename(src_dex, dst_dex) < 0) {
439         ALOGE("Couldn't move %s: %s\n", src_dex, strerror(errno));
440         return -1;
441     } else {
442         return 0;
443     }
444 }
445 
rm_dex(const char * path,const char * instruction_set)446 int rm_dex(const char *path, const char *instruction_set)
447 {
448     char dex_path[PKG_PATH_MAX];
449 
450     if (validate_apk_path(path) && validate_system_app_path(path)) {
451         ALOGE("invalid apk path '%s' (bad prefix)\n", path);
452         return -1;
453     }
454 
455     if (create_cache_path(dex_path, path, instruction_set)) return -1;
456 
457     ALOGV("unlink %s\n", dex_path);
458     if (unlink(dex_path) < 0) {
459         if (errno != ENOENT) {
460             ALOGE("Couldn't unlink %s: %s\n", dex_path, strerror(errno));
461         }
462         return -1;
463     } else {
464         return 0;
465     }
466 }
467 
get_size(const char * pkgname,userid_t userid,const char * apkpath,const char * libdirpath,const char * fwdlock_apkpath,const char * asecpath,const char * instruction_set,int64_t * _codesize,int64_t * _datasize,int64_t * _cachesize,int64_t * _asecsize)468 int get_size(const char *pkgname, userid_t userid, const char *apkpath,
469              const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath,
470              const char *instruction_set, int64_t *_codesize, int64_t *_datasize,
471              int64_t *_cachesize, int64_t* _asecsize)
472 {
473     DIR *d;
474     int dfd;
475     struct dirent *de;
476     struct stat s;
477     char path[PKG_PATH_MAX];
478 
479     int64_t codesize = 0;
480     int64_t datasize = 0;
481     int64_t cachesize = 0;
482     int64_t asecsize = 0;
483 
484         /* count the source apk as code -- but only if it's not
485          * on the /system partition and its not on the sdcard.
486          */
487     if (validate_system_app_path(apkpath) &&
488             strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
489         if (stat(apkpath, &s) == 0) {
490             codesize += stat_size(&s);
491         }
492     }
493         /* count the forward locked apk as code if it is given
494          */
495     if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
496         if (stat(fwdlock_apkpath, &s) == 0) {
497             codesize += stat_size(&s);
498         }
499     }
500         /* count the cached dexfile as code */
501     if (!create_cache_path(path, apkpath, instruction_set)) {
502         if (stat(path, &s) == 0) {
503             codesize += stat_size(&s);
504         }
505     }
506 
507         /* add in size of any libraries */
508     if (libdirpath != NULL && libdirpath[0] != '!') {
509         d = opendir(libdirpath);
510         if (d != NULL) {
511             dfd = dirfd(d);
512             codesize += calculate_dir_size(dfd);
513             closedir(d);
514         }
515     }
516 
517         /* compute asec size if it is given
518          */
519     if (asecpath != NULL && asecpath[0] != '!') {
520         if (stat(asecpath, &s) == 0) {
521             asecsize += stat_size(&s);
522         }
523     }
524 
525     if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, userid)) {
526         goto done;
527     }
528 
529     d = opendir(path);
530     if (d == NULL) {
531         goto done;
532     }
533     dfd = dirfd(d);
534 
535     /* most stuff in the pkgdir is data, except for the "cache"
536      * directory and below, which is cache, and the "lib" directory
537      * and below, which is code...
538      */
539     while ((de = readdir(d))) {
540         const char *name = de->d_name;
541 
542         if (de->d_type == DT_DIR) {
543             int subfd;
544             int64_t statsize = 0;
545             int64_t dirsize = 0;
546                 /* always skip "." and ".." */
547             if (name[0] == '.') {
548                 if (name[1] == 0) continue;
549                 if ((name[1] == '.') && (name[2] == 0)) continue;
550             }
551             if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
552                 statsize = stat_size(&s);
553             }
554             subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
555             if (subfd >= 0) {
556                 dirsize = calculate_dir_size(subfd);
557             }
558             if(!strcmp(name,"lib")) {
559                 codesize += dirsize + statsize;
560             } else if(!strcmp(name,"cache")) {
561                 cachesize += dirsize + statsize;
562             } else {
563                 datasize += dirsize + statsize;
564             }
565         } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
566             // This is the symbolic link to the application's library
567             // code.  We'll count this as code instead of data, since
568             // it is not something that the app creates.
569             if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
570                 codesize += stat_size(&s);
571             }
572         } else {
573             if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
574                 datasize += stat_size(&s);
575             }
576         }
577     }
578     closedir(d);
579 done:
580     *_codesize = codesize;
581     *_datasize = datasize;
582     *_cachesize = cachesize;
583     *_asecsize = asecsize;
584     return 0;
585 }
586 
create_cache_path(char path[PKG_PATH_MAX],const char * src,const char * instruction_set)587 int create_cache_path(char path[PKG_PATH_MAX], const char *src, const char *instruction_set)
588 {
589     char *tmp;
590     int srclen;
591     int dstlen;
592 
593     srclen = strlen(src);
594 
595         /* demand that we are an absolute path */
596     if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
597         return -1;
598     }
599 
600     if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
601         return -1;
602     }
603 
604     dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
605         strlen(instruction_set) +
606         strlen(DALVIK_CACHE_POSTFIX) + 2;
607 
608     if (dstlen > PKG_PATH_MAX) {
609         return -1;
610     }
611 
612     sprintf(path,"%s%s/%s%s",
613             DALVIK_CACHE_PREFIX,
614             instruction_set,
615             src + 1, /* skip the leading / */
616             DALVIK_CACHE_POSTFIX);
617 
618     for(tmp = path + strlen(DALVIK_CACHE_PREFIX) + strlen(instruction_set) + 1; *tmp; tmp++) {
619         if (*tmp == '/') {
620             *tmp = '@';
621         }
622     }
623 
624     return 0;
625 }
626 
run_dexopt(int zip_fd,int odex_fd,const char * input_file_name,const char * output_file_name)627 static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
628     const char* output_file_name)
629 {
630     /* platform-specific flags affecting optimization and verification */
631     char dexopt_flags[PROPERTY_VALUE_MAX];
632     property_get("dalvik.vm.dexopt-flags", dexopt_flags, "");
633     ALOGV("dalvik.vm.dexopt-flags=%s\n", dexopt_flags);
634 
635     static const char* DEX_OPT_BIN = "/system/bin/dexopt";
636     static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
637     char zip_num[MAX_INT_LEN];
638     char odex_num[MAX_INT_LEN];
639 
640     sprintf(zip_num, "%d", zip_fd);
641     sprintf(odex_num, "%d", odex_fd);
642 
643     ALOGV("Running %s in=%s out=%s\n", DEX_OPT_BIN, input_file_name, output_file_name);
644     execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name,
645         dexopt_flags, (char*) NULL);
646     ALOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
647 }
648 
run_patchoat(int input_fd,int oat_fd,const char * input_file_name,const char * output_file_name,const char * pkgname,const char * instruction_set)649 static void run_patchoat(int input_fd, int oat_fd, const char* input_file_name,
650     const char* output_file_name, const char *pkgname, const char *instruction_set)
651 {
652     static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
653     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
654 
655     static const char* PATCHOAT_BIN = "/system/bin/patchoat";
656     if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
657         ALOGE("Instruction set %s longer than max length of %d",
658               instruction_set, MAX_INSTRUCTION_SET_LEN);
659         return;
660     }
661 
662     /* input_file_name/input_fd should be the .odex/.oat file that is precompiled. I think*/
663     char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
664     char output_oat_fd_arg[strlen("--output-oat-fd=") + MAX_INT_LEN];
665     char input_oat_fd_arg[strlen("--input-oat-fd=") + MAX_INT_LEN];
666     const char* patched_image_location_arg = "--patched-image-location=/system/framework/boot.art";
667     // The caller has already gotten all the locks we need.
668     const char* no_lock_arg = "--no-lock-output";
669     sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
670     sprintf(output_oat_fd_arg, "--output-oat-fd=%d", oat_fd);
671     sprintf(input_oat_fd_arg, "--input-oat-fd=%d", input_fd);
672     ALOGE("Running %s isa=%s in-fd=%d (%s) out-fd=%d (%s)\n",
673           PATCHOAT_BIN, instruction_set, input_fd, input_file_name, oat_fd, output_file_name);
674 
675     /* patchoat, patched-image-location, no-lock, isa, input-fd, output-fd */
676     char* argv[7];
677     argv[0] = (char*) PATCHOAT_BIN;
678     argv[1] = (char*) patched_image_location_arg;
679     argv[2] = (char*) no_lock_arg;
680     argv[3] = instruction_set_arg;
681     argv[4] = output_oat_fd_arg;
682     argv[5] = input_oat_fd_arg;
683     argv[6] = NULL;
684 
685     execv(PATCHOAT_BIN, (char* const *)argv);
686     ALOGE("execv(%s) failed: %s\n", PATCHOAT_BIN, strerror(errno));
687 }
688 
run_dex2oat(int zip_fd,int oat_fd,const char * input_file_name,const char * output_file_name,const char * pkgname,const char * instruction_set,bool vm_safe_mode)689 static void run_dex2oat(int zip_fd, int oat_fd, const char* input_file_name,
690     const char* output_file_name, const char *pkgname, const char *instruction_set,
691     bool vm_safe_mode)
692 {
693     static const unsigned int MAX_INSTRUCTION_SET_LEN = 7;
694 
695     if (strlen(instruction_set) >= MAX_INSTRUCTION_SET_LEN) {
696         ALOGE("Instruction set %s longer than max length of %d",
697               instruction_set, MAX_INSTRUCTION_SET_LEN);
698         return;
699     }
700 
701     char prop_buf[PROPERTY_VALUE_MAX];
702     bool profiler = (property_get("dalvik.vm.profiler", prop_buf, "0") > 0) && (prop_buf[0] == '1');
703 
704     char dex2oat_Xms_flag[PROPERTY_VALUE_MAX];
705     bool have_dex2oat_Xms_flag = property_get("dalvik.vm.dex2oat-Xms", dex2oat_Xms_flag, NULL) > 0;
706 
707     char dex2oat_Xmx_flag[PROPERTY_VALUE_MAX];
708     bool have_dex2oat_Xmx_flag = property_get("dalvik.vm.dex2oat-Xmx", dex2oat_Xmx_flag, NULL) > 0;
709 
710     char dex2oat_compiler_filter_flag[PROPERTY_VALUE_MAX];
711     bool have_dex2oat_compiler_filter_flag = property_get("dalvik.vm.dex2oat-filter",
712                                                           dex2oat_compiler_filter_flag, NULL) > 0;
713 
714     char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
715     sprintf(dex2oat_isa_features_key, "dalvik.vm.isa.%s.features", instruction_set);
716     char dex2oat_isa_features[PROPERTY_VALUE_MAX];
717     bool have_dex2oat_isa_features = property_get(dex2oat_isa_features_key,
718                                                   dex2oat_isa_features, NULL) > 0;
719 
720     char dex2oat_flags[PROPERTY_VALUE_MAX];
721     bool have_dex2oat_flags = property_get("dalvik.vm.dex2oat-flags", dex2oat_flags, NULL) > 0;
722     ALOGV("dalvik.vm.dex2oat-flags=%s\n", dex2oat_flags);
723 
724     // If we booting without the real /data, don't spend time compiling.
725     char vold_decrypt[PROPERTY_VALUE_MAX];
726     bool have_vold_decrypt = property_get("vold.decrypt", vold_decrypt, "") > 0;
727     bool skip_compilation = (have_vold_decrypt &&
728                              (strcmp(vold_decrypt, "trigger_restart_min_framework") == 0 ||
729                              (strcmp(vold_decrypt, "1") == 0)));
730 
731     static const char* DEX2OAT_BIN = "/system/bin/dex2oat";
732 
733     static const char* RUNTIME_ARG = "--runtime-arg";
734 
735     static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
736 
737     char zip_fd_arg[strlen("--zip-fd=") + MAX_INT_LEN];
738     char zip_location_arg[strlen("--zip-location=") + PKG_PATH_MAX];
739     char oat_fd_arg[strlen("--oat-fd=") + MAX_INT_LEN];
740     char oat_location_arg[strlen("--oat-location=") + PKG_PATH_MAX];
741     char instruction_set_arg[strlen("--instruction-set=") + MAX_INSTRUCTION_SET_LEN];
742     char instruction_set_features_arg[strlen("--instruction-set-features=") + PROPERTY_VALUE_MAX];
743     char profile_file_arg[strlen("--profile-file=") + PKG_PATH_MAX];
744     char top_k_profile_threshold_arg[strlen("--top-k-profile-threshold=") + PROPERTY_VALUE_MAX];
745     char dex2oat_Xms_arg[strlen("-Xms") + PROPERTY_VALUE_MAX];
746     char dex2oat_Xmx_arg[strlen("-Xmx") + PROPERTY_VALUE_MAX];
747     char dex2oat_compiler_filter_arg[strlen("--compiler-filter=") + PROPERTY_VALUE_MAX];
748 
749     sprintf(zip_fd_arg, "--zip-fd=%d", zip_fd);
750     sprintf(zip_location_arg, "--zip-location=%s", input_file_name);
751     sprintf(oat_fd_arg, "--oat-fd=%d", oat_fd);
752     sprintf(oat_location_arg, "--oat-location=%s", output_file_name);
753     sprintf(instruction_set_arg, "--instruction-set=%s", instruction_set);
754     sprintf(instruction_set_features_arg, "--instruction-set-features=%s", dex2oat_isa_features);
755 
756     bool have_profile_file = false;
757     bool have_top_k_profile_threshold = false;
758     if (profiler && (strcmp(pkgname, "*") != 0)) {
759         char profile_file[PKG_PATH_MAX];
760         snprintf(profile_file, sizeof(profile_file), "%s/%s",
761                  DALVIK_CACHE_PREFIX "profiles", pkgname);
762         struct stat st;
763         if ((stat(profile_file, &st) == 0) && (st.st_size > 0)) {
764             sprintf(profile_file_arg, "--profile-file=%s", profile_file);
765             have_profile_file = true;
766             if (property_get("dalvik.vm.profile.top-k-thr", prop_buf, NULL) > 0) {
767                 snprintf(top_k_profile_threshold_arg, sizeof(top_k_profile_threshold_arg),
768                          "--top-k-profile-threshold=%s", prop_buf);
769                 have_top_k_profile_threshold = true;
770             }
771         }
772     }
773 
774     if (have_dex2oat_Xms_flag) {
775         sprintf(dex2oat_Xms_arg, "-Xms%s", dex2oat_Xms_flag);
776     }
777     if (have_dex2oat_Xmx_flag) {
778         sprintf(dex2oat_Xmx_arg, "-Xmx%s", dex2oat_Xmx_flag);
779     }
780     if (skip_compilation) {
781         strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=verify-none");
782         have_dex2oat_compiler_filter_flag = true;
783     } else if (vm_safe_mode) {
784         strcpy(dex2oat_compiler_filter_arg, "--compiler-filter=interpret-only");
785         have_dex2oat_compiler_filter_flag = true;
786     } else if (have_dex2oat_compiler_filter_flag) {
787         sprintf(dex2oat_compiler_filter_arg, "--compiler-filter=%s", dex2oat_compiler_filter_flag);
788     }
789 
790     ALOGV("Running %s in=%s out=%s\n", DEX2OAT_BIN, input_file_name, output_file_name);
791 
792     char* argv[7  // program name, mandatory arguments and the final NULL
793                + (have_dex2oat_isa_features ? 1 : 0)
794                + (have_profile_file ? 1 : 0)
795                + (have_top_k_profile_threshold ? 1 : 0)
796                + (have_dex2oat_Xms_flag ? 2 : 0)
797                + (have_dex2oat_Xmx_flag ? 2 : 0)
798                + (have_dex2oat_compiler_filter_flag ? 1 : 0)
799                + (have_dex2oat_flags ? 1 : 0)];
800     int i = 0;
801     argv[i++] = (char*)DEX2OAT_BIN;
802     argv[i++] = zip_fd_arg;
803     argv[i++] = zip_location_arg;
804     argv[i++] = oat_fd_arg;
805     argv[i++] = oat_location_arg;
806     argv[i++] = instruction_set_arg;
807     if (have_dex2oat_isa_features) {
808         argv[i++] = instruction_set_features_arg;
809     }
810     if (have_profile_file) {
811         argv[i++] = profile_file_arg;
812     }
813     if (have_top_k_profile_threshold) {
814         argv[i++] = top_k_profile_threshold_arg;
815     }
816     if (have_dex2oat_Xms_flag) {
817         argv[i++] = (char*)RUNTIME_ARG;
818         argv[i++] = dex2oat_Xms_arg;
819     }
820     if (have_dex2oat_Xmx_flag) {
821         argv[i++] = (char*)RUNTIME_ARG;
822         argv[i++] = dex2oat_Xmx_arg;
823     }
824     if (have_dex2oat_compiler_filter_flag) {
825         argv[i++] = dex2oat_compiler_filter_arg;
826     }
827     if (have_dex2oat_flags) {
828         argv[i++] = dex2oat_flags;
829     }
830     // Do not add after dex2oat_flags, they should override others for debugging.
831     argv[i] = NULL;
832 
833     execv(DEX2OAT_BIN, (char* const *)argv);
834     ALOGE("execl(%s) failed: %s\n", DEX2OAT_BIN, strerror(errno));
835 }
836 
wait_child(pid_t pid)837 static int wait_child(pid_t pid)
838 {
839     int status;
840     pid_t got_pid;
841 
842     while (1) {
843         got_pid = waitpid(pid, &status, 0);
844         if (got_pid == -1 && errno == EINTR) {
845             printf("waitpid interrupted, retrying\n");
846         } else {
847             break;
848         }
849     }
850     if (got_pid != pid) {
851         ALOGW("waitpid failed: wanted %d, got %d: %s\n",
852             (int) pid, (int) got_pid, strerror(errno));
853         return 1;
854     }
855 
856     if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
857         return 0;
858     } else {
859         return status;      /* always nonzero */
860     }
861 }
862 
dexopt(const char * apk_path,uid_t uid,bool is_public,const char * pkgname,const char * instruction_set,bool vm_safe_mode,bool is_patchoat)863 int dexopt(const char *apk_path, uid_t uid, bool is_public,
864            const char *pkgname, const char *instruction_set,
865            bool vm_safe_mode, bool is_patchoat)
866 {
867     struct utimbuf ut;
868     struct stat input_stat, dex_stat;
869     char out_path[PKG_PATH_MAX];
870     char persist_sys_dalvik_vm_lib[PROPERTY_VALUE_MAX];
871     char *end;
872     const char *input_file;
873     char in_odex_path[PKG_PATH_MAX];
874     int res, input_fd=-1, out_fd=-1;
875 
876     if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
877         return -1;
878     }
879 
880     /* The command to run depend on the value of persist.sys.dalvik.vm.lib */
881     property_get("persist.sys.dalvik.vm.lib.2", persist_sys_dalvik_vm_lib, "libart.so");
882 
883     if (is_patchoat && strncmp(persist_sys_dalvik_vm_lib, "libart", 6) != 0) {
884         /* We may only patch if we are libart */
885         ALOGE("Patching is only supported in libart\n");
886         return -1;
887     }
888 
889     /* Before anything else: is there a .odex file?  If so, we have
890      * precompiled the apk and there is nothing to do here.
891      *
892      * We skip this if we are doing a patchoat.
893      */
894     strcpy(out_path, apk_path);
895     end = strrchr(out_path, '.');
896     if (end != NULL && !is_patchoat) {
897         strcpy(end, ".odex");
898         if (stat(out_path, &dex_stat) == 0) {
899             return 0;
900         }
901     }
902 
903     if (create_cache_path(out_path, apk_path, instruction_set)) {
904         return -1;
905     }
906 
907     if (is_patchoat) {
908         /* /system/framework/whatever.jar -> /system/framework/<isa>/whatever.odex */
909         strcpy(in_odex_path, apk_path);
910         end = strrchr(in_odex_path, '/');
911         if (end == NULL) {
912             ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
913             return -1;
914         }
915         const char *apk_end = apk_path + (end - in_odex_path); // strrchr(apk_path, '/');
916         strcpy(end + 1, instruction_set); // in_odex_path now is /system/framework/<isa>\0
917         strcat(in_odex_path, apk_end);
918         end = strrchr(in_odex_path, '.');
919         if (end == NULL) {
920             return -1;
921         }
922         strcpy(end + 1, "odex");
923         input_file = in_odex_path;
924     } else {
925         input_file = apk_path;
926     }
927 
928     memset(&input_stat, 0, sizeof(input_stat));
929     stat(input_file, &input_stat);
930 
931     input_fd = open(input_file, O_RDONLY, 0);
932     if (input_fd < 0) {
933         ALOGE("installd cannot open '%s' for input during dexopt\n", input_file);
934         return -1;
935     }
936 
937     unlink(out_path);
938     out_fd = open(out_path, O_RDWR | O_CREAT | O_EXCL, 0644);
939     if (out_fd < 0) {
940         ALOGE("installd cannot open '%s' for output during dexopt\n", out_path);
941         goto fail;
942     }
943     if (fchmod(out_fd,
944                S_IRUSR|S_IWUSR|S_IRGRP |
945                (is_public ? S_IROTH : 0)) < 0) {
946         ALOGE("installd cannot chmod '%s' during dexopt\n", out_path);
947         goto fail;
948     }
949     if (fchown(out_fd, AID_SYSTEM, uid) < 0) {
950         ALOGE("installd cannot chown '%s' during dexopt\n", out_path);
951         goto fail;
952     }
953 
954     // Create profile file if there is a package name present.
955     if (strcmp(pkgname, "*") != 0) {
956         create_profile_file(pkgname, uid);
957     }
958 
959 
960     ALOGV("DexInv: --- BEGIN '%s' ---\n", input_file);
961 
962     pid_t pid;
963     pid = fork();
964     if (pid == 0) {
965         /* child -- drop privileges before continuing */
966         if (setgid(uid) != 0) {
967             ALOGE("setgid(%d) failed in installd during dexopt\n", uid);
968             exit(64);
969         }
970         if (setuid(uid) != 0) {
971             ALOGE("setuid(%d) failed in installd during dexopt\n", uid);
972             exit(65);
973         }
974         // drop capabilities
975         struct __user_cap_header_struct capheader;
976         struct __user_cap_data_struct capdata[2];
977         memset(&capheader, 0, sizeof(capheader));
978         memset(&capdata, 0, sizeof(capdata));
979         capheader.version = _LINUX_CAPABILITY_VERSION_3;
980         if (capset(&capheader, &capdata[0]) < 0) {
981             ALOGE("capset failed: %s\n", strerror(errno));
982             exit(66);
983         }
984         if (set_sched_policy(0, SP_BACKGROUND) < 0) {
985             ALOGE("set_sched_policy failed: %s\n", strerror(errno));
986             exit(70);
987         }
988         if (flock(out_fd, LOCK_EX | LOCK_NB) != 0) {
989             ALOGE("flock(%s) failed: %s\n", out_path, strerror(errno));
990             exit(67);
991         }
992 
993         if (strncmp(persist_sys_dalvik_vm_lib, "libdvm", 6) == 0) {
994             run_dexopt(input_fd, out_fd, input_file, out_path);
995         } else if (strncmp(persist_sys_dalvik_vm_lib, "libart", 6) == 0) {
996             if (is_patchoat) {
997                 run_patchoat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set);
998             } else {
999                 run_dex2oat(input_fd, out_fd, input_file, out_path, pkgname, instruction_set,
1000                             vm_safe_mode);
1001             }
1002         } else {
1003             exit(69);   /* Unexpected persist.sys.dalvik.vm.lib value */
1004         }
1005         exit(68);   /* only get here on exec failure */
1006     } else {
1007         res = wait_child(pid);
1008         if (res == 0) {
1009             ALOGV("DexInv: --- END '%s' (success) ---\n", input_file);
1010         } else {
1011             ALOGE("DexInv: --- END '%s' --- status=0x%04x, process failed\n", input_file, res);
1012             goto fail;
1013         }
1014     }
1015 
1016     ut.actime = input_stat.st_atime;
1017     ut.modtime = input_stat.st_mtime;
1018     utime(out_path, &ut);
1019 
1020     close(out_fd);
1021     close(input_fd);
1022     return 0;
1023 
1024 fail:
1025     if (out_fd >= 0) {
1026         close(out_fd);
1027         unlink(out_path);
1028     }
1029     if (input_fd >= 0) {
1030         close(input_fd);
1031     }
1032     return -1;
1033 }
1034 
mkinnerdirs(char * path,int basepos,mode_t mode,int uid,int gid,struct stat * statbuf)1035 void mkinnerdirs(char* path, int basepos, mode_t mode, int uid, int gid,
1036         struct stat* statbuf)
1037 {
1038     while (path[basepos] != 0) {
1039         if (path[basepos] == '/') {
1040             path[basepos] = 0;
1041             if (lstat(path, statbuf) < 0) {
1042                 ALOGV("Making directory: %s\n", path);
1043                 if (mkdir(path, mode) == 0) {
1044                     chown(path, uid, gid);
1045                 } else {
1046                     ALOGW("Unable to make directory %s: %s\n", path, strerror(errno));
1047                 }
1048             }
1049             path[basepos] = '/';
1050             basepos++;
1051         }
1052         basepos++;
1053     }
1054 }
1055 
movefileordir(char * srcpath,char * dstpath,int dstbasepos,int dstuid,int dstgid,struct stat * statbuf)1056 int movefileordir(char* srcpath, char* dstpath, int dstbasepos,
1057         int dstuid, int dstgid, struct stat* statbuf)
1058 {
1059     DIR *d;
1060     struct dirent *de;
1061     int res;
1062 
1063     int srcend = strlen(srcpath);
1064     int dstend = strlen(dstpath);
1065 
1066     if (lstat(srcpath, statbuf) < 0) {
1067         ALOGW("Unable to stat %s: %s\n", srcpath, strerror(errno));
1068         return 1;
1069     }
1070 
1071     if ((statbuf->st_mode&S_IFDIR) == 0) {
1072         mkinnerdirs(dstpath, dstbasepos, S_IRWXU|S_IRWXG|S_IXOTH,
1073                 dstuid, dstgid, statbuf);
1074         ALOGV("Renaming %s to %s (uid %d)\n", srcpath, dstpath, dstuid);
1075         if (rename(srcpath, dstpath) >= 0) {
1076             if (chown(dstpath, dstuid, dstgid) < 0) {
1077                 ALOGE("cannot chown %s: %s\n", dstpath, strerror(errno));
1078                 unlink(dstpath);
1079                 return 1;
1080             }
1081         } else {
1082             ALOGW("Unable to rename %s to %s: %s\n",
1083                 srcpath, dstpath, strerror(errno));
1084             return 1;
1085         }
1086         return 0;
1087     }
1088 
1089     d = opendir(srcpath);
1090     if (d == NULL) {
1091         ALOGW("Unable to opendir %s: %s\n", srcpath, strerror(errno));
1092         return 1;
1093     }
1094 
1095     res = 0;
1096 
1097     while ((de = readdir(d))) {
1098         const char *name = de->d_name;
1099             /* always skip "." and ".." */
1100         if (name[0] == '.') {
1101             if (name[1] == 0) continue;
1102             if ((name[1] == '.') && (name[2] == 0)) continue;
1103         }
1104 
1105         if ((srcend+strlen(name)) >= (PKG_PATH_MAX-2)) {
1106             ALOGW("Source path too long; skipping: %s/%s\n", srcpath, name);
1107             continue;
1108         }
1109 
1110         if ((dstend+strlen(name)) >= (PKG_PATH_MAX-2)) {
1111             ALOGW("Destination path too long; skipping: %s/%s\n", dstpath, name);
1112             continue;
1113         }
1114 
1115         srcpath[srcend] = dstpath[dstend] = '/';
1116         strcpy(srcpath+srcend+1, name);
1117         strcpy(dstpath+dstend+1, name);
1118 
1119         if (movefileordir(srcpath, dstpath, dstbasepos, dstuid, dstgid, statbuf) != 0) {
1120             res = 1;
1121         }
1122 
1123         // Note: we will be leaving empty directories behind in srcpath,
1124         // but that is okay, the package manager will be erasing all of the
1125         // data associated with .apks that disappear.
1126 
1127         srcpath[srcend] = dstpath[dstend] = 0;
1128     }
1129 
1130     closedir(d);
1131     return res;
1132 }
1133 
movefiles()1134 int movefiles()
1135 {
1136     DIR *d;
1137     int dfd, subfd;
1138     struct dirent *de;
1139     struct stat s;
1140     char buf[PKG_PATH_MAX+1];
1141     int bufp, bufe, bufi, readlen;
1142 
1143     char srcpkg[PKG_NAME_MAX];
1144     char dstpkg[PKG_NAME_MAX];
1145     char srcpath[PKG_PATH_MAX];
1146     char dstpath[PKG_PATH_MAX];
1147     int dstuid=-1, dstgid=-1;
1148     int hasspace;
1149 
1150     d = opendir(UPDATE_COMMANDS_DIR_PREFIX);
1151     if (d == NULL) {
1152         goto done;
1153     }
1154     dfd = dirfd(d);
1155 
1156         /* Iterate through all files in the directory, executing the
1157          * file movements requested there-in.
1158          */
1159     while ((de = readdir(d))) {
1160         const char *name = de->d_name;
1161 
1162         if (de->d_type == DT_DIR) {
1163             continue;
1164         } else {
1165             subfd = openat(dfd, name, O_RDONLY);
1166             if (subfd < 0) {
1167                 ALOGW("Unable to open update commands at %s%s\n",
1168                         UPDATE_COMMANDS_DIR_PREFIX, name);
1169                 continue;
1170             }
1171 
1172             bufp = 0;
1173             bufe = 0;
1174             buf[PKG_PATH_MAX] = 0;
1175             srcpkg[0] = dstpkg[0] = 0;
1176             while (1) {
1177                 bufi = bufp;
1178                 while (bufi < bufe && buf[bufi] != '\n') {
1179                     bufi++;
1180                 }
1181                 if (bufi < bufe) {
1182                     buf[bufi] = 0;
1183                     ALOGV("Processing line: %s\n", buf+bufp);
1184                     hasspace = 0;
1185                     while (bufp < bufi && isspace(buf[bufp])) {
1186                         hasspace = 1;
1187                         bufp++;
1188                     }
1189                     if (buf[bufp] == '#' || bufp == bufi) {
1190                         // skip comments and empty lines.
1191                     } else if (hasspace) {
1192                         if (dstpkg[0] == 0) {
1193                             ALOGW("Path before package line in %s%s: %s\n",
1194                                     UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
1195                         } else if (srcpkg[0] == 0) {
1196                             // Skip -- source package no longer exists.
1197                         } else {
1198                             ALOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg);
1199                             if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) &&
1200                                     !create_move_path(dstpath, dstpkg, buf+bufp, 0)) {
1201                                 movefileordir(srcpath, dstpath,
1202                                         strlen(dstpath)-strlen(buf+bufp),
1203                                         dstuid, dstgid, &s);
1204                             }
1205                         }
1206                     } else {
1207                         char* div = strchr(buf+bufp, ':');
1208                         if (div == NULL) {
1209                             ALOGW("Bad package spec in %s%s; no ':' sep: %s\n",
1210                                     UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
1211                         } else {
1212                             *div = 0;
1213                             div++;
1214                             if (strlen(buf+bufp) < PKG_NAME_MAX) {
1215                                 strcpy(dstpkg, buf+bufp);
1216                             } else {
1217                                 srcpkg[0] = dstpkg[0] = 0;
1218                                 ALOGW("Package name too long in %s%s: %s\n",
1219                                         UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
1220                             }
1221                             if (strlen(div) < PKG_NAME_MAX) {
1222                                 strcpy(srcpkg, div);
1223                             } else {
1224                                 srcpkg[0] = dstpkg[0] = 0;
1225                                 ALOGW("Package name too long in %s%s: %s\n",
1226                                         UPDATE_COMMANDS_DIR_PREFIX, name, div);
1227                             }
1228                             if (srcpkg[0] != 0) {
1229                                 if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) {
1230                                     if (lstat(srcpath, &s) < 0) {
1231                                         // Package no longer exists -- skip.
1232                                         srcpkg[0] = 0;
1233                                     }
1234                                 } else {
1235                                     srcpkg[0] = 0;
1236                                     ALOGW("Can't create path %s in %s%s\n",
1237                                             div, UPDATE_COMMANDS_DIR_PREFIX, name);
1238                                 }
1239                                 if (srcpkg[0] != 0) {
1240                                     if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) {
1241                                         if (lstat(dstpath, &s) == 0) {
1242                                             dstuid = s.st_uid;
1243                                             dstgid = s.st_gid;
1244                                         } else {
1245                                             // Destination package doesn't
1246                                             // exist...  due to original-package,
1247                                             // this is normal, so don't be
1248                                             // noisy about it.
1249                                             srcpkg[0] = 0;
1250                                         }
1251                                     } else {
1252                                         srcpkg[0] = 0;
1253                                         ALOGW("Can't create path %s in %s%s\n",
1254                                                 div, UPDATE_COMMANDS_DIR_PREFIX, name);
1255                                     }
1256                                 }
1257                                 ALOGV("Transfering from %s to %s: uid=%d\n",
1258                                     srcpkg, dstpkg, dstuid);
1259                             }
1260                         }
1261                     }
1262                     bufp = bufi+1;
1263                 } else {
1264                     if (bufp == 0) {
1265                         if (bufp < bufe) {
1266                             ALOGW("Line too long in %s%s, skipping: %s\n",
1267                                     UPDATE_COMMANDS_DIR_PREFIX, name, buf);
1268                         }
1269                     } else if (bufp < bufe) {
1270                         memcpy(buf, buf+bufp, bufe-bufp);
1271                         bufe -= bufp;
1272                         bufp = 0;
1273                     }
1274                     readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe);
1275                     if (readlen < 0) {
1276                         ALOGW("Failure reading update commands in %s%s: %s\n",
1277                                 UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno));
1278                         break;
1279                     } else if (readlen == 0) {
1280                         break;
1281                     }
1282                     bufe += readlen;
1283                     buf[bufe] = 0;
1284                     ALOGV("Read buf: %s\n", buf);
1285                 }
1286             }
1287             close(subfd);
1288         }
1289     }
1290     closedir(d);
1291 done:
1292     return 0;
1293 }
1294 
linklib(const char * pkgname,const char * asecLibDir,int userId)1295 int linklib(const char* pkgname, const char* asecLibDir, int userId)
1296 {
1297     char pkgdir[PKG_PATH_MAX];
1298     char libsymlink[PKG_PATH_MAX];
1299     struct stat s, libStat;
1300     int rc = 0;
1301 
1302     if (create_pkg_path(pkgdir, pkgname, PKG_DIR_POSTFIX, userId)) {
1303         ALOGE("cannot create package path\n");
1304         return -1;
1305     }
1306     if (create_pkg_path(libsymlink, pkgname, PKG_LIB_POSTFIX, userId)) {
1307         ALOGE("cannot create package lib symlink origin path\n");
1308         return -1;
1309     }
1310 
1311     if (stat(pkgdir, &s) < 0) return -1;
1312 
1313     if (chown(pkgdir, AID_INSTALL, AID_INSTALL) < 0) {
1314         ALOGE("failed to chown '%s': %s\n", pkgdir, strerror(errno));
1315         return -1;
1316     }
1317 
1318     if (chmod(pkgdir, 0700) < 0) {
1319         ALOGE("linklib() 1: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
1320         rc = -1;
1321         goto out;
1322     }
1323 
1324     if (lstat(libsymlink, &libStat) < 0) {
1325         if (errno != ENOENT) {
1326             ALOGE("couldn't stat lib dir: %s\n", strerror(errno));
1327             rc = -1;
1328             goto out;
1329         }
1330     } else {
1331         if (S_ISDIR(libStat.st_mode)) {
1332             if (delete_dir_contents(libsymlink, 1, NULL) < 0) {
1333                 rc = -1;
1334                 goto out;
1335             }
1336         } else if (S_ISLNK(libStat.st_mode)) {
1337             if (unlink(libsymlink) < 0) {
1338                 ALOGE("couldn't unlink lib dir: %s\n", strerror(errno));
1339                 rc = -1;
1340                 goto out;
1341             }
1342         }
1343     }
1344 
1345     if (symlink(asecLibDir, libsymlink) < 0) {
1346         ALOGE("couldn't symlink directory '%s' -> '%s': %s\n", libsymlink, asecLibDir,
1347                 strerror(errno));
1348         rc = -errno;
1349         goto out;
1350     }
1351 
1352 out:
1353     if (chmod(pkgdir, s.st_mode) < 0) {
1354         ALOGE("linklib() 2: failed to chmod '%s': %s\n", pkgdir, strerror(errno));
1355         rc = -errno;
1356     }
1357 
1358     if (chown(pkgdir, s.st_uid, s.st_gid) < 0) {
1359         ALOGE("failed to chown '%s' : %s\n", pkgdir, strerror(errno));
1360         return -errno;
1361     }
1362 
1363     return rc;
1364 }
1365 
run_idmap(const char * target_apk,const char * overlay_apk,int idmap_fd)1366 static void run_idmap(const char *target_apk, const char *overlay_apk, int idmap_fd)
1367 {
1368     static const char *IDMAP_BIN = "/system/bin/idmap";
1369     static const size_t MAX_INT_LEN = 32;
1370     char idmap_str[MAX_INT_LEN];
1371 
1372     snprintf(idmap_str, sizeof(idmap_str), "%d", idmap_fd);
1373 
1374     execl(IDMAP_BIN, IDMAP_BIN, "--fd", target_apk, overlay_apk, idmap_str, (char*)NULL);
1375     ALOGE("execl(%s) failed: %s\n", IDMAP_BIN, strerror(errno));
1376 }
1377 
1378 // Transform string /a/b/c.apk to (prefix)/a@b@c.apk@(suffix)
1379 // eg /a/b/c.apk to /data/resource-cache/a@b@c.apk@idmap
flatten_path(const char * prefix,const char * suffix,const char * overlay_path,char * idmap_path,size_t N)1380 static int flatten_path(const char *prefix, const char *suffix,
1381         const char *overlay_path, char *idmap_path, size_t N)
1382 {
1383     if (overlay_path == NULL || idmap_path == NULL) {
1384         return -1;
1385     }
1386     const size_t len_overlay_path = strlen(overlay_path);
1387     // will access overlay_path + 1 further below; requires absolute path
1388     if (len_overlay_path < 2 || *overlay_path != '/') {
1389         return -1;
1390     }
1391     const size_t len_idmap_root = strlen(prefix);
1392     const size_t len_suffix = strlen(suffix);
1393     if (SIZE_MAX - len_idmap_root < len_overlay_path ||
1394             SIZE_MAX - (len_idmap_root + len_overlay_path) < len_suffix) {
1395         // additions below would cause overflow
1396         return -1;
1397     }
1398     if (N < len_idmap_root + len_overlay_path + len_suffix) {
1399         return -1;
1400     }
1401     memset(idmap_path, 0, N);
1402     snprintf(idmap_path, N, "%s%s%s", prefix, overlay_path + 1, suffix);
1403     char *ch = idmap_path + len_idmap_root;
1404     while (*ch != '\0') {
1405         if (*ch == '/') {
1406             *ch = '@';
1407         }
1408         ++ch;
1409     }
1410     return 0;
1411 }
1412 
idmap(const char * target_apk,const char * overlay_apk,uid_t uid)1413 int idmap(const char *target_apk, const char *overlay_apk, uid_t uid)
1414 {
1415     ALOGV("idmap target_apk=%s overlay_apk=%s uid=%d\n", target_apk, overlay_apk, uid);
1416 
1417     int idmap_fd = -1;
1418     char idmap_path[PATH_MAX];
1419 
1420     if (flatten_path(IDMAP_PREFIX, IDMAP_SUFFIX, overlay_apk,
1421                 idmap_path, sizeof(idmap_path)) == -1) {
1422         ALOGE("idmap cannot generate idmap path for overlay %s\n", overlay_apk);
1423         goto fail;
1424     }
1425 
1426     unlink(idmap_path);
1427     idmap_fd = open(idmap_path, O_RDWR | O_CREAT | O_EXCL, 0644);
1428     if (idmap_fd < 0) {
1429         ALOGE("idmap cannot open '%s' for output: %s\n", idmap_path, strerror(errno));
1430         goto fail;
1431     }
1432     if (fchown(idmap_fd, AID_SYSTEM, uid) < 0) {
1433         ALOGE("idmap cannot chown '%s'\n", idmap_path);
1434         goto fail;
1435     }
1436     if (fchmod(idmap_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) < 0) {
1437         ALOGE("idmap cannot chmod '%s'\n", idmap_path);
1438         goto fail;
1439     }
1440 
1441     pid_t pid;
1442     pid = fork();
1443     if (pid == 0) {
1444         /* child -- drop privileges before continuing */
1445         if (setgid(uid) != 0) {
1446             ALOGE("setgid(%d) failed during idmap\n", uid);
1447             exit(1);
1448         }
1449         if (setuid(uid) != 0) {
1450             ALOGE("setuid(%d) failed during idmap\n", uid);
1451             exit(1);
1452         }
1453         if (flock(idmap_fd, LOCK_EX | LOCK_NB) != 0) {
1454             ALOGE("flock(%s) failed during idmap: %s\n", idmap_path, strerror(errno));
1455             exit(1);
1456         }
1457 
1458         run_idmap(target_apk, overlay_apk, idmap_fd);
1459         exit(1); /* only if exec call to idmap failed */
1460     } else {
1461         int status = wait_child(pid);
1462         if (status != 0) {
1463             ALOGE("idmap failed, status=0x%04x\n", status);
1464             goto fail;
1465         }
1466     }
1467 
1468     close(idmap_fd);
1469     return 0;
1470 fail:
1471     if (idmap_fd >= 0) {
1472         close(idmap_fd);
1473         unlink(idmap_path);
1474     }
1475     return -1;
1476 }
1477 
restorecon_data(const char * pkgName,const char * seinfo,uid_t uid)1478 int restorecon_data(const char* pkgName, const char* seinfo, uid_t uid)
1479 {
1480     struct dirent *entry;
1481     DIR *d;
1482     struct stat s;
1483     char *userdir;
1484     char *primarydir;
1485     char *pkgdir;
1486     int ret = 0;
1487 
1488     // SELINUX_ANDROID_RESTORECON_DATADATA flag is set by libselinux. Not needed here.
1489     unsigned int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
1490 
1491     if (!pkgName || !seinfo) {
1492         ALOGE("Package name or seinfo tag is null when trying to restorecon.");
1493         return -1;
1494     }
1495 
1496     if (asprintf(&primarydir, "%s%s%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgName) < 0) {
1497         return -1;
1498     }
1499 
1500     // Relabel for primary user.
1501     if (selinux_android_restorecon_pkgdir(primarydir, seinfo, uid, flags) < 0) {
1502         ALOGE("restorecon failed for %s: %s\n", primarydir, strerror(errno));
1503         ret |= -1;
1504     }
1505 
1506     if (asprintf(&userdir, "%s%s", android_data_dir.path, SECONDARY_USER_PREFIX) < 0) {
1507         free(primarydir);
1508         return -1;
1509     }
1510 
1511     // Relabel package directory for all secondary users.
1512     d = opendir(userdir);
1513     if (d == NULL) {
1514         free(primarydir);
1515         free(userdir);
1516         return -1;
1517     }
1518 
1519     while ((entry = readdir(d))) {
1520         if (entry->d_type != DT_DIR) {
1521             continue;
1522         }
1523 
1524         const char *user = entry->d_name;
1525         // Ignore "." and ".."
1526         if (!strcmp(user, ".") || !strcmp(user, "..")) {
1527             continue;
1528         }
1529 
1530         // user directories start with a number
1531         if (user[0] < '0' || user[0] > '9') {
1532             ALOGE("Expecting numbered directory during restorecon. Instead got '%s'.", user);
1533             continue;
1534         }
1535 
1536         if (asprintf(&pkgdir, "%s%s/%s", userdir, user, pkgName) < 0) {
1537             continue;
1538         }
1539 
1540         if (stat(pkgdir, &s) < 0) {
1541             free(pkgdir);
1542             continue;
1543         }
1544 
1545         if (selinux_android_restorecon_pkgdir(pkgdir, seinfo, uid, flags) < 0) {
1546             ALOGE("restorecon failed for %s: %s\n", pkgdir, strerror(errno));
1547             ret |= -1;
1548         }
1549         free(pkgdir);
1550     }
1551 
1552     closedir(d);
1553     free(primarydir);
1554     free(userdir);
1555     return ret;
1556 }
1557 
1558