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/fsuid.h>
22 #include <sys/prctl.h>
23 #include <sys/socket.h>
24 #include <sys/stat.h>
25 
26 #include <android-base/logging.h>
27 #include <cutils/fs.h>
28 #include <cutils/log.h>               // TODO: Move everything to base::logging.
29 #include <cutils/properties.h>
30 #include <cutils/sockets.h>
31 #include <private/android_filesystem_config.h>
32 
33 #include <commands.h>
34 #include <globals.h>
35 #include <installd_constants.h>
36 #include <installd_deps.h>  // Need to fill in requirements of commands.
37 #include <utils.h>
38 
39 #ifndef LOG_TAG
40 #define LOG_TAG "installd"
41 #endif
42 #define SOCKET_PATH "installd"
43 
44 #define BUFFER_MAX    1024  /* input buffer for commands */
45 #define TOKEN_MAX     16    /* max number of arguments in buffer */
46 #define REPLY_MAX     256   /* largest reply allowed */
47 
48 namespace android {
49 namespace installd {
50 
51 // Check that installd-deps sizes match cutils sizes.
52 static_assert(kPropertyKeyMax == PROPERTY_KEY_MAX, "Size mismatch.");
53 static_assert(kPropertyValueMax == PROPERTY_VALUE_MAX, "Size mismatch.");
54 
55 ////////////////////////
56 // Plug-in functions. //
57 ////////////////////////
58 
get_property(const char * key,char * value,const char * default_value)59 int 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
calculate_oat_file_path(char path[PKG_PATH_MAX],const char * oat_dir,const char * apk_path,const char * instruction_set)64 bool 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  */
calculate_odex_file_path(char path[PKG_PATH_MAX],const char * apk_path,const char * instruction_set)99 bool 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 
create_cache_path(char path[PKG_PATH_MAX],const char * src,const char * instruction_set)128 bool create_cache_path(char path[PKG_PATH_MAX],
129                        const char *src,
130                        const char *instruction_set) {
131     /* demand that we are an absolute path */
132     if ((src == nullptr) || (src[0] != '/') || strstr(src,"..")) {
133         return false;
134     }
135 
136     size_t srclen = strlen(src);
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 
parse_null(char * arg)178 static char* parse_null(char* arg) {
179     if (strcmp(arg, "!") == 0) {
180         return nullptr;
181     } else {
182         return arg;
183     }
184 }
185 
do_ping(char ** arg ATTRIBUTE_UNUSED,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)186 static int do_ping(char **arg ATTRIBUTE_UNUSED, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
187 {
188     return 0;
189 }
190 
do_create_app_data(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)191 static int do_create_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
192     /* const char *uuid, const char *pkgname, userid_t userid, int flags,
193             appid_t appid, const char* seinfo, int target_sdk_version */
194     return create_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]),
195                            atoi(arg[4]), arg[5], atoi(arg[6]));
196 }
197 
do_restorecon_app_data(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)198 static int do_restorecon_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
199     /* const char* uuid, const char* pkgName, userid_t userid, int flags,
200             appid_t appid, const char* seinfo */
201     return restorecon_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atoi(arg[4]), arg[5]);
202 }
203 
do_migrate_app_data(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)204 static int do_migrate_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
205     /* const char *uuid, const char *pkgname, userid_t userid, int flags */
206     return migrate_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]));
207 }
208 
do_clear_app_data(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)209 static int do_clear_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
210     /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
211     return clear_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
212 }
213 
do_destroy_app_data(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)214 static int do_destroy_app_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
215     /* const char *uuid, const char *pkgname, userid_t userid, int flags, ino_t ce_data_inode */
216     return destroy_app_data(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]));
217 }
218 
219 // We use otapreopt_chroot to get into the chroot.
220 static constexpr const char* kOtaPreopt = "/system/bin/otapreopt_chroot";
221 
do_ota_dexopt(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)222 static int do_ota_dexopt(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
223     // Time to fork and run otapreopt.
224 
225     // Check that the tool exists.
226     struct stat s;
227     if (stat(kOtaPreopt, &s) != 0) {
228         LOG(ERROR) << "Otapreopt chroot tool not found.";
229         return -1;
230     }
231 
232     pid_t pid = fork();
233     if (pid == 0) {
234         const char* argv[1 + 9 + 1];
235         argv[0] = kOtaPreopt;
236         for (size_t i = 1; i <= 9; ++i) {
237             argv[i] = arg[i - 1];
238         }
239         argv[10] = nullptr;
240 
241         execv(argv[0], (char * const *)argv);
242         PLOG(ERROR) << "execv(OTAPREOPT_CHROOT) failed";
243         exit(99);
244     } else {
245         int res = wait_child(pid);
246         if (res == 0) {
247             ALOGV("DexInv: --- END OTAPREOPT (success) ---\n");
248         } else {
249             ALOGE("DexInv: --- END OTAPREOPT --- status=0x%04x, process failed\n", res);
250         }
251         return res;
252     }
253 }
254 
do_dexopt(char ** arg,char reply[REPLY_MAX])255 static int do_dexopt(char **arg, char reply[REPLY_MAX])
256 {
257     int dexopt_flags = atoi(arg[6]);
258     if ((dexopt_flags & DEXOPT_OTA) != 0) {
259       return do_ota_dexopt(arg, reply);
260     }
261     return dexopt(arg[0],                      // apk_path
262                   atoi(arg[1]),                // uid
263                   arg[2],                      // pkgname
264                   arg[3],                      // instruction_set
265                   atoi(arg[4]),                // dexopt_needed
266                   arg[5],                      // oat_dir
267                   dexopt_flags,
268                   arg[7],                      // compiler_filter
269                   parse_null(arg[8]),          // volume_uuid
270                   parse_null(arg[9]));         // shared_libraries
271 }
272 
do_merge_profiles(char ** arg,char reply[REPLY_MAX])273 static int do_merge_profiles(char **arg, char reply[REPLY_MAX])
274 {
275     uid_t uid = static_cast<uid_t>(atoi(arg[0]));
276     const char* pkgname = arg[1];
277     if (merge_profiles(uid, pkgname)) {
278         strncpy(reply, "true", REPLY_MAX);
279     } else {
280         strncpy(reply, "false", REPLY_MAX);
281     }
282     return 0;
283 }
284 
do_dump_profiles(char ** arg,char reply[REPLY_MAX])285 static int do_dump_profiles(char **arg, char reply[REPLY_MAX])
286 {
287     uid_t uid = static_cast<uid_t>(atoi(arg[0]));
288     const char* pkgname = arg[1];
289     const char* dex_files = arg[2];
290     if (dump_profile(uid, pkgname, dex_files)) {
291         strncpy(reply, "true", REPLY_MAX);
292     } else {
293         strncpy(reply, "false", REPLY_MAX);
294     }
295     return 0;
296 }
297 
do_mark_boot_complete(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)298 static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
299 {
300     return mark_boot_complete(arg[0] /* instruction set */);
301 }
302 
do_rm_dex(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)303 static int do_rm_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
304 {
305     return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */
306 }
307 
do_free_cache(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)308 static int do_free_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) /* TODO int:free_size */
309 {
310     return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */
311 }
312 
do_get_app_size(char ** arg,char reply[REPLY_MAX])313 static int do_get_app_size(char **arg, char reply[REPLY_MAX]) {
314     int64_t codesize = 0;
315     int64_t datasize = 0;
316     int64_t cachesize = 0;
317     int64_t asecsize = 0;
318     int res = 0;
319 
320     /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
321             const char* code_path */
322     res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]),
323             arg[5], &codesize, &datasize, &cachesize, &asecsize);
324 
325     /*
326      * Each int64_t can take up 22 characters printed out. Make sure it
327      * doesn't go over REPLY_MAX in the future.
328      */
329     snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
330             codesize, datasize, cachesize, asecsize);
331     return res;
332 }
333 
do_get_app_data_inode(char ** arg,char reply[REPLY_MAX])334 static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) {
335     ino_t inode = 0;
336     int res = 0;
337 
338     /* const char *uuid, const char *pkgname, int userid, int flags */
339     res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode);
340 
341     snprintf(reply, REPLY_MAX, "%" PRId64, (int64_t) inode);
342     return res;
343 }
344 
do_move_complete_app(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)345 static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
346     /* const char* from_uuid, const char *to_uuid, const char *package_name,
347             const char *data_app_name, appid_t appid, const char* seinfo,
348             int target_sdk_version */
349     return move_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3],
350                              atoi(arg[4]), arg[5], atoi(arg[6]));
351 }
352 
do_create_user_data(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)353 static int do_create_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
354 {
355     /* const char *uuid, userid_t userid, int user_serial, int flags */
356     return create_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]), atoi(arg[3]));
357 }
358 
do_destroy_user_data(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)359 static int do_destroy_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
360 {
361     /* const char *uuid, userid_t userid, int flags */
362     return destroy_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]));
363 }
364 
do_linklib(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)365 static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
366 {
367     return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
368 }
369 
do_idmap(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)370 static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
371 {
372     return idmap(arg[0], arg[1], atoi(arg[2]));
373 }
374 
do_create_oat_dir(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)375 static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
376 {
377     /* oat_dir, instruction_set */
378     return create_oat_dir(arg[0], arg[1]);
379 }
380 
do_rm_package_dir(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)381 static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
382 {
383     /* oat_dir */
384     return rm_package_dir(arg[0]);
385 }
386 
do_clear_app_profiles(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)387 static int do_clear_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
388 {
389     /* package_name */
390     return clear_app_profiles(arg[0]);
391 }
392 
do_destroy_app_profiles(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)393 static int do_destroy_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
394 {
395     /* package_name */
396     return destroy_app_profiles(arg[0]);
397 }
398 
do_link_file(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)399 static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
400 {
401     /* relative_path, from_base, to_base */
402     return link_file(arg[0], arg[1], arg[2]);
403 }
404 
do_move_ab(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)405 static int do_move_ab(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
406     // apk_path, instruction_set, oat_dir
407     return move_ab(arg[0], arg[1], arg[2]);
408 }
409 
410 struct cmdinfo {
411     const char *name;
412     unsigned numargs;
413     int (*func)(char **arg, char reply[REPLY_MAX]);
414 };
415 
416 struct cmdinfo cmds[] = {
417     { "ping",                 0, do_ping },
418 
419     { "create_app_data",      7, do_create_app_data },
420     { "restorecon_app_data",  6, do_restorecon_app_data },
421     { "migrate_app_data",     4, do_migrate_app_data },
422     { "clear_app_data",       5, do_clear_app_data },
423     { "destroy_app_data",     5, do_destroy_app_data },
424     { "move_complete_app",    7, do_move_complete_app },
425     { "get_app_size",         6, do_get_app_size },
426     { "get_app_data_inode",   4, do_get_app_data_inode },
427 
428     { "create_user_data",     4, do_create_user_data },
429     { "destroy_user_data",    3, do_destroy_user_data },
430 
431     { "dexopt",              10, do_dexopt },
432     { "markbootcomplete",     1, do_mark_boot_complete },
433     { "rmdex",                2, do_rm_dex },
434     { "freecache",            2, do_free_cache },
435     { "linklib",              4, do_linklib },
436     { "idmap",                3, do_idmap },
437     { "createoatdir",         2, do_create_oat_dir },
438     { "rmpackagedir",         1, do_rm_package_dir },
439     { "clear_app_profiles",   1, do_clear_app_profiles },
440     { "destroy_app_profiles", 1, do_destroy_app_profiles },
441     { "linkfile",             3, do_link_file },
442     { "move_ab",              3, do_move_ab },
443     { "merge_profiles",       2, do_merge_profiles },
444     { "dump_profiles",        3, do_dump_profiles },
445 };
446 
readx(int s,void * _buf,int count)447 static int readx(int s, void *_buf, int count)
448 {
449     char *buf = (char *) _buf;
450     int n = 0, r;
451     if (count < 0) return -1;
452     while (n < count) {
453         r = read(s, buf + n, count - n);
454         if (r < 0) {
455             if (errno == EINTR) continue;
456             ALOGE("read error: %s\n", strerror(errno));
457             return -1;
458         }
459         if (r == 0) {
460             ALOGE("eof\n");
461             return -1; /* EOF */
462         }
463         n += r;
464     }
465     return 0;
466 }
467 
writex(int s,const void * _buf,int count)468 static int writex(int s, const void *_buf, int count)
469 {
470     const char *buf = (const char *) _buf;
471     int n = 0, r;
472     if (count < 0) return -1;
473     while (n < count) {
474         r = write(s, buf + n, count - n);
475         if (r < 0) {
476             if (errno == EINTR) continue;
477             ALOGE("write error: %s\n", strerror(errno));
478             return -1;
479         }
480         n += r;
481     }
482     return 0;
483 }
484 
485 
486 /* Tokenize the command buffer, locate a matching command,
487  * ensure that the required number of arguments are provided,
488  * call the function(), return the result.
489  */
execute(int s,char cmd[BUFFER_MAX])490 static int execute(int s, char cmd[BUFFER_MAX])
491 {
492     char reply[REPLY_MAX];
493     char *arg[TOKEN_MAX+1];
494     unsigned i;
495     unsigned n = 0;
496     unsigned short count;
497     int ret = -1;
498 
499     // ALOGI("execute('%s')\n", cmd);
500 
501         /* default reply is "" */
502     reply[0] = 0;
503 
504         /* n is number of args (not counting arg[0]) */
505     arg[0] = cmd;
506     while (*cmd) {
507         if (isspace(*cmd)) {
508             *cmd++ = 0;
509             n++;
510             arg[n] = cmd;
511             if (n == TOKEN_MAX) {
512                 ALOGE("too many arguments\n");
513                 goto done;
514             }
515         }
516         if (*cmd) {
517           cmd++;
518         }
519     }
520 
521     for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
522         if (!strcmp(cmds[i].name,arg[0])) {
523             if (n != cmds[i].numargs) {
524                 ALOGE("%s requires %d arguments (%d given)\n",
525                      cmds[i].name, cmds[i].numargs, n);
526             } else {
527                 ret = cmds[i].func(arg + 1, reply);
528             }
529             goto done;
530         }
531     }
532     ALOGE("unsupported command '%s'\n", arg[0]);
533 
534 done:
535     if (reply[0]) {
536         n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
537     } else {
538         n = snprintf(cmd, BUFFER_MAX, "%d", ret);
539     }
540     if (n > BUFFER_MAX) n = BUFFER_MAX;
541     count = n;
542 
543     // ALOGI("reply: '%s'\n", cmd);
544     if (writex(s, &count, sizeof(count))) return -1;
545     if (writex(s, cmd, count)) return -1;
546     return 0;
547 }
548 
initialize_globals()549 bool initialize_globals() {
550     const char* data_path = getenv("ANDROID_DATA");
551     if (data_path == nullptr) {
552         ALOGE("Could not find ANDROID_DATA");
553         return false;
554     }
555     const char* root_path = getenv("ANDROID_ROOT");
556     if (root_path == nullptr) {
557         ALOGE("Could not find ANDROID_ROOT");
558         return false;
559     }
560 
561     return init_globals_from_data_and_root(data_path, root_path);
562 }
563 
initialize_directories()564 static int initialize_directories() {
565     int res = -1;
566 
567     // Read current filesystem layout version to handle upgrade paths
568     char version_path[PATH_MAX];
569     snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
570 
571     int oldVersion;
572     if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
573         oldVersion = 0;
574     }
575     int version = oldVersion;
576 
577     if (version < 2) {
578         SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported");
579         version = 2;
580     }
581 
582     if (ensure_config_user_dirs(0) == -1) {
583         ALOGE("Failed to setup misc for user 0");
584         goto fail;
585     }
586 
587     if (version == 2) {
588         ALOGD("Upgrading to /data/misc/user directories");
589 
590         char misc_dir[PATH_MAX];
591         snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.path);
592 
593         char keychain_added_dir[PATH_MAX];
594         snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir);
595 
596         char keychain_removed_dir[PATH_MAX];
597         snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir);
598 
599         DIR *dir;
600         struct dirent *dirent;
601         dir = opendir("/data/user");
602         if (dir != NULL) {
603             while ((dirent = readdir(dir))) {
604                 const char *name = dirent->d_name;
605 
606                 // skip "." and ".."
607                 if (name[0] == '.') {
608                     if (name[1] == 0) continue;
609                     if ((name[1] == '.') && (name[2] == 0)) continue;
610                 }
611 
612                 uint32_t user_id = atoi(name);
613 
614                 // /data/misc/user/<user_id>
615                 if (ensure_config_user_dirs(user_id) == -1) {
616                     goto fail;
617                 }
618 
619                 char misc_added_dir[PATH_MAX];
620                 snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name);
621 
622                 char misc_removed_dir[PATH_MAX];
623                 snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name);
624 
625                 uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM);
626                 gid_t gid = uid;
627                 if (access(keychain_added_dir, F_OK) == 0) {
628                     if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) {
629                         ALOGE("Some files failed to copy");
630                     }
631                 }
632                 if (access(keychain_removed_dir, F_OK) == 0) {
633                     if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) {
634                         ALOGE("Some files failed to copy");
635                     }
636                 }
637             }
638             closedir(dir);
639 
640             if (access(keychain_added_dir, F_OK) == 0) {
641                 delete_dir_contents(keychain_added_dir, 1, 0);
642             }
643             if (access(keychain_removed_dir, F_OK) == 0) {
644                 delete_dir_contents(keychain_removed_dir, 1, 0);
645             }
646         }
647 
648         version = 3;
649     }
650 
651     // Persist layout version if changed
652     if (version != oldVersion) {
653         if (fs_write_atomic_int(version_path, version) == -1) {
654             ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
655             goto fail;
656         }
657     }
658 
659     // Success!
660     res = 0;
661 
662 fail:
663     return res;
664 }
665 
log_callback(int type,const char * fmt,...)666 static int log_callback(int type, const char *fmt, ...) {
667     va_list ap;
668     int priority;
669 
670     switch (type) {
671     case SELINUX_WARNING:
672         priority = ANDROID_LOG_WARN;
673         break;
674     case SELINUX_INFO:
675         priority = ANDROID_LOG_INFO;
676         break;
677     default:
678         priority = ANDROID_LOG_ERROR;
679         break;
680     }
681     va_start(ap, fmt);
682     LOG_PRI_VA(priority, "SELinux", fmt, ap);
683     va_end(ap);
684     return 0;
685 }
686 
installd_main(const int argc ATTRIBUTE_UNUSED,char * argv[])687 static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
688     char buf[BUFFER_MAX];
689     struct sockaddr addr;
690     socklen_t alen;
691     int lsocket, s;
692     int selinux_enabled = (is_selinux_enabled() > 0);
693 
694     setenv("ANDROID_LOG_TAGS", "*:v", 1);
695     android::base::InitLogging(argv);
696 
697     ALOGI("installd firing up\n");
698 
699     union selinux_callback cb;
700     cb.func_log = log_callback;
701     selinux_set_callback(SELINUX_CB_LOG, cb);
702 
703     if (!initialize_globals()) {
704         ALOGE("Could not initialize globals; exiting.\n");
705         exit(1);
706     }
707 
708     if (initialize_directories() < 0) {
709         ALOGE("Could not create directories; exiting.\n");
710         exit(1);
711     }
712 
713     if (selinux_enabled && selinux_status_open(true) < 0) {
714         ALOGE("Could not open selinux status; exiting.\n");
715         exit(1);
716     }
717 
718     lsocket = android_get_control_socket(SOCKET_PATH);
719     if (lsocket < 0) {
720         ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
721         exit(1);
722     }
723     if (listen(lsocket, 5)) {
724         ALOGE("Listen on socket failed: %s\n", strerror(errno));
725         exit(1);
726     }
727     fcntl(lsocket, F_SETFD, FD_CLOEXEC);
728 
729     for (;;) {
730         alen = sizeof(addr);
731         s = accept(lsocket, &addr, &alen);
732         if (s < 0) {
733             ALOGE("Accept failed: %s\n", strerror(errno));
734             continue;
735         }
736         fcntl(s, F_SETFD, FD_CLOEXEC);
737 
738         ALOGI("new connection\n");
739         for (;;) {
740             unsigned short count;
741             if (readx(s, &count, sizeof(count))) {
742                 ALOGE("failed to read size\n");
743                 break;
744             }
745             if ((count < 1) || (count >= BUFFER_MAX)) {
746                 ALOGE("invalid size %d\n", count);
747                 break;
748             }
749             if (readx(s, buf, count)) {
750                 ALOGE("failed to read command\n");
751                 break;
752             }
753             buf[count] = 0;
754             if (selinux_enabled && selinux_status_updated() > 0) {
755                 selinux_android_seapp_context_reload();
756             }
757             if (execute(s, buf)) break;
758         }
759         ALOGI("closing connection\n");
760         close(s);
761     }
762 
763     return 0;
764 }
765 
766 }  // namespace installd
767 }  // namespace android
768 
main(const int argc,char * argv[])769 int main(const int argc, char *argv[]) {
770     return android::installd::installd_main(argc, argv);
771 }
772