builtins.c revision 2a36ae5608e9d655b2bb14ce538f6fbdb910cada
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#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, 0622); 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 } 199} 200 201int do_chdir(int nargs, char **args) 202{ 203 chdir(args[1]); 204 return 0; 205} 206 207int do_chroot(int nargs, char **args) 208{ 209 chroot(args[1]); 210 return 0; 211} 212 213int do_class_start(int nargs, char **args) 214{ 215 /* Starting a class does not start services 216 * which are explicitly disabled. They must 217 * be started individually. 218 */ 219 service_for_each_class(args[1], service_start_if_not_disabled); 220 return 0; 221} 222 223int do_class_stop(int nargs, char **args) 224{ 225 service_for_each_class(args[1], service_stop); 226 return 0; 227} 228 229int do_class_reset(int nargs, char **args) 230{ 231 service_for_each_class(args[1], service_reset); 232 return 0; 233} 234 235int do_domainname(int nargs, char **args) 236{ 237 return write_file("/proc/sys/kernel/domainname", args[1]); 238} 239 240int do_exec(int nargs, char **args) 241{ 242 return -1; 243} 244 245int do_export(int nargs, char **args) 246{ 247 add_environment(args[1], args[2]); 248 return 0; 249} 250 251int do_hostname(int nargs, char **args) 252{ 253 return write_file("/proc/sys/kernel/hostname", args[1]); 254} 255 256int do_ifup(int nargs, char **args) 257{ 258 return __ifupdown(args[1], 1); 259} 260 261 262static int do_insmod_inner(int nargs, char **args, int opt_len) 263{ 264 char options[opt_len + 1]; 265 int i; 266 267 options[0] = '\0'; 268 if (nargs > 2) { 269 strcpy(options, args[2]); 270 for (i = 3; i < nargs; ++i) { 271 strcat(options, " "); 272 strcat(options, args[i]); 273 } 274 } 275 276 return insmod(args[1], options); 277} 278 279int do_insmod(int nargs, char **args) 280{ 281 int i; 282 int size = 0; 283 284 if (nargs > 2) { 285 for (i = 2; i < nargs; ++i) 286 size += strlen(args[i]) + 1; 287 } 288 289 return do_insmod_inner(nargs, args, size); 290} 291 292int do_mkdir(int nargs, char **args) 293{ 294 mode_t mode = 0755; 295 int ret; 296 297 /* mkdir <path> [mode] [owner] [group] */ 298 299 if (nargs >= 3) { 300 mode = strtoul(args[2], 0, 8); 301 } 302 303 ret = make_dir(args[1], mode); 304 /* chmod in case the directory already exists */ 305 if (ret == -1 && errno == EEXIST) { 306 ret = _chmod(args[1], mode); 307 } 308 if (ret == -1) { 309 return -errno; 310 } 311 312 if (nargs >= 4) { 313 uid_t uid = decode_uid(args[3]); 314 gid_t gid = -1; 315 316 if (nargs == 5) { 317 gid = decode_uid(args[4]); 318 } 319 320 if (_chown(args[1], uid, gid) < 0) { 321 return -errno; 322 } 323 324 /* chown may have cleared S_ISUID and S_ISGID, chmod again */ 325 if (mode & (S_ISUID | S_ISGID)) { 326 ret = _chmod(args[1], mode); 327 if (ret == -1) { 328 return -errno; 329 } 330 } 331 } 332 333 return 0; 334} 335 336static struct { 337 const char *name; 338 unsigned flag; 339} mount_flags[] = { 340 { "noatime", MS_NOATIME }, 341 { "noexec", MS_NOEXEC }, 342 { "nosuid", MS_NOSUID }, 343 { "nodev", MS_NODEV }, 344 { "nodiratime", MS_NODIRATIME }, 345 { "ro", MS_RDONLY }, 346 { "rw", 0 }, 347 { "remount", MS_REMOUNT }, 348 { "bind", MS_BIND }, 349 { "rec", MS_REC }, 350 { "unbindable", MS_UNBINDABLE }, 351 { "private", MS_PRIVATE }, 352 { "slave", MS_SLAVE }, 353 { "shared", MS_SHARED }, 354 { "defaults", 0 }, 355 { 0, 0 }, 356}; 357 358#define DATA_MNT_POINT "/data" 359 360/* mount <type> <device> <path> <flags ...> <options> */ 361int do_mount(int nargs, char **args) 362{ 363 char tmp[64]; 364 char *source, *target, *system; 365 char *options = NULL; 366 unsigned flags = 0; 367 int n, i; 368 int wait = 0; 369 370 for (n = 4; n < nargs; n++) { 371 for (i = 0; mount_flags[i].name; i++) { 372 if (!strcmp(args[n], mount_flags[i].name)) { 373 flags |= mount_flags[i].flag; 374 break; 375 } 376 } 377 378 if (!mount_flags[i].name) { 379 if (!strcmp(args[n], "wait")) 380 wait = 1; 381 /* if our last argument isn't a flag, wolf it up as an option string */ 382 else if (n + 1 == nargs) 383 options = args[n]; 384 } 385 } 386 387 system = args[1]; 388 source = args[2]; 389 target = args[3]; 390 391 if (!strncmp(source, "mtd@", 4)) { 392 n = mtd_name_to_number(source + 4); 393 if (n < 0) { 394 return -1; 395 } 396 397 sprintf(tmp, "/dev/block/mtdblock%d", n); 398 399 if (wait) 400 wait_for_file(tmp, COMMAND_RETRY_TIMEOUT); 401 if (mount(tmp, target, system, flags, options) < 0) { 402 return -1; 403 } 404 405 goto exit_success; 406 } else if (!strncmp(source, "loop@", 5)) { 407 int mode, loop, fd; 408 struct loop_info info; 409 410 mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR; 411 fd = open(source + 5, mode); 412 if (fd < 0) { 413 return -1; 414 } 415 416 for (n = 0; ; n++) { 417 sprintf(tmp, "/dev/block/loop%d", n); 418 loop = open(tmp, mode); 419 if (loop < 0) { 420 return -1; 421 } 422 423 /* if it is a blank loop device */ 424 if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) { 425 /* if it becomes our loop device */ 426 if (ioctl(loop, LOOP_SET_FD, fd) >= 0) { 427 close(fd); 428 429 if (mount(tmp, target, system, flags, options) < 0) { 430 ioctl(loop, LOOP_CLR_FD, 0); 431 close(loop); 432 return -1; 433 } 434 435 close(loop); 436 goto exit_success; 437 } 438 } 439 440 close(loop); 441 } 442 443 close(fd); 444 ERROR("out of loopback devices"); 445 return -1; 446 } else { 447 if (wait) 448 wait_for_file(source, COMMAND_RETRY_TIMEOUT); 449 if (mount(source, target, system, flags, options) < 0) { 450 return -1; 451 } 452 453 } 454 455exit_success: 456 return 0; 457 458} 459 460int do_mount_all(int nargs, char **args) 461{ 462 pid_t pid; 463 int ret = -1; 464 int child_ret = -1; 465 int status; 466 const char *prop; 467 468 if (nargs != 2) { 469 return -1; 470 } 471 472 /* 473 * Call fs_mgr_mount_all() to mount all filesystems. We fork(2) and 474 * do the call in the child to provide protection to the main init 475 * process if anything goes wrong (crash or memory leak), and wait for 476 * the child to finish in the parent. 477 */ 478 pid = fork(); 479 if (pid > 0) { 480 /* Parent. Wait for the child to return */ 481 waitpid(pid, &status, 0); 482 if (WIFEXITED(status)) { 483 ret = WEXITSTATUS(status); 484 } else { 485 ret = -1; 486 } 487 } else if (pid == 0) { 488 /* child, call fs_mgr_mount_all() */ 489 klog_set_level(6); /* So we can see what fs_mgr_mount_all() does */ 490 child_ret = fs_mgr_mount_all(args[1]); 491 if (child_ret == -1) { 492 ERROR("fs_mgr_mount_all returned an error\n"); 493 } 494 exit(child_ret); 495 } else { 496 /* fork failed, return an error */ 497 return -1; 498 } 499 500 /* ret is 1 if the device is encrypted, 0 if not, and -1 on error */ 501 if (ret == 1) { 502 property_set("ro.crypto.state", "encrypted"); 503 property_set("vold.decrypt", "1"); 504 } else if (ret == 0) { 505 property_set("ro.crypto.state", "unencrypted"); 506 /* If fs_mgr determined this is an unencrypted device, then trigger 507 * that action. 508 */ 509 action_for_each_trigger("nonencrypted", action_add_queue_tail); 510 } 511 512 return ret; 513} 514 515int do_setcon(int nargs, char **args) { 516 if (is_selinux_enabled() <= 0) 517 return 0; 518 if (setcon(args[1]) < 0) { 519 return -errno; 520 } 521 return 0; 522} 523 524int do_setenforce(int nargs, char **args) { 525 if (is_selinux_enabled() <= 0) 526 return 0; 527 if (security_setenforce(atoi(args[1])) < 0) { 528 return -errno; 529 } 530 return 0; 531} 532 533int do_setkey(int nargs, char **args) 534{ 535 struct kbentry kbe; 536 kbe.kb_table = strtoul(args[1], 0, 0); 537 kbe.kb_index = strtoul(args[2], 0, 0); 538 kbe.kb_value = strtoul(args[3], 0, 0); 539 return setkey(&kbe); 540} 541 542int do_setprop(int nargs, char **args) 543{ 544 const char *name = args[1]; 545 const char *value = args[2]; 546 char prop_val[PROP_VALUE_MAX]; 547 int ret; 548 549 ret = expand_props(prop_val, value, sizeof(prop_val)); 550 if (ret) { 551 ERROR("cannot expand '%s' while assigning to '%s'\n", value, name); 552 return -EINVAL; 553 } 554 property_set(name, prop_val); 555 return 0; 556} 557 558int do_setrlimit(int nargs, char **args) 559{ 560 struct rlimit limit; 561 int resource; 562 resource = atoi(args[1]); 563 limit.rlim_cur = atoi(args[2]); 564 limit.rlim_max = atoi(args[3]); 565 return setrlimit(resource, &limit); 566} 567 568int do_start(int nargs, char **args) 569{ 570 struct service *svc; 571 svc = service_find_by_name(args[1]); 572 if (svc) { 573 service_start(svc, NULL); 574 } 575 return 0; 576} 577 578int do_stop(int nargs, char **args) 579{ 580 struct service *svc; 581 svc = service_find_by_name(args[1]); 582 if (svc) { 583 service_stop(svc); 584 } 585 return 0; 586} 587 588int do_restart(int nargs, char **args) 589{ 590 struct service *svc; 591 svc = service_find_by_name(args[1]); 592 if (svc) { 593 service_stop(svc); 594 service_start(svc, NULL); 595 } 596 return 0; 597} 598 599int do_trigger(int nargs, char **args) 600{ 601 action_for_each_trigger(args[1], action_add_queue_tail); 602 return 0; 603} 604 605int do_symlink(int nargs, char **args) 606{ 607 return symlink(args[1], args[2]); 608} 609 610int do_rm(int nargs, char **args) 611{ 612 return unlink(args[1]); 613} 614 615int do_rmdir(int nargs, char **args) 616{ 617 return rmdir(args[1]); 618} 619 620int do_sysclktz(int nargs, char **args) 621{ 622 struct timezone tz; 623 624 if (nargs != 2) 625 return -1; 626 627 memset(&tz, 0, sizeof(tz)); 628 tz.tz_minuteswest = atoi(args[1]); 629 if (settimeofday(NULL, &tz)) 630 return -1; 631 return 0; 632} 633 634int do_write(int nargs, char **args) 635{ 636 const char *path = args[1]; 637 const char *value = args[2]; 638 char prop_val[PROP_VALUE_MAX]; 639 int ret; 640 641 ret = expand_props(prop_val, value, sizeof(prop_val)); 642 if (ret) { 643 ERROR("cannot expand '%s' while writing to '%s'\n", value, path); 644 return -EINVAL; 645 } 646 return write_file(path, prop_val); 647} 648 649int do_copy(int nargs, char **args) 650{ 651 char *buffer = NULL; 652 int rc = 0; 653 int fd1 = -1, fd2 = -1; 654 struct stat info; 655 int brtw, brtr; 656 char *p; 657 658 if (nargs != 3) 659 return -1; 660 661 if (stat(args[1], &info) < 0) 662 return -1; 663 664 if ((fd1 = open(args[1], O_RDONLY)) < 0) 665 goto out_err; 666 667 if ((fd2 = open(args[2], O_WRONLY|O_CREAT|O_TRUNC, 0660)) < 0) 668 goto out_err; 669 670 if (!(buffer = malloc(info.st_size))) 671 goto out_err; 672 673 p = buffer; 674 brtr = info.st_size; 675 while(brtr) { 676 rc = read(fd1, p, brtr); 677 if (rc < 0) 678 goto out_err; 679 if (rc == 0) 680 break; 681 p += rc; 682 brtr -= rc; 683 } 684 685 p = buffer; 686 brtw = info.st_size; 687 while(brtw) { 688 rc = write(fd2, p, brtw); 689 if (rc < 0) 690 goto out_err; 691 if (rc == 0) 692 break; 693 p += rc; 694 brtw -= rc; 695 } 696 697 rc = 0; 698 goto out; 699out_err: 700 rc = -1; 701out: 702 if (buffer) 703 free(buffer); 704 if (fd1 >= 0) 705 close(fd1); 706 if (fd2 >= 0) 707 close(fd2); 708 return rc; 709} 710 711int do_chown(int nargs, char **args) { 712 /* GID is optional. */ 713 if (nargs == 3) { 714 if (_chown(args[2], decode_uid(args[1]), -1) < 0) 715 return -errno; 716 } else if (nargs == 4) { 717 if (_chown(args[3], decode_uid(args[1]), decode_uid(args[2])) < 0) 718 return -errno; 719 } else { 720 return -1; 721 } 722 return 0; 723} 724 725static mode_t get_mode(const char *s) { 726 mode_t mode = 0; 727 while (*s) { 728 if (*s >= '0' && *s <= '7') { 729 mode = (mode<<3) | (*s-'0'); 730 } else { 731 return -1; 732 } 733 s++; 734 } 735 return mode; 736} 737 738int do_chmod(int nargs, char **args) { 739 mode_t mode = get_mode(args[1]); 740 if (_chmod(args[2], mode) < 0) { 741 return -errno; 742 } 743 return 0; 744} 745 746int do_restorecon(int nargs, char **args) { 747 int i; 748 749 for (i = 1; i < nargs; i++) { 750 if (restorecon(args[i]) < 0) 751 return -errno; 752 } 753 return 0; 754} 755 756int do_setsebool(int nargs, char **args) { 757 SELboolean *b = alloca(nargs * sizeof(SELboolean)); 758 char *v; 759 int i; 760 761 if (is_selinux_enabled() <= 0) 762 return 0; 763 764 for (i = 1; i < nargs; i++) { 765 char *name = args[i]; 766 v = strchr(name, '='); 767 if (!v) { 768 ERROR("setsebool: argument %s had no =\n", name); 769 return -EINVAL; 770 } 771 *v++ = 0; 772 b[i-1].name = name; 773 if (!strcmp(v, "1") || !strcasecmp(v, "true") || !strcasecmp(v, "on")) 774 b[i-1].value = 1; 775 else if (!strcmp(v, "0") || !strcasecmp(v, "false") || !strcasecmp(v, "off")) 776 b[i-1].value = 0; 777 else { 778 ERROR("setsebool: invalid value %s\n", v); 779 return -EINVAL; 780 } 781 } 782 783 if (security_set_boolean_list(nargs - 1, b, 0) < 0) 784 return -errno; 785 786 return 0; 787} 788 789int do_loglevel(int nargs, char **args) { 790 if (nargs == 2) { 791 klog_set_level(atoi(args[1])); 792 return 0; 793 } 794 return -1; 795} 796 797int do_load_persist_props(int nargs, char **args) { 798 if (nargs == 1) { 799 load_persist_props(); 800 return 0; 801 } 802 return -1; 803} 804 805int do_wait(int nargs, char **args) 806{ 807 if (nargs == 2) { 808 return wait_for_file(args[1], COMMAND_RETRY_TIMEOUT); 809 } else if (nargs == 3) { 810 return wait_for_file(args[1], atoi(args[2])); 811 } else 812 return -1; 813} 814