1 /* 2 * Copyright (C) 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 "builtins.h" 18 19 #include <dirent.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <mntent.h> 23 #include <net/if.h> 24 #include <signal.h> 25 #include <sched.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 #include <sys/socket.h> 30 #include <sys/mount.h> 31 #include <sys/resource.h> 32 #include <sys/syscall.h> 33 #include <sys/time.h> 34 #include <sys/types.h> 35 #include <sys/stat.h> 36 #include <sys/wait.h> 37 #include <unistd.h> 38 #include <linux/loop.h> 39 #include <linux/module.h> 40 41 #include <string> 42 #include <thread> 43 44 #include <selinux/android.h> 45 #include <selinux/selinux.h> 46 #include <selinux/label.h> 47 48 #include <android-base/file.h> 49 #include <android-base/parseint.h> 50 #include <android-base/properties.h> 51 #include <android-base/stringprintf.h> 52 #include <android-base/strings.h> 53 #include <bootloader_message/bootloader_message.h> 54 #include <cutils/android_reboot.h> 55 #include <ext4_utils/ext4_crypt.h> 56 #include <ext4_utils/ext4_crypt_init_extensions.h> 57 #include <fs_mgr.h> 58 #include <logwrap/logwrap.h> 59 60 #include "action.h" 61 #include "bootchart.h" 62 #include "devices.h" 63 #include "init.h" 64 #include "init_parser.h" 65 #include "log.h" 66 #include "property_service.h" 67 #include "reboot.h" 68 #include "service.h" 69 #include "signal_handler.h" 70 #include "util.h" 71 72 using namespace std::literals::string_literals; 73 74 #define chmod DO_NOT_USE_CHMOD_USE_FCHMODAT_SYMLINK_NOFOLLOW 75 76 static constexpr std::chrono::nanoseconds kCommandRetryTimeout = 5s; 77 78 static int insmod(const char *filename, const char *options, int flags) { 79 int fd = open(filename, O_RDONLY | O_NOFOLLOW | O_CLOEXEC); 80 if (fd == -1) { 81 PLOG(ERROR) << "insmod: open(\"" << filename << "\") failed"; 82 return -1; 83 } 84 int rc = syscall(__NR_finit_module, fd, options, flags); 85 if (rc == -1) { 86 PLOG(ERROR) << "finit_module for \"" << filename << "\" failed"; 87 } 88 close(fd); 89 return rc; 90 } 91 92 static int __ifupdown(const char *interface, int up) { 93 struct ifreq ifr; 94 int s, ret; 95 96 strlcpy(ifr.ifr_name, interface, IFNAMSIZ); 97 98 s = socket(AF_INET, SOCK_DGRAM, 0); 99 if (s < 0) 100 return -1; 101 102 ret = ioctl(s, SIOCGIFFLAGS, &ifr); 103 if (ret < 0) { 104 goto done; 105 } 106 107 if (up) 108 ifr.ifr_flags |= IFF_UP; 109 else 110 ifr.ifr_flags &= ~IFF_UP; 111 112 ret = ioctl(s, SIOCSIFFLAGS, &ifr); 113 114 done: 115 close(s); 116 return ret; 117 } 118 119 static int reboot_into_recovery(const std::vector<std::string>& options) { 120 std::string err; 121 if (!write_bootloader_message(options, &err)) { 122 LOG(ERROR) << "failed to set bootloader message: " << err; 123 return -1; 124 } 125 DoReboot(ANDROID_RB_RESTART2, "reboot", "recovery", false); 126 return 0; 127 } 128 129 static int do_class_start(const std::vector<std::string>& args) { 130 /* Starting a class does not start services 131 * which are explicitly disabled. They must 132 * be started individually. 133 */ 134 ServiceManager::GetInstance(). 135 ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); }); 136 return 0; 137 } 138 139 static int do_class_stop(const std::vector<std::string>& args) { 140 ServiceManager::GetInstance(). 141 ForEachServiceInClass(args[1], [] (Service* s) { s->Stop(); }); 142 return 0; 143 } 144 145 static int do_class_reset(const std::vector<std::string>& args) { 146 ServiceManager::GetInstance(). 147 ForEachServiceInClass(args[1], [] (Service* s) { s->Reset(); }); 148 return 0; 149 } 150 151 static int do_class_restart(const std::vector<std::string>& args) { 152 ServiceManager::GetInstance(). 153 ForEachServiceInClass(args[1], [] (Service* s) { s->Restart(); }); 154 return 0; 155 } 156 157 static int do_domainname(const std::vector<std::string>& args) { 158 return write_file("/proc/sys/kernel/domainname", args[1]) ? 0 : 1; 159 } 160 161 static int do_enable(const std::vector<std::string>& args) { 162 Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]); 163 if (!svc) { 164 return -1; 165 } 166 return svc->Enable(); 167 } 168 169 static int do_exec(const std::vector<std::string>& args) { 170 return ServiceManager::GetInstance().Exec(args) ? 0 : -1; 171 } 172 173 static int do_exec_start(const std::vector<std::string>& args) { 174 return ServiceManager::GetInstance().ExecStart(args[1]) ? 0 : -1; 175 } 176 177 static int do_export(const std::vector<std::string>& args) { 178 return add_environment(args[1].c_str(), args[2].c_str()); 179 } 180 181 static int do_hostname(const std::vector<std::string>& args) { 182 return write_file("/proc/sys/kernel/hostname", args[1]) ? 0 : 1; 183 } 184 185 static int do_ifup(const std::vector<std::string>& args) { 186 return __ifupdown(args[1].c_str(), 1); 187 } 188 189 static int do_insmod(const std::vector<std::string>& args) { 190 int flags = 0; 191 auto it = args.begin() + 1; 192 193 if (!(*it).compare("-f")) { 194 flags = MODULE_INIT_IGNORE_VERMAGIC | MODULE_INIT_IGNORE_MODVERSIONS; 195 it++; 196 } 197 198 std::string filename = *it++; 199 std::string options = android::base::Join(std::vector<std::string>(it, args.end()), ' '); 200 return insmod(filename.c_str(), options.c_str(), flags); 201 } 202 203 static int do_mkdir(const std::vector<std::string>& args) { 204 mode_t mode = 0755; 205 int ret; 206 207 /* mkdir <path> [mode] [owner] [group] */ 208 209 if (args.size() >= 3) { 210 mode = std::strtoul(args[2].c_str(), 0, 8); 211 } 212 213 ret = make_dir(args[1].c_str(), mode); 214 /* chmod in case the directory already exists */ 215 if (ret == -1 && errno == EEXIST) { 216 ret = fchmodat(AT_FDCWD, args[1].c_str(), mode, AT_SYMLINK_NOFOLLOW); 217 } 218 if (ret == -1) { 219 return -errno; 220 } 221 222 if (args.size() >= 4) { 223 uid_t uid = decode_uid(args[3].c_str()); 224 gid_t gid = -1; 225 226 if (args.size() == 5) { 227 gid = decode_uid(args[4].c_str()); 228 } 229 230 if (lchown(args[1].c_str(), uid, gid) == -1) { 231 return -errno; 232 } 233 234 /* chown may have cleared S_ISUID and S_ISGID, chmod again */ 235 if (mode & (S_ISUID | S_ISGID)) { 236 ret = fchmodat(AT_FDCWD, args[1].c_str(), mode, AT_SYMLINK_NOFOLLOW); 237 if (ret == -1) { 238 return -errno; 239 } 240 } 241 } 242 243 if (e4crypt_is_native()) { 244 if (e4crypt_set_directory_policy(args[1].c_str())) { 245 const std::vector<std::string> options = { 246 "--prompt_and_wipe_data", 247 "--reason=set_policy_failed:"s + args[1]}; 248 reboot_into_recovery(options); 249 return -1; 250 } 251 } 252 return 0; 253 } 254 255 /* umount <path> */ 256 static int do_umount(const std::vector<std::string>& args) { 257 return umount(args[1].c_str()); 258 } 259 260 static struct { 261 const char *name; 262 unsigned flag; 263 } mount_flags[] = { 264 { "noatime", MS_NOATIME }, 265 { "noexec", MS_NOEXEC }, 266 { "nosuid", MS_NOSUID }, 267 { "nodev", MS_NODEV }, 268 { "nodiratime", MS_NODIRATIME }, 269 { "ro", MS_RDONLY }, 270 { "rw", 0 }, 271 { "remount", MS_REMOUNT }, 272 { "bind", MS_BIND }, 273 { "rec", MS_REC }, 274 { "unbindable", MS_UNBINDABLE }, 275 { "private", MS_PRIVATE }, 276 { "slave", MS_SLAVE }, 277 { "shared", MS_SHARED }, 278 { "defaults", 0 }, 279 { 0, 0 }, 280 }; 281 282 #define DATA_MNT_POINT "/data" 283 284 /* mount <type> <device> <path> <flags ...> <options> */ 285 static int do_mount(const std::vector<std::string>& args) { 286 char tmp[64]; 287 const char *source, *target, *system; 288 const char *options = NULL; 289 unsigned flags = 0; 290 std::size_t na = 0; 291 int n, i; 292 int wait = 0; 293 294 for (na = 4; na < args.size(); na++) { 295 for (i = 0; mount_flags[i].name; i++) { 296 if (!args[na].compare(mount_flags[i].name)) { 297 flags |= mount_flags[i].flag; 298 break; 299 } 300 } 301 302 if (!mount_flags[i].name) { 303 if (!args[na].compare("wait")) 304 wait = 1; 305 /* if our last argument isn't a flag, wolf it up as an option string */ 306 else if (na + 1 == args.size()) 307 options = args[na].c_str(); 308 } 309 } 310 311 system = args[1].c_str(); 312 source = args[2].c_str(); 313 target = args[3].c_str(); 314 315 if (!strncmp(source, "loop@", 5)) { 316 int mode, loop, fd; 317 struct loop_info info; 318 319 mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR; 320 fd = open(source + 5, mode | O_CLOEXEC); 321 if (fd < 0) { 322 return -1; 323 } 324 325 for (n = 0; ; n++) { 326 snprintf(tmp, sizeof(tmp), "/dev/block/loop%d", n); 327 loop = open(tmp, mode | O_CLOEXEC); 328 if (loop < 0) { 329 close(fd); 330 return -1; 331 } 332 333 /* if it is a blank loop device */ 334 if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) { 335 /* if it becomes our loop device */ 336 if (ioctl(loop, LOOP_SET_FD, fd) >= 0) { 337 close(fd); 338 339 if (mount(tmp, target, system, flags, options) < 0) { 340 ioctl(loop, LOOP_CLR_FD, 0); 341 close(loop); 342 return -1; 343 } 344 345 close(loop); 346 goto exit_success; 347 } 348 } 349 350 close(loop); 351 } 352 353 close(fd); 354 LOG(ERROR) << "out of loopback devices"; 355 return -1; 356 } else { 357 if (wait) 358 wait_for_file(source, kCommandRetryTimeout); 359 if (mount(source, target, system, flags, options) < 0) { 360 return -1; 361 } 362 363 } 364 365 exit_success: 366 return 0; 367 368 } 369 370 /* Imports .rc files from the specified paths. Default ones are applied if none is given. 371 * 372 * start_index: index of the first path in the args list 373 */ 374 static void import_late(const std::vector<std::string>& args, size_t start_index, size_t end_index) { 375 Parser& parser = Parser::GetInstance(); 376 if (end_index <= start_index) { 377 // Fallbacks for partitions on which early mount isn't enabled. 378 if (!parser.is_system_etc_init_loaded()) { 379 parser.ParseConfig("/system/etc/init"); 380 parser.set_is_system_etc_init_loaded(true); 381 } 382 if (!parser.is_vendor_etc_init_loaded()) { 383 parser.ParseConfig("/vendor/etc/init"); 384 parser.set_is_vendor_etc_init_loaded(true); 385 } 386 if (!parser.is_odm_etc_init_loaded()) { 387 parser.ParseConfig("/odm/etc/init"); 388 parser.set_is_odm_etc_init_loaded(true); 389 } 390 } else { 391 for (size_t i = start_index; i < end_index; ++i) { 392 parser.ParseConfig(args[i]); 393 } 394 } 395 396 // Turning this on and letting the INFO logging be discarded adds 0.2s to 397 // Nexus 9 boot time, so it's disabled by default. 398 if (false) parser.DumpState(); 399 } 400 401 /* mount_fstab 402 * 403 * Call fs_mgr_mount_all() to mount the given fstab 404 */ 405 static int mount_fstab(const char* fstabfile, int mount_mode) { 406 int ret = -1; 407 408 /* 409 * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and 410 * do the call in the child to provide protection to the main init 411 * process if anything goes wrong (crash or memory leak), and wait for 412 * the child to finish in the parent. 413 */ 414 pid_t pid = fork(); 415 if (pid > 0) { 416 /* Parent. Wait for the child to return */ 417 int status; 418 int wp_ret = TEMP_FAILURE_RETRY(waitpid(pid, &status, 0)); 419 if (wp_ret == -1) { 420 // Unexpected error code. We will continue anyway. 421 PLOG(WARNING) << "waitpid failed"; 422 } 423 424 if (WIFEXITED(status)) { 425 ret = WEXITSTATUS(status); 426 } else { 427 ret = -1; 428 } 429 } else if (pid == 0) { 430 /* child, call fs_mgr_mount_all() */ 431 432 // So we can always see what fs_mgr_mount_all() does. 433 // Only needed if someone explicitly changes the default log level in their init.rc. 434 android::base::ScopedLogSeverity info(android::base::INFO); 435 436 struct fstab* fstab = fs_mgr_read_fstab(fstabfile); 437 int child_ret = fs_mgr_mount_all(fstab, mount_mode); 438 fs_mgr_free_fstab(fstab); 439 if (child_ret == -1) { 440 PLOG(ERROR) << "fs_mgr_mount_all returned an error"; 441 } 442 _exit(child_ret); 443 } else { 444 /* fork failed, return an error */ 445 return -1; 446 } 447 return ret; 448 } 449 450 /* Queue event based on fs_mgr return code. 451 * 452 * code: return code of fs_mgr_mount_all 453 * 454 * This function might request a reboot, in which case it will 455 * not return. 456 * 457 * return code is processed based on input code 458 */ 459 static int queue_fs_event(int code) { 460 int ret = code; 461 if (code == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) { 462 ActionManager::GetInstance().QueueEventTrigger("encrypt"); 463 } else if (code == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) { 464 property_set("ro.crypto.state", "encrypted"); 465 property_set("ro.crypto.type", "block"); 466 ActionManager::GetInstance().QueueEventTrigger("defaultcrypto"); 467 } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { 468 property_set("ro.crypto.state", "unencrypted"); 469 ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); 470 } else if (code == FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { 471 property_set("ro.crypto.state", "unsupported"); 472 ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); 473 } else if (code == FS_MGR_MNTALL_DEV_NEEDS_RECOVERY) { 474 /* Setup a wipe via recovery, and reboot into recovery */ 475 PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery."; 476 const std::vector<std::string> options = {"--wipe_data", "--reason=fs_mgr_mount_all" }; 477 ret = reboot_into_recovery(options); 478 /* If reboot worked, there is no return. */ 479 } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) { 480 if (e4crypt_install_keyring()) { 481 return -1; 482 } 483 property_set("ro.crypto.state", "encrypted"); 484 property_set("ro.crypto.type", "file"); 485 486 // Although encrypted, we have device key, so we do not need to 487 // do anything different from the nonencrypted case. 488 ActionManager::GetInstance().QueueEventTrigger("nonencrypted"); 489 } else if (code > 0) { 490 PLOG(ERROR) << "fs_mgr_mount_all returned unexpected error " << code; 491 } 492 /* else ... < 0: error */ 493 494 return ret; 495 } 496 497 /* mount_all <fstab> [ <path> ]* [--<options>]* 498 * 499 * This function might request a reboot, in which case it will 500 * not return. 501 */ 502 static int do_mount_all(const std::vector<std::string>& args) { 503 std::size_t na = 0; 504 bool import_rc = true; 505 bool queue_event = true; 506 int mount_mode = MOUNT_MODE_DEFAULT; 507 const char* fstabfile = args[1].c_str(); 508 std::size_t path_arg_end = args.size(); 509 const char* prop_post_fix = "default"; 510 511 for (na = args.size() - 1; na > 1; --na) { 512 if (args[na] == "--early") { 513 path_arg_end = na; 514 queue_event = false; 515 mount_mode = MOUNT_MODE_EARLY; 516 prop_post_fix = "early"; 517 } else if (args[na] == "--late") { 518 path_arg_end = na; 519 import_rc = false; 520 mount_mode = MOUNT_MODE_LATE; 521 prop_post_fix = "late"; 522 } 523 } 524 525 std::string prop_name = android::base::StringPrintf("ro.boottime.init.mount_all.%s", 526 prop_post_fix); 527 Timer t; 528 int ret = mount_fstab(fstabfile, mount_mode); 529 property_set(prop_name.c_str(), std::to_string(t.duration_ms()).c_str()); 530 531 if (import_rc) { 532 /* Paths of .rc files are specified at the 2nd argument and beyond */ 533 import_late(args, 2, path_arg_end); 534 } 535 536 if (queue_event) { 537 /* queue_fs_event will queue event based on mount_fstab return code 538 * and return processed return code*/ 539 ret = queue_fs_event(ret); 540 } 541 542 return ret; 543 } 544 545 static int do_swapon_all(const std::vector<std::string>& args) { 546 struct fstab *fstab; 547 int ret; 548 549 fstab = fs_mgr_read_fstab(args[1].c_str()); 550 ret = fs_mgr_swapon_all(fstab); 551 fs_mgr_free_fstab(fstab); 552 553 return ret; 554 } 555 556 static int do_setprop(const std::vector<std::string>& args) { 557 const char* name = args[1].c_str(); 558 const char* value = args[2].c_str(); 559 property_set(name, value); 560 return 0; 561 } 562 563 static int do_setrlimit(const std::vector<std::string>& args) { 564 struct rlimit limit; 565 int resource; 566 if (android::base::ParseInt(args[1], &resource) && 567 android::base::ParseUint(args[2], &limit.rlim_cur) && 568 android::base::ParseUint(args[3], &limit.rlim_max)) { 569 return setrlimit(resource, &limit); 570 } 571 LOG(WARNING) << "ignoring setrlimit " << args[1] << " " << args[2] << " " << args[3]; 572 return -1; 573 } 574 575 static int do_start(const std::vector<std::string>& args) { 576 Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]); 577 if (!svc) { 578 LOG(ERROR) << "do_start: Service " << args[1] << " not found"; 579 return -1; 580 } 581 if (!svc->Start()) 582 return -1; 583 return 0; 584 } 585 586 static int do_stop(const std::vector<std::string>& args) { 587 Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]); 588 if (!svc) { 589 LOG(ERROR) << "do_stop: Service " << args[1] << " not found"; 590 return -1; 591 } 592 svc->Stop(); 593 return 0; 594 } 595 596 static int do_restart(const std::vector<std::string>& args) { 597 Service* svc = ServiceManager::GetInstance().FindServiceByName(args[1]); 598 if (!svc) { 599 LOG(ERROR) << "do_restart: Service " << args[1] << " not found"; 600 return -1; 601 } 602 svc->Restart(); 603 return 0; 604 } 605 606 static int do_trigger(const std::vector<std::string>& args) { 607 ActionManager::GetInstance().QueueEventTrigger(args[1]); 608 return 0; 609 } 610 611 static int do_symlink(const std::vector<std::string>& args) { 612 return symlink(args[1].c_str(), args[2].c_str()); 613 } 614 615 static int do_rm(const std::vector<std::string>& args) { 616 return unlink(args[1].c_str()); 617 } 618 619 static int do_rmdir(const std::vector<std::string>& args) { 620 return rmdir(args[1].c_str()); 621 } 622 623 static int do_sysclktz(const std::vector<std::string>& args) { 624 struct timezone tz = {}; 625 if (android::base::ParseInt(args[1], &tz.tz_minuteswest) && settimeofday(NULL, &tz) != -1) { 626 return 0; 627 } 628 return -1; 629 } 630 631 static int do_verity_load_state(const std::vector<std::string>& args) { 632 int mode = -1; 633 bool loaded = fs_mgr_load_verity_state(&mode); 634 if (loaded && mode != VERITY_MODE_DEFAULT) { 635 ActionManager::GetInstance().QueueEventTrigger("verity-logging"); 636 } 637 return loaded ? 0 : 1; 638 } 639 640 static void verity_update_property(fstab_rec *fstab, const char *mount_point, 641 int mode, int status) { 642 property_set(android::base::StringPrintf("partition.%s.verified", mount_point).c_str(), 643 android::base::StringPrintf("%d", mode).c_str()); 644 } 645 646 static int do_verity_update_state(const std::vector<std::string>& args) { 647 return fs_mgr_update_verity_state(verity_update_property) ? 0 : 1; 648 } 649 650 static int do_write(const std::vector<std::string>& args) { 651 return write_file(args[1], args[2]) ? 0 : 1; 652 } 653 654 static int do_copy(const std::vector<std::string>& args) { 655 std::string data; 656 if (read_file(args[1], &data)) { 657 return write_file(args[2], data) ? 0 : 1; 658 } 659 return 1; 660 } 661 662 static int do_chown(const std::vector<std::string>& args) { 663 /* GID is optional. */ 664 if (args.size() == 3) { 665 if (lchown(args[2].c_str(), decode_uid(args[1].c_str()), -1) == -1) 666 return -errno; 667 } else if (args.size() == 4) { 668 if (lchown(args[3].c_str(), decode_uid(args[1].c_str()), 669 decode_uid(args[2].c_str())) == -1) 670 return -errno; 671 } else { 672 return -1; 673 } 674 return 0; 675 } 676 677 static mode_t get_mode(const char *s) { 678 mode_t mode = 0; 679 while (*s) { 680 if (*s >= '0' && *s <= '7') { 681 mode = (mode<<3) | (*s-'0'); 682 } else { 683 return -1; 684 } 685 s++; 686 } 687 return mode; 688 } 689 690 static int do_chmod(const std::vector<std::string>& args) { 691 mode_t mode = get_mode(args[1].c_str()); 692 if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) { 693 return -errno; 694 } 695 return 0; 696 } 697 698 static int do_restorecon(const std::vector<std::string>& args) { 699 int ret = 0; 700 701 struct flag_type {const char* name; int value;}; 702 static const flag_type flags[] = { 703 {"--recursive", SELINUX_ANDROID_RESTORECON_RECURSE}, 704 {"--skip-ce", SELINUX_ANDROID_RESTORECON_SKIPCE}, 705 {"--cross-filesystems", SELINUX_ANDROID_RESTORECON_CROSS_FILESYSTEMS}, 706 {0, 0} 707 }; 708 709 int flag = 0; 710 711 bool in_flags = true; 712 for (size_t i = 1; i < args.size(); ++i) { 713 if (android::base::StartsWith(args[i], "--")) { 714 if (!in_flags) { 715 LOG(ERROR) << "restorecon - flags must precede paths"; 716 return -1; 717 } 718 bool found = false; 719 for (size_t j = 0; flags[j].name; ++j) { 720 if (args[i] == flags[j].name) { 721 flag |= flags[j].value; 722 found = true; 723 break; 724 } 725 } 726 if (!found) { 727 LOG(ERROR) << "restorecon - bad flag " << args[i]; 728 return -1; 729 } 730 } else { 731 in_flags = false; 732 if (restorecon(args[i].c_str(), flag) < 0) { 733 ret = -errno; 734 } 735 } 736 } 737 return ret; 738 } 739 740 static int do_restorecon_recursive(const std::vector<std::string>& args) { 741 std::vector<std::string> non_const_args(args); 742 non_const_args.insert(std::next(non_const_args.begin()), "--recursive"); 743 return do_restorecon(non_const_args); 744 } 745 746 static int do_loglevel(const std::vector<std::string>& args) { 747 // TODO: support names instead/as well? 748 int log_level = -1; 749 android::base::ParseInt(args[1], &log_level); 750 android::base::LogSeverity severity; 751 switch (log_level) { 752 case 7: severity = android::base::DEBUG; break; 753 case 6: severity = android::base::INFO; break; 754 case 5: 755 case 4: severity = android::base::WARNING; break; 756 case 3: severity = android::base::ERROR; break; 757 case 2: 758 case 1: 759 case 0: severity = android::base::FATAL; break; 760 default: 761 LOG(ERROR) << "loglevel: invalid log level " << log_level; 762 return -EINVAL; 763 } 764 android::base::SetMinimumLogSeverity(severity); 765 return 0; 766 } 767 768 static int do_load_persist_props(const std::vector<std::string>& args) { 769 load_persist_props(); 770 return 0; 771 } 772 773 static int do_load_system_props(const std::vector<std::string>& args) { 774 load_system_props(); 775 return 0; 776 } 777 778 static int do_wait(const std::vector<std::string>& args) { 779 if (args.size() == 2) { 780 return wait_for_file(args[1].c_str(), kCommandRetryTimeout); 781 } else if (args.size() == 3) { 782 int timeout; 783 if (android::base::ParseInt(args[2], &timeout)) { 784 return wait_for_file(args[1].c_str(), std::chrono::seconds(timeout)); 785 } 786 } 787 return -1; 788 } 789 790 static int do_wait_for_prop(const std::vector<std::string>& args) { 791 const char* name = args[1].c_str(); 792 const char* value = args[2].c_str(); 793 size_t value_len = strlen(value); 794 795 if (!is_legal_property_name(name)) { 796 LOG(ERROR) << "do_wait_for_prop(\"" << name << "\", \"" << value 797 << "\") failed: bad name"; 798 return -1; 799 } 800 if (value_len >= PROP_VALUE_MAX) { 801 LOG(ERROR) << "do_wait_for_prop(\"" << name << "\", \"" << value 802 << "\") failed: value too long"; 803 return -1; 804 } 805 if (!start_waiting_for_property(name, value)) { 806 LOG(ERROR) << "do_wait_for_prop(\"" << name << "\", \"" << value 807 << "\") failed: init already in waiting"; 808 return -1; 809 } 810 return 0; 811 } 812 813 /* 814 * Callback to make a directory from the ext4 code 815 */ 816 static int do_installkeys_ensure_dir_exists(const char* dir) { 817 if (make_dir(dir, 0700) && errno != EEXIST) { 818 return -1; 819 } 820 821 return 0; 822 } 823 824 static bool is_file_crypto() { 825 return android::base::GetProperty("ro.crypto.type", "") == "file"; 826 } 827 828 static int do_installkey(const std::vector<std::string>& args) { 829 if (!is_file_crypto()) { 830 return 0; 831 } 832 auto unencrypted_dir = args[1] + e4crypt_unencrypted_folder; 833 if (do_installkeys_ensure_dir_exists(unencrypted_dir.c_str())) { 834 PLOG(ERROR) << "Failed to create " << unencrypted_dir; 835 return -1; 836 } 837 std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", 838 "enablefilecrypto"}; 839 return do_exec(exec_args); 840 } 841 842 static int do_init_user0(const std::vector<std::string>& args) { 843 return e4crypt_do_init_user0(); 844 } 845 846 BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const { 847 constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max(); 848 // clang-format off 849 static const Map builtin_functions = { 850 {"bootchart", {1, 1, do_bootchart}}, 851 {"chmod", {2, 2, do_chmod}}, 852 {"chown", {2, 3, do_chown}}, 853 {"class_reset", {1, 1, do_class_reset}}, 854 {"class_restart", {1, 1, do_class_restart}}, 855 {"class_start", {1, 1, do_class_start}}, 856 {"class_stop", {1, 1, do_class_stop}}, 857 {"copy", {2, 2, do_copy}}, 858 {"domainname", {1, 1, do_domainname}}, 859 {"enable", {1, 1, do_enable}}, 860 {"exec", {1, kMax, do_exec}}, 861 {"exec_start", {1, 1, do_exec_start}}, 862 {"export", {2, 2, do_export}}, 863 {"hostname", {1, 1, do_hostname}}, 864 {"ifup", {1, 1, do_ifup}}, 865 {"init_user0", {0, 0, do_init_user0}}, 866 {"insmod", {1, kMax, do_insmod}}, 867 {"installkey", {1, 1, do_installkey}}, 868 {"load_persist_props", {0, 0, do_load_persist_props}}, 869 {"load_system_props", {0, 0, do_load_system_props}}, 870 {"loglevel", {1, 1, do_loglevel}}, 871 {"mkdir", {1, 4, do_mkdir}}, 872 {"mount_all", {1, kMax, do_mount_all}}, 873 {"mount", {3, kMax, do_mount}}, 874 {"umount", {1, 1, do_umount}}, 875 {"restart", {1, 1, do_restart}}, 876 {"restorecon", {1, kMax, do_restorecon}}, 877 {"restorecon_recursive", {1, kMax, do_restorecon_recursive}}, 878 {"rm", {1, 1, do_rm}}, 879 {"rmdir", {1, 1, do_rmdir}}, 880 {"setprop", {2, 2, do_setprop}}, 881 {"setrlimit", {3, 3, do_setrlimit}}, 882 {"start", {1, 1, do_start}}, 883 {"stop", {1, 1, do_stop}}, 884 {"swapon_all", {1, 1, do_swapon_all}}, 885 {"symlink", {2, 2, do_symlink}}, 886 {"sysclktz", {1, 1, do_sysclktz}}, 887 {"trigger", {1, 1, do_trigger}}, 888 {"verity_load_state", {0, 0, do_verity_load_state}}, 889 {"verity_update_state", {0, 0, do_verity_update_state}}, 890 {"wait", {1, 2, do_wait}}, 891 {"wait_for_prop", {2, 2, do_wait_for_prop}}, 892 {"write", {2, 2, do_write}}, 893 }; 894 // clang-format on 895 return builtin_functions; 896 } 897