summaryrefslogtreecommitdiffstats
path: root/init/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'init/init.c')
-rw-r--r--init/init.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/init/init.c b/init/init.c
index c497d78..ab52749 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>
@@ -220,6 +221,9 @@ void service_start(struct service *svc, const char *dynamic_args)
}
rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon);
+ if (rc == 0 && !strcmp(scon, mycon)) {
+ ERROR("Warning! Service %s needs a SELinux domain defined; please fix!\n", svc->name);
+ }
freecon(mycon);
freecon(fcon);
if (rc < 0) {
@@ -556,6 +560,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 +1040,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 +1055,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");