diff options
Diffstat (limited to 'init/init.c')
| -rw-r--r--[-rwxr-xr-x] | init/init.c | 103 |
1 files changed, 63 insertions, 40 deletions
diff --git a/init/init.c b/init/init.c index f8b21e6..4196620 100755..100644 --- a/init/init.c +++ b/init/init.c @@ -39,6 +39,7 @@ #include <libgen.h> #include <cutils/list.h> +#include <cutils/android_reboot.h> #include <cutils/sockets.h> #include <cutils/iosched_policy.h> #include <private/android_filesystem_config.h> @@ -73,8 +74,6 @@ static char hardware[32]; static unsigned revision = 0; static char qemu[32]; -static int selinux_enabled = 1; - static struct action *cur_action = NULL; static struct command *cur_command = NULL; static struct listnode *command_queue = NULL; @@ -164,7 +163,7 @@ void service_start(struct service *svc, const char *dynamic_args) * state and immediately takes it out of the restarting * state if it was in there */ - svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET)); + svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART)); svc->time_started = 0; /* running processes require no additional work -- if @@ -359,15 +358,14 @@ void service_start(struct service *svc, const char *dynamic_args) notify_service_state(svc->name, "running"); } -/* The how field should be either SVC_DISABLED or SVC_RESET */ +/* The how field should be either SVC_DISABLED, SVC_RESET, or SVC_RESTART */ static void service_stop_or_reset(struct service *svc, int how) { - /* we are no longer running, nor should we - * attempt to restart - */ - svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING)); + /* The service is still SVC_RUNNING until its process exits, but if it has + * already exited it shoudn't attempt a restart yet. */ + svc->flags &= (~SVC_RESTARTING); - if ((how != SVC_DISABLED) && (how != SVC_RESET)) { + if ((how != SVC_DISABLED) && (how != SVC_RESET) && (how != SVC_RESTART)) { /* Hrm, an illegal flag. Default to SVC_DISABLED */ how = SVC_DISABLED; } @@ -399,6 +397,17 @@ void service_stop(struct service *svc) service_stop_or_reset(svc, SVC_DISABLED); } +void service_restart(struct service *svc) +{ + if (svc->flags & SVC_RUNNING) { + /* Stop, wait, then start the service. */ + service_stop_or_reset(svc, SVC_RESTART); + } else if (!(svc->flags & SVC_RESTARTING)) { + /* Just start the service since it's not running. */ + service_start(svc, NULL); + } /* else: Service is restarting anyways. */ +} + void property_changed(const char *name, const char *value) { if (property_triggers_enabled) @@ -467,6 +476,17 @@ static void msg_stop(const char *name) } } +static void msg_restart(const char *name) +{ + struct service *svc = service_find_by_name(name); + + if (svc) { + service_restart(svc); + } else { + ERROR("no such service '%s'\n", name); + } +} + void handle_control_message(const char *msg, const char *arg) { if (!strcmp(msg,"start")) { @@ -474,8 +494,7 @@ void handle_control_message(const char *msg, const char *arg) } else if (!strcmp(msg,"stop")) { msg_stop(arg); } else if (!strcmp(msg,"restart")) { - msg_stop(arg); - msg_start(arg); + msg_restart(arg); } else { ERROR("unknown control msg '%s'\n", msg); } @@ -594,10 +613,6 @@ static void import_kernel_nv(char *name, int for_emulator) *value++ = 0; if (name_len == 0) return; - if (!strcmp(name,"selinux")) { - selinux_enabled = atoi(value); - } - if (for_emulator) { /* in the emulator, export any kernel option with the * ro.kernel. prefix */ @@ -625,7 +640,7 @@ static void import_kernel_nv(char *name, int for_emulator) static void export_kernel_boot_props(void) { char tmp[PROP_VALUE_MAX]; - const char *pval; + int ret; unsigned i; struct { const char *src_prop; @@ -639,22 +654,26 @@ static void export_kernel_boot_props(void) }; for (i = 0; i < ARRAY_SIZE(prop_map); i++) { - pval = property_get(prop_map[i].src_prop); - property_set(prop_map[i].dest_prop, pval ?: prop_map[i].def_val); + ret = property_get(prop_map[i].src_prop, tmp); + if (ret > 0) + property_set(prop_map[i].dest_prop, tmp); + else + property_set(prop_map[i].dest_prop, prop_map[i].def_val); } - pval = property_get("ro.boot.console"); - if (pval) - strlcpy(console, pval, sizeof(console)); + ret = property_get("ro.boot.console", tmp); + if (ret) + strlcpy(console, tmp, sizeof(console)); /* save a copy for init's usage during boot */ - strlcpy(bootmode, property_get("ro.bootmode"), sizeof(bootmode)); + property_get("ro.bootmode", tmp); + strlcpy(bootmode, tmp, sizeof(bootmode)); /* if this was given on kernel command line, override what we read * before (e.g. from /proc/cpuinfo), if anything */ - pval = property_get("ro.boot.hardware"); - if (pval) - strlcpy(hardware, pval, sizeof(hardware)); + ret = property_get("ro.boot.hardware", tmp); + if (ret) + strlcpy(hardware, tmp, sizeof(hardware)); property_set("ro.hardware", hardware); snprintf(tmp, PROP_VALUE_MAX, "%d", revision); @@ -776,10 +795,6 @@ void selinux_init_all_handles(void) int selinux_reload_policy(void) { - if (!selinux_enabled) { - return -1; - } - INFO("SELinux: Attempting to reload policy files\n"); if (selinux_android_reload_policy() == -1) { @@ -802,6 +817,24 @@ int audit_callback(void *data, security_class_t cls, char *buf, size_t len) return 0; } +static void selinux_initialize(void) +{ + if (access("/sys/fs/selinux", F_OK) != 0) { + // SELinux is not compiled into this kernel. Fail gracefully. + return; + } + + INFO("loading selinux policy\n"); + if (selinux_android_load_policy() < 0) { + ERROR("SELinux: Failed to load policy; rebooting into recovery mode\n"); + android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); + while (1) { pause(); } // never reached + } + + selinux_init_all_handles(); + security_setenforce(1); +} + int main(int argc, char **argv) { int fd_count = 0; @@ -862,17 +895,7 @@ int main(int argc, char **argv) cb.func_audit = audit_callback; selinux_set_callback(SELINUX_CB_AUDIT, cb); - INFO("loading selinux policy\n"); - if (selinux_enabled) { - if (selinux_android_load_policy() < 0) { - selinux_enabled = 0; - INFO("SELinux: Disabled due to failed policy load\n"); - } else { - selinux_init_all_handles(); - } - } else { - INFO("SELinux: Disabled by command line option\n"); - } + selinux_initialize(); /* These directories were necessarily created before initial policy load * and therefore need their security context restored to the proper value. * This must happen before /dev is populated by ueventd. |
