summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2013-11-22 11:28:10 -0800
committerConley Owens <cco3@android.com>2013-11-22 13:44:43 -0800
commit66ed50af6870210ce013a5588a688434a5d48ee9 (patch)
treea879f3ea31083496d0efe491bc187b6e0ebada39 /init
parentdd2ac3de625e6c0328a0f70530d8ade0d2151bfc (diff)
parent536dea9d61a032e64bbe584a97463c6638ead009 (diff)
downloadsystem_core-66ed50af6870210ce013a5588a688434a5d48ee9.zip
system_core-66ed50af6870210ce013a5588a688434a5d48ee9.tar.gz
system_core-66ed50af6870210ce013a5588a688434a5d48ee9.tar.bz2
Merge commit '536dea9d61a032e64bbe584a97463c6638ead009' into HEAD
Change-Id: I5c469a4b738629d99d721cad7ded02d6c35f56d5
Diffstat (limited to 'init')
-rw-r--r--init/Android.mk4
-rw-r--r--init/builtins.c52
-rw-r--r--init/init.c85
-rw-r--r--init/init_parser.c3
-rw-r--r--init/keywords.h4
-rw-r--r--[-rwxr-xr-x]init/property_service.c42
6 files changed, 184 insertions, 6 deletions
diff --git a/init/Android.mk b/init/Android.mk
index 8b436db..1f43ba6 100644
--- a/init/Android.mk
+++ b/init/Android.mk
@@ -38,7 +38,9 @@ LOCAL_STATIC_LIBRARIES := \
libcutils \
liblog \
libc \
- libselinux
+ libselinux \
+ libmincrypt \
+ libext4_utils_static
include $(BUILD_EXECUTABLE)
diff --git a/init/builtins.c b/init/builtins.c
index 33fc6c6..e2932d5 100644
--- a/init/builtins.c
+++ b/init/builtins.c
@@ -32,6 +32,7 @@
#include <sys/wait.h>
#include <linux/loop.h>
#include <cutils/partition_utils.h>
+#include <cutils/android_reboot.h>
#include <sys/system_properties.h>
#include <fs_mgr.h>
@@ -56,7 +57,7 @@ static int write_file(const char *path, const char *value)
{
int fd, ret, len;
- fd = open(path, O_WRONLY|O_CREAT, 0622);
+ fd = open(path, O_WRONLY|O_CREAT|O_NOFOLLOW, 0600);
if (fd < 0)
return -errno;
@@ -515,6 +516,18 @@ int do_mount_all(int nargs, char **args)
return ret;
}
+int do_swapon_all(int nargs, char **args)
+{
+ struct fstab *fstab;
+ int ret;
+
+ fstab = fs_mgr_read_fstab(args[1]);
+ ret = fs_mgr_swapon_all(fstab);
+ fs_mgr_free_fstab(fstab);
+
+ return ret;
+}
+
int do_setcon(int nargs, char **args) {
if (is_selinux_enabled() <= 0)
return 0;
@@ -598,6 +611,43 @@ int do_restart(int nargs, char **args)
return 0;
}
+int do_powerctl(int nargs, char **args)
+{
+ char command[PROP_VALUE_MAX];
+ int res;
+ int len = 0;
+ int cmd = 0;
+ char *reboot_target;
+
+ res = expand_props(command, args[1], sizeof(command));
+ if (res) {
+ ERROR("powerctl: cannot expand '%s'\n", args[1]);
+ return -EINVAL;
+ }
+
+ if (strncmp(command, "shutdown", 8) == 0) {
+ cmd = ANDROID_RB_POWEROFF;
+ len = 8;
+ } else if (strncmp(command, "reboot", 6) == 0) {
+ cmd = ANDROID_RB_RESTART2;
+ len = 6;
+ } else {
+ ERROR("powerctl: unrecognized command '%s'\n", command);
+ return -EINVAL;
+ }
+
+ if (command[len] == ',') {
+ reboot_target = &command[len + 1];
+ } else if (command[len] == '\0') {
+ reboot_target = "";
+ } else {
+ ERROR("powerctl: unrecognized reboot target '%s'\n", &command[len]);
+ return -EINVAL;
+ }
+
+ return android_reboot(cmd, 0, reboot_target);
+}
+
int do_trigger(int nargs, char **args)
{
action_for_each_trigger(args[1], action_add_queue_tail);
diff --git a/init/init.c b/init/init.c
index 525b69f..864fc6c 100644
--- a/init/init.c
+++ b/init/init.c
@@ -42,6 +42,7 @@
#include <cutils/android_reboot.h>
#include <cutils/sockets.h>
#include <cutils/iosched_policy.h>
+#include <cutils/fs.h>
#include <private/android_filesystem_config.h>
#include <termios.h>
@@ -556,6 +557,84 @@ static int wait_for_coldboot_done_action(int nargs, char **args)
return ret;
}
+/*
+ * Writes 512 bytes of output from Hardware RNG (/dev/hw_random, backed
+ * by Linux kernel's hw_random framework) into Linux RNG's via /dev/urandom.
+ * Does nothing if Hardware RNG is not present.
+ *
+ * Since we don't yet trust the quality of Hardware RNG, these bytes are not
+ * mixed into the primary pool of Linux RNG and the entropy estimate is left
+ * unmodified.
+ *
+ * If the HW RNG device /dev/hw_random is present, we require that at least
+ * 512 bytes read from it are written into Linux RNG. QA is expected to catch
+ * devices/configurations where these I/O operations are blocking for a long
+ * time. We do not reboot or halt on failures, as this is a best-effort
+ * attempt.
+ */
+static int mix_hwrng_into_linux_rng_action(int nargs, char **args)
+{
+ int result = -1;
+ int hwrandom_fd = -1;
+ int urandom_fd = -1;
+ char buf[512];
+ ssize_t chunk_size;
+ size_t total_bytes_written = 0;
+
+ hwrandom_fd = TEMP_FAILURE_RETRY(
+ open("/dev/hw_random", O_RDONLY | O_NOFOLLOW));
+ if (hwrandom_fd == -1) {
+ if (errno == ENOENT) {
+ ERROR("/dev/hw_random not found\n");
+ /* It's not an error to not have a Hardware RNG. */
+ result = 0;
+ } else {
+ ERROR("Failed to open /dev/hw_random: %s\n", strerror(errno));
+ }
+ goto ret;
+ }
+
+ urandom_fd = TEMP_FAILURE_RETRY(
+ open("/dev/urandom", O_WRONLY | O_NOFOLLOW));
+ if (urandom_fd == -1) {
+ ERROR("Failed to open /dev/urandom: %s\n", strerror(errno));
+ goto ret;
+ }
+
+ while (total_bytes_written < sizeof(buf)) {
+ chunk_size = TEMP_FAILURE_RETRY(
+ read(hwrandom_fd, buf, sizeof(buf) - total_bytes_written));
+ if (chunk_size == -1) {
+ ERROR("Failed to read from /dev/hw_random: %s\n", strerror(errno));
+ goto ret;
+ } else if (chunk_size == 0) {
+ ERROR("Failed to read from /dev/hw_random: EOF\n");
+ goto ret;
+ }
+
+ chunk_size = TEMP_FAILURE_RETRY(write(urandom_fd, buf, chunk_size));
+ if (chunk_size == -1) {
+ ERROR("Failed to write to /dev/urandom: %s\n", strerror(errno));
+ goto ret;
+ }
+ total_bytes_written += chunk_size;
+ }
+
+ INFO("Mixed %d bytes from /dev/hw_random into /dev/urandom",
+ total_bytes_written);
+ result = 0;
+
+ret:
+ if (hwrandom_fd != -1) {
+ close(hwrandom_fd);
+ }
+ if (urandom_fd != -1) {
+ close(urandom_fd);
+ }
+ memset(buf, 0, sizeof(buf));
+ return result;
+}
+
static int keychord_init_action(int nargs, char **args)
{
keychord_init();
@@ -958,6 +1037,7 @@ int main(int argc, char **argv)
action_for_each_trigger("early-init", action_add_queue_tail);
queue_builtin_action(wait_for_coldboot_done_action, "wait_for_coldboot_done");
+ queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
queue_builtin_action(keychord_init_action, "keychord_init");
queue_builtin_action(console_init_action, "console_init");
@@ -972,6 +1052,11 @@ int main(int argc, char **argv)
action_for_each_trigger("post-fs-data", action_add_queue_tail);
}
+ /* Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random
+ * wasn't ready immediately after wait_for_coldboot_done
+ */
+ queue_builtin_action(mix_hwrng_into_linux_rng_action, "mix_hwrng_into_linux_rng");
+
queue_builtin_action(property_service_init_action, "property_service_init");
queue_builtin_action(signal_init_action, "signal_init");
queue_builtin_action(check_startup_action, "check_startup");
diff --git a/init/init_parser.c b/init/init_parser.c
index 38582f5..3f0838f 100644
--- a/init/init_parser.c
+++ b/init/init_parser.c
@@ -130,6 +130,8 @@ int lookup_keyword(const char *s)
if (!strcmp(s, "neshot")) return K_oneshot;
if (!strcmp(s, "nrestart")) return K_onrestart;
break;
+ case 'p':
+ if (!strcmp(s, "owerctl")) return K_powerctl;
case 'r':
if (!strcmp(s, "estart")) return K_restart;
if (!strcmp(s, "estorecon")) return K_restorecon;
@@ -150,6 +152,7 @@ int lookup_keyword(const char *s)
if (!strcmp(s, "ocket")) return K_socket;
if (!strcmp(s, "tart")) return K_start;
if (!strcmp(s, "top")) return K_stop;
+ if (!strcmp(s, "wapon_all")) return K_swapon_all;
if (!strcmp(s, "ymlink")) return K_symlink;
if (!strcmp(s, "ysclktz")) return K_sysclktz;
break;
diff --git a/init/keywords.h b/init/keywords.h
index 414db08..97fe50c 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -14,6 +14,7 @@ int do_insmod(int nargs, char **args);
int do_mkdir(int nargs, char **args);
int do_mount_all(int nargs, char **args);
int do_mount(int nargs, char **args);
+int do_powerctl(int nargs, char **args);
int do_restart(int nargs, char **args);
int do_restorecon(int nargs, char **args);
int do_restorecon_recursive(int nargs, char **args);
@@ -27,6 +28,7 @@ int do_setrlimit(int nargs, char **args);
int do_setsebool(int nargs, char **args);
int do_start(int nargs, char **args);
int do_stop(int nargs, char **args);
+int do_swapon_all(int nargs, char **args);
int do_trigger(int nargs, char **args);
int do_symlink(int nargs, char **args);
int do_sysclktz(int nargs, char **args);
@@ -67,6 +69,7 @@ enum {
KEYWORD(on, SECTION, 0, 0)
KEYWORD(oneshot, OPTION, 0, 0)
KEYWORD(onrestart, OPTION, 0, 0)
+ KEYWORD(powerctl, COMMAND, 1, do_powerctl)
KEYWORD(restart, COMMAND, 1, do_restart)
KEYWORD(restorecon, COMMAND, 1, do_restorecon)
KEYWORD(restorecon_recursive, COMMAND, 1, do_restorecon_recursive)
@@ -84,6 +87,7 @@ enum {
KEYWORD(socket, OPTION, 0, 0)
KEYWORD(start, COMMAND, 1, do_start)
KEYWORD(stop, COMMAND, 1, do_stop)
+ KEYWORD(swapon_all, COMMAND, 1, do_swapon_all)
KEYWORD(trigger, COMMAND, 1, do_trigger)
KEYWORD(symlink, COMMAND, 1, do_symlink)
KEYWORD(sysclktz, COMMAND, 1, do_sysclktz)
diff --git a/init/property_service.c b/init/property_service.c
index f5f5457..c370769 100755..100644
--- a/init/property_service.c
+++ b/init/property_service.c
@@ -78,6 +78,7 @@ struct {
{ "runtime.", AID_SYSTEM, 0 },
{ "hw.", AID_SYSTEM, 0 },
{ "sys.", AID_SYSTEM, 0 },
+ { "sys.powerctl", AID_SHELL, 0 },
{ "service.", AID_SYSTEM, 0 },
{ "wlan.", AID_SYSTEM, 0 },
{ "gps.", AID_GPS, 0 },
@@ -277,6 +278,34 @@ static void write_persistent_property(const char *name, const char *value)
}
}
+static bool is_legal_property_name(const char* name, size_t namelen)
+{
+ size_t i;
+ bool previous_was_dot = false;
+ if (namelen >= PROP_NAME_MAX) return false;
+ if (namelen < 1) return false;
+ if (name[0] == '.') return false;
+ if (name[namelen - 1] == '.') return false;
+
+ /* Only allow alphanumeric, plus '.', '-', or '_' */
+ /* Don't allow ".." to appear in a property name */
+ for (i = 0; i < namelen; i++) {
+ if (name[i] == '.') {
+ if (previous_was_dot == true) return false;
+ previous_was_dot = true;
+ continue;
+ }
+ previous_was_dot = false;
+ if (name[i] == '_' || name[i] == '-') continue;
+ if (name[i] >= 'a' && name[i] <= 'z') continue;
+ if (name[i] >= 'A' && name[i] <= 'Z') continue;
+ if (name[i] >= '0' && name[i] <= '9') continue;
+ return false;
+ }
+
+ return true;
+}
+
int property_set(const char *name, const char *value)
{
prop_info *pi;
@@ -285,9 +314,8 @@ int property_set(const char *name, const char *value)
size_t namelen = strlen(name);
size_t valuelen = strlen(value);
- if(namelen >= PROP_NAME_MAX) return -1;
- if(valuelen >= PROP_VALUE_MAX) return -1;
- if(namelen < 1) return -1;
+ if (!is_legal_property_name(name, namelen)) return -1;
+ if (valuelen >= PROP_VALUE_MAX) return -1;
pi = (prop_info*) __system_property_find(name);
@@ -299,7 +327,7 @@ int property_set(const char *name, const char *value)
} else {
ret = __system_property_add(name, namelen, value, valuelen);
if (ret < 0) {
- ERROR("Failed to set '%s'='%s'", name, value);
+ ERROR("Failed to set '%s'='%s'\n", name, value);
return ret;
}
}
@@ -365,6 +393,12 @@ void handle_property_set_fd()
msg.name[PROP_NAME_MAX-1] = 0;
msg.value[PROP_VALUE_MAX-1] = 0;
+ if (!is_legal_property_name(msg.name, strlen(msg.name))) {
+ ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name);
+ close(s);
+ return;
+ }
+
getpeercon(s, &source_ctx);
if(memcmp(msg.name,"ctl.",4) == 0) {