Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 55c2e1f4 authored by Elliott Hughes's avatar Elliott Hughes Committed by Gerrit Code Review
Browse files

Merge "Clean up init /proc/cmdline handling."

parents 0e278e2e e5ce30fe
Loading
Loading
Loading
Loading
+31 −57
Original line number Diff line number Diff line
@@ -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>
@@ -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;
    }
@@ -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());
    }
}

@@ -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);
@@ -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);

@@ -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)
@@ -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;
}
@@ -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.
@@ -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();
    }
@@ -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__");
+8 −10
Original line number Diff line number Diff line
@@ -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)
+1 −1
Original line number Diff line number Diff line
@@ -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);
+17 −12
Original line number Diff line number Diff line
@@ -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, ...) {
+10 −25
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@
#include <sys/un.h>

#include <base/file.h>
#include <base/strings.h>

/* for ANDROID_SOCKET_* */
#include <cutils/sockets.h>
@@ -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