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