summaryrefslogtreecommitdiffstats
path: root/init/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'init/init.c')
-rw-r--r--[-rwxr-xr-x]init/init.c103
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.