commands.c revision 9066cfe9886ac131c34d59ed0e2d287b0e3c0087
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
19int install(const char *pkgname, uid_t uid, gid_t gid)
20{
21    char pkgdir[PKG_PATH_MAX];
22    char libdir[PKG_PATH_MAX];
23
24    if ((uid < AID_SYSTEM) || (gid < AID_SYSTEM)) {
25        LOGE("invalid uid/gid: %d %d\n", uid, gid);
26        return -1;
27
28    }
29    if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
30        return -1;
31    if (create_pkg_path(libdir, PKG_LIB_PREFIX, pkgname, PKG_LIB_POSTFIX))
32        return -1;
33
34    if (mkdir(pkgdir, 0755) < 0) {
35        LOGE("cannot create dir '%s': %s\n", pkgdir, strerror(errno));
36        return -errno;
37    }
38    if (chown(pkgdir, uid, gid) < 0) {
39        LOGE("cannot chown dir '%s': %s\n", pkgdir, strerror(errno));
40        unlink(pkgdir);
41        return -errno;
42    }
43    if (mkdir(libdir, 0755) < 0) {
44        LOGE("cannot create dir '%s': %s\n", libdir, strerror(errno));
45        unlink(pkgdir);
46        return -errno;
47    }
48    if (chown(libdir, AID_SYSTEM, AID_SYSTEM) < 0) {
49        LOGE("cannot chown dir '%s': %s\n", libdir, strerror(errno));
50        unlink(libdir);
51        unlink(pkgdir);
52        return -errno;
53    }
54    return 0;
55}
56
57int uninstall(const char *pkgname)
58{
59    char pkgdir[PKG_PATH_MAX];
60
61    if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
62        return -1;
63
64        /* delete contents AND directory, no exceptions */
65    return delete_dir_contents(pkgdir, 1, 0);
66}
67
68int delete_user_data(const char *pkgname)
69{
70    char pkgdir[PKG_PATH_MAX];
71
72    if (create_pkg_path(pkgdir, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX))
73        return -1;
74
75        /* delete contents, excluding "lib", but not the directory itself */
76    return delete_dir_contents(pkgdir, 0, "lib");
77}
78
79int delete_cache(const char *pkgname)
80{
81    char cachedir[PKG_PATH_MAX];
82
83    if (create_pkg_path(cachedir, CACHE_DIR_PREFIX, pkgname, CACHE_DIR_POSTFIX))
84        return -1;
85
86        /* delete contents, not the directory, no exceptions */
87    return delete_dir_contents(cachedir, 0, 0);
88}
89
90
91static int disk_free(void)
92{
93    struct statfs sfs;
94    if (statfs(PKG_DIR_PREFIX, &sfs) == 0) {
95        return sfs.f_bavail * sfs.f_bsize;
96    } else {
97        return -1;
98    }
99}
100
101
102/* Try to ensure free_size bytes of storage are available.
103 * Returns 0 on success.
104 * This is rather simple-minded because doing a full LRU would
105 * be potentially memory-intensive, and without atime it would
106 * also require that apps constantly modify file metadata even
107 * when just reading from the cache, which is pretty awful.
108 */
109int free_cache(int free_size)
110{
111    const char *name;
112    int dfd, subfd;
113    DIR *d;
114    struct dirent *de;
115    int avail;
116
117    avail = disk_free();
118    if (avail < 0) return -1;
119
120    LOGI("free_cache(%d) avail %d\n", free_size, avail);
121    if (avail >= free_size) return 0;
122
123    d = opendir(PKG_DIR_PREFIX);
124    if (d == NULL) {
125        LOGE("cannot open %s\n", PKG_DIR_PREFIX);
126        return -1;
127    }
128    dfd = dirfd(d);
129
130    while ((de = readdir(d))) {
131        if (de->d_type != DT_DIR) continue;
132        name = de->d_name;
133
134            /* always skip "." and ".." */
135        if (name[0] == '.') {
136            if (name[1] == 0) continue;
137            if ((name[1] == '.') && (name[2] == 0)) continue;
138        }
139
140        subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
141        if (subfd < 0) continue;
142
143        delete_dir_contents_fd(subfd, "cache");
144        close(subfd);
145
146        avail = disk_free();
147        if (avail >= free_size) {
148            closedir(d);
149            return 0;
150        }
151    }
152    closedir(d);
153    return -1;
154}
155
156
157/* used by move_dex, rm_dex, etc to ensure that the provided paths
158 * don't point anywhere other than at the APK_DIR_PREFIX
159 */
160static int is_valid_apk_path(const char *path)
161{
162    int len = strlen(APK_DIR_PREFIX);
163    if (strncmp(path, APK_DIR_PREFIX, len)) {
164        len = strlen(PROTECTED_DIR_PREFIX);
165        if (strncmp(path, PROTECTED_DIR_PREFIX, len)) {
166            LOGE("invalid apk path '%s' (bad prefix)\n", path);
167            return 0;
168        }
169    }
170    if (strchr(path + len, '/')) {
171        LOGE("invalid apk path '%s' (subdir?)\n", path);
172        return 0;
173    }
174    if (path[len] == '.') {
175        LOGE("invalid apk path '%s' (trickery)\n", path);
176        return 0;
177    }
178    return 1;
179}
180
181int move_dex(const char *src, const char *dst)
182{
183    char src_dex[PKG_PATH_MAX];
184    char dst_dex[PKG_PATH_MAX];
185
186    if (!is_valid_apk_path(src)) return -1;
187    if (!is_valid_apk_path(dst)) return -1;
188
189    if (create_cache_path(src_dex, src)) return -1;
190    if (create_cache_path(dst_dex, dst)) return -1;
191
192    LOGI("move %s -> %s\n", src_dex, dst_dex);
193    if (rename(src_dex, dst_dex) < 0) {
194        return -1;
195    } else {
196        return 0;
197    }
198}
199
200int rm_dex(const char *path)
201{
202    char dex_path[PKG_PATH_MAX];
203
204    if (!is_valid_apk_path(path)) return -1;
205    if (create_cache_path(dex_path, path)) return -1;
206
207    LOGI("unlink %s\n", dex_path);
208    if (unlink(dex_path) < 0) {
209        return -1;
210    } else {
211        return 0;
212    }
213}
214
215int protect(char *pkgname, gid_t gid)
216{
217    struct stat s;
218    char pkgpath[PKG_PATH_MAX];
219
220    if (gid < AID_SYSTEM) return -1;
221
222    if (create_pkg_path(pkgpath, PROTECTED_DIR_PREFIX, pkgname, ".apk"))
223        return -1;
224
225    if (stat(pkgpath, &s) < 0) return -1;
226
227    if (chown(pkgpath, s.st_uid, gid) < 0) {
228        LOGE("failed to chgrp '%s': %s\n", pkgpath, strerror(errno));
229        return -1;
230    }
231
232    if (chmod(pkgpath, S_IRUSR|S_IWUSR|S_IRGRP) < 0) {
233        LOGE("failed to chmod '%s': %s\n", pkgpath, strerror(errno));
234        return -1;
235    }
236
237    return 0;
238}
239
240static int stat_size(struct stat *s)
241{
242    int blksize = s->st_blksize;
243    int size = s->st_size;
244
245    if (blksize) {
246            /* round up to filesystem block size */
247        size = (size + blksize - 1) & (~(blksize - 1));
248    }
249
250    return size;
251}
252
253static int calculate_dir_size(int dfd)
254{
255    int size = 0;
256    struct stat s;
257    DIR *d;
258    struct dirent *de;
259
260    d = fdopendir(dfd);
261    if (d == NULL) {
262        close(dfd);
263        return 0;
264    }
265
266    while ((de = readdir(d))) {
267        const char *name = de->d_name;
268        if (de->d_type == DT_DIR) {
269            int subfd;
270                /* always skip "." and ".." */
271            if (name[0] == '.') {
272                if (name[1] == 0) continue;
273                if ((name[1] == '.') && (name[2] == 0)) continue;
274            }
275            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
276            if (subfd >= 0) {
277                size += calculate_dir_size(subfd);
278            }
279        } else {
280            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
281                size += stat_size(&s);
282            }
283        }
284    }
285    closedir(d);
286    return size;
287}
288
289int get_size(const char *pkgname, const char *apkpath,
290             const char *fwdlock_apkpath,
291             int *_codesize, int *_datasize, int *_cachesize)
292{
293    DIR *d;
294    int dfd;
295    struct dirent *de;
296    struct stat s;
297    char path[PKG_PATH_MAX];
298
299    int codesize = 0;
300    int datasize = 0;
301    int cachesize = 0;
302
303        /* count the source apk as code -- but only if it's not
304         * on the /system partition
305         */
306    if (strncmp(apkpath, "/system", 7) != 0) {
307        if (stat(apkpath, &s) == 0) {
308            codesize += stat_size(&s);
309        }
310    }
311        /* count the forward locked apk as code if it is given
312         */
313    if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
314        if (stat(fwdlock_apkpath, &s) == 0) {
315            codesize += stat_size(&s);
316        }
317    }
318
319
320        /* count the cached dexfile as code */
321    if (!create_cache_path(path, apkpath)) {
322        if (stat(path, &s) == 0) {
323            codesize += stat_size(&s);
324        }
325    }
326
327    if (create_pkg_path(path, PKG_DIR_PREFIX, pkgname, PKG_DIR_POSTFIX)) {
328        goto done;
329    }
330
331    d = opendir(path);
332    if (d == NULL) {
333        goto done;
334    }
335    dfd = dirfd(d);
336
337        /* most stuff in the pkgdir is data, except for the "cache"
338         * directory and below, which is cache, and the "lib" directory
339         * and below, which is code...
340         */
341    while ((de = readdir(d))) {
342        const char *name = de->d_name;
343
344        if (de->d_type == DT_DIR) {
345            int subfd;
346                /* always skip "." and ".." */
347            if (name[0] == '.') {
348                if (name[1] == 0) continue;
349                if ((name[1] == '.') && (name[2] == 0)) continue;
350            }
351            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
352            if (subfd >= 0) {
353                int size = calculate_dir_size(subfd);
354                if (!strcmp(name,"lib")) {
355                    codesize += size;
356                } else if(!strcmp(name,"cache")) {
357                    cachesize += size;
358                } else {
359                    datasize += size;
360                }
361            }
362        } else {
363            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
364                datasize += stat_size(&s);
365            }
366        }
367    }
368    closedir(d);
369done:
370    *_codesize = codesize;
371    *_datasize = datasize;
372    *_cachesize = cachesize;
373    return 0;
374}
375
376
377/* a simpler version of dexOptGenerateCacheFileName() */
378int create_cache_path(char path[PKG_PATH_MAX], const char *src)
379{
380    char *tmp;
381    int srclen;
382    int dstlen;
383
384    srclen = strlen(src);
385
386        /* demand that we are an absolute path */
387    if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
388        return -1;
389    }
390
391    if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
392        return -1;
393    }
394
395    dstlen = srclen + strlen(DALVIK_CACHE_PREFIX) +
396        strlen(DALVIK_CACHE_POSTFIX) + 1;
397
398    if (dstlen > PKG_PATH_MAX) {
399        return -1;
400    }
401
402    sprintf(path,"%s%s%s",
403            DALVIK_CACHE_PREFIX,
404            src + 1, /* skip the leading / */
405            DALVIK_CACHE_POSTFIX);
406
407    for(tmp = path + strlen(DALVIK_CACHE_PREFIX); *tmp; tmp++) {
408        if (*tmp == '/') {
409            *tmp = '@';
410        }
411    }
412
413    return 0;
414}
415
416static void run_dexopt(int zip_fd, int odex_fd, const char* input_file_name,
417    const char* dexopt_flags)
418{
419    static const char* DEX_OPT_BIN = "/system/bin/dexopt";
420    static const int MAX_INT_LEN = 12;      // '-'+10dig+'\0' -OR- 0x+8dig
421    char zip_num[MAX_INT_LEN];
422    char odex_num[MAX_INT_LEN];
423
424    sprintf(zip_num, "%d", zip_fd);
425    sprintf(odex_num, "%d", odex_fd);
426
427    execl(DEX_OPT_BIN, DEX_OPT_BIN, "--zip", zip_num, odex_num, input_file_name,
428        dexopt_flags, (char*) NULL);
429    LOGE("execl(%s) failed: %s\n", DEX_OPT_BIN, strerror(errno));
430}
431
432static int wait_dexopt(pid_t pid, const char* apk_path)
433{
434    int status;
435    pid_t got_pid;
436
437    /*
438     * Wait for the optimization process to finish.
439     */
440    while (1) {
441        got_pid = waitpid(pid, &status, 0);
442        if (got_pid == -1 && errno == EINTR) {
443            printf("waitpid interrupted, retrying\n");
444        } else {
445            break;
446        }
447    }
448    if (got_pid != pid) {
449        LOGW("waitpid failed: wanted %d, got %d: %s\n",
450            (int) pid, (int) got_pid, strerror(errno));
451        return 1;
452    }
453
454    if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
455        LOGD("DexInv: --- END '%s' (success) ---\n", apk_path);
456        return 0;
457    } else {
458        LOGW("DexInv: --- END '%s' --- status=0x%04x, process failed\n",
459            apk_path, status);
460        return status;      /* always nonzero */
461    }
462}
463
464int dexopt(const char *apk_path, uid_t uid, int is_public)
465{
466    struct utimbuf ut;
467    struct stat apk_stat, dex_stat;
468    char dex_path[PKG_PATH_MAX];
469    char dexopt_flags[PROPERTY_VALUE_MAX];
470    char *end;
471    int res, zip_fd=-1, odex_fd=-1;
472
473        /* Before anything else: is there a .odex file?  If so, we have
474         * pre-optimized the apk and there is nothing to do here.
475         */
476    if (strlen(apk_path) >= (PKG_PATH_MAX - 8)) {
477        return -1;
478    }
479
480    /* platform-specific flags affecting optimization and verification */
481    property_get("dalvik.vm.dexopt-flags", dexopt_flags, "");
482
483    strcpy(dex_path, apk_path);
484    end = strrchr(dex_path, '.');
485    if (end != NULL) {
486        strcpy(end, ".odex");
487        if (stat(dex_path, &dex_stat) == 0) {
488            return 0;
489        }
490    }
491
492    if (create_cache_path(dex_path, apk_path)) {
493        return -1;
494    }
495
496    memset(&apk_stat, 0, sizeof(apk_stat));
497    stat(apk_path, &apk_stat);
498
499    zip_fd = open(apk_path, O_RDONLY, 0);
500    if (zip_fd < 0) {
501        LOGE("dexopt cannot open '%s' for input\n", apk_path);
502        return -1;
503    }
504
505    unlink(dex_path);
506    odex_fd = open(dex_path, O_RDWR | O_CREAT | O_EXCL, 0644);
507    if (odex_fd < 0) {
508        LOGE("dexopt cannot open '%s' for output\n", dex_path);
509        goto fail;
510    }
511    if (fchown(odex_fd, AID_SYSTEM, uid) < 0) {
512        LOGE("dexopt cannot chown '%s'\n", dex_path);
513        goto fail;
514    }
515    if (fchmod(odex_fd,
516               S_IRUSR|S_IWUSR|S_IRGRP |
517               (is_public ? S_IROTH : 0)) < 0) {
518        LOGE("dexopt cannot chmod '%s'\n", dex_path);
519        goto fail;
520    }
521
522    LOGD("DexInv: --- BEGIN '%s' ---\n", apk_path);
523
524    pid_t pid;
525    pid = fork();
526    if (pid == 0) {
527        /* child -- drop privileges before continuing */
528        if (setgid(uid) != 0) {
529            LOGE("setgid(%d) failed during dexopt\n", uid);
530            exit(64);
531        }
532        if (setuid(uid) != 0) {
533            LOGE("setuid(%d) during dexopt\n", uid);
534            exit(65);
535        }
536        if (flock(odex_fd, LOCK_EX | LOCK_NB) != 0) {
537            LOGE("flock(%s) failed: %s\n", dex_path, strerror(errno));
538            exit(66);
539        }
540
541        run_dexopt(zip_fd, odex_fd, apk_path, dexopt_flags);
542        exit(67);   /* only get here on exec failure */
543    } else {
544        res = wait_dexopt(pid, apk_path);
545        if (res != 0) {
546            LOGE("dexopt failed on '%s' res = %d\n", dex_path, res);
547            goto fail;
548        }
549    }
550
551    ut.actime = apk_stat.st_atime;
552    ut.modtime = apk_stat.st_mtime;
553    utime(dex_path, &ut);
554
555    close(odex_fd);
556    close(zip_fd);
557    return 0;
558
559fail:
560    if (odex_fd >= 0) {
561        close(odex_fd);
562        unlink(dex_path);
563    }
564    if (zip_fd >= 0) {
565        close(zip_fd);
566    }
567    return -1;
568}
569