installd.cpp revision 02d0de56c75347a0cb8d5a8565dc8c4ee7616057
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 <fcntl.h>
18#include <selinux/android.h>
19#include <selinux/avc.h>
20#include <sys/capability.h>
21#include <sys/prctl.h>
22#include <sys/socket.h>
23#include <sys/stat.h>
24
25#include <android-base/logging.h>
26#include <cutils/fs.h>
27#include <cutils/log.h>               // TODO: Move everything to base::logging.
28#include <cutils/properties.h>
29#include <cutils/sockets.h>
30#include <private/android_filesystem_config.h>
31
32#include <commands.h>
33#include <globals.h>
34#include <installd_constants.h>
35#include <installd_deps.h>  // Need to fill in requirements of commands.
36#include <utils.h>
37
38#ifndef LOG_TAG
39#define LOG_TAG "installd"
40#endif
41#define SOCKET_PATH "installd"
42
43#define BUFFER_MAX    1024  /* input buffer for commands */
44#define TOKEN_MAX     16    /* max number of arguments in buffer */
45#define REPLY_MAX     256   /* largest reply allowed */
46
47
48namespace android {
49namespace installd {
50
51// Check that installd-deps sizes match cutils sizes.
52static_assert(kPropertyKeyMax == PROPERTY_KEY_MAX, "Size mismatch.");
53static_assert(kPropertyValueMax == PROPERTY_VALUE_MAX, "Size mismatch.");
54
55////////////////////////
56// Plug-in functions. //
57////////////////////////
58
59int get_property(const char *key, char *value, const char *default_value) {
60    return property_get(key, value, default_value);
61}
62
63// Compute the output path of
64bool calculate_oat_file_path(char path[PKG_PATH_MAX],
65                             const char *oat_dir,
66                             const char *apk_path,
67                             const char *instruction_set) {
68    char *file_name_start;
69    char *file_name_end;
70
71    file_name_start = strrchr(apk_path, '/');
72    if (file_name_start == NULL) {
73        ALOGE("apk_path '%s' has no '/'s in it\n", apk_path);
74        return false;
75    }
76    file_name_end = strrchr(apk_path, '.');
77    if (file_name_end < file_name_start) {
78        ALOGE("apk_path '%s' has no extension\n", apk_path);
79        return false;
80    }
81
82    // Calculate file_name
83    int file_name_len = file_name_end - file_name_start - 1;
84    char file_name[file_name_len + 1];
85    memcpy(file_name, file_name_start + 1, file_name_len);
86    file_name[file_name_len] = '\0';
87
88    // <apk_parent_dir>/oat/<isa>/<file_name>.odex
89    snprintf(path, PKG_PATH_MAX, "%s/%s/%s.odex", oat_dir, instruction_set, file_name);
90    return true;
91}
92
93/*
94 * Computes the odex file for the given apk_path and instruction_set.
95 * /system/framework/whatever.jar -> /system/framework/oat/<isa>/whatever.odex
96 *
97 * Returns false if it failed to determine the odex file path.
98 */
99bool calculate_odex_file_path(char path[PKG_PATH_MAX],
100                              const char *apk_path,
101                              const char *instruction_set) {
102    if (strlen(apk_path) + strlen("oat/") + strlen(instruction_set)
103            + strlen("/") + strlen("odex") + 1 > PKG_PATH_MAX) {
104        ALOGE("apk_path '%s' may be too long to form odex file path.\n", apk_path);
105        return false;
106    }
107
108    strcpy(path, apk_path);
109    char *end = strrchr(path, '/');
110    if (end == NULL) {
111        ALOGE("apk_path '%s' has no '/'s in it?!\n", apk_path);
112        return false;
113    }
114    const char *apk_end = apk_path + (end - path); // strrchr(apk_path, '/');
115
116    strcpy(end + 1, "oat/");       // path = /system/framework/oat/\0
117    strcat(path, instruction_set); // path = /system/framework/oat/<isa>\0
118    strcat(path, apk_end);         // path = /system/framework/oat/<isa>/whatever.jar\0
119    end = strrchr(path, '.');
120    if (end == NULL) {
121        ALOGE("apk_path '%s' has no extension.\n", apk_path);
122        return false;
123    }
124    strcpy(end + 1, "odex");
125    return true;
126}
127
128bool create_cache_path(char path[PKG_PATH_MAX],
129                       const char *src,
130                       const char *instruction_set) {
131    size_t srclen = strlen(src);
132
133        /* demand that we are an absolute path */
134    if ((src == 0) || (src[0] != '/') || strstr(src,"..")) {
135        return false;
136    }
137
138    if (srclen > PKG_PATH_MAX) {        // XXX: PKG_NAME_MAX?
139        return false;
140    }
141
142    size_t dstlen =
143        android_data_dir.len +
144        strlen(DALVIK_CACHE) +
145        1 +
146        strlen(instruction_set) +
147        srclen +
148        strlen(DALVIK_CACHE_POSTFIX) + 2;
149
150    if (dstlen > PKG_PATH_MAX) {
151        return false;
152    }
153
154    sprintf(path,"%s%s/%s/%s%s",
155            android_data_dir.path,
156            DALVIK_CACHE,
157            instruction_set,
158            src + 1, /* skip the leading / */
159            DALVIK_CACHE_POSTFIX);
160
161    char* tmp =
162            path +
163            android_data_dir.len +
164            strlen(DALVIK_CACHE) +
165            1 +
166            strlen(instruction_set) + 1;
167
168    for(; *tmp; tmp++) {
169        if (*tmp == '/') {
170            *tmp = '@';
171        }
172    }
173
174    return true;
175}
176
177
178static char* parse_null(char* arg) {
179    if (strcmp(arg, "!") == 0) {
180        return nullptr;
181    } else {
182        return arg;
183    }
184}
185
186static int do_ping(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
187{
188    return 0;
189}
190
191static int do_install(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
192{
193    return install(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]); /* uuid, pkgname, uid, gid, seinfo */
194}
195
196static int do_dexopt(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
197{
198    /* apk_path, uid, pkgname, instruction_set, dexopt_needed, oat_dir, dexopt_flags */
199    return dexopt(arg[0], atoi(arg[1]), arg[2], arg[3], atoi(arg[4]),
200                  arg[5], atoi(arg[6]));
201}
202
203static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
204{
205    return mark_boot_complete(arg[0] /* instruction set */);
206}
207
208static int do_move_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
209{
210    return move_dex(arg[0], arg[1], arg[2]); /* src, dst, instruction_set */
211}
212
213static int do_rm_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
214{
215    return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */
216}
217
218static int do_remove(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
219{
220    return uninstall(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
221}
222
223static int do_fixuid(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
224{
225    return fix_uid(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3])); /* uuid, pkgname, uid, gid */
226}
227
228static int do_free_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) /* TODO int:free_size */
229{
230    return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */
231}
232
233static int do_rm_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
234{
235    return delete_cache(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
236}
237
238static int do_rm_code_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
239{
240    return delete_code_cache(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
241}
242
243static int do_get_size(char **arg, char reply[REPLY_MAX])
244{
245    int64_t codesize = 0;
246    int64_t datasize = 0;
247    int64_t cachesize = 0;
248    int64_t asecsize = 0;
249    int res = 0;
250
251        /* uuid, pkgdir, userid, apkpath */
252    res = get_size(parse_null(arg[0]), arg[1], atoi(arg[2]), arg[3], arg[4], arg[5], arg[6],
253            arg[7], &codesize, &datasize, &cachesize, &asecsize);
254
255    /*
256     * Each int64_t can take up 22 characters printed out. Make sure it
257     * doesn't go over REPLY_MAX in the future.
258     */
259    snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
260            codesize, datasize, cachesize, asecsize);
261    return res;
262}
263
264static int do_rm_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
265{
266    return delete_user_data(parse_null(arg[0]), arg[1], atoi(arg[2])); /* uuid, pkgname, userid */
267}
268
269static int do_cp_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
270{
271    // from_uuid, to_uuid, package_name, data_app_name, appid, seinfo
272    return copy_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3], atoi(arg[4]), arg[5]);
273}
274
275static int do_mk_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
276{
277    return make_user_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), arg[4]);
278                             /* uuid, pkgname, uid, userid, seinfo */
279}
280
281static int do_mk_user_config(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
282{
283    return make_user_config(atoi(arg[0])); /* userid */
284}
285
286static int do_rm_user(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
287{
288    return delete_user(parse_null(arg[0]), atoi(arg[1])); /* uuid, userid */
289}
290
291static int do_movefiles(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
292{
293    return movefiles();
294}
295
296static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
297{
298    return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
299}
300
301static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
302{
303    return idmap(arg[0], arg[1], atoi(arg[2]));
304}
305
306static int do_restorecon_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
307{
308    return restorecon_data(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
309                             /* uuid, pkgName, seinfo, uid*/
310}
311
312static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
313{
314    /* oat_dir, instruction_set */
315    return create_oat_dir(arg[0], arg[1]);
316}
317
318static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
319{
320    /* oat_dir */
321    return rm_package_dir(arg[0]);
322}
323
324static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
325{
326    /* relative_path, from_base, to_base */
327    return link_file(arg[0], arg[1], arg[2]);
328}
329
330struct cmdinfo {
331    const char *name;
332    unsigned numargs;
333    int (*func)(char **arg, char reply[REPLY_MAX]);
334};
335
336struct cmdinfo cmds[] = {
337    { "ping",                 0, do_ping },
338    { "install",              5, do_install },
339    { "dexopt",               7, do_dexopt },
340    { "markbootcomplete",     1, do_mark_boot_complete },
341    { "movedex",              3, do_move_dex },
342    { "rmdex",                2, do_rm_dex },
343    { "remove",               3, do_remove },
344    { "fixuid",               4, do_fixuid },
345    { "freecache",            2, do_free_cache },
346    { "rmcache",              3, do_rm_cache },
347    { "rmcodecache",          3, do_rm_code_cache },
348    { "getsize",              8, do_get_size },
349    { "rmuserdata",           3, do_rm_user_data },
350    { "cpcompleteapp",        6, do_cp_complete_app },
351    { "movefiles",            0, do_movefiles },
352    { "linklib",              4, do_linklib },
353    { "mkuserdata",           5, do_mk_user_data },
354    { "mkuserconfig",         1, do_mk_user_config },
355    { "rmuser",               2, do_rm_user },
356    { "idmap",                3, do_idmap },
357    { "restorecondata",       4, do_restorecon_data },
358    { "createoatdir",         2, do_create_oat_dir },
359    { "rmpackagedir",         1, do_rm_package_dir },
360    { "linkfile",             3, do_link_file }
361};
362
363static int readx(int s, void *_buf, int count)
364{
365    char *buf = (char *) _buf;
366    int n = 0, r;
367    if (count < 0) return -1;
368    while (n < count) {
369        r = read(s, buf + n, count - n);
370        if (r < 0) {
371            if (errno == EINTR) continue;
372            ALOGE("read error: %s\n", strerror(errno));
373            return -1;
374        }
375        if (r == 0) {
376            ALOGE("eof\n");
377            return -1; /* EOF */
378        }
379        n += r;
380    }
381    return 0;
382}
383
384static int writex(int s, const void *_buf, int count)
385{
386    const char *buf = (const char *) _buf;
387    int n = 0, r;
388    if (count < 0) return -1;
389    while (n < count) {
390        r = write(s, buf + n, count - n);
391        if (r < 0) {
392            if (errno == EINTR) continue;
393            ALOGE("write error: %s\n", strerror(errno));
394            return -1;
395        }
396        n += r;
397    }
398    return 0;
399}
400
401
402/* Tokenize the command buffer, locate a matching command,
403 * ensure that the required number of arguments are provided,
404 * call the function(), return the result.
405 */
406static int execute(int s, char cmd[BUFFER_MAX])
407{
408    char reply[REPLY_MAX];
409    char *arg[TOKEN_MAX+1];
410    unsigned i;
411    unsigned n = 0;
412    unsigned short count;
413    int ret = -1;
414
415    // ALOGI("execute('%s')\n", cmd);
416
417        /* default reply is "" */
418    reply[0] = 0;
419
420        /* n is number of args (not counting arg[0]) */
421    arg[0] = cmd;
422    while (*cmd) {
423        if (isspace(*cmd)) {
424            *cmd++ = 0;
425            n++;
426            arg[n] = cmd;
427            if (n == TOKEN_MAX) {
428                ALOGE("too many arguments\n");
429                goto done;
430            }
431        }
432        if (*cmd) {
433          cmd++;
434        }
435    }
436
437    for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
438        if (!strcmp(cmds[i].name,arg[0])) {
439            if (n != cmds[i].numargs) {
440                ALOGE("%s requires %d arguments (%d given)\n",
441                     cmds[i].name, cmds[i].numargs, n);
442            } else {
443                ret = cmds[i].func(arg + 1, reply);
444            }
445            goto done;
446        }
447    }
448    ALOGE("unsupported command '%s'\n", arg[0]);
449
450done:
451    if (reply[0]) {
452        n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
453    } else {
454        n = snprintf(cmd, BUFFER_MAX, "%d", ret);
455    }
456    if (n > BUFFER_MAX) n = BUFFER_MAX;
457    count = n;
458
459    // ALOGI("reply: '%s'\n", cmd);
460    if (writex(s, &count, sizeof(count))) return -1;
461    if (writex(s, cmd, count)) return -1;
462    return 0;
463}
464
465bool initialize_globals() {
466    const char* data_path = getenv("ANDROID_DATA");
467    if (data_path == nullptr) {
468        ALOGE("Could not find ANDROID_DATA");
469        return false;
470    }
471    const char* root_path = getenv("ANDROID_ROOT");
472    if (root_path == nullptr) {
473        ALOGE("Could not find ANDROID_ROOT");
474        return false;
475    }
476
477    return init_globals_from_data_and_root(data_path, root_path);
478}
479
480static int initialize_directories() {
481    int res = -1;
482
483    // Read current filesystem layout version to handle upgrade paths
484    char version_path[PATH_MAX];
485    snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
486
487    int oldVersion;
488    if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
489        oldVersion = 0;
490    }
491    int version = oldVersion;
492
493    // /data/user
494    char *user_data_dir = build_string2(android_data_dir.path, SECONDARY_USER_PREFIX);
495    // /data/data
496    char *legacy_data_dir = build_string2(android_data_dir.path, PRIMARY_USER_PREFIX);
497    // /data/user/0
498    char *primary_data_dir = build_string3(android_data_dir.path, SECONDARY_USER_PREFIX, "0");
499    if (!user_data_dir || !legacy_data_dir || !primary_data_dir) {
500        goto fail;
501    }
502
503    // Make the /data/user directory if necessary
504    if (access(user_data_dir, R_OK) < 0) {
505        if (mkdir(user_data_dir, 0711) < 0) {
506            goto fail;
507        }
508        if (chown(user_data_dir, AID_SYSTEM, AID_SYSTEM) < 0) {
509            goto fail;
510        }
511        if (chmod(user_data_dir, 0711) < 0) {
512            goto fail;
513        }
514    }
515    // Make the /data/user/0 symlink to /data/data if necessary
516    if (access(primary_data_dir, R_OK) < 0) {
517        if (symlink(legacy_data_dir, primary_data_dir)) {
518            goto fail;
519        }
520    }
521
522    if (version == 0) {
523        // Introducing multi-user, so migrate /data/media contents into /data/media/0
524        ALOGD("Upgrading /data/media for multi-user");
525
526        // Ensure /data/media
527        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
528            goto fail;
529        }
530
531        // /data/media.tmp
532        char media_tmp_dir[PATH_MAX];
533        snprintf(media_tmp_dir, PATH_MAX, "%smedia.tmp", android_data_dir.path);
534
535        // Only copy when upgrade not already in progress
536        if (access(media_tmp_dir, F_OK) == -1) {
537            if (rename(android_media_dir.path, media_tmp_dir) == -1) {
538                ALOGE("Failed to move legacy media path: %s", strerror(errno));
539                goto fail;
540            }
541        }
542
543        // Create /data/media again
544        if (fs_prepare_dir(android_media_dir.path, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
545            goto fail;
546        }
547
548        if (selinux_android_restorecon(android_media_dir.path, 0)) {
549            goto fail;
550        }
551
552        // /data/media/0
553        char owner_media_dir[PATH_MAX];
554        snprintf(owner_media_dir, PATH_MAX, "%s0", android_media_dir.path);
555
556        // Move any owner data into place
557        if (access(media_tmp_dir, F_OK) == 0) {
558            if (rename(media_tmp_dir, owner_media_dir) == -1) {
559                ALOGE("Failed to move owner media path: %s", strerror(errno));
560                goto fail;
561            }
562        }
563
564        // Ensure media directories for any existing users
565        DIR *dir;
566        struct dirent *dirent;
567        char user_media_dir[PATH_MAX];
568
569        dir = opendir(user_data_dir);
570        if (dir != NULL) {
571            while ((dirent = readdir(dir))) {
572                if (dirent->d_type == DT_DIR) {
573                    const char *name = dirent->d_name;
574
575                    // skip "." and ".."
576                    if (name[0] == '.') {
577                        if (name[1] == 0) continue;
578                        if ((name[1] == '.') && (name[2] == 0)) continue;
579                    }
580
581                    // /data/media/<user_id>
582                    snprintf(user_media_dir, PATH_MAX, "%s%s", android_media_dir.path, name);
583                    if (fs_prepare_dir(user_media_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
584                        goto fail;
585                    }
586                }
587            }
588            closedir(dir);
589        }
590
591        version = 1;
592    }
593
594    // /data/media/obb
595    char media_obb_dir[PATH_MAX];
596    snprintf(media_obb_dir, PATH_MAX, "%sobb", android_media_dir.path);
597
598    if (version == 1) {
599        // Introducing /data/media/obb for sharing OBB across users; migrate
600        // any existing OBB files from owner.
601        ALOGD("Upgrading to shared /data/media/obb");
602
603        // /data/media/0/Android/obb
604        char owner_obb_path[PATH_MAX];
605        snprintf(owner_obb_path, PATH_MAX, "%s0/Android/obb", android_media_dir.path);
606
607        // Only move if target doesn't already exist
608        if (access(media_obb_dir, F_OK) != 0 && access(owner_obb_path, F_OK) == 0) {
609            if (rename(owner_obb_path, media_obb_dir) == -1) {
610                ALOGE("Failed to move OBB from owner: %s", strerror(errno));
611                goto fail;
612            }
613        }
614
615        version = 2;
616    }
617
618    if (ensure_media_user_dirs(nullptr, 0) == -1) {
619        ALOGE("Failed to setup media for user 0");
620        goto fail;
621    }
622    if (fs_prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW) == -1) {
623        goto fail;
624    }
625
626    if (ensure_config_user_dirs(0) == -1) {
627        ALOGE("Failed to setup misc for user 0");
628        goto fail;
629    }
630
631    if (version == 2) {
632        ALOGD("Upgrading to /data/misc/user directories");
633
634        char misc_dir[PATH_MAX];
635        snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.path);
636
637        char keychain_added_dir[PATH_MAX];
638        snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir);
639
640        char keychain_removed_dir[PATH_MAX];
641        snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir);
642
643        DIR *dir;
644        struct dirent *dirent;
645        dir = opendir(user_data_dir);
646        if (dir != NULL) {
647            while ((dirent = readdir(dir))) {
648                const char *name = dirent->d_name;
649
650                // skip "." and ".."
651                if (name[0] == '.') {
652                    if (name[1] == 0) continue;
653                    if ((name[1] == '.') && (name[2] == 0)) continue;
654                }
655
656                uint32_t user_id = atoi(name);
657
658                // /data/misc/user/<user_id>
659                if (ensure_config_user_dirs(user_id) == -1) {
660                    goto fail;
661                }
662
663                char misc_added_dir[PATH_MAX];
664                snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name);
665
666                char misc_removed_dir[PATH_MAX];
667                snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name);
668
669                uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM);
670                gid_t gid = uid;
671                if (access(keychain_added_dir, F_OK) == 0) {
672                    if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) {
673                        ALOGE("Some files failed to copy");
674                    }
675                }
676                if (access(keychain_removed_dir, F_OK) == 0) {
677                    if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) {
678                        ALOGE("Some files failed to copy");
679                    }
680                }
681            }
682            closedir(dir);
683
684            if (access(keychain_added_dir, F_OK) == 0) {
685                delete_dir_contents(keychain_added_dir, 1, 0);
686            }
687            if (access(keychain_removed_dir, F_OK) == 0) {
688                delete_dir_contents(keychain_removed_dir, 1, 0);
689            }
690        }
691
692        version = 3;
693    }
694
695    // Persist layout version if changed
696    if (version != oldVersion) {
697        if (fs_write_atomic_int(version_path, version) == -1) {
698            ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
699            goto fail;
700        }
701    }
702
703    // Success!
704    res = 0;
705
706fail:
707    free(user_data_dir);
708    free(legacy_data_dir);
709    free(primary_data_dir);
710    return res;
711}
712
713static int log_callback(int type, const char *fmt, ...) {
714    va_list ap;
715    int priority;
716
717    switch (type) {
718    case SELINUX_WARNING:
719        priority = ANDROID_LOG_WARN;
720        break;
721    case SELINUX_INFO:
722        priority = ANDROID_LOG_INFO;
723        break;
724    default:
725        priority = ANDROID_LOG_ERROR;
726        break;
727    }
728    va_start(ap, fmt);
729    LOG_PRI_VA(priority, "SELinux", fmt, ap);
730    va_end(ap);
731    return 0;
732}
733
734static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
735    char buf[BUFFER_MAX];
736    struct sockaddr addr;
737    socklen_t alen;
738    int lsocket, s;
739    int selinux_enabled = (is_selinux_enabled() > 0);
740
741    setenv("ANDROID_LOG_TAGS", "*:v", 1);
742    android::base::InitLogging(argv);
743
744    ALOGI("installd firing up\n");
745
746    union selinux_callback cb;
747    cb.func_log = log_callback;
748    selinux_set_callback(SELINUX_CB_LOG, cb);
749
750    if (!initialize_globals()) {
751        ALOGE("Could not initialize globals; exiting.\n");
752        exit(1);
753    }
754
755    if (initialize_directories() < 0) {
756        ALOGE("Could not create directories; exiting.\n");
757        exit(1);
758    }
759
760    if (selinux_enabled && selinux_status_open(true) < 0) {
761        ALOGE("Could not open selinux status; exiting.\n");
762        exit(1);
763    }
764
765    lsocket = android_get_control_socket(SOCKET_PATH);
766    if (lsocket < 0) {
767        ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
768        exit(1);
769    }
770    if (listen(lsocket, 5)) {
771        ALOGE("Listen on socket failed: %s\n", strerror(errno));
772        exit(1);
773    }
774    fcntl(lsocket, F_SETFD, FD_CLOEXEC);
775
776    for (;;) {
777        alen = sizeof(addr);
778        s = accept(lsocket, &addr, &alen);
779        if (s < 0) {
780            ALOGE("Accept failed: %s\n", strerror(errno));
781            continue;
782        }
783        fcntl(s, F_SETFD, FD_CLOEXEC);
784
785        ALOGI("new connection\n");
786        for (;;) {
787            unsigned short count;
788            if (readx(s, &count, sizeof(count))) {
789                ALOGE("failed to read size\n");
790                break;
791            }
792            if ((count < 1) || (count >= BUFFER_MAX)) {
793                ALOGE("invalid size %d\n", count);
794                break;
795            }
796            if (readx(s, buf, count)) {
797                ALOGE("failed to read command\n");
798                break;
799            }
800            buf[count] = 0;
801            if (selinux_enabled && selinux_status_updated() > 0) {
802                selinux_android_seapp_context_reload();
803            }
804            if (execute(s, buf)) break;
805        }
806        ALOGI("closing connection\n");
807        close(s);
808    }
809
810    return 0;
811}
812
813}  // namespace installd
814}  // namespace android
815
816int main(const int argc, char *argv[]) {
817    return android::installd::installd_main(argc, argv);
818}
819