• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
51 void add_environment(const char *name, const char *value);
52 
53 extern int init_module(void *, unsigned long, const char *);
54 
write_file(const char * path,const char * value)55 static 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 
_open(const char * path)78 static 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 
_chown(const char * path,unsigned int uid,unsigned int gid)89 static 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 
_chmod(const char * path,mode_t mode)112 static 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 
insmod(const char * filename,char * options)135 static 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 
setkey(struct kbentry * kbe)152 static 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 
__ifupdown(const char * interface,int up)166 static 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 
189 done:
190     close(s);
191     return ret;
192 }
193 
service_start_if_not_disabled(struct service * svc)194 static void service_start_if_not_disabled(struct service *svc)
195 {
196     if (!(svc->flags & SVC_DISABLED)) {
197         service_start(svc, NULL);
198     }
199 }
200 
do_chdir(int nargs,char ** args)201 int do_chdir(int nargs, char **args)
202 {
203     chdir(args[1]);
204     return 0;
205 }
206 
do_chroot(int nargs,char ** args)207 int do_chroot(int nargs, char **args)
208 {
209     chroot(args[1]);
210     return 0;
211 }
212 
do_class_start(int nargs,char ** args)213 int 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 
do_class_stop(int nargs,char ** args)223 int do_class_stop(int nargs, char **args)
224 {
225     service_for_each_class(args[1], service_stop);
226     return 0;
227 }
228 
do_class_reset(int nargs,char ** args)229 int do_class_reset(int nargs, char **args)
230 {
231     service_for_each_class(args[1], service_reset);
232     return 0;
233 }
234 
do_domainname(int nargs,char ** args)235 int do_domainname(int nargs, char **args)
236 {
237     return write_file("/proc/sys/kernel/domainname", args[1]);
238 }
239 
do_exec(int nargs,char ** args)240 int do_exec(int nargs, char **args)
241 {
242     return -1;
243 }
244 
do_export(int nargs,char ** args)245 int do_export(int nargs, char **args)
246 {
247     add_environment(args[1], args[2]);
248     return 0;
249 }
250 
do_hostname(int nargs,char ** args)251 int do_hostname(int nargs, char **args)
252 {
253     return write_file("/proc/sys/kernel/hostname", args[1]);
254 }
255 
do_ifup(int nargs,char ** args)256 int do_ifup(int nargs, char **args)
257 {
258     return __ifupdown(args[1], 1);
259 }
260 
261 
do_insmod_inner(int nargs,char ** args,int opt_len)262 static 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 
do_insmod(int nargs,char ** args)279 int 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 
do_mkdir(int nargs,char ** args)292 int 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 
336 static 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> */
do_mount(int nargs,char ** args)361 int 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 
455 exit_success:
456     return 0;
457 
458 }
459 
do_mount_all(int nargs,char ** args)460 int 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     struct fstab *fstab;
468 
469     if (nargs != 2) {
470         return -1;
471     }
472 
473     /*
474      * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and
475      * do the call in the child to provide protection to the main init
476      * process if anything goes wrong (crash or memory leak), and wait for
477      * the child to finish in the parent.
478      */
479     pid = fork();
480     if (pid > 0) {
481         /* Parent.  Wait for the child to return */
482         waitpid(pid, &status, 0);
483         if (WIFEXITED(status)) {
484             ret = WEXITSTATUS(status);
485         } else {
486             ret = -1;
487         }
488     } else if (pid == 0) {
489         /* child, call fs_mgr_mount_all() */
490         klog_set_level(6);  /* So we can see what fs_mgr_mount_all() does */
491         fstab = fs_mgr_read_fstab(args[1]);
492         child_ret = fs_mgr_mount_all(fstab);
493         fs_mgr_free_fstab(fstab);
494         if (child_ret == -1) {
495             ERROR("fs_mgr_mount_all returned an error\n");
496         }
497         exit(child_ret);
498     } else {
499         /* fork failed, return an error */
500         return -1;
501     }
502 
503     /* ret is 1 if the device is encrypted, 0 if not, and -1 on error */
504     if (ret == 1) {
505         property_set("ro.crypto.state", "encrypted");
506         property_set("vold.decrypt", "1");
507     } else if (ret == 0) {
508         property_set("ro.crypto.state", "unencrypted");
509         /* If fs_mgr determined this is an unencrypted device, then trigger
510          * that action.
511          */
512         action_for_each_trigger("nonencrypted", action_add_queue_tail);
513     }
514 
515     return ret;
516 }
517 
do_setcon(int nargs,char ** args)518 int do_setcon(int nargs, char **args) {
519     if (is_selinux_enabled() <= 0)
520         return 0;
521     if (setcon(args[1]) < 0) {
522         return -errno;
523     }
524     return 0;
525 }
526 
do_setenforce(int nargs,char ** args)527 int do_setenforce(int nargs, char **args) {
528     if (is_selinux_enabled() <= 0)
529         return 0;
530     if (security_setenforce(atoi(args[1])) < 0) {
531         return -errno;
532     }
533     return 0;
534 }
535 
do_setkey(int nargs,char ** args)536 int do_setkey(int nargs, char **args)
537 {
538     struct kbentry kbe;
539     kbe.kb_table = strtoul(args[1], 0, 0);
540     kbe.kb_index = strtoul(args[2], 0, 0);
541     kbe.kb_value = strtoul(args[3], 0, 0);
542     return setkey(&kbe);
543 }
544 
do_setprop(int nargs,char ** args)545 int do_setprop(int nargs, char **args)
546 {
547     const char *name = args[1];
548     const char *value = args[2];
549     char prop_val[PROP_VALUE_MAX];
550     int ret;
551 
552     ret = expand_props(prop_val, value, sizeof(prop_val));
553     if (ret) {
554         ERROR("cannot expand '%s' while assigning to '%s'\n", value, name);
555         return -EINVAL;
556     }
557     property_set(name, prop_val);
558     return 0;
559 }
560 
do_setrlimit(int nargs,char ** args)561 int do_setrlimit(int nargs, char **args)
562 {
563     struct rlimit limit;
564     int resource;
565     resource = atoi(args[1]);
566     limit.rlim_cur = atoi(args[2]);
567     limit.rlim_max = atoi(args[3]);
568     return setrlimit(resource, &limit);
569 }
570 
do_start(int nargs,char ** args)571 int do_start(int nargs, char **args)
572 {
573     struct service *svc;
574     svc = service_find_by_name(args[1]);
575     if (svc) {
576         service_start(svc, NULL);
577     }
578     return 0;
579 }
580 
do_stop(int nargs,char ** args)581 int do_stop(int nargs, char **args)
582 {
583     struct service *svc;
584     svc = service_find_by_name(args[1]);
585     if (svc) {
586         service_stop(svc);
587     }
588     return 0;
589 }
590 
do_restart(int nargs,char ** args)591 int do_restart(int nargs, char **args)
592 {
593     struct service *svc;
594     svc = service_find_by_name(args[1]);
595     if (svc) {
596         service_stop(svc);
597         service_start(svc, NULL);
598     }
599     return 0;
600 }
601 
do_trigger(int nargs,char ** args)602 int do_trigger(int nargs, char **args)
603 {
604     action_for_each_trigger(args[1], action_add_queue_tail);
605     return 0;
606 }
607 
do_symlink(int nargs,char ** args)608 int do_symlink(int nargs, char **args)
609 {
610     return symlink(args[1], args[2]);
611 }
612 
do_rm(int nargs,char ** args)613 int do_rm(int nargs, char **args)
614 {
615     return unlink(args[1]);
616 }
617 
do_rmdir(int nargs,char ** args)618 int do_rmdir(int nargs, char **args)
619 {
620     return rmdir(args[1]);
621 }
622 
do_sysclktz(int nargs,char ** args)623 int do_sysclktz(int nargs, char **args)
624 {
625     struct timezone tz;
626 
627     if (nargs != 2)
628         return -1;
629 
630     memset(&tz, 0, sizeof(tz));
631     tz.tz_minuteswest = atoi(args[1]);
632     if (settimeofday(NULL, &tz))
633         return -1;
634     return 0;
635 }
636 
do_write(int nargs,char ** args)637 int do_write(int nargs, char **args)
638 {
639     const char *path = args[1];
640     const char *value = args[2];
641     char prop_val[PROP_VALUE_MAX];
642     int ret;
643 
644     ret = expand_props(prop_val, value, sizeof(prop_val));
645     if (ret) {
646         ERROR("cannot expand '%s' while writing to '%s'\n", value, path);
647         return -EINVAL;
648     }
649     return write_file(path, prop_val);
650 }
651 
do_copy(int nargs,char ** args)652 int do_copy(int nargs, char **args)
653 {
654     char *buffer = NULL;
655     int rc = 0;
656     int fd1 = -1, fd2 = -1;
657     struct stat info;
658     int brtw, brtr;
659     char *p;
660 
661     if (nargs != 3)
662         return -1;
663 
664     if (stat(args[1], &info) < 0)
665         return -1;
666 
667     if ((fd1 = open(args[1], O_RDONLY)) < 0)
668         goto out_err;
669 
670     if ((fd2 = open(args[2], O_WRONLY|O_CREAT|O_TRUNC, 0660)) < 0)
671         goto out_err;
672 
673     if (!(buffer = malloc(info.st_size)))
674         goto out_err;
675 
676     p = buffer;
677     brtr = info.st_size;
678     while(brtr) {
679         rc = read(fd1, p, brtr);
680         if (rc < 0)
681             goto out_err;
682         if (rc == 0)
683             break;
684         p += rc;
685         brtr -= rc;
686     }
687 
688     p = buffer;
689     brtw = info.st_size;
690     while(brtw) {
691         rc = write(fd2, p, brtw);
692         if (rc < 0)
693             goto out_err;
694         if (rc == 0)
695             break;
696         p += rc;
697         brtw -= rc;
698     }
699 
700     rc = 0;
701     goto out;
702 out_err:
703     rc = -1;
704 out:
705     if (buffer)
706         free(buffer);
707     if (fd1 >= 0)
708         close(fd1);
709     if (fd2 >= 0)
710         close(fd2);
711     return rc;
712 }
713 
do_chown(int nargs,char ** args)714 int do_chown(int nargs, char **args) {
715     /* GID is optional. */
716     if (nargs == 3) {
717         if (_chown(args[2], decode_uid(args[1]), -1) < 0)
718             return -errno;
719     } else if (nargs == 4) {
720         if (_chown(args[3], decode_uid(args[1]), decode_uid(args[2])) < 0)
721             return -errno;
722     } else {
723         return -1;
724     }
725     return 0;
726 }
727 
get_mode(const char * s)728 static mode_t get_mode(const char *s) {
729     mode_t mode = 0;
730     while (*s) {
731         if (*s >= '0' && *s <= '7') {
732             mode = (mode<<3) | (*s-'0');
733         } else {
734             return -1;
735         }
736         s++;
737     }
738     return mode;
739 }
740 
do_chmod(int nargs,char ** args)741 int do_chmod(int nargs, char **args) {
742     mode_t mode = get_mode(args[1]);
743     if (_chmod(args[2], mode) < 0) {
744         return -errno;
745     }
746     return 0;
747 }
748 
do_restorecon(int nargs,char ** args)749 int do_restorecon(int nargs, char **args) {
750     int i;
751 
752     for (i = 1; i < nargs; i++) {
753         if (restorecon(args[i]) < 0)
754             return -errno;
755     }
756     return 0;
757 }
758 
do_setsebool(int nargs,char ** args)759 int do_setsebool(int nargs, char **args) {
760     const char *name = args[1];
761     const char *value = args[2];
762     SELboolean b;
763     int ret;
764 
765     if (is_selinux_enabled() <= 0)
766         return 0;
767 
768     b.name = name;
769     if (!strcmp(value, "1") || !strcasecmp(value, "true") || !strcasecmp(value, "on"))
770         b.value = 1;
771     else if (!strcmp(value, "0") || !strcasecmp(value, "false") || !strcasecmp(value, "off"))
772         b.value = 0;
773     else {
774         ERROR("setsebool: invalid value %s\n", value);
775         return -EINVAL;
776     }
777 
778     if (security_set_boolean_list(1, &b, 0) < 0) {
779         ret = -errno;
780         ERROR("setsebool: could not set %s to %s\n", name, value);
781         return ret;
782     }
783 
784     return 0;
785 }
786 
do_loglevel(int nargs,char ** args)787 int do_loglevel(int nargs, char **args) {
788     if (nargs == 2) {
789         klog_set_level(atoi(args[1]));
790         return 0;
791     }
792     return -1;
793 }
794 
do_load_persist_props(int nargs,char ** args)795 int do_load_persist_props(int nargs, char **args) {
796     if (nargs == 1) {
797         load_persist_props();
798         return 0;
799     }
800     return -1;
801 }
802 
do_wait(int nargs,char ** args)803 int do_wait(int nargs, char **args)
804 {
805     if (nargs == 2) {
806         return wait_for_file(args[1], COMMAND_RETRY_TIMEOUT);
807     } else if (nargs == 3) {
808         return wait_for_file(args[1], atoi(args[2]));
809     } else
810         return -1;
811 }
812