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 "installd.h"
18 
19 #define CACHE_NOISY(x) //x
20 
create_pkg_path_in_dir(char path[PKG_PATH_MAX],const dir_rec_t * dir,const char * pkgname,const char * postfix)21 int create_pkg_path_in_dir(char path[PKG_PATH_MAX],
22                                 const dir_rec_t* dir,
23                                 const char* pkgname,
24                                 const char* postfix)
25 {
26      const size_t postfix_len = strlen(postfix);
27 
28      const size_t pkgname_len = strlen(pkgname);
29      if (pkgname_len > PKG_NAME_MAX) {
30          return -1;
31      }
32 
33      if (is_valid_package_name(pkgname) < 0) {
34          return -1;
35      }
36 
37      if ((pkgname_len + dir->len + postfix_len) >= PKG_PATH_MAX) {
38          return -1;
39      }
40 
41      char *dst = path;
42      size_t dst_size = PKG_PATH_MAX;
43 
44      if (append_and_increment(&dst, dir->path, &dst_size) < 0
45              || append_and_increment(&dst, pkgname, &dst_size) < 0
46              || append_and_increment(&dst, postfix, &dst_size) < 0) {
47          ALOGE("Error building APK path");
48          return -1;
49      }
50 
51      return 0;
52 }
53 
54 /**
55  * Create the package path name for a given package name with a postfix for
56  * a certain userid. Returns 0 on success, and -1 on failure.
57  */
create_pkg_path(char path[PKG_PATH_MAX],const char * pkgname,const char * postfix,userid_t userid)58 int create_pkg_path(char path[PKG_PATH_MAX],
59                     const char *pkgname,
60                     const char *postfix,
61                     userid_t userid)
62 {
63     size_t userid_len;
64     char* userid_prefix;
65     if (userid == 0) {
66         userid_prefix = PRIMARY_USER_PREFIX;
67         userid_len = 0;
68     } else {
69         userid_prefix = SECONDARY_USER_PREFIX;
70         userid_len = snprintf(NULL, 0, "%d", userid);
71     }
72 
73     const size_t prefix_len = android_data_dir.len + strlen(userid_prefix)
74             + userid_len + 1 /*slash*/;
75     char prefix[prefix_len + 1];
76 
77     char *dst = prefix;
78     size_t dst_size = sizeof(prefix);
79 
80     if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0
81             || append_and_increment(&dst, userid_prefix, &dst_size) < 0) {
82         ALOGE("Error building prefix for APK path");
83         return -1;
84     }
85 
86     if (userid != 0) {
87         int ret = snprintf(dst, dst_size, "%d/", userid);
88         if (ret < 0 || (size_t) ret != userid_len + 1) {
89             ALOGW("Error appending UID to APK path");
90             return -1;
91         }
92     }
93 
94     dir_rec_t dir;
95     dir.path = prefix;
96     dir.len = prefix_len;
97 
98     return create_pkg_path_in_dir(path, &dir, pkgname, postfix);
99 }
100 
101 /**
102  * Create the path name for user data for a certain userid.
103  * Returns 0 on success, and -1 on failure.
104  */
create_user_path(char path[PKG_PATH_MAX],userid_t userid)105 int create_user_path(char path[PKG_PATH_MAX],
106                     userid_t userid)
107 {
108     size_t userid_len;
109     char* userid_prefix;
110     if (userid == 0) {
111         userid_prefix = PRIMARY_USER_PREFIX;
112         userid_len = 0;
113     } else {
114         userid_prefix = SECONDARY_USER_PREFIX;
115         userid_len = snprintf(NULL, 0, "%d/", userid);
116     }
117 
118     char *dst = path;
119     size_t dst_size = PKG_PATH_MAX;
120 
121     if (append_and_increment(&dst, android_data_dir.path, &dst_size) < 0
122             || append_and_increment(&dst, userid_prefix, &dst_size) < 0) {
123         ALOGE("Error building prefix for user path");
124         return -1;
125     }
126 
127     if (userid != 0) {
128         if (dst_size < userid_len + 1) {
129             ALOGE("Error building user path");
130             return -1;
131         }
132         int ret = snprintf(dst, dst_size, "%d/", userid);
133         if (ret < 0 || (size_t) ret != userid_len) {
134             ALOGE("Error appending userid to path");
135             return -1;
136         }
137     }
138     return 0;
139 }
140 
141 /**
142  * Create the path name for media for a certain userid.
143  * Returns 0 on success, and -1 on failure.
144  */
create_user_media_path(char path[PATH_MAX],userid_t userid)145 int create_user_media_path(char path[PATH_MAX], userid_t userid) {
146     if (snprintf(path, PATH_MAX, "%s%d", android_media_dir.path, userid) > PATH_MAX) {
147         return -1;
148     }
149     return 0;
150 }
151 
152 /**
153  * Create the path name for config for a certain userid.
154  * Returns 0 on success, and -1 on failure.
155  */
create_user_config_path(char path[PATH_MAX],userid_t userid)156 int create_user_config_path(char path[PATH_MAX], userid_t userid) {
157     if (snprintf(path, PATH_MAX, "%s%d", "/data/misc/user/", userid) > PATH_MAX) {
158         return -1;
159     }
160     return 0;
161 }
162 
create_move_path(char path[PKG_PATH_MAX],const char * pkgname,const char * leaf,userid_t userid)163 int create_move_path(char path[PKG_PATH_MAX],
164     const char* pkgname,
165     const char* leaf,
166     userid_t userid)
167 {
168     if ((android_data_dir.len + strlen(PRIMARY_USER_PREFIX) + strlen(pkgname) + strlen(leaf) + 1)
169             >= PKG_PATH_MAX) {
170         return -1;
171     }
172 
173     sprintf(path, "%s%s%s/%s", android_data_dir.path, PRIMARY_USER_PREFIX, pkgname, leaf);
174     return 0;
175 }
176 
177 /**
178  * Checks whether the package name is valid. Returns -1 on error and
179  * 0 on success.
180  */
is_valid_package_name(const char * pkgname)181 int is_valid_package_name(const char* pkgname) {
182     const char *x = pkgname;
183     int alpha = -1;
184 
185     while (*x) {
186         if (isalnum(*x) || (*x == '_')) {
187                 /* alphanumeric or underscore are fine */
188         } else if (*x == '.') {
189             if ((x == pkgname) || (x[1] == '.') || (x[1] == 0)) {
190                     /* periods must not be first, last, or doubled */
191                 ALOGE("invalid package name '%s'\n", pkgname);
192                 return -1;
193             }
194         } else if (*x == '-') {
195             /* Suffix -X is fine to let versioning of packages.
196                But whatever follows should be alphanumeric.*/
197             alpha = 1;
198         } else {
199                 /* anything not A-Z, a-z, 0-9, _, or . is invalid */
200             ALOGE("invalid package name '%s'\n", pkgname);
201             return -1;
202         }
203 
204         x++;
205     }
206 
207     if (alpha == 1) {
208         // Skip current character
209         x++;
210         while (*x) {
211             if (!isalnum(*x)) {
212                 ALOGE("invalid package name '%s' should include only numbers after -\n", pkgname);
213                 return -1;
214             }
215             x++;
216         }
217     }
218 
219     return 0;
220 }
221 
_delete_dir_contents(DIR * d,int (* exclusion_predicate)(const char * name,const int is_dir))222 static int _delete_dir_contents(DIR *d,
223                                 int (*exclusion_predicate)(const char *name, const int is_dir))
224 {
225     int result = 0;
226     struct dirent *de;
227     int dfd;
228 
229     dfd = dirfd(d);
230 
231     if (dfd < 0) return -1;
232 
233     while ((de = readdir(d))) {
234         const char *name = de->d_name;
235 
236             /* check using the exclusion predicate, if provided */
237         if (exclusion_predicate && exclusion_predicate(name, (de->d_type == DT_DIR))) {
238             continue;
239         }
240 
241         if (de->d_type == DT_DIR) {
242             int r, subfd;
243             DIR *subdir;
244 
245                 /* always skip "." and ".." */
246             if (name[0] == '.') {
247                 if (name[1] == 0) continue;
248                 if ((name[1] == '.') && (name[2] == 0)) continue;
249             }
250 
251             subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
252             if (subfd < 0) {
253                 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
254                 result = -1;
255                 continue;
256             }
257             subdir = fdopendir(subfd);
258             if (subdir == NULL) {
259                 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
260                 close(subfd);
261                 result = -1;
262                 continue;
263             }
264             if (_delete_dir_contents(subdir, exclusion_predicate)) {
265                 result = -1;
266             }
267             closedir(subdir);
268             if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
269                 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
270                 result = -1;
271             }
272         } else {
273             if (unlinkat(dfd, name, 0) < 0) {
274                 ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
275                 result = -1;
276             }
277         }
278     }
279 
280     return result;
281 }
282 
delete_dir_contents(const char * pathname,int also_delete_dir,int (* exclusion_predicate)(const char *,const int))283 int delete_dir_contents(const char *pathname,
284                         int also_delete_dir,
285                         int (*exclusion_predicate)(const char*, const int))
286 {
287     int res = 0;
288     DIR *d;
289 
290     d = opendir(pathname);
291     if (d == NULL) {
292         ALOGE("Couldn't opendir %s: %s\n", pathname, strerror(errno));
293         return -errno;
294     }
295     res = _delete_dir_contents(d, exclusion_predicate);
296     closedir(d);
297     if (also_delete_dir) {
298         if (rmdir(pathname)) {
299             ALOGE("Couldn't rmdir %s: %s\n", pathname, strerror(errno));
300             res = -1;
301         }
302     }
303     return res;
304 }
305 
delete_dir_contents_fd(int dfd,const char * name)306 int delete_dir_contents_fd(int dfd, const char *name)
307 {
308     int fd, res;
309     DIR *d;
310 
311     fd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
312     if (fd < 0) {
313         ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
314         return -1;
315     }
316     d = fdopendir(fd);
317     if (d == NULL) {
318         ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
319         close(fd);
320         return -1;
321     }
322     res = _delete_dir_contents(d, 0);
323     closedir(d);
324     return res;
325 }
326 
_copy_owner_permissions(int srcfd,int dstfd)327 static int _copy_owner_permissions(int srcfd, int dstfd)
328 {
329     struct stat st;
330     if (fstat(srcfd, &st) != 0) {
331         return -1;
332     }
333     if (fchmod(dstfd, st.st_mode) != 0) {
334         return -1;
335     }
336     return 0;
337 }
338 
_copy_dir_files(int sdfd,int ddfd,uid_t owner,gid_t group)339 static int _copy_dir_files(int sdfd, int ddfd, uid_t owner, gid_t group)
340 {
341     int result = 0;
342     if (_copy_owner_permissions(sdfd, ddfd) != 0) {
343         ALOGE("_copy_dir_files failed to copy dir permissions\n");
344     }
345     if (fchown(ddfd, owner, group) != 0) {
346         ALOGE("_copy_dir_files failed to change dir owner\n");
347     }
348 
349     DIR *ds = fdopendir(sdfd);
350     if (ds == NULL) {
351         ALOGE("Couldn't fdopendir: %s\n", strerror(errno));
352         return -1;
353     }
354     struct dirent *de;
355     while ((de = readdir(ds))) {
356         if (de->d_type != DT_REG) {
357             continue;
358         }
359 
360         const char *name = de->d_name;
361         int fsfd = openat(sdfd, name, O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
362         int fdfd = openat(ddfd, name, O_WRONLY | O_NOFOLLOW | O_CLOEXEC | O_CREAT, 0600);
363         if (fsfd == -1 || fdfd == -1) {
364             ALOGW("Couldn't copy %s: %s\n", name, strerror(errno));
365         } else {
366             if (_copy_owner_permissions(fsfd, fdfd) != 0) {
367                 ALOGE("Failed to change file permissions\n");
368             }
369             if (fchown(fdfd, owner, group) != 0) {
370                 ALOGE("Failed to change file owner\n");
371             }
372 
373             char buf[8192];
374             ssize_t size;
375             while ((size = read(fsfd, buf, sizeof(buf))) > 0) {
376                 write(fdfd, buf, size);
377             }
378             if (size < 0) {
379                 ALOGW("Couldn't copy %s: %s\n", name, strerror(errno));
380                 result = -1;
381             }
382         }
383         close(fdfd);
384         close(fsfd);
385     }
386 
387     return result;
388 }
389 
copy_dir_files(const char * srcname,const char * dstname,uid_t owner,uid_t group)390 int copy_dir_files(const char *srcname,
391                    const char *dstname,
392                    uid_t owner,
393                    uid_t group)
394 {
395     int res = 0;
396     DIR *ds = NULL;
397     DIR *dd = NULL;
398 
399     ds = opendir(srcname);
400     if (ds == NULL) {
401         ALOGE("Couldn't opendir %s: %s\n", srcname, strerror(errno));
402         return -errno;
403     }
404 
405     mkdir(dstname, 0600);
406     dd = opendir(dstname);
407     if (dd == NULL) {
408         ALOGE("Couldn't opendir %s: %s\n", dstname, strerror(errno));
409         closedir(ds);
410         return -errno;
411     }
412 
413     int sdfd = dirfd(ds);
414     int ddfd = dirfd(dd);
415     if (sdfd != -1 && ddfd != -1) {
416         res = _copy_dir_files(sdfd, ddfd, owner, group);
417     } else {
418         res = -errno;
419     }
420     closedir(dd);
421     closedir(ds);
422     return res;
423 }
424 
lookup_media_dir(char basepath[PATH_MAX],const char * dir)425 int lookup_media_dir(char basepath[PATH_MAX], const char *dir)
426 {
427     DIR *d;
428     struct dirent *de;
429     struct stat s;
430     char* dirpos = basepath + strlen(basepath);
431 
432     if ((*(dirpos-1)) != '/') {
433         *dirpos = '/';
434         dirpos++;
435     }
436 
437     CACHE_NOISY(ALOGI("Looking up %s in %s\n", dir, basepath));
438     // Verify the path won't extend beyond our buffer, to avoid
439     // repeated checking later.
440     if ((dirpos-basepath+strlen(dir)) >= (PATH_MAX-1)) {
441         ALOGW("Path exceeds limit: %s%s", basepath, dir);
442         return -1;
443     }
444 
445     // First, can we find this directory with the case that is given?
446     strcpy(dirpos, dir);
447     if (stat(basepath, &s) >= 0) {
448         CACHE_NOISY(ALOGI("Found direct: %s\n", basepath));
449         return 0;
450     }
451 
452     // Not found with that case...  search through all entries to find
453     // one that matches regardless of case.
454     *dirpos = 0;
455 
456     d = opendir(basepath);
457     if (d == NULL) {
458         return -1;
459     }
460 
461     while ((de = readdir(d))) {
462         if (strcasecmp(de->d_name, dir) == 0) {
463             strcpy(dirpos, de->d_name);
464             closedir(d);
465             CACHE_NOISY(ALOGI("Found search: %s\n", basepath));
466             return 0;
467         }
468     }
469 
470     ALOGW("Couldn't find %s in %s", dir, basepath);
471     closedir(d);
472     return -1;
473 }
474 
data_disk_free()475 int64_t data_disk_free()
476 {
477     struct statfs sfs;
478     if (statfs(android_data_dir.path, &sfs) == 0) {
479         return sfs.f_bavail * sfs.f_bsize;
480     } else {
481         ALOGE("Couldn't statfs %s: %s\n", android_data_dir.path, strerror(errno));
482         return -1;
483     }
484 }
485 
start_cache_collection()486 cache_t* start_cache_collection()
487 {
488     cache_t* cache = (cache_t*)calloc(1, sizeof(cache_t));
489     return cache;
490 }
491 
492 #define CACHE_BLOCK_SIZE (512*1024)
493 
_cache_malloc(cache_t * cache,size_t len)494 static void* _cache_malloc(cache_t* cache, size_t len)
495 {
496     len = (len+3)&~3;
497     if (len > (CACHE_BLOCK_SIZE/2)) {
498         // It doesn't make sense to try to put this allocation into one
499         // of our blocks, because it is so big.  Instead, make a new dedicated
500         // block for it.
501         int8_t* res = (int8_t*)malloc(len+sizeof(void*));
502         if (res == NULL) {
503             return NULL;
504         }
505         CACHE_NOISY(ALOGI("Allocated large cache mem block: %p size %d", res, len));
506         // Link it into our list of blocks, not disrupting the current one.
507         if (cache->memBlocks == NULL) {
508             *(void**)res = NULL;
509             cache->memBlocks = res;
510         } else {
511             *(void**)res = *(void**)cache->memBlocks;
512             *(void**)cache->memBlocks = res;
513         }
514         return res + sizeof(void*);
515     }
516     int8_t* res = cache->curMemBlockAvail;
517     int8_t* nextPos = res + len;
518     if (cache->memBlocks == NULL || nextPos > cache->curMemBlockEnd) {
519         int8_t* newBlock = malloc(CACHE_BLOCK_SIZE);
520         if (newBlock == NULL) {
521             return NULL;
522         }
523         CACHE_NOISY(ALOGI("Allocated new cache mem block: %p", newBlock));
524         *(void**)newBlock = cache->memBlocks;
525         cache->memBlocks = newBlock;
526         res = cache->curMemBlockAvail = newBlock + sizeof(void*);
527         cache->curMemBlockEnd = newBlock + CACHE_BLOCK_SIZE;
528         nextPos = res + len;
529     }
530     CACHE_NOISY(ALOGI("cache_malloc: ret %p size %d, block=%p, nextPos=%p",
531             res, len, cache->memBlocks, nextPos));
532     cache->curMemBlockAvail = nextPos;
533     return res;
534 }
535 
_cache_realloc(cache_t * cache,void * cur,size_t origLen,size_t len)536 static void* _cache_realloc(cache_t* cache, void* cur, size_t origLen, size_t len)
537 {
538     // This isn't really a realloc, but it is good enough for our purposes here.
539     void* alloc = _cache_malloc(cache, len);
540     if (alloc != NULL && cur != NULL) {
541         memcpy(alloc, cur, origLen < len ? origLen : len);
542     }
543     return alloc;
544 }
545 
_inc_num_cache_collected(cache_t * cache)546 static void _inc_num_cache_collected(cache_t* cache)
547 {
548     cache->numCollected++;
549     if ((cache->numCollected%20000) == 0) {
550         ALOGI("Collected cache so far: %zd directories, %zd files",
551             cache->numDirs, cache->numFiles);
552     }
553 }
554 
_add_cache_dir_t(cache_t * cache,cache_dir_t * parent,const char * name)555 static cache_dir_t* _add_cache_dir_t(cache_t* cache, cache_dir_t* parent, const char *name)
556 {
557     size_t nameLen = strlen(name);
558     cache_dir_t* dir = (cache_dir_t*)_cache_malloc(cache, sizeof(cache_dir_t)+nameLen+1);
559     if (dir != NULL) {
560         dir->parent = parent;
561         dir->childCount = 0;
562         dir->hiddenCount = 0;
563         dir->deleted = 0;
564         strcpy(dir->name, name);
565         if (cache->numDirs >= cache->availDirs) {
566             size_t newAvail = cache->availDirs < 1000 ? 1000 : cache->availDirs*2;
567             cache_dir_t** newDirs = (cache_dir_t**)_cache_realloc(cache, cache->dirs,
568                     cache->availDirs*sizeof(cache_dir_t*), newAvail*sizeof(cache_dir_t*));
569             if (newDirs == NULL) {
570                 ALOGE("Failure growing cache dirs array for %s\n", name);
571                 return NULL;
572             }
573             cache->availDirs = newAvail;
574             cache->dirs = newDirs;
575         }
576         cache->dirs[cache->numDirs] = dir;
577         cache->numDirs++;
578         if (parent != NULL) {
579             parent->childCount++;
580         }
581         _inc_num_cache_collected(cache);
582     } else {
583         ALOGE("Failure allocating cache_dir_t for %s\n", name);
584     }
585     return dir;
586 }
587 
_add_cache_file_t(cache_t * cache,cache_dir_t * dir,time_t modTime,const char * name)588 static cache_file_t* _add_cache_file_t(cache_t* cache, cache_dir_t* dir, time_t modTime,
589         const char *name)
590 {
591     size_t nameLen = strlen(name);
592     cache_file_t* file = (cache_file_t*)_cache_malloc(cache, sizeof(cache_file_t)+nameLen+1);
593     if (file != NULL) {
594         file->dir = dir;
595         file->modTime = modTime;
596         strcpy(file->name, name);
597         if (cache->numFiles >= cache->availFiles) {
598             size_t newAvail = cache->availFiles < 1000 ? 1000 : cache->availFiles*2;
599             cache_file_t** newFiles = (cache_file_t**)_cache_realloc(cache, cache->files,
600                     cache->availFiles*sizeof(cache_file_t*), newAvail*sizeof(cache_file_t*));
601             if (newFiles == NULL) {
602                 ALOGE("Failure growing cache file array for %s\n", name);
603                 return NULL;
604             }
605             cache->availFiles = newAvail;
606             cache->files = newFiles;
607         }
608         CACHE_NOISY(ALOGI("Setting file %p at position %d in array %p", file,
609                 cache->numFiles, cache->files));
610         cache->files[cache->numFiles] = file;
611         cache->numFiles++;
612         dir->childCount++;
613         _inc_num_cache_collected(cache);
614     } else {
615         ALOGE("Failure allocating cache_file_t for %s\n", name);
616     }
617     return file;
618 }
619 
_add_cache_files(cache_t * cache,cache_dir_t * parentDir,const char * dirName,DIR * dir,char * pathBase,char * pathPos,size_t pathAvailLen)620 static int _add_cache_files(cache_t *cache, cache_dir_t *parentDir, const char *dirName,
621         DIR* dir, char *pathBase, char *pathPos, size_t pathAvailLen)
622 {
623     struct dirent *de;
624     cache_dir_t* cacheDir = NULL;
625     int dfd;
626 
627     CACHE_NOISY(ALOGI("_add_cache_files: parent=%p dirName=%s dir=%p pathBase=%s",
628             parentDir, dirName, dir, pathBase));
629 
630     dfd = dirfd(dir);
631 
632     if (dfd < 0) return 0;
633 
634     // Sub-directories always get added to the data structure, so if they
635     // are empty we will know about them to delete them later.
636     cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
637 
638     while ((de = readdir(dir))) {
639         const char *name = de->d_name;
640 
641         if (de->d_type == DT_DIR) {
642             int subfd;
643             DIR *subdir;
644 
645                 /* always skip "." and ".." */
646             if (name[0] == '.') {
647                 if (name[1] == 0) continue;
648                 if ((name[1] == '.') && (name[2] == 0)) continue;
649             }
650 
651             subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
652             if (subfd < 0) {
653                 ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
654                 continue;
655             }
656             subdir = fdopendir(subfd);
657             if (subdir == NULL) {
658                 ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
659                 close(subfd);
660                 continue;
661             }
662             if (cacheDir == NULL) {
663                 cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
664             }
665             if (cacheDir != NULL) {
666                 // Update pathBase for the new path...  this may change dirName
667                 // if that is also pointing to the path, but we are done with it
668                 // now.
669                 size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
670                 CACHE_NOISY(ALOGI("Collecting dir %s\n", pathBase));
671                 if (finallen < pathAvailLen) {
672                     _add_cache_files(cache, cacheDir, name, subdir, pathBase,
673                             pathPos+finallen, pathAvailLen-finallen);
674                 } else {
675                     // Whoops, the final path is too long!  We'll just delete
676                     // this directory.
677                     ALOGW("Cache dir %s truncated in path %s; deleting dir\n",
678                             name, pathBase);
679                     _delete_dir_contents(subdir, NULL);
680                     if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
681                         ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
682                     }
683                 }
684             }
685             closedir(subdir);
686         } else if (de->d_type == DT_REG) {
687             // Skip files that start with '.'; they will be deleted if
688             // their entire directory is deleted.  This allows for metadata
689             // like ".nomedia" to remain in the directory until the entire
690             // directory is deleted.
691             if (cacheDir == NULL) {
692                 cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
693             }
694             if (name[0] == '.') {
695                 cacheDir->hiddenCount++;
696                 continue;
697             }
698             if (cacheDir != NULL) {
699                 // Build final full path for file...  this may change dirName
700                 // if that is also pointing to the path, but we are done with it
701                 // now.
702                 size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
703                 CACHE_NOISY(ALOGI("Collecting file %s\n", pathBase));
704                 if (finallen < pathAvailLen) {
705                     struct stat s;
706                     if (stat(pathBase, &s) >= 0) {
707                         _add_cache_file_t(cache, cacheDir, s.st_mtime, name);
708                     } else {
709                         ALOGW("Unable to stat cache file %s; deleting\n", pathBase);
710                         if (unlink(pathBase) < 0) {
711                             ALOGE("Couldn't unlink %s: %s\n", pathBase, strerror(errno));
712                         }
713                     }
714                 } else {
715                     // Whoops, the final path is too long!  We'll just delete
716                     // this file.
717                     ALOGW("Cache file %s truncated in path %s; deleting\n",
718                             name, pathBase);
719                     if (unlinkat(dfd, name, 0) < 0) {
720                         *pathPos = 0;
721                         ALOGE("Couldn't unlinkat %s in %s: %s\n", name, pathBase,
722                                 strerror(errno));
723                     }
724                 }
725             }
726         } else {
727             cacheDir->hiddenCount++;
728         }
729     }
730     return 0;
731 }
732 
add_cache_files(cache_t * cache,const char * basepath,const char * cachedir)733 void add_cache_files(cache_t* cache, const char *basepath, const char *cachedir)
734 {
735     DIR *d;
736     struct dirent *de;
737     char dirname[PATH_MAX];
738 
739     CACHE_NOISY(ALOGI("add_cache_files: base=%s cachedir=%s\n", basepath, cachedir));
740 
741     d = opendir(basepath);
742     if (d == NULL) {
743         return;
744     }
745 
746     while ((de = readdir(d))) {
747         if (de->d_type == DT_DIR) {
748             DIR* subdir;
749             const char *name = de->d_name;
750             char* pathpos;
751 
752                 /* always skip "." and ".." */
753             if (name[0] == '.') {
754                 if (name[1] == 0) continue;
755                 if ((name[1] == '.') && (name[2] == 0)) continue;
756             }
757 
758             strcpy(dirname, basepath);
759             pathpos = dirname + strlen(dirname);
760             if ((*(pathpos-1)) != '/') {
761                 *pathpos = '/';
762                 pathpos++;
763                 *pathpos = 0;
764             }
765             if (cachedir != NULL) {
766                 snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s/%s", name, cachedir);
767             } else {
768                 snprintf(pathpos, sizeof(dirname)-(pathpos-dirname), "%s", name);
769             }
770             CACHE_NOISY(ALOGI("Adding cache files from dir: %s\n", dirname));
771             subdir = opendir(dirname);
772             if (subdir != NULL) {
773                 size_t dirnameLen = strlen(dirname);
774                 _add_cache_files(cache, NULL, dirname, subdir, dirname, dirname+dirnameLen,
775                         PATH_MAX - dirnameLen);
776                 closedir(subdir);
777             }
778         }
779     }
780 
781     closedir(d);
782 }
783 
create_dir_path(char path[PATH_MAX],cache_dir_t * dir)784 static char *create_dir_path(char path[PATH_MAX], cache_dir_t* dir)
785 {
786     char *pos = path;
787     if (dir->parent != NULL) {
788         pos = create_dir_path(path, dir->parent);
789     }
790     // Note that we don't need to worry about going beyond the buffer,
791     // since when we were constructing the cache entries our maximum
792     // buffer size for full paths was PATH_MAX.
793     strcpy(pos, dir->name);
794     pos += strlen(pos);
795     *pos = '/';
796     pos++;
797     *pos = 0;
798     return pos;
799 }
800 
delete_cache_dir(char path[PATH_MAX],cache_dir_t * dir)801 static void delete_cache_dir(char path[PATH_MAX], cache_dir_t* dir)
802 {
803     if (dir->parent != NULL) {
804         create_dir_path(path, dir);
805         ALOGI("DEL DIR %s\n", path);
806         if (dir->hiddenCount <= 0) {
807             if (rmdir(path)) {
808                 ALOGE("Couldn't rmdir %s: %s\n", path, strerror(errno));
809                 return;
810             }
811         } else {
812             // The directory contains hidden files so we need to delete
813             // them along with the directory itself.
814             if (delete_dir_contents(path, 1, NULL)) {
815                 return;
816             }
817         }
818         dir->parent->childCount--;
819         dir->deleted = 1;
820         if (dir->parent->childCount <= 0) {
821             delete_cache_dir(path, dir->parent);
822         }
823     } else if (dir->hiddenCount > 0) {
824         // This is a root directory, but it has hidden files.  Get rid of
825         // all of those files, but not the directory itself.
826         create_dir_path(path, dir);
827         ALOGI("DEL CONTENTS %s\n", path);
828         delete_dir_contents(path, 0, NULL);
829     }
830 }
831 
cache_modtime_sort(const void * lhsP,const void * rhsP)832 static int cache_modtime_sort(const void *lhsP, const void *rhsP)
833 {
834     const cache_file_t *lhs = *(const cache_file_t**)lhsP;
835     const cache_file_t *rhs = *(const cache_file_t**)rhsP;
836     return lhs->modTime < rhs->modTime ? -1 : (lhs->modTime > rhs->modTime ? 1 : 0);
837 }
838 
clear_cache_files(cache_t * cache,int64_t free_size)839 void clear_cache_files(cache_t* cache, int64_t free_size)
840 {
841     size_t i;
842     int skip = 0;
843     char path[PATH_MAX];
844 
845     ALOGI("Collected cache files: %zd directories, %zd files",
846         cache->numDirs, cache->numFiles);
847 
848     CACHE_NOISY(ALOGI("Sorting files..."));
849     qsort(cache->files, cache->numFiles, sizeof(cache_file_t*),
850             cache_modtime_sort);
851 
852     CACHE_NOISY(ALOGI("Cleaning empty directories..."));
853     for (i=cache->numDirs; i>0; i--) {
854         cache_dir_t* dir = cache->dirs[i-1];
855         if (dir->childCount <= 0 && !dir->deleted) {
856             delete_cache_dir(path, dir);
857         }
858     }
859 
860     CACHE_NOISY(ALOGI("Trimming files..."));
861     for (i=0; i<cache->numFiles; i++) {
862         skip++;
863         if (skip > 10) {
864             if (data_disk_free() > free_size) {
865                 return;
866             }
867             skip = 0;
868         }
869         cache_file_t* file = cache->files[i];
870         strcpy(create_dir_path(path, file->dir), file->name);
871         ALOGI("DEL (mod %d) %s\n", (int)file->modTime, path);
872         if (unlink(path) < 0) {
873             ALOGE("Couldn't unlink %s: %s\n", path, strerror(errno));
874         }
875         file->dir->childCount--;
876         if (file->dir->childCount <= 0) {
877             delete_cache_dir(path, file->dir);
878         }
879     }
880 }
881 
finish_cache_collection(cache_t * cache)882 void finish_cache_collection(cache_t* cache)
883 {
884     size_t i;
885 
886     CACHE_NOISY(ALOGI("clear_cache_files: %d dirs, %d files\n", cache->numDirs, cache->numFiles));
887     CACHE_NOISY(
888         for (i=0; i<cache->numDirs; i++) {
889             cache_dir_t* dir = cache->dirs[i];
890             ALOGI("dir #%d: %p %s parent=%p\n", i, dir, dir->name, dir->parent);
891         })
892     CACHE_NOISY(
893         for (i=0; i<cache->numFiles; i++) {
894             cache_file_t* file = cache->files[i];
895             ALOGI("file #%d: %p %s time=%d dir=%p\n", i, file, file->name,
896                     (int)file->modTime, file->dir);
897         })
898     void* block = cache->memBlocks;
899     while (block != NULL) {
900         void* nextBlock = *(void**)block;
901         CACHE_NOISY(ALOGI("Freeing cache mem block: %p", block));
902         free(block);
903         block = nextBlock;
904     }
905     free(cache);
906 }
907 
908 /**
909  * Validate that the path is valid in the context of the provided directory.
910  * The path is allowed to have at most one subdirectory and no indirections
911  * to top level directories (i.e. have "..").
912  */
validate_path(const dir_rec_t * dir,const char * path)913 static int validate_path(const dir_rec_t* dir, const char* path) {
914     size_t dir_len = dir->len;
915     const char* subdir = strchr(path + dir_len, '/');
916 
917     // Only allow the path to have at most one subdirectory.
918     if (subdir != NULL) {
919         ++subdir;
920         if (strchr(subdir, '/') != NULL) {
921             ALOGE("invalid apk path '%s' (subdir?)\n", path);
922             return -1;
923         }
924     }
925 
926     // Directories can't have a period directly after the directory markers to prevent "..".
927     if ((path[dir_len] == '.') || ((subdir != NULL) && (*subdir == '.'))) {
928         ALOGE("invalid apk path '%s' (trickery)\n", path);
929         return -1;
930     }
931 
932     return 0;
933 }
934 
935 /**
936  * Checks whether a path points to a system app (.apk file). Returns 0
937  * if it is a system app or -1 if it is not.
938  */
validate_system_app_path(const char * path)939 int validate_system_app_path(const char* path) {
940     size_t i;
941 
942     for (i = 0; i < android_system_dirs.count; i++) {
943         const size_t dir_len = android_system_dirs.dirs[i].len;
944         if (!strncmp(path, android_system_dirs.dirs[i].path, dir_len)) {
945             return validate_path(android_system_dirs.dirs + i, path);
946         }
947     }
948 
949     return -1;
950 }
951 
952 /**
953  * Get the contents of a environment variable that contains a path. Caller
954  * owns the string that is inserted into the directory record. Returns
955  * 0 on success and -1 on error.
956  */
get_path_from_env(dir_rec_t * rec,const char * var)957 int get_path_from_env(dir_rec_t* rec, const char* var) {
958     const char* path = getenv(var);
959     int ret = get_path_from_string(rec, path);
960     if (ret < 0) {
961         ALOGW("Problem finding value for environment variable %s\n", var);
962     }
963     return ret;
964 }
965 
966 /**
967  * Puts the string into the record as a directory. Appends '/' to the end
968  * of all paths. Caller owns the string that is inserted into the directory
969  * record. A null value will result in an error.
970  *
971  * Returns 0 on success and -1 on error.
972  */
get_path_from_string(dir_rec_t * rec,const char * path)973 int get_path_from_string(dir_rec_t* rec, const char* path) {
974     if (path == NULL) {
975         return -1;
976     } else {
977         const size_t path_len = strlen(path);
978         if (path_len <= 0) {
979             return -1;
980         }
981 
982         // Make sure path is absolute.
983         if (path[0] != '/') {
984             return -1;
985         }
986 
987         if (path[path_len - 1] == '/') {
988             // Path ends with a forward slash. Make our own copy.
989 
990             rec->path = strdup(path);
991             if (rec->path == NULL) {
992                 return -1;
993             }
994 
995             rec->len = path_len;
996         } else {
997             // Path does not end with a slash. Generate a new string.
998             char *dst;
999 
1000             // Add space for slash and terminating null.
1001             size_t dst_size = path_len + 2;
1002 
1003             rec->path = malloc(dst_size);
1004             if (rec->path == NULL) {
1005                 return -1;
1006             }
1007 
1008             dst = rec->path;
1009 
1010             if (append_and_increment(&dst, path, &dst_size) < 0
1011                     || append_and_increment(&dst, "/", &dst_size)) {
1012                 ALOGE("Error canonicalizing path");
1013                 return -1;
1014             }
1015 
1016             rec->len = dst - rec->path;
1017         }
1018     }
1019     return 0;
1020 }
1021 
copy_and_append(dir_rec_t * dst,const dir_rec_t * src,const char * suffix)1022 int copy_and_append(dir_rec_t* dst, const dir_rec_t* src, const char* suffix) {
1023     dst->len = src->len + strlen(suffix);
1024     const size_t dstSize = dst->len + 1;
1025     dst->path = (char*) malloc(dstSize);
1026 
1027     if (dst->path == NULL
1028             || snprintf(dst->path, dstSize, "%s%s", src->path, suffix)
1029                     != (ssize_t) dst->len) {
1030         ALOGE("Could not allocate memory to hold appended path; aborting\n");
1031         return -1;
1032     }
1033 
1034     return 0;
1035 }
1036 
1037 /**
1038  * Check whether path points to a valid path for an APK file. Only one level of
1039  * subdirectory names is allowed. Returns -1 when an invalid path is encountered
1040  * and 0 when a valid path is encountered.
1041  */
validate_apk_path(const char * path)1042 int validate_apk_path(const char *path)
1043 {
1044     const dir_rec_t* dir = NULL;
1045 
1046     if (!strncmp(path, android_app_dir.path, android_app_dir.len)) {
1047         dir = &android_app_dir;
1048     } else if (!strncmp(path, android_app_private_dir.path, android_app_private_dir.len)) {
1049         dir = &android_app_private_dir;
1050     } else if (!strncmp(path, android_asec_dir.path, android_asec_dir.len)) {
1051         dir = &android_asec_dir;
1052     } else {
1053         return -1;
1054     }
1055 
1056     return validate_path(dir, path);
1057 }
1058 
append_and_increment(char ** dst,const char * src,size_t * dst_size)1059 int append_and_increment(char** dst, const char* src, size_t* dst_size) {
1060     ssize_t ret = strlcpy(*dst, src, *dst_size);
1061     if (ret < 0 || (size_t) ret >= *dst_size) {
1062         return -1;
1063     }
1064     *dst += ret;
1065     *dst_size -= ret;
1066     return 0;
1067 }
1068 
build_string2(char * s1,char * s2)1069 char *build_string2(char *s1, char *s2) {
1070     if (s1 == NULL || s2 == NULL) return NULL;
1071 
1072     int len_s1 = strlen(s1);
1073     int len_s2 = strlen(s2);
1074     int len = len_s1 + len_s2 + 1;
1075     char *result = malloc(len);
1076     if (result == NULL) return NULL;
1077 
1078     strcpy(result, s1);
1079     strcpy(result + len_s1, s2);
1080 
1081     return result;
1082 }
1083 
build_string3(char * s1,char * s2,char * s3)1084 char *build_string3(char *s1, char *s2, char *s3) {
1085     if (s1 == NULL || s2 == NULL || s3 == NULL) return NULL;
1086 
1087     int len_s1 = strlen(s1);
1088     int len_s2 = strlen(s2);
1089     int len_s3 = strlen(s3);
1090     int len = len_s1 + len_s2 + len_s3 + 1;
1091     char *result = malloc(len);
1092     if (result == NULL) return NULL;
1093 
1094     strcpy(result, s1);
1095     strcpy(result + len_s1, s2);
1096     strcpy(result + len_s1 + len_s2, s3);
1097 
1098     return result;
1099 }
1100 
1101 /* Ensure that /data/media directories are prepared for given user. */
ensure_media_user_dirs(userid_t userid)1102 int ensure_media_user_dirs(userid_t userid) {
1103     char media_user_path[PATH_MAX];
1104     char path[PATH_MAX];
1105 
1106     // Ensure /data/media/<userid> exists
1107     create_user_media_path(media_user_path, userid);
1108     if (fs_prepare_dir(media_user_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
1109         return -1;
1110     }
1111 
1112     return 0;
1113 }
1114 
ensure_config_user_dirs(userid_t userid)1115 int ensure_config_user_dirs(userid_t userid) {
1116     char config_user_path[PATH_MAX];
1117     char path[PATH_MAX];
1118 
1119     // writable by system, readable by any app within the same user
1120     const int uid = multiuser_get_uid(userid, AID_SYSTEM);
1121     const int gid = multiuser_get_uid(userid, AID_EVERYBODY);
1122 
1123     // Ensure /data/misc/user/<userid> exists
1124     create_user_config_path(config_user_path, userid);
1125     if (fs_prepare_dir(config_user_path, 0750, uid, gid) == -1) {
1126         return -1;
1127     }
1128 
1129    return 0;
1130 }
1131 
create_profile_file(const char * pkgname,gid_t gid)1132 int create_profile_file(const char *pkgname, gid_t gid) {
1133     const char *profile_dir = DALVIK_CACHE_PREFIX "profiles";
1134     char profile_file[PKG_PATH_MAX];
1135 
1136     snprintf(profile_file, sizeof(profile_file), "%s/%s", profile_dir, pkgname);
1137 
1138     // The 'system' user needs to be able to read the profile to determine if dex2oat
1139     // needs to be run.  This is done in dalvik.system.DexFile.isDexOptNeededInternal().  So
1140     // we assign ownership to AID_SYSTEM and ensure it's not world-readable.
1141 
1142     int fd = open(profile_file, O_WRONLY | O_CREAT | O_NOFOLLOW | O_CLOEXEC, 0660);
1143 
1144     // Always set the uid/gid/permissions. The file could have been previously created
1145     // with different permissions.
1146     if (fd >= 0) {
1147         if (fchown(fd, AID_SYSTEM, gid) < 0) {
1148             ALOGE("cannot chown profile file '%s': %s\n", profile_file, strerror(errno));
1149             close(fd);
1150             unlink(profile_file);
1151             return -1;
1152         }
1153 
1154         if (fchmod(fd, 0660) < 0) {
1155             ALOGE("cannot chmod profile file '%s': %s\n", profile_file, strerror(errno));
1156             close(fd);
1157             unlink(profile_file);
1158             return -1;
1159         }
1160         close(fd);
1161     }
1162     return 0;
1163 }
1164 
remove_profile_file(const char * pkgname)1165 void remove_profile_file(const char *pkgname) {
1166     char profile_file[PKG_PATH_MAX];
1167     snprintf(profile_file, sizeof(profile_file), "%s/%s", DALVIK_CACHE_PREFIX "profiles", pkgname);
1168     unlink(profile_file);
1169 }
1170