diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2013-11-22 11:28:10 -0800 |
---|---|---|
committer | Conley Owens <cco3@android.com> | 2013-11-22 13:44:43 -0800 |
commit | 66ed50af6870210ce013a5588a688434a5d48ee9 (patch) | |
tree | a879f3ea31083496d0efe491bc187b6e0ebada39 /init | |
parent | dd2ac3de625e6c0328a0f70530d8ade0d2151bfc (diff) | |
parent | 536dea9d61a032e64bbe584a97463c6638ead009 (diff) | |
download | system_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.mk | 4 | ||||
-rw-r--r-- | init/builtins.c | 52 | ||||
-rw-r--r-- | init/init.c | 85 | ||||
-rw-r--r-- | init/init_parser.c | 3 | ||||
-rw-r--r-- | init/keywords.h | 4 | ||||
-rw-r--r--[-rwxr-xr-x] | init/property_service.c | 42 |
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) { |