builtins.c revision f22b7452940c99b830749cabdd929f9f7cfdaacc
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 <sys/types.h> 18#include <sys/stat.h> 19#include <fcntl.h> 20#include <unistd.h> 21#include <string.h> 22#include <stdio.h> 23#include <linux/kd.h> 24#include <errno.h> 25#include <sys/socket.h> 26#include <netinet/in.h> 27#include <linux/if.h> 28#include <arpa/inet.h> 29#include <stdlib.h> 30#include <sys/mount.h> 31#include <sys/resource.h> 32#include <sys/wait.h> 33#include <linux/loop.h> 34#include <cutils/partition_utils.h> 35#include <cutils/android_reboot.h> 36#include <fs_mgr.h> 37 38#include <selinux/selinux.h> 39#include <selinux/label.h> 40 41#include "init.h" 42#include "keywords.h" 43#include "property_service.h" 44#include "devices.h" 45#include "init_parser.h" 46#include "util.h" 47#include "log.h" 48 49#include <private/android_filesystem_config.h> 50 51void add_environment(const char *name, const char *value); 52 53extern int init_module(void *, unsigned long, const char *); 54 55static int write_file(const char *path, const char *value) 56{ 57 int fd, ret, len; 58 59 fd = open(path, O_WRONLY|O_CREAT|O_NOFOLLOW, 0600); 60 61 if (fd < 0) 62 return -errno; 63 64 len = strlen(value); 65 66 do { 67 ret = write(fd, value, len); 68 } while (ret < 0 && errno == EINTR); 69 70 close(fd); 71 if (ret < 0) { 72 return -errno; 73 } else { 74 return 0; 75 } 76} 77 78static int _open(const char *path) 79{ 80 int fd; 81 82 fd = open(path, O_RDONLY | O_NOFOLLOW); 83 if (fd < 0) 84 fd = open(path, O_WRONLY | O_NOFOLLOW); 85 86 return fd; 87} 88 89static int _chown(const char *path, unsigned int uid, unsigned int gid) 90{ 91 int fd; 92 int ret; 93 94 fd = _open(path); 95 if (fd < 0) { 96 return -1; 97 } 98 99 ret = fchown(fd, uid, gid); 100 if (ret < 0) { 101 int errno_copy = errno; 102 close(fd); 103 errno = errno_copy; 104 return -1; 105 } 106 107 close(fd); 108 109 return 0; 110} 111 112static int _chmod(const char *path, mode_t mode) 113{ 114 int fd; 115 int ret; 116 117 fd = _open(path); 118 if (fd < 0) { 119 return -1; 120 } 121 122 ret = fchmod(fd, mode); 123 if (ret < 0) { 124 int errno_copy = errno; 125 close(fd); 126 errno = errno_copy; 127 return -1; 128 } 129 130 close(fd); 131 132 return 0; 133} 134 135static int insmod(const char *filename, char *options) 136{ 137 void *module; 138 unsigned size; 139 int ret; 140 141 module = read_file(filename, &size); 142 if (!module) 143 return -1; 144 145 ret = init_module(module, size, options); 146 147 free(module); 148 149 return ret; 150} 151 152static int setkey(struct kbentry *kbe) 153{ 154 int fd, ret; 155 156 fd = open("/dev/tty0", O_RDWR | O_SYNC); 157 if (fd < 0) 158 return -1; 159 160 ret = ioctl(fd, KDSKBENT, kbe); 161 162 close(fd); 163 return ret; 164} 165 166static int __ifupdown(const char *interface, int up) 167{ 168 struct ifreq ifr; 169 int s, ret; 170 171 strlcpy(ifr.ifr_name, interface, IFNAMSIZ); 172 173 s = socket(AF_INET, SOCK_DGRAM, 0); 174 if (s < 0) 175 return -1; 176 177 ret = ioctl(s, SIOCGIFFLAGS, &ifr); 178 if (ret < 0) { 179 goto done; 180 } 181 182 if (up) 183 ifr.ifr_flags |= IFF_UP; 184 else 185 ifr.ifr_flags &= ~IFF_UP; 186 187 ret = ioctl(s, SIOCSIFFLAGS, &ifr); 188 189done: 190 close(s); 191 return ret; 192} 193 194static void service_start_if_not_disabled(struct service *svc) 195{ 196 if (!(svc->flags & SVC_DISABLED)) { 197 service_start(svc, NULL); 198 } else { 199 svc->flags |= SVC_DISABLED_START; 200 } 201} 202 203int do_chdir(int nargs, char **args) 204{ 205 chdir(args[1]); 206 return 0; 207} 208 209int do_chroot(int nargs, char **args) 210{ 211 chroot(args[1]); 212 return 0; 213} 214 215int do_class_start(int nargs, char **args) 216{ 217 /* Starting a class does not start services 218 * which are explicitly disabled. They must 219 * be started individually. 220 */ 221 service_for_each_class(args[1], service_start_if_not_disabled); 222 return 0; 223} 224 225int do_class_stop(int nargs, char **args) 226{ 227 service_for_each_class(args[1], service_stop); 228 return 0; 229} 230 231int do_class_reset(int nargs, char **args) 232{ 233 service_for_each_class(args[1], service_reset); 234 return 0; 235} 236 237int do_domainname(int nargs, char **args) 238{ 239 return write_file("/proc/sys/kernel/domainname", args[1]); 240} 241 242int do_enable(int nargs, char **args) 243{ 244 struct service *svc; 245 svc = service_find_by_name(args[1]); 246 if (svc) { 247 svc->flags &= ~(SVC_DISABLED | SVC_RC_DISABLED); 248 if (svc->flags & SVC_DISABLED_START) { 249 service_start(svc, NULL); 250 } 251 } else { 252 return -1; 253 } 254 return 0; 255} 256 257int do_exec(int nargs, char **args) 258{ 259 return -1; 260} 261 262int do_export(int nargs, char **args) 263{ 264 add_environment(args[1], args[2]); 265 return 0; 266} 267 268int do_hostname(int nargs, char **args) 269{ 270 return write_file("/proc/sys/kernel/hostname", args[1]); 271} 272 273int do_ifup(int nargs, char **args) 274{ 275 return __ifupdown(args[1], 1); 276} 277 278 279static int do_insmod_inner(int nargs, char **args, int opt_len) 280{ 281 char options[opt_len + 1]; 282 int i; 283 284 options[0] = '\0'; 285 if (nargs > 2) { 286 strcpy(options, args[2]); 287 for (i = 3; i < nargs; ++i) { 288 strcat(options, " "); 289 strcat(options, args[i]); 290 } 291 } 292 293 return insmod(args[1], options); 294} 295 296int do_insmod(int nargs, char **args) 297{ 298 int i; 299 int size = 0; 300 301 if (nargs > 2) { 302 for (i = 2; i < nargs; ++i) 303 size += strlen(args[i]) + 1; 304 } 305 306 return do_insmod_inner(nargs, args, size); 307} 308 309int do_mkdir(int nargs, char **args) 310{ 311 mode_t mode = 0755; 312 int ret; 313 314 /* mkdir <path> [mode] [owner] [group] */ 315 316 if (nargs >= 3) { 317 mode = strtoul(args[2], 0, 8); 318 } 319 320 ret = make_dir(args[1], mode); 321 /* chmod in case the directory already exists */ 322 if (ret == -1 && errno == EEXIST) { 323 ret = _chmod(args[1], mode); 324 } 325 if (ret == -1) { 326 return -errno; 327 } 328 329 if (nargs >= 4) { 330 uid_t uid = decode_uid(args[3]); 331 gid_t gid = -1; 332 333 if (nargs == 5) { 334 gid = decode_uid(args[4]); 335 } 336 337 if (_chown(args[1], uid, gid) < 0) { 338 return -errno; 339 } 340 341 /* chown may have cleared S_ISUID and S_ISGID, chmod again */ 342 if (mode & (S_ISUID | S_ISGID)) { 343 ret = _chmod(args[1], mode); 344 if (ret == -1) { 345 return -errno; 346 } 347 } 348 } 349 350 return 0; 351} 352 353static struct { 354 const char *name; 355 unsigned flag; 356} mount_flags[] = { 357 { "noatime", MS_NOATIME }, 358 { "noexec", MS_NOEXEC }, 359 { "nosuid", MS_NOSUID }, 360 { "nodev", MS_NODEV }, 361 { "nodiratime", MS_NODIRATIME }, 362 { "ro", MS_RDONLY }, 363 { "rw", 0 }, 364 { "remount", MS_REMOUNT }, 365 { "bind", MS_BIND }, 366 { "rec", MS_REC }, 367 { "unbindable", MS_UNBINDABLE }, 368 { "private", MS_PRIVATE }, 369 { "slave", MS_SLAVE }, 370 { "shared", MS_SHARED }, 371 { "defaults", 0 }, 372 { 0, 0 }, 373}; 374 375#define DATA_MNT_POINT "/data" 376 377/* mount <type> <device> <path> <flags ...> <options> */ 378int do_mount(int nargs, char **args) 379{ 380 char tmp[64]; 381 char *source, *target, *system; 382 char *options = NULL; 383 unsigned flags = 0; 384 int n, i; 385 int wait = 0; 386 387 for (n = 4; n < nargs; n++) { 388 for (i = 0; mount_flags[i].name; i++) { 389 if (!strcmp(args[n], mount_flags[i].name)) { 390 flags |= mount_flags[i].flag; 391 break; 392 } 393 } 394 395 if (!mount_flags[i].name) { 396 if (!strcmp(args[n], "wait")) 397 wait = 1; 398 /* if our last argument isn't a flag, wolf it up as an option string */ 399 else if (n + 1 == nargs) 400 options = args[n]; 401 } 402 } 403 404 system = args[1]; 405 source = args[2]; 406 target = args[3]; 407 408 if (!strncmp(source, "mtd@", 4)) { 409 n = mtd_name_to_number(source + 4); 410 if (n < 0) { 411 return -1; 412 } 413 414 sprintf(tmp, "/dev/block/mtdblock%d", n); 415 416 if (wait) 417 wait_for_file(tmp, COMMAND_RETRY_TIMEOUT); 418 if (mount(tmp, target, system, flags, options) < 0) { 419 return -1; 420 } 421 422 goto exit_success; 423 } else if (!strncmp(source, "loop@", 5)) { 424 int mode, loop, fd; 425 struct loop_info info; 426 427 mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR; 428 fd = open(source + 5, mode); 429 if (fd < 0) { 430 return -1; 431 } 432 433 for (n = 0; ; n++) { 434 sprintf(tmp, "/dev/block/loop%d", n); 435 loop = open(tmp, mode); 436 if (loop < 0) { 437 return -1; 438 } 439 440 /* if it is a blank loop device */ 441 if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) { 442 /* if it becomes our loop device */ 443 if (ioctl(loop, LOOP_SET_FD, fd) >= 0) { 444 close(fd); 445 446 if (mount(tmp, target, system, flags, options) < 0) { 447 ioctl(loop, LOOP_CLR_FD, 0); 448 close(loop); 449 return -1; 450 } 451 452 close(loop); 453 goto exit_success; 454 } 455 } 456 457 close(loop); 458 } 459 460 close(fd); 461 ERROR("out of loopback devices"); 462 return -1; 463 } else { 464 if (wait) 465 wait_for_file(source, COMMAND_RETRY_TIMEOUT); 466 if (mount(source, target, system, flags, options) < 0) { 467 return -1; 468 } 469 470 } 471 472exit_success: 473 return 0; 474 475} 476 477int do_mount_all(int nargs, char **args) 478{ 479 pid_t pid; 480 int ret = -1; 481 int child_ret = -1; 482 int status; 483 const char *prop; 484 struct fstab *fstab; 485 486 if (nargs != 2) { 487 return -1; 488 } 489 490 /* 491 * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and 492 * do the call in the child to provide protection to the main init 493 * process if anything goes wrong (crash or memory leak), and wait for 494 * the child to finish in the parent. 495 */ 496 pid = fork(); 497 if (pid > 0) { 498 /* Parent. Wait for the child to return */ 499 waitpid(pid, &status, 0); 500 if (WIFEXITED(status)) { 501 ret = WEXITSTATUS(status); 502 } else { 503 ret = -1; 504 } 505 } else if (pid == 0) { 506 /* child, call fs_mgr_mount_all() */ 507 klog_set_level(6); /* So we can see what fs_mgr_mount_all() does */ 508 fstab = fs_mgr_read_fstab(args[1]); 509 child_ret = fs_mgr_mount_all(fstab); 510 fs_mgr_free_fstab(fstab); 511 if (child_ret == -1) { 512 ERROR("fs_mgr_mount_all returned an error\n"); 513 } 514 _exit(child_ret); 515 } else { 516 /* fork failed, return an error */ 517 return -1; 518 } 519 520 if (ret == FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION) { 521 property_set("ro.crypto.state", "unencrypted"); 522 property_set("vold.decrypt", "trigger_encryption"); 523 } else if (ret == FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED) { 524 property_set("ro.crypto.state", "encrypted"); 525 property_set("vold.decrypt", "trigger_default_encryption"); 526 } else if (ret == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { 527 property_set("ro.crypto.state", "unencrypted"); 528 /* If fs_mgr determined this is an unencrypted device, then trigger 529 * that action. 530 */ 531 action_for_each_trigger("nonencrypted", action_add_queue_tail); 532 } 533 /* else ... < 0: error */ 534 535 return ret; 536} 537 538int do_swapon_all(int nargs, char **args) 539{ 540 struct fstab *fstab; 541 int ret; 542 543 fstab = fs_mgr_read_fstab(args[1]); 544 ret = fs_mgr_swapon_all(fstab); 545 fs_mgr_free_fstab(fstab); 546 547 return ret; 548} 549 550int do_setcon(int nargs, char **args) { 551 if (is_selinux_enabled() <= 0) 552 return 0; 553 if (setcon(args[1]) < 0) { 554 return -errno; 555 } 556 return 0; 557} 558 559int do_setenforce(int nargs, char **args) { 560 if (is_selinux_enabled() <= 0) 561 return 0; 562 if (security_setenforce(atoi(args[1])) < 0) { 563 return -errno; 564 } 565 return 0; 566} 567 568int do_setkey(int nargs, char **args) 569{ 570 struct kbentry kbe; 571 kbe.kb_table = strtoul(args[1], 0, 0); 572 kbe.kb_index = strtoul(args[2], 0, 0); 573 kbe.kb_value = strtoul(args[3], 0, 0); 574 return setkey(&kbe); 575} 576 577int do_setprop(int nargs, char **args) 578{ 579 const char *name = args[1]; 580 const char *value = args[2]; 581 char prop_val[PROP_VALUE_MAX]; 582 int ret; 583 584 ret = expand_props(prop_val, value, sizeof(prop_val)); 585 if (ret) { 586 ERROR("cannot expand '%s' while assigning to '%s'\n", value, name); 587 return -EINVAL; 588 } 589 property_set(name, prop_val); 590 return 0; 591} 592 593int do_setrlimit(int nargs, char **args) 594{ 595 struct rlimit limit; 596 int resource; 597 resource = atoi(args[1]); 598 limit.rlim_cur = atoi(args[2]); 599 limit.rlim_max = atoi(args[3]); 600 return setrlimit(resource, &limit); 601} 602 603int do_start(int nargs, char **args) 604{ 605 struct service *svc; 606 svc = service_find_by_name(args[1]); 607 if (svc) { 608 service_start(svc, NULL); 609 } 610 return 0; 611} 612 613int do_stop(int nargs, char **args) 614{ 615 struct service *svc; 616 svc = service_find_by_name(args[1]); 617 if (svc) { 618 service_stop(svc); 619 } 620 return 0; 621} 622 623int do_restart(int nargs, char **args) 624{ 625 struct service *svc; 626 svc = service_find_by_name(args[1]); 627 if (svc) { 628 service_restart(svc); 629 } 630 return 0; 631} 632 633int do_powerctl(int nargs, char **args) 634{ 635 char command[PROP_VALUE_MAX]; 636 int res; 637 int len = 0; 638 int cmd = 0; 639 char *reboot_target; 640 641 res = expand_props(command, args[1], sizeof(command)); 642 if (res) { 643 ERROR("powerctl: cannot expand '%s'\n", args[1]); 644 return -EINVAL; 645 } 646 647 if (strncmp(command, "shutdown", 8) == 0) { 648 cmd = ANDROID_RB_POWEROFF; 649 len = 8; 650 } else if (strncmp(command, "reboot", 6) == 0) { 651 cmd = ANDROID_RB_RESTART2; 652 len = 6; 653 } else { 654 ERROR("powerctl: unrecognized command '%s'\n", command); 655 return -EINVAL; 656 } 657 658 if (command[len] == ',') { 659 reboot_target = &command[len + 1]; 660 } else if (command[len] == '\0') { 661 reboot_target = ""; 662 } else { 663 ERROR("powerctl: unrecognized reboot target '%s'\n", &command[len]); 664 return -EINVAL; 665 } 666 667 return android_reboot(cmd, 0, reboot_target); 668} 669 670int do_trigger(int nargs, char **args) 671{ 672 action_for_each_trigger(args[1], action_add_queue_tail); 673 return 0; 674} 675 676int do_symlink(int nargs, char **args) 677{ 678 return symlink(args[1], args[2]); 679} 680 681int do_rm(int nargs, char **args) 682{ 683 return unlink(args[1]); 684} 685 686int do_rmdir(int nargs, char **args) 687{ 688 return rmdir(args[1]); 689} 690 691int do_sysclktz(int nargs, char **args) 692{ 693 struct timezone tz; 694 695 if (nargs != 2) 696 return -1; 697 698 memset(&tz, 0, sizeof(tz)); 699 tz.tz_minuteswest = atoi(args[1]); 700 if (settimeofday(NULL, &tz)) 701 return -1; 702 return 0; 703} 704 705int do_write(int nargs, char **args) 706{ 707 const char *path = args[1]; 708 const char *value = args[2]; 709 char prop_val[PROP_VALUE_MAX]; 710 int ret; 711 712 ret = expand_props(prop_val, value, sizeof(prop_val)); 713 if (ret) { 714 ERROR("cannot expand '%s' while writing to '%s'\n", value, path); 715 return -EINVAL; 716 } 717 return write_file(path, prop_val); 718} 719 720int do_copy(int nargs, char **args) 721{ 722 char *buffer = NULL; 723 int rc = 0; 724 int fd1 = -1, fd2 = -1; 725 struct stat info; 726 int brtw, brtr; 727 char *p; 728 729 if (nargs != 3) 730 return -1; 731 732 if (stat(args[1], &info) < 0) 733 return -1; 734 735 if ((fd1 = open(args[1], O_RDONLY)) < 0) 736 goto out_err; 737 738 if ((fd2 = open(args[2], O_WRONLY|O_CREAT|O_TRUNC, 0660)) < 0) 739 goto out_err; 740 741 if (!(buffer = malloc(info.st_size))) 742 goto out_err; 743 744 p = buffer; 745 brtr = info.st_size; 746 while(brtr) { 747 rc = read(fd1, p, brtr); 748 if (rc < 0) 749 goto out_err; 750 if (rc == 0) 751 break; 752 p += rc; 753 brtr -= rc; 754 } 755 756 p = buffer; 757 brtw = info.st_size; 758 while(brtw) { 759 rc = write(fd2, p, brtw); 760 if (rc < 0) 761 goto out_err; 762 if (rc == 0) 763 break; 764 p += rc; 765 brtw -= rc; 766 } 767 768 rc = 0; 769 goto out; 770out_err: 771 rc = -1; 772out: 773 if (buffer) 774 free(buffer); 775 if (fd1 >= 0) 776 close(fd1); 777 if (fd2 >= 0) 778 close(fd2); 779 return rc; 780} 781 782int do_chown(int nargs, char **args) { 783 /* GID is optional. */ 784 if (nargs == 3) { 785 if (_chown(args[2], decode_uid(args[1]), -1) < 0) 786 return -errno; 787 } else if (nargs == 4) { 788 if (_chown(args[3], decode_uid(args[1]), decode_uid(args[2])) < 0) 789 return -errno; 790 } else { 791 return -1; 792 } 793 return 0; 794} 795 796static mode_t get_mode(const char *s) { 797 mode_t mode = 0; 798 while (*s) { 799 if (*s >= '0' && *s <= '7') { 800 mode = (mode<<3) | (*s-'0'); 801 } else { 802 return -1; 803 } 804 s++; 805 } 806 return mode; 807} 808 809int do_chmod(int nargs, char **args) { 810 mode_t mode = get_mode(args[1]); 811 if (_chmod(args[2], mode) < 0) { 812 return -errno; 813 } 814 return 0; 815} 816 817int do_restorecon(int nargs, char **args) { 818 int i; 819 int ret = 0; 820 821 for (i = 1; i < nargs; i++) { 822 if (restorecon(args[i]) < 0) 823 ret = -errno; 824 } 825 return ret; 826} 827 828int do_restorecon_recursive(int nargs, char **args) { 829 int i; 830 int ret = 0; 831 832 for (i = 1; i < nargs; i++) { 833 if (restorecon_recursive(args[i]) < 0) 834 ret = -errno; 835 } 836 return ret; 837} 838 839int do_setsebool(int nargs, char **args) { 840 const char *name = args[1]; 841 const char *value = args[2]; 842 SELboolean b; 843 int ret; 844 845 if (is_selinux_enabled() <= 0) 846 return 0; 847 848 b.name = name; 849 if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on")) 850 b.value = 1; 851 else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off")) 852 b.value = 0; 853 else { 854 ERROR("setsebool: invalid value %s\n", value); 855 return -EINVAL; 856 } 857 858 if (security_set_boolean_list(1, &b, 0) < 0) { 859 ret = -errno; 860 ERROR("setsebool: could not set %s to %s\n", name, value); 861 return ret; 862 } 863 864 return 0; 865} 866 867int do_loglevel(int nargs, char **args) { 868 int log_level; 869 char log_level_str[PROP_VALUE_MAX] = ""; 870 if (nargs != 2) { 871 ERROR("loglevel: missing argument\n"); 872 return -EINVAL; 873 } 874 875 if (expand_props(log_level_str, args[1], sizeof(log_level_str))) { 876 ERROR("loglevel: cannot expand '%s'\n", args[1]); 877 return -EINVAL; 878 } 879 log_level = atoi(log_level_str); 880 if (log_level < KLOG_ERROR_LEVEL || log_level > KLOG_DEBUG_LEVEL) { 881 ERROR("loglevel: invalid log level'%d'\n", log_level); 882 return -EINVAL; 883 } 884 klog_set_level(log_level); 885 return 0; 886} 887 888int do_load_persist_props(int nargs, char **args) { 889 if (nargs == 1) { 890 load_persist_props(); 891 return 0; 892 } 893 return -1; 894} 895 896int do_load_all_props(int nargs, char **args) { 897 if (nargs == 1) { 898 load_all_props(); 899 return 0; 900 } 901 return -1; 902} 903 904int do_wait(int nargs, char **args) 905{ 906 if (nargs == 2) { 907 return wait_for_file(args[1], COMMAND_RETRY_TIMEOUT); 908 } else if (nargs == 3) { 909 return wait_for_file(args[1], atoi(args[2])); 910 } else 911 return -1; 912} 913