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