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