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

Commit 9590e5ea authored by Felipe Leme's avatar Felipe Leme Committed by android-build-merger
Browse files

Merge "Don\'t use su to when calling am or dumpsys." into nyc-dev

am: 7363bafd

* commit '7363bafd':
  Don't use su to when calling am or dumpsys.
parents 3ff5cc8b 7363bafd
Loading
Loading
Loading
Loading
+3 −47
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@
#include <stdlib.h>
#include <string>
#include <string.h>
#include <sys/capability.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/stat.h>
@@ -1004,49 +1003,6 @@ static std::string SHA256_file_hash(std::string filepath) {
    return std::string(hash_buffer);
}

/* switch to non-root user and group */
bool drop_root() {
    /* ensure we will keep capabilities when we drop root */
    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
        MYLOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
        return false;
    }

    gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
            AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC };
    if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
        MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
        return false;
    }
    if (setgid(AID_SHELL) != 0) {
        MYLOGE("Unable to setgid, aborting: %s\n", strerror(errno));
        return false;
    }
    if (setuid(AID_SHELL) != 0) {
        MYLOGE("Unable to setuid, aborting: %s\n", strerror(errno));
        return false;
    }

    struct __user_cap_header_struct capheader;
    struct __user_cap_data_struct capdata[2];
    memset(&capheader, 0, sizeof(capheader));
    memset(&capdata, 0, sizeof(capdata));
    capheader.version = _LINUX_CAPABILITY_VERSION_3;
    capheader.pid = 0;

    capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
    capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
    capdata[0].inheritable = 0;
    capdata[1].inheritable = 0;

    if (capset(&capheader, &capdata[0]) < 0) {
        MYLOGE("capset failed: %s\n", strerror(errno));
        return false;
    }

    return true;
}

int main(int argc, char *argv[]) {
    struct sigaction sigact;
    int do_add_date = 0;
@@ -1294,8 +1250,8 @@ int main(int argc, char *argv[]) {

    // Invoking the following dumpsys calls before dump_traces() to try and
    // keep the system stats as close to its initial state as possible.
    run_command("DUMPSYS MEMINFO", 30, SU_PATH, "shell", "dumpsys", "meminfo", "-a", NULL);
    run_command("DUMPSYS CPUINFO", 30, SU_PATH, "shell", "dumpsys", "cpuinfo", "-a", NULL);
    run_command_as_shell("DUMPSYS MEMINFO", 30, "dumpsys", "meminfo", "-a", NULL);
    run_command_as_shell("DUMPSYS CPUINFO", 30, "dumpsys", "cpuinfo", "-a", NULL);


    /* collect stack traces from Dalvik and native processes (needs root) */
@@ -1306,7 +1262,7 @@ int main(int argc, char *argv[]) {
    add_dir(RECOVERY_DIR, true);
    add_mountinfo();

    if (!drop_root()) {
    if (!drop_root_user()) {
        return -1;
    }

+8 −1
Original line number Diff line number Diff line
@@ -103,13 +103,20 @@ int dump_files(const char *title, const char *dir,
        bool (*skip)(const char *path),
        int (*dump_from_fd)(const char *title, const char *path, int fd));

// TODO: need to refactor all those run_command variations; there shold be just one, receiving an
// optional CommandOptions objects with values such as run_always, drop_root, etc...

/* forks a command and waits for it to finish -- terminate args with NULL */
int run_command_as_shell(const char *title, int timeout_seconds, const char *command, ...);
int run_command(const char *title, int timeout_seconds, const char *command, ...);

/* forks a command and waits for it to finish
   first element of args is the command, and last must be NULL.
   command is always ran, even when _DUMPSTATE_DRY_RUN_ is defined. */
int run_command_always(const char *title, int timeout_seconds, const char *args[]);
int run_command_always(const char *title, bool drop_root, int timeout_seconds, const char *args[]);

/* switch to non-root user and group */
bool drop_root_user();

/* sends a broadcast using Activity Manager */
void send_broadcast(const std::string& action, const std::vector<std::string>& args);
+93 −7
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <string>
#include <string.h>
#include <sys/capability.h>
#include <sys/inotify.h>
#include <sys/stat.h>
#include <sys/sysconf.h>
@@ -662,13 +663,48 @@ int run_command(const char *title, int timeout_seconds, const char *command, ...

    ON_DRY_RUN({ update_progress(timeout_seconds); va_end(ap); return 0; });

    int status = run_command_always(title, timeout_seconds, args);
    int status = run_command_always(title, false, timeout_seconds, args);
    va_end(ap);
    return status;
}

int run_command_as_shell(const char *title, int timeout_seconds, const char *command, ...) {
    DurationReporter duration_reporter(title);
    fflush(stdout);

    const char *args[1024] = {command};
    size_t arg;
    va_list ap;
    va_start(ap, command);
    if (title) printf("------ %s (%s", title, command);
    bool null_terminated = false;
    for (arg = 1; arg < sizeof(args) / sizeof(args[0]); ++arg) {
        args[arg] = va_arg(ap, const char *);
        if (args[arg] == nullptr) {
            null_terminated = true;
            break;
        }
        if (title) printf(" %s", args[arg]);
    }
    if (title) printf(") ------\n");
    fflush(stdout);
    if (!null_terminated) {
        // Fail now, otherwise execvp() call on run_command_always() might hang.
        std::string cmd;
        format_args(command, args, &cmd);
        MYLOGE("skipping command %s because its args were not NULL-terminated", cmd.c_str());
        return -1;
    }

    ON_DRY_RUN({ update_progress(timeout_seconds); va_end(ap); return 0; });

    int status = run_command_always(title, true, timeout_seconds, args);
    va_end(ap);
    return status;
}

/* forks a command and waits for it to finish */
int run_command_always(const char *title, int timeout_seconds, const char *args[]) {
int run_command_always(const char *title, bool drop_root, int timeout_seconds, const char *args[]) {
    /* TODO: for now we're simplifying the progress calculation by using the timeout as the weight.
     * It's a good approximation for most cases, except when calling dumpsys, where its weight
     * should be much higher proportionally to its timeout. */
@@ -686,6 +722,10 @@ int run_command_always(const char *title, int timeout_seconds, const char *args[

    /* handle child case */
    if (pid == 0) {
        if (drop_root && !drop_root_user()) {
            printf("*** could not drop root before running %s: %s\n", command, strerror(errno));
            _exit(-1);
        }

        /* make sure the child dies when dumpstate dies */
        prctl(PR_SET_PDEATHSIG, SIGKILL);
@@ -747,14 +787,60 @@ int run_command_always(const char *title, int timeout_seconds, const char *args[
    return status;
}

bool drop_root_user() {
    if (getgid() == AID_SHELL && getuid() == AID_SHELL) {
        MYLOGD("drop_root_user(): already running as Shell");
        return true;
    }
    /* ensure we will keep capabilities when we drop root */
    if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
        MYLOGE("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
        return false;
    }

    gid_t groups[] = { AID_LOG, AID_SDCARD_R, AID_SDCARD_RW,
            AID_MOUNT, AID_INET, AID_NET_BW_STATS, AID_READPROC };
    if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
        MYLOGE("Unable to setgroups, aborting: %s\n", strerror(errno));
        return false;
    }
    if (setgid(AID_SHELL) != 0) {
        MYLOGE("Unable to setgid, aborting: %s\n", strerror(errno));
        return false;
    }
    if (setuid(AID_SHELL) != 0) {
        MYLOGE("Unable to setuid, aborting: %s\n", strerror(errno));
        return false;
    }

    struct __user_cap_header_struct capheader;
    struct __user_cap_data_struct capdata[2];
    memset(&capheader, 0, sizeof(capheader));
    memset(&capdata, 0, sizeof(capdata));
    capheader.version = _LINUX_CAPABILITY_VERSION_3;
    capheader.pid = 0;

    capdata[CAP_TO_INDEX(CAP_SYSLOG)].permitted = CAP_TO_MASK(CAP_SYSLOG);
    capdata[CAP_TO_INDEX(CAP_SYSLOG)].effective = CAP_TO_MASK(CAP_SYSLOG);
    capdata[0].inheritable = 0;
    capdata[1].inheritable = 0;

    if (capset(&capheader, &capdata[0]) < 0) {
        MYLOGE("capset failed: %s\n", strerror(errno));
        return false;
    }

    return true;
}

void send_broadcast(const std::string& action, const std::vector<std::string>& args) {
    if (args.size() > 1000) {
        MYLOGE("send_broadcast: too many arguments (%d)\n", (int) args.size());
        return;
    }
    const char *am_args[1024] = { SU_PATH, "shell", "/system/bin/am", "broadcast",
                                  "--user", "0", "-a", action.c_str() };
    size_t am_index = 7; // Starts at the index of last initial value above.
    const char *am_args[1024] = { "/system/bin/am", "broadcast", "--user", "0", "-a",
                                  action.c_str() };
    size_t am_index = 5; // Starts at the index of last initial value above.
    for (const std::string& arg : args) {
        am_args[++am_index] = arg.c_str();
    }
@@ -763,7 +849,7 @@ void send_broadcast(const std::string& action, const std::vector<std::string>& a
    std::string args_string;
    format_args(am_index + 1, am_args, &args_string);
    MYLOGD("send_broadcast command: %s\n", args_string.c_str());
    run_command_always(NULL, 5, am_args);
    run_command_always(NULL, 5, true, am_args);
}

size_t num_props = 0;
@@ -1102,7 +1188,7 @@ void update_progress(int delta) {

void take_screenshot(const std::string& path) {
    const char *args[] = { "/system/bin/screencap", "-p", path.c_str(), NULL };
    run_command_always(NULL, 10, args);
    run_command_always(NULL, false, 10, args);
}

void vibrate(FILE* vibrator, int ms) {