Loading init/init.cpp +31 −57 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <base/file.h> #include <base/stringprintf.h> #include <base/strings.h> #include <cutils/android_reboot.h> #include <cutils/fs.h> #include <cutils/iosched_policy.h> Loading Loading @@ -205,16 +206,15 @@ void service_start(struct service *svc, const char *dynamic_args) return; } struct stat s; if (stat(svc->args[0], &s) != 0) { ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name); struct stat sb; if (stat(svc->args[0], &sb) == -1) { ERROR("cannot find '%s' (%s), disabling '%s'\n", svc->args[0], strerror(errno), svc->name); svc->flags |= SVC_DISABLED; return; } if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) { ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]); ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]); svc->flags |= SVC_DISABLED; return; } Loading Loading @@ -746,36 +746,20 @@ static int console_init_action(int nargs, char **args) return 0; } static void import_kernel_nv(char *name, bool for_emulator) { char *value = strchr(name, '='); int name_len = strlen(name); if (value == 0) return; *value++ = 0; if (name_len == 0) return; static void import_kernel_nv(const std::string& key, const std::string& value, bool for_emulator) { if (key.empty()) return; if (for_emulator) { /* in the emulator, export any kernel option with the * ro.kernel. prefix */ char buff[PROP_NAME_MAX]; int len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name ); if (len < (int)sizeof(buff)) property_set( buff, value ); // In the emulator, export any kernel option with the "ro.kernel." prefix. property_set(android::base::StringPrintf("ro.kernel.%s", key.c_str()).c_str(), value.c_str()); return; } if (!strcmp(name,"qemu")) { strlcpy(qemu, value, sizeof(qemu)); } else if (!strncmp(name, "androidboot.", 12) && name_len > 12) { const char *boot_prop_name = name + 12; char prop[PROP_NAME_MAX]; int cnt; cnt = snprintf(prop, sizeof(prop), "ro.boot.%s", boot_prop_name); if (cnt < PROP_NAME_MAX) property_set(prop, value); if (key == "qemu") { strlcpy(qemu, value.c_str(), sizeof(qemu)); } else if (android::base::StartsWith(key, "androidboot.")) { property_set(android::base::StringPrintf("ro.boot.%s", key.c_str() + 12).c_str(), value.c_str()); } } Loading @@ -799,8 +783,7 @@ static void export_kernel_boot_props() { } } static void process_kernel_dt(void) { static void process_kernel_dt() { static const char android_dir[] = "/proc/device-tree/firmware/android"; std::string file_name = android::base::StringPrintf("%s/compatible", android_dir); Loading @@ -813,13 +796,13 @@ static void process_kernel_dt(void) } std::unique_ptr<DIR, int(*)(DIR*)>dir(opendir(android_dir), closedir); if (!dir) return; if (!dir) return; struct dirent *dp; while ((dp = readdir(dir.get())) != NULL) { if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible")) if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible")) { continue; } file_name = android::base::StringPrintf("%s/%s", android_dir, dp->d_name); Loading @@ -831,18 +814,15 @@ static void process_kernel_dt(void) } } static void process_kernel_cmdline(void) { /* don't expose the raw commandline to nonpriv processes */ static void process_kernel_cmdline() { // Don't expose the raw commandline to unprivileged processes. chmod("/proc/cmdline", 0440); /* first pass does the common stuff, and finds if we are in qemu. * second pass is only necessary for qemu to export all kernel params * as props. */ // The first pass does the common stuff, and finds if we are in qemu. // The second pass is only necessary for qemu to export all kernel params // as properties. import_kernel_cmdline(false, import_kernel_nv); if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv); if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv); } static int queue_property_triggers_action(int nargs, char **args) Loading @@ -865,17 +845,11 @@ enum selinux_enforcing_status { SELINUX_PERMISSIVE, SELINUX_ENFORCING }; static selinux_enforcing_status selinux_status_from_cmdline() { selinux_enforcing_status status = SELINUX_ENFORCING; std::function<void(char*,bool)> fn = [&](char* name, bool in_qemu) { char *value = strchr(name, '='); if (value == nullptr) { return; } *value++ = '\0'; if (strcmp(name, "androidboot.selinux") == 0) { if (strcmp(value, "permissive") == 0) { import_kernel_cmdline(false, [&](const std::string& key, const std::string& value, bool in_qemu) { if (key == "androidboot.selinux" && value == "permissive") { status = SELINUX_PERMISSIVE; } } }; import_kernel_cmdline(false, fn); }); return status; } Loading Loading @@ -989,7 +963,7 @@ int main(int argc, char** argv) { klog_init(); klog_set_level(KLOG_NOTICE_LEVEL); NOTICE("init%s started!\n", is_first_stage ? "" : " second stage"); NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage"); if (!is_first_stage) { // Indicate that booting is in progress to background fw loaders, etc. Loading @@ -1002,7 +976,7 @@ int main(int argc, char** argv) { process_kernel_dt(); process_kernel_cmdline(); // Propogate the kernel variables to internal variables // Propagate the kernel variables to internal variables // used by init as well as the current required properties. export_kernel_boot_props(); } Loading @@ -1028,7 +1002,7 @@ int main(int argc, char** argv) { // 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. INFO("Running restorecon...\n"); NOTICE("Running restorecon...\n"); restorecon("/dev"); restorecon("/dev/socket"); restorecon("/dev/__properties__"); Loading init/init_parser.cpp +8 −10 Original line number Diff line number Diff line Loading @@ -427,28 +427,26 @@ static void parse_config(const char *fn, const std::string& data) parser_done: list_for_each(node, &import_list) { struct import* import = node_to_item(node, struct import, list); int ret; ret = init_parse_config_file(import->filename); if (ret) ERROR("could not import file '%s' from '%s'\n", import->filename, fn); if (!init_parse_config_file(import->filename)) { ERROR("could not import file '%s' from '%s': %s\n", import->filename, fn, strerror(errno)); } } } int init_parse_config_file(const char* path) { bool init_parse_config_file(const char* path) { INFO("Parsing %s...\n", path); Timer t; std::string data; if (!read_file(path, &data)) { return -1; return false; } parse_config(path, data); dump_parser_state(); NOTICE("(Parsing %s took %.2fs.)\n", path, t.duration()); return 0; return true; } static int valid_name(const char *name) Loading init/init_parser.h +1 −1 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ void queue_property_triggers(const char *name, const char *value); void queue_all_property_triggers(); void queue_builtin_action(int (*func)(int nargs, char **args), const char *name); int init_parse_config_file(const char *fn); bool init_parse_config_file(const char* path); int expand_props(char *dst, const char *src, int len); service* make_exec_oneshot_service(int argc, char** argv); Loading init/log.cpp +17 −12 Original line number Diff line number Diff line Loading @@ -14,30 +14,35 @@ * limitations under the License. */ #include "log.h" #include <stdlib.h> #include <string.h> #include <sys/uio.h> #include <selinux/selinux.h> #include "log.h" #include <base/stringprintf.h> static void init_klog_vwrite(int level, const char* fmt, va_list ap) { static const char* tag = basename(getprogname()); char prefix[64]; snprintf(prefix, sizeof(prefix), "<%d>%s: ", level, tag); char msg[512]; vsnprintf(msg, sizeof(msg), fmt, ap); // The kernel's printk buffer is only 1024 bytes. // TODO: should we automatically break up long lines into multiple lines? // Or we could log but with something like "..." at the end? char buf[1024]; size_t prefix_size = snprintf(buf, sizeof(buf), "<%d>%s: ", level, tag); size_t msg_size = vsnprintf(buf + prefix_size, sizeof(buf) - prefix_size, fmt, ap); if (msg_size >= sizeof(buf) - prefix_size) { msg_size = snprintf(buf + prefix_size, sizeof(buf) - prefix_size, "(%zu-byte message too long for printk)\n", msg_size); } iovec iov[2]; iov[0].iov_base = prefix; iov[0].iov_len = strlen(prefix); iov[1].iov_base = msg; iov[1].iov_len = strlen(msg); iovec iov[1]; iov[0].iov_base = buf; iov[0].iov_len = prefix_size + msg_size; klog_writev(level, iov, 2); klog_writev(level, iov, 1); } void init_klog_write(int level, const char* fmt, ...) { Loading init/util.cpp +10 −25 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <sys/un.h> #include <base/file.h> #include <base/strings.h> /* for ANDROID_SOCKET_* */ #include <cutils/sockets.h> Loading Loading @@ -403,32 +404,16 @@ void open_devnull_stdio(void) } } void import_kernel_cmdline(bool in_qemu, std::function<void(char*,bool)> import_kernel_nv) { char cmdline[2048]; char *ptr; int fd; fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC); if (fd >= 0) { int n = read(fd, cmdline, sizeof(cmdline) - 1); if (n < 0) n = 0; /* get rid of trailing newline, it happens */ if (n > 0 && cmdline[n-1] == '\n') n--; void import_kernel_cmdline(bool in_qemu, std::function<void(const std::string&, const std::string&, bool)> fn) { std::string cmdline; android::base::ReadFileToString("/proc/cmdline", &cmdline); cmdline[n] = 0; close(fd); } else { cmdline[0] = 0; for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { std::vector<std::string> pieces = android::base::Split(entry, "="); if (pieces.size() == 2) { fn(pieces[0], pieces[1], in_qemu); } ptr = cmdline; while (ptr && *ptr) { char *x = strchr(ptr, ' '); if (x != 0) *x++ = 0; import_kernel_nv(ptr, in_qemu); ptr = x; } } Loading Loading
init/init.cpp +31 −57 Original line number Diff line number Diff line Loading @@ -43,6 +43,7 @@ #include <base/file.h> #include <base/stringprintf.h> #include <base/strings.h> #include <cutils/android_reboot.h> #include <cutils/fs.h> #include <cutils/iosched_policy.h> Loading Loading @@ -205,16 +206,15 @@ void service_start(struct service *svc, const char *dynamic_args) return; } struct stat s; if (stat(svc->args[0], &s) != 0) { ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name); struct stat sb; if (stat(svc->args[0], &sb) == -1) { ERROR("cannot find '%s' (%s), disabling '%s'\n", svc->args[0], strerror(errno), svc->name); svc->flags |= SVC_DISABLED; return; } if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) { ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]); ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]); svc->flags |= SVC_DISABLED; return; } Loading Loading @@ -746,36 +746,20 @@ static int console_init_action(int nargs, char **args) return 0; } static void import_kernel_nv(char *name, bool for_emulator) { char *value = strchr(name, '='); int name_len = strlen(name); if (value == 0) return; *value++ = 0; if (name_len == 0) return; static void import_kernel_nv(const std::string& key, const std::string& value, bool for_emulator) { if (key.empty()) return; if (for_emulator) { /* in the emulator, export any kernel option with the * ro.kernel. prefix */ char buff[PROP_NAME_MAX]; int len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name ); if (len < (int)sizeof(buff)) property_set( buff, value ); // In the emulator, export any kernel option with the "ro.kernel." prefix. property_set(android::base::StringPrintf("ro.kernel.%s", key.c_str()).c_str(), value.c_str()); return; } if (!strcmp(name,"qemu")) { strlcpy(qemu, value, sizeof(qemu)); } else if (!strncmp(name, "androidboot.", 12) && name_len > 12) { const char *boot_prop_name = name + 12; char prop[PROP_NAME_MAX]; int cnt; cnt = snprintf(prop, sizeof(prop), "ro.boot.%s", boot_prop_name); if (cnt < PROP_NAME_MAX) property_set(prop, value); if (key == "qemu") { strlcpy(qemu, value.c_str(), sizeof(qemu)); } else if (android::base::StartsWith(key, "androidboot.")) { property_set(android::base::StringPrintf("ro.boot.%s", key.c_str() + 12).c_str(), value.c_str()); } } Loading @@ -799,8 +783,7 @@ static void export_kernel_boot_props() { } } static void process_kernel_dt(void) { static void process_kernel_dt() { static const char android_dir[] = "/proc/device-tree/firmware/android"; std::string file_name = android::base::StringPrintf("%s/compatible", android_dir); Loading @@ -813,13 +796,13 @@ static void process_kernel_dt(void) } std::unique_ptr<DIR, int(*)(DIR*)>dir(opendir(android_dir), closedir); if (!dir) return; if (!dir) return; struct dirent *dp; while ((dp = readdir(dir.get())) != NULL) { if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible")) if (dp->d_type != DT_REG || !strcmp(dp->d_name, "compatible")) { continue; } file_name = android::base::StringPrintf("%s/%s", android_dir, dp->d_name); Loading @@ -831,18 +814,15 @@ static void process_kernel_dt(void) } } static void process_kernel_cmdline(void) { /* don't expose the raw commandline to nonpriv processes */ static void process_kernel_cmdline() { // Don't expose the raw commandline to unprivileged processes. chmod("/proc/cmdline", 0440); /* first pass does the common stuff, and finds if we are in qemu. * second pass is only necessary for qemu to export all kernel params * as props. */ // The first pass does the common stuff, and finds if we are in qemu. // The second pass is only necessary for qemu to export all kernel params // as properties. import_kernel_cmdline(false, import_kernel_nv); if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv); if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv); } static int queue_property_triggers_action(int nargs, char **args) Loading @@ -865,17 +845,11 @@ enum selinux_enforcing_status { SELINUX_PERMISSIVE, SELINUX_ENFORCING }; static selinux_enforcing_status selinux_status_from_cmdline() { selinux_enforcing_status status = SELINUX_ENFORCING; std::function<void(char*,bool)> fn = [&](char* name, bool in_qemu) { char *value = strchr(name, '='); if (value == nullptr) { return; } *value++ = '\0'; if (strcmp(name, "androidboot.selinux") == 0) { if (strcmp(value, "permissive") == 0) { import_kernel_cmdline(false, [&](const std::string& key, const std::string& value, bool in_qemu) { if (key == "androidboot.selinux" && value == "permissive") { status = SELINUX_PERMISSIVE; } } }; import_kernel_cmdline(false, fn); }); return status; } Loading Loading @@ -989,7 +963,7 @@ int main(int argc, char** argv) { klog_init(); klog_set_level(KLOG_NOTICE_LEVEL); NOTICE("init%s started!\n", is_first_stage ? "" : " second stage"); NOTICE("init %s started!\n", is_first_stage ? "first stage" : "second stage"); if (!is_first_stage) { // Indicate that booting is in progress to background fw loaders, etc. Loading @@ -1002,7 +976,7 @@ int main(int argc, char** argv) { process_kernel_dt(); process_kernel_cmdline(); // Propogate the kernel variables to internal variables // Propagate the kernel variables to internal variables // used by init as well as the current required properties. export_kernel_boot_props(); } Loading @@ -1028,7 +1002,7 @@ int main(int argc, char** argv) { // 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. INFO("Running restorecon...\n"); NOTICE("Running restorecon...\n"); restorecon("/dev"); restorecon("/dev/socket"); restorecon("/dev/__properties__"); Loading
init/init_parser.cpp +8 −10 Original line number Diff line number Diff line Loading @@ -427,28 +427,26 @@ static void parse_config(const char *fn, const std::string& data) parser_done: list_for_each(node, &import_list) { struct import* import = node_to_item(node, struct import, list); int ret; ret = init_parse_config_file(import->filename); if (ret) ERROR("could not import file '%s' from '%s'\n", import->filename, fn); if (!init_parse_config_file(import->filename)) { ERROR("could not import file '%s' from '%s': %s\n", import->filename, fn, strerror(errno)); } } } int init_parse_config_file(const char* path) { bool init_parse_config_file(const char* path) { INFO("Parsing %s...\n", path); Timer t; std::string data; if (!read_file(path, &data)) { return -1; return false; } parse_config(path, data); dump_parser_state(); NOTICE("(Parsing %s took %.2fs.)\n", path, t.duration()); return 0; return true; } static int valid_name(const char *name) Loading
init/init_parser.h +1 −1 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ void queue_property_triggers(const char *name, const char *value); void queue_all_property_triggers(); void queue_builtin_action(int (*func)(int nargs, char **args), const char *name); int init_parse_config_file(const char *fn); bool init_parse_config_file(const char* path); int expand_props(char *dst, const char *src, int len); service* make_exec_oneshot_service(int argc, char** argv); Loading
init/log.cpp +17 −12 Original line number Diff line number Diff line Loading @@ -14,30 +14,35 @@ * limitations under the License. */ #include "log.h" #include <stdlib.h> #include <string.h> #include <sys/uio.h> #include <selinux/selinux.h> #include "log.h" #include <base/stringprintf.h> static void init_klog_vwrite(int level, const char* fmt, va_list ap) { static const char* tag = basename(getprogname()); char prefix[64]; snprintf(prefix, sizeof(prefix), "<%d>%s: ", level, tag); char msg[512]; vsnprintf(msg, sizeof(msg), fmt, ap); // The kernel's printk buffer is only 1024 bytes. // TODO: should we automatically break up long lines into multiple lines? // Or we could log but with something like "..." at the end? char buf[1024]; size_t prefix_size = snprintf(buf, sizeof(buf), "<%d>%s: ", level, tag); size_t msg_size = vsnprintf(buf + prefix_size, sizeof(buf) - prefix_size, fmt, ap); if (msg_size >= sizeof(buf) - prefix_size) { msg_size = snprintf(buf + prefix_size, sizeof(buf) - prefix_size, "(%zu-byte message too long for printk)\n", msg_size); } iovec iov[2]; iov[0].iov_base = prefix; iov[0].iov_len = strlen(prefix); iov[1].iov_base = msg; iov[1].iov_len = strlen(msg); iovec iov[1]; iov[0].iov_base = buf; iov[0].iov_len = prefix_size + msg_size; klog_writev(level, iov, 2); klog_writev(level, iov, 1); } void init_klog_write(int level, const char* fmt, ...) { Loading
init/util.cpp +10 −25 Original line number Diff line number Diff line Loading @@ -33,6 +33,7 @@ #include <sys/un.h> #include <base/file.h> #include <base/strings.h> /* for ANDROID_SOCKET_* */ #include <cutils/sockets.h> Loading Loading @@ -403,32 +404,16 @@ void open_devnull_stdio(void) } } void import_kernel_cmdline(bool in_qemu, std::function<void(char*,bool)> import_kernel_nv) { char cmdline[2048]; char *ptr; int fd; fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC); if (fd >= 0) { int n = read(fd, cmdline, sizeof(cmdline) - 1); if (n < 0) n = 0; /* get rid of trailing newline, it happens */ if (n > 0 && cmdline[n-1] == '\n') n--; void import_kernel_cmdline(bool in_qemu, std::function<void(const std::string&, const std::string&, bool)> fn) { std::string cmdline; android::base::ReadFileToString("/proc/cmdline", &cmdline); cmdline[n] = 0; close(fd); } else { cmdline[0] = 0; for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { std::vector<std::string> pieces = android::base::Split(entry, "="); if (pieces.size() == 2) { fn(pieces[0], pieces[1], in_qemu); } ptr = cmdline; while (ptr && *ptr) { char *x = strchr(ptr, ' '); if (x != 0) *x++ = 0; import_kernel_nv(ptr, in_qemu); ptr = x; } } Loading