• 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 #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 
53 void add_environment(const char *name, const char *value);
54 
55 extern int init_module(void *, unsigned long, const char *);
56 
write_file(const char * path,const char * value)57 static 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 
_open(const char * path)80 static 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 
_chown(const char * path,unsigned int uid,unsigned int gid)91 static 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 
_chmod(const char * path,mode_t mode)114 static 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 
insmod(const char * filename,char * options)137 static 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 
setkey(struct kbentry * kbe)154 static 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 
__ifupdown(const char * interface,int up)168 static 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 
191 done:
192     close(s);
193     return ret;
194 }
195 
service_start_if_not_disabled(struct service * svc)196 static void service_start_if_not_disabled(struct service *svc)
197 {
198     if (!(svc->flags & SVC_DISABLED)) {
199         service_start(svc, NULL);
200     }
201 }
202 
do_chdir(int nargs,char ** args)203 int do_chdir(int nargs, char **args)
204 {
205     chdir(args[1]);
206     return 0;
207 }
208 
do_chroot(int nargs,char ** args)209 int do_chroot(int nargs, char **args)
210 {
211     chroot(args[1]);
212     return 0;
213 }
214 
do_class_start(int nargs,char ** args)215 int 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 
do_class_stop(int nargs,char ** args)225 int do_class_stop(int nargs, char **args)
226 {
227     service_for_each_class(args[1], service_stop);
228     return 0;
229 }
230 
do_class_reset(int nargs,char ** args)231 int do_class_reset(int nargs, char **args)
232 {
233     service_for_each_class(args[1], service_reset);
234     return 0;
235 }
236 
do_domainname(int nargs,char ** args)237 int do_domainname(int nargs, char **args)
238 {
239     return write_file("/proc/sys/kernel/domainname", args[1]);
240 }
241 
do_exec(int nargs,char ** args)242 int do_exec(int nargs, char **args)
243 {
244     return -1;
245 }
246 
do_export(int nargs,char ** args)247 int do_export(int nargs, char **args)
248 {
249     add_environment(args[1], args[2]);
250     return 0;
251 }
252 
do_hostname(int nargs,char ** args)253 int do_hostname(int nargs, char **args)
254 {
255     return write_file("/proc/sys/kernel/hostname", args[1]);
256 }
257 
do_ifup(int nargs,char ** args)258 int do_ifup(int nargs, char **args)
259 {
260     return __ifupdown(args[1], 1);
261 }
262 
263 
do_insmod_inner(int nargs,char ** args,int opt_len)264 static 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 
do_insmod(int nargs,char ** args)281 int 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 
do_mkdir(int nargs,char ** args)294 int 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 
338 static 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> */
do_mount(int nargs,char ** args)363 int 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 
457 exit_success:
458     return 0;
459 
460 }
461 
do_mount_all(int nargs,char ** args)462 int 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 
do_setcon(int nargs,char ** args)517 int 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 
do_setenforce(int nargs,char ** args)528 int 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 
do_setkey(int nargs,char ** args)539 int 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 
do_setprop(int nargs,char ** args)548 int 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 
do_setrlimit(int nargs,char ** args)564 int 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 
do_start(int nargs,char ** args)574 int 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 
do_stop(int nargs,char ** args)584 int 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 
do_restart(int nargs,char ** args)594 int 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 
do_trigger(int nargs,char ** args)605 int do_trigger(int nargs, char **args)
606 {
607     action_for_each_trigger(args[1], action_add_queue_tail);
608     return 0;
609 }
610 
do_symlink(int nargs,char ** args)611 int do_symlink(int nargs, char **args)
612 {
613     return symlink(args[1], args[2]);
614 }
615 
do_rm(int nargs,char ** args)616 int do_rm(int nargs, char **args)
617 {
618     return unlink(args[1]);
619 }
620 
do_rmdir(int nargs,char ** args)621 int do_rmdir(int nargs, char **args)
622 {
623     return rmdir(args[1]);
624 }
625 
do_sysclktz(int nargs,char ** args)626 int 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 
do_write(int nargs,char ** args)640 int 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 
do_copy(int nargs,char ** args)655 int 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;
705 out_err:
706     rc = -1;
707 out:
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 
do_chown(int nargs,char ** args)717 int 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 
get_mode(const char * s)731 static 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 
do_chmod(int nargs,char ** args)744 int 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 
do_restorecon(int nargs,char ** args)752 int 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 
do_setsebool(int nargs,char ** args)762 int 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 
do_loglevel(int nargs,char ** args)796 int 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 
do_load_persist_props(int nargs,char ** args)804 int 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 
do_wait(int nargs,char ** args)812 int 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