• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright 2008, The Android Open Source Project
3 **
4 ** Licensed under the Apache License, Version 2.0 (the "License");
5 ** you may not use this file except in compliance with the License.
6 ** You may obtain a copy of the License at
7 **
8 **     http://www.apache.org/licenses/LICENSE-2.0
9 **
10 ** Unless required by applicable law or agreed to in writing, software
11 ** distributed under the License is distributed on an "AS IS" BASIS,
12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 ** See the License for the specific language governing permissions and
14 ** limitations under the License.
15 */
16 
17 #include <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(const char * args[DEXOPT_PARAM_COUNT],char reply[REPLY_MAX]ATTRIBUTE_UNUSED)222 static int do_ota_dexopt(const char* args[DEXOPT_PARAM_COUNT],
223                          char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
224     // Time to fork and run otapreopt.
225 
226     // Check that the tool exists.
227     struct stat s;
228     if (stat(kOtaPreopt, &s) != 0) {
229         LOG(ERROR) << "Otapreopt chroot tool not found.";
230         return -1;
231     }
232 
233     pid_t pid = fork();
234     if (pid == 0) {
235         const char* argv[1 + DEXOPT_PARAM_COUNT + 1];
236         argv[0] = kOtaPreopt;
237 
238         for (size_t i = 0; i < DEXOPT_PARAM_COUNT; ++i) {
239             argv[i + 1] = args[i];
240         }
241 
242         argv[DEXOPT_PARAM_COUNT + 1] = nullptr;
243 
244         execv(argv[0], (char * const *)argv);
245         PLOG(ERROR) << "execv(OTAPREOPT_CHROOT) failed";
246         exit(99);
247     } else {
248         int res = wait_child(pid);
249         if (res == 0) {
250             ALOGV("DexInv: --- END OTAPREOPT (success) ---\n");
251         } else {
252             ALOGE("DexInv: --- END OTAPREOPT --- status=0x%04x, process failed\n", res);
253         }
254         return res;
255     }
256 }
257 
do_regular_dexopt(const char * args[DEXOPT_PARAM_COUNT],char reply[REPLY_MAX]ATTRIBUTE_UNUSED)258 static int do_regular_dexopt(const char* args[DEXOPT_PARAM_COUNT],
259                              char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
260     return dexopt(args);
261 }
262 
263 using DexoptFn = int (*)(const char* args[DEXOPT_PARAM_COUNT],
264                          char reply[REPLY_MAX]);
265 
do_dexopt(char ** arg,char reply[REPLY_MAX])266 static int do_dexopt(char **arg, char reply[REPLY_MAX])
267 {
268     const char* args[DEXOPT_PARAM_COUNT];
269     for (size_t i = 0; i < DEXOPT_PARAM_COUNT; ++i) {
270         CHECK(arg[i] != nullptr);
271         args[i] = arg[i];
272     }
273 
274     int dexopt_flags = atoi(arg[6]);
275     DexoptFn dexopt_fn;
276     if ((dexopt_flags & DEXOPT_OTA) != 0) {
277         dexopt_fn = do_ota_dexopt;
278     } else {
279         dexopt_fn = do_regular_dexopt;
280     }
281     return dexopt_fn(args, reply);
282 }
283 
do_merge_profiles(char ** arg,char reply[REPLY_MAX])284 static int do_merge_profiles(char **arg, char reply[REPLY_MAX])
285 {
286     uid_t uid = static_cast<uid_t>(atoi(arg[0]));
287     const char* pkgname = arg[1];
288     if (merge_profiles(uid, pkgname)) {
289         strncpy(reply, "true", REPLY_MAX);
290     } else {
291         strncpy(reply, "false", REPLY_MAX);
292     }
293     return 0;
294 }
295 
do_dump_profiles(char ** arg,char reply[REPLY_MAX])296 static int do_dump_profiles(char **arg, char reply[REPLY_MAX])
297 {
298     uid_t uid = static_cast<uid_t>(atoi(arg[0]));
299     const char* pkgname = arg[1];
300     const char* dex_files = arg[2];
301     if (dump_profile(uid, pkgname, dex_files)) {
302         strncpy(reply, "true", REPLY_MAX);
303     } else {
304         strncpy(reply, "false", REPLY_MAX);
305     }
306     return 0;
307 }
308 
do_mark_boot_complete(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)309 static int do_mark_boot_complete(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
310 {
311     return mark_boot_complete(arg[0] /* instruction set */);
312 }
313 
do_rm_dex(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)314 static int do_rm_dex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
315 {
316     return rm_dex(arg[0], arg[1]); /* pkgname, instruction_set */
317 }
318 
do_free_cache(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)319 static int do_free_cache(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) /* TODO int:free_size */
320 {
321     return free_cache(parse_null(arg[0]), (int64_t)atoll(arg[1])); /* uuid, free_size */
322 }
323 
do_get_app_size(char ** arg,char reply[REPLY_MAX])324 static int do_get_app_size(char **arg, char reply[REPLY_MAX]) {
325     int64_t codesize = 0;
326     int64_t datasize = 0;
327     int64_t cachesize = 0;
328     int64_t asecsize = 0;
329     int res = 0;
330 
331     /* const char *uuid, const char *pkgname, int userid, int flags, ino_t ce_data_inode,
332             const char* code_path */
333     res = get_app_size(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), atol(arg[4]),
334             arg[5], &codesize, &datasize, &cachesize, &asecsize);
335 
336     /*
337      * Each int64_t can take up 22 characters printed out. Make sure it
338      * doesn't go over REPLY_MAX in the future.
339      */
340     snprintf(reply, REPLY_MAX, "%" PRId64 " %" PRId64 " %" PRId64 " %" PRId64,
341             codesize, datasize, cachesize, asecsize);
342     return res;
343 }
344 
do_get_app_data_inode(char ** arg,char reply[REPLY_MAX])345 static int do_get_app_data_inode(char **arg, char reply[REPLY_MAX]) {
346     ino_t inode = 0;
347     int res = 0;
348 
349     /* const char *uuid, const char *pkgname, int userid, int flags */
350     res = get_app_data_inode(parse_null(arg[0]), arg[1], atoi(arg[2]), atoi(arg[3]), &inode);
351 
352     snprintf(reply, REPLY_MAX, "%" PRId64, (int64_t) inode);
353     return res;
354 }
355 
do_move_complete_app(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)356 static int do_move_complete_app(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
357     /* const char* from_uuid, const char *to_uuid, const char *package_name,
358             const char *data_app_name, appid_t appid, const char* seinfo,
359             int target_sdk_version */
360     return move_complete_app(parse_null(arg[0]), parse_null(arg[1]), arg[2], arg[3],
361                              atoi(arg[4]), arg[5], atoi(arg[6]));
362 }
363 
do_create_user_data(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)364 static int do_create_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
365 {
366     /* const char *uuid, userid_t userid, int user_serial, int flags */
367     return create_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]), atoi(arg[3]));
368 }
369 
do_destroy_user_data(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)370 static int do_destroy_user_data(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
371 {
372     /* const char *uuid, userid_t userid, int flags */
373     return destroy_user_data(parse_null(arg[0]), atoi(arg[1]), atoi(arg[2]));
374 }
375 
do_linklib(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)376 static int do_linklib(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
377 {
378     return linklib(parse_null(arg[0]), arg[1], arg[2], atoi(arg[3]));
379 }
380 
do_idmap(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)381 static int do_idmap(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
382 {
383     return idmap(arg[0], arg[1], atoi(arg[2]));
384 }
385 
do_create_oat_dir(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)386 static int do_create_oat_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
387 {
388     /* oat_dir, instruction_set */
389     return create_oat_dir(arg[0], arg[1]);
390 }
391 
do_rm_package_dir(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)392 static int do_rm_package_dir(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
393 {
394     /* oat_dir */
395     return rm_package_dir(arg[0]);
396 }
397 
do_clear_app_profiles(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)398 static int do_clear_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
399 {
400     /* package_name */
401     return clear_app_profiles(arg[0]);
402 }
403 
do_destroy_app_profiles(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)404 static int do_destroy_app_profiles(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
405 {
406     /* package_name */
407     return destroy_app_profiles(arg[0]);
408 }
409 
do_link_file(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)410 static int do_link_file(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED)
411 {
412     /* relative_path, from_base, to_base */
413     return link_file(arg[0], arg[1], arg[2]);
414 }
415 
do_move_ab(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)416 static int do_move_ab(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
417     // apk_path, instruction_set, oat_dir
418     return move_ab(arg[0], arg[1], arg[2]);
419 }
420 
do_delete_odex(char ** arg,char reply[REPLY_MAX]ATTRIBUTE_UNUSED)421 static int do_delete_odex(char **arg, char reply[REPLY_MAX] ATTRIBUTE_UNUSED) {
422     // apk_path, instruction_set, oat_dir
423     return delete_odex(arg[0], arg[1], arg[2]) ? 0 : -1;
424 }
425 
426 struct cmdinfo {
427     const char *name;
428     unsigned numargs;
429     int (*func)(char **arg, char reply[REPLY_MAX]);
430 };
431 
432 struct cmdinfo cmds[] = {
433     { "ping",                 0, do_ping },
434 
435     { "create_app_data",      7, do_create_app_data },
436     { "restorecon_app_data",  6, do_restorecon_app_data },
437     { "migrate_app_data",     4, do_migrate_app_data },
438     { "clear_app_data",       5, do_clear_app_data },
439     { "destroy_app_data",     5, do_destroy_app_data },
440     { "move_complete_app",    7, do_move_complete_app },
441     { "get_app_size",         6, do_get_app_size },
442     { "get_app_data_inode",   4, do_get_app_data_inode },
443 
444     { "create_user_data",     4, do_create_user_data },
445     { "destroy_user_data",    3, do_destroy_user_data },
446 
447     { "dexopt",              10, do_dexopt },
448     { "markbootcomplete",     1, do_mark_boot_complete },
449     { "rmdex",                2, do_rm_dex },
450     { "freecache",            2, do_free_cache },
451     { "linklib",              4, do_linklib },
452     { "idmap",                3, do_idmap },
453     { "createoatdir",         2, do_create_oat_dir },
454     { "rmpackagedir",         1, do_rm_package_dir },
455     { "clear_app_profiles",   1, do_clear_app_profiles },
456     { "destroy_app_profiles", 1, do_destroy_app_profiles },
457     { "linkfile",             3, do_link_file },
458     { "move_ab",              3, do_move_ab },
459     { "merge_profiles",       2, do_merge_profiles },
460     { "dump_profiles",        3, do_dump_profiles },
461     { "delete_odex",          3, do_delete_odex },
462 };
463 
readx(int s,void * _buf,int count)464 static int readx(int s, void *_buf, int count)
465 {
466     char *buf = (char *) _buf;
467     int n = 0, r;
468     if (count < 0) return -1;
469     while (n < count) {
470         r = read(s, buf + n, count - n);
471         if (r < 0) {
472             if (errno == EINTR) continue;
473             ALOGE("read error: %s\n", strerror(errno));
474             return -1;
475         }
476         if (r == 0) {
477             ALOGE("eof\n");
478             return -1; /* EOF */
479         }
480         n += r;
481     }
482     return 0;
483 }
484 
writex(int s,const void * _buf,int count)485 static int writex(int s, const void *_buf, int count)
486 {
487     const char *buf = (const char *) _buf;
488     int n = 0, r;
489     if (count < 0) return -1;
490     while (n < count) {
491         r = write(s, buf + n, count - n);
492         if (r < 0) {
493             if (errno == EINTR) continue;
494             ALOGE("write error: %s\n", strerror(errno));
495             return -1;
496         }
497         n += r;
498     }
499     return 0;
500 }
501 
502 
503 /* Tokenize the command buffer, locate a matching command,
504  * ensure that the required number of arguments are provided,
505  * call the function(), return the result.
506  */
execute(int s,char cmd[BUFFER_MAX])507 static int execute(int s, char cmd[BUFFER_MAX])
508 {
509     char reply[REPLY_MAX];
510     char *arg[TOKEN_MAX+1];
511     unsigned i;
512     unsigned n = 0;
513     unsigned short count;
514     int ret = -1;
515 
516     // ALOGI("execute('%s')\n", cmd);
517 
518         /* default reply is "" */
519     reply[0] = 0;
520 
521         /* n is number of args (not counting arg[0]) */
522     arg[0] = cmd;
523     while (*cmd) {
524         if (isspace(*cmd)) {
525             *cmd++ = 0;
526             n++;
527             arg[n] = cmd;
528             if (n == TOKEN_MAX) {
529                 ALOGE("too many arguments\n");
530                 goto done;
531             }
532         }
533         if (*cmd) {
534           cmd++;
535         }
536     }
537 
538     for (i = 0; i < sizeof(cmds) / sizeof(cmds[0]); i++) {
539         if (!strcmp(cmds[i].name,arg[0])) {
540             if (n != cmds[i].numargs) {
541                 ALOGE("%s requires %d arguments (%d given)\n",
542                      cmds[i].name, cmds[i].numargs, n);
543             } else {
544                 ret = cmds[i].func(arg + 1, reply);
545             }
546             goto done;
547         }
548     }
549     ALOGE("unsupported command '%s'\n", arg[0]);
550 
551 done:
552     if (reply[0]) {
553         n = snprintf(cmd, BUFFER_MAX, "%d %s", ret, reply);
554     } else {
555         n = snprintf(cmd, BUFFER_MAX, "%d", ret);
556     }
557     if (n > BUFFER_MAX) n = BUFFER_MAX;
558     count = n;
559 
560     // ALOGI("reply: '%s'\n", cmd);
561     if (writex(s, &count, sizeof(count))) return -1;
562     if (writex(s, cmd, count)) return -1;
563     return 0;
564 }
565 
initialize_globals()566 static bool initialize_globals() {
567     const char* data_path = getenv("ANDROID_DATA");
568     if (data_path == nullptr) {
569         ALOGE("Could not find ANDROID_DATA");
570         return false;
571     }
572     const char* root_path = getenv("ANDROID_ROOT");
573     if (root_path == nullptr) {
574         ALOGE("Could not find ANDROID_ROOT");
575         return false;
576     }
577 
578     return init_globals_from_data_and_root(data_path, root_path);
579 }
580 
initialize_directories()581 static int initialize_directories() {
582     int res = -1;
583 
584     // Read current filesystem layout version to handle upgrade paths
585     char version_path[PATH_MAX];
586     snprintf(version_path, PATH_MAX, "%s.layout_version", android_data_dir.path);
587 
588     int oldVersion;
589     if (fs_read_atomic_int(version_path, &oldVersion) == -1) {
590         oldVersion = 0;
591     }
592     int version = oldVersion;
593 
594     if (version < 2) {
595         SLOGD("Assuming that device has multi-user storage layout; upgrade no longer supported");
596         version = 2;
597     }
598 
599     if (ensure_config_user_dirs(0) == -1) {
600         ALOGE("Failed to setup misc for user 0");
601         goto fail;
602     }
603 
604     if (version == 2) {
605         ALOGD("Upgrading to /data/misc/user directories");
606 
607         char misc_dir[PATH_MAX];
608         snprintf(misc_dir, PATH_MAX, "%smisc", android_data_dir.path);
609 
610         char keychain_added_dir[PATH_MAX];
611         snprintf(keychain_added_dir, PATH_MAX, "%s/keychain/cacerts-added", misc_dir);
612 
613         char keychain_removed_dir[PATH_MAX];
614         snprintf(keychain_removed_dir, PATH_MAX, "%s/keychain/cacerts-removed", misc_dir);
615 
616         DIR *dir;
617         struct dirent *dirent;
618         dir = opendir("/data/user");
619         if (dir != NULL) {
620             while ((dirent = readdir(dir))) {
621                 const char *name = dirent->d_name;
622 
623                 // skip "." and ".."
624                 if (name[0] == '.') {
625                     if (name[1] == 0) continue;
626                     if ((name[1] == '.') && (name[2] == 0)) continue;
627                 }
628 
629                 uint32_t user_id = atoi(name);
630 
631                 // /data/misc/user/<user_id>
632                 if (ensure_config_user_dirs(user_id) == -1) {
633                     goto fail;
634                 }
635 
636                 char misc_added_dir[PATH_MAX];
637                 snprintf(misc_added_dir, PATH_MAX, "%s/user/%s/cacerts-added", misc_dir, name);
638 
639                 char misc_removed_dir[PATH_MAX];
640                 snprintf(misc_removed_dir, PATH_MAX, "%s/user/%s/cacerts-removed", misc_dir, name);
641 
642                 uid_t uid = multiuser_get_uid(user_id, AID_SYSTEM);
643                 gid_t gid = uid;
644                 if (access(keychain_added_dir, F_OK) == 0) {
645                     if (copy_dir_files(keychain_added_dir, misc_added_dir, uid, gid) != 0) {
646                         ALOGE("Some files failed to copy");
647                     }
648                 }
649                 if (access(keychain_removed_dir, F_OK) == 0) {
650                     if (copy_dir_files(keychain_removed_dir, misc_removed_dir, uid, gid) != 0) {
651                         ALOGE("Some files failed to copy");
652                     }
653                 }
654             }
655             closedir(dir);
656 
657             if (access(keychain_added_dir, F_OK) == 0) {
658                 delete_dir_contents(keychain_added_dir, 1, 0);
659             }
660             if (access(keychain_removed_dir, F_OK) == 0) {
661                 delete_dir_contents(keychain_removed_dir, 1, 0);
662             }
663         }
664 
665         version = 3;
666     }
667 
668     // Persist layout version if changed
669     if (version != oldVersion) {
670         if (fs_write_atomic_int(version_path, version) == -1) {
671             ALOGE("Failed to save version to %s: %s", version_path, strerror(errno));
672             goto fail;
673         }
674     }
675 
676     // Success!
677     res = 0;
678 
679 fail:
680     return res;
681 }
682 
log_callback(int type,const char * fmt,...)683 static int log_callback(int type, const char *fmt, ...) {
684     va_list ap;
685     int priority;
686 
687     switch (type) {
688     case SELINUX_WARNING:
689         priority = ANDROID_LOG_WARN;
690         break;
691     case SELINUX_INFO:
692         priority = ANDROID_LOG_INFO;
693         break;
694     default:
695         priority = ANDROID_LOG_ERROR;
696         break;
697     }
698     va_start(ap, fmt);
699     LOG_PRI_VA(priority, "SELinux", fmt, ap);
700     va_end(ap);
701     return 0;
702 }
703 
installd_main(const int argc ATTRIBUTE_UNUSED,char * argv[])704 static int installd_main(const int argc ATTRIBUTE_UNUSED, char *argv[]) {
705     char buf[BUFFER_MAX];
706     struct sockaddr addr;
707     socklen_t alen;
708     int lsocket, s;
709     int selinux_enabled = (is_selinux_enabled() > 0);
710 
711     setenv("ANDROID_LOG_TAGS", "*:v", 1);
712     android::base::InitLogging(argv);
713 
714     ALOGI("installd firing up\n");
715 
716     union selinux_callback cb;
717     cb.func_log = log_callback;
718     selinux_set_callback(SELINUX_CB_LOG, cb);
719 
720     if (!initialize_globals()) {
721         ALOGE("Could not initialize globals; exiting.\n");
722         exit(1);
723     }
724 
725     if (initialize_directories() < 0) {
726         ALOGE("Could not create directories; exiting.\n");
727         exit(1);
728     }
729 
730     if (selinux_enabled && selinux_status_open(true) < 0) {
731         ALOGE("Could not open selinux status; exiting.\n");
732         exit(1);
733     }
734 
735     lsocket = android_get_control_socket(SOCKET_PATH);
736     if (lsocket < 0) {
737         ALOGE("Failed to get socket from environment: %s\n", strerror(errno));
738         exit(1);
739     }
740     if (listen(lsocket, 5)) {
741         ALOGE("Listen on socket failed: %s\n", strerror(errno));
742         exit(1);
743     }
744     fcntl(lsocket, F_SETFD, FD_CLOEXEC);
745 
746     for (;;) {
747         alen = sizeof(addr);
748         s = accept(lsocket, &addr, &alen);
749         if (s < 0) {
750             ALOGE("Accept failed: %s\n", strerror(errno));
751             continue;
752         }
753         fcntl(s, F_SETFD, FD_CLOEXEC);
754 
755         ALOGI("new connection\n");
756         for (;;) {
757             unsigned short count;
758             if (readx(s, &count, sizeof(count))) {
759                 ALOGE("failed to read size\n");
760                 break;
761             }
762             if ((count < 1) || (count >= BUFFER_MAX)) {
763                 ALOGE("invalid size %d\n", count);
764                 break;
765             }
766             if (readx(s, buf, count)) {
767                 ALOGE("failed to read command\n");
768                 break;
769             }
770             buf[count] = 0;
771             if (selinux_enabled && selinux_status_updated() > 0) {
772                 selinux_android_seapp_context_reload();
773             }
774             if (execute(s, buf)) break;
775         }
776         ALOGI("closing connection\n");
777         close(s);
778     }
779 
780     return 0;
781 }
782 
783 }  // namespace installd
784 }  // namespace android
785 
main(const int argc,char * argv[])786 int main(const int argc, char *argv[]) {
787     return android::installd::installd_main(argc, argv);
788 }
789