Exemple #1
0
static bool read_package_list(struct fuse_global* global) {
    pthread_mutex_lock(&global->lock);

    global->package_to_appid->clear();
    bool rc = packagelist_parse(package_parse_callback, global);
    DLOG(INFO) << "read_package_list: found " << global->package_to_appid->size() << " packages";

    // Regenerate ownership details using newly loaded mapping.
    derive_permissions_recursive_locked(global->fuse_default, &global->root);

    pthread_mutex_unlock(&global->lock);

    return rc;
}
static void *reinit_thread_start(void * /*obj*/) {
    prctl(PR_SET_NAME, "logd.daemon");
    set_sched_policy(0, SP_BACKGROUND);
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND);

    setgid(AID_SYSTEM);
    setuid(AID_SYSTEM);

    while (reinit_running && !sem_wait(&reinit) && reinit_running) {

        // uidToName Privileged Worker
        if (uid) {
            name = NULL;

            packagelist_parse(package_list_parser_cb, NULL);

            uid = 0;
            sem_post(&uidName);
            continue;
        }

        if (fdDmesg >= 0) {
            static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO),
                'l', 'o', 'g', 'd', '.', 'd', 'a', 'e', 'm', 'o', 'n', ':',
                ' ', 'r', 'e', 'i', 'n', 'i', 't', '\n' };
            write(fdDmesg, reinit_message, sizeof(reinit_message));
        }

        // Anything that reads persist.<property>
        if (logBuf) {
            logBuf->init();
            logBuf->initPrune(NULL);
        }

        if (logAudit) {
            logAudit->allowSafeMode();
        }
    }

    return NULL;
}
Exemple #3
0
static void* reinit_thread_start(void* /*obj*/) {
    prctl(PR_SET_NAME, "logd.daemon");
    set_sched_policy(0, SP_BACKGROUND);
    setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_BACKGROUND);

    // We should drop to AID_LOGD, if we are anything else, we have
    // even lesser privileges and accept our fate.
    gid_t groups[] = {
        AID_SYSTEM,        // search access to /data/system path
        AID_PACKAGE_INFO,  // readonly access to /data/system/packages.list
    };
    if (setgroups(arraysize(groups), groups) == -1) {
        android::prdebug(
            "logd.daemon: failed to set AID_SYSTEM AID_PACKAGE_INFO groups");
    }
    if (setgid(AID_LOGD) != 0) {
        android::prdebug("logd.daemon: failed to set AID_LOGD gid");
    }
    if (setuid(AID_LOGD) != 0) {
        android::prdebug("logd.daemon: failed to set AID_LOGD uid");
    }

    cap_t caps = cap_init();
    (void)cap_clear(caps);
    (void)cap_set_proc(caps);
    (void)cap_free(caps);

    while (reinit_running && !sem_wait(&reinit) && reinit_running) {
        // uidToName Privileged Worker
        if (uid) {
            name = nullptr;

            // if we got the perms wrong above, this would spam if we reported
            // problems with acquisition of an uid name from the packages.
            (void)packagelist_parse(package_list_parser_cb, nullptr);

            uid = 0;
            sem_post(&uidName);
            continue;
        }

        if (fdDmesg >= 0) {
            static const char reinit_message[] = { KMSG_PRIORITY(LOG_INFO),
                                                   'l',
                                                   'o',
                                                   'g',
                                                   'd',
                                                   '.',
                                                   'd',
                                                   'a',
                                                   'e',
                                                   'm',
                                                   'o',
                                                   'n',
                                                   ':',
                                                   ' ',
                                                   'r',
                                                   'e',
                                                   'i',
                                                   'n',
                                                   'i',
                                                   't',
                                                   '\n' };
            write(fdDmesg, reinit_message, sizeof(reinit_message));
        }

        // Anything that reads persist.<property>
        if (logBuf) {
            logBuf->init();
            logBuf->initPrune(nullptr);
        }
        android::ReReadEventLogTags();
    }

    return nullptr;
}
int main(int argc, char* argv[]) {
  // Check arguments.
  if (argc < 2) {
    error(1, 0, "usage: run-as <package-name> [--user <uid>] <command> [<args>]\n");
  }

  // This program runs with CAP_SETUID and CAP_SETGID capabilities on Android
  // production devices. Check user id of caller --- must be 'shell' or 'root'.
  if (getuid() != AID_SHELL && getuid() != AID_ROOT) {
    error(1, 0, "only 'shell' or 'root' users can run this program");
  }

  __user_cap_header_struct capheader;
  __user_cap_data_struct capdata[2];
  memset(&capheader, 0, sizeof(capheader));
  memset(&capdata, 0, sizeof(capdata));
  capheader.version = _LINUX_CAPABILITY_VERSION_3;
  capdata[CAP_TO_INDEX(CAP_SETUID)].effective |= CAP_TO_MASK(CAP_SETUID);
  capdata[CAP_TO_INDEX(CAP_SETGID)].effective |= CAP_TO_MASK(CAP_SETGID);
  capdata[CAP_TO_INDEX(CAP_SETUID)].permitted |= CAP_TO_MASK(CAP_SETUID);
  capdata[CAP_TO_INDEX(CAP_SETGID)].permitted |= CAP_TO_MASK(CAP_SETGID);
  if (capset(&capheader, &capdata[0]) == -1) {
    error(1, errno, "couldn't set capabilities");
  }

  char* pkgname = argv[1];
  int cmd_argv_offset = 2;

  // Get user_id from command line if provided.
  int userId = 0;
  if ((argc >= 4) && !strcmp(argv[2], "--user")) {
    userId = atoi(argv[3]);
    if (userId < 0) error(1, 0, "negative user id: %d", userId);
    cmd_argv_offset += 2;
  }

  // Retrieve package information from system, switching egid so we can read the file.
  gid_t old_egid = getegid();
  if (setegid(AID_PACKAGE_INFO) == -1) error(1, errno, "setegid(AID_PACKAGE_INFO) failed");
  pkg_info info;
  memset(&info, 0, sizeof(info));
  info.name = pkgname;
  if (!packagelist_parse(packagelist_parse_callback, &info)) {
    error(1, errno, "packagelist_parse failed");
  }
  if (info.uid == 0) {
    error(1, 0, "unknown package: %s", pkgname);
  }
  if (setegid(old_egid) == -1) error(1, errno, "couldn't restore egid");

  // Verify that user id is not too big.
  if ((UID_MAX - info.uid) / AID_USER < (uid_t)userId) {
    error(1, 0, "user id too big: %d", userId);
  }

  // Calculate user app ID.
  uid_t userAppId = (AID_USER * userId) + info.uid;

  // Reject system packages.
  if (userAppId < AID_APP) {
    error(1, 0, "package not an application: %s", pkgname);
  }

  // Reject any non-debuggable package.
  if (!info.debuggable) {
    error(1, 0, "package not debuggable: %s", pkgname);
  }

  // Check that the data directory path is valid.
  if (!check_data_path(info.data_dir, userAppId)) {
    error(1, 0, "package has corrupt installation: %s", pkgname);
  }

  // Ensure that we change all real/effective/saved IDs at the
  // same time to avoid nasty surprises.
  uid_t uid = userAppId;
  uid_t gid = userAppId;
  if (setresgid(gid, gid, gid) == -1) {
    error(1, errno, "setresgid failed");
  }
  if (setresuid(uid, uid, uid) == -1) {
    error(1, errno, "setresuid failed");
  }

  // Required if caller has uid and gid all non-zero.
  memset(&capdata, 0, sizeof(capdata));
  if (capset(&capheader, &capdata[0]) == -1) {
    error(1, errno, "couldn't clear all capabilities");
  }

  if (selinux_android_setcontext(uid, 0, info.seinfo, pkgname) < 0) {
    error(1, errno, "couldn't set SELinux security context");
  }

  // cd into the data directory, and set $HOME correspondingly.
  if (TEMP_FAILURE_RETRY(chdir(info.data_dir)) == -1) {
    error(1, errno, "couldn't chdir to package's data directory");
  }
  setenv("HOME", info.data_dir, 1);

  // Reset parts of the environment, like su would.
  setenv("PATH", _PATH_DEFPATH, 1);
  unsetenv("IFS");

  // Set the user-specific parts for this user.
  passwd* pw = getpwuid(uid);
  setenv("LOGNAME", pw->pw_name, 1);
  setenv("SHELL", pw->pw_shell, 1);
  setenv("USER", pw->pw_name, 1);

  // User specified command for exec.
  if ((argc >= cmd_argv_offset + 1) &&
      (execvp(argv[cmd_argv_offset], argv+cmd_argv_offset) == -1)) {
    error(1, errno, "exec failed for %s", argv[cmd_argv_offset]);
  }

  // Default exec shell.
  execlp(_PATH_BSHELL, "sh", NULL);
  error(1, errno, "exec failed");
}
Exemple #5
0
int main(int argc, char* argv[]) {
  // Check arguments.
  if (argc < 2) {
    error(1, 0, "usage: run-as <package-name> [--user <uid>] <command> [<args>]\n");
  }

  // This program runs with CAP_SETUID and CAP_SETGID capabilities on Android
  // production devices. Check user id of caller --- must be 'shell' or 'root'.
  if (getuid() != AID_SHELL && getuid() != AID_ROOT) {
    error(1, 0, "only 'shell' or 'root' users can run this program");
  }

  // Some devices can disable running run-as, such as Chrome OS when running in
  // non-developer mode.
  if (android::base::GetBoolProperty("ro.boot.disable_runas", false)) {
    error(1, 0, "run-as is disabled from the kernel commandline");
  }

  char* pkgname = argv[1];
  int cmd_argv_offset = 2;

  // Get user_id from command line if provided.
  int userId = 0;
  if ((argc >= 4) && !strcmp(argv[2], "--user")) {
    userId = atoi(argv[3]);
    if (userId < 0) error(1, 0, "negative user id: %d", userId);
    cmd_argv_offset += 2;
  }

  // Retrieve package information from system, switching egid so we can read the file.
  gid_t old_egid = getegid();
  if (setegid(AID_PACKAGE_INFO) == -1) error(1, errno, "setegid(AID_PACKAGE_INFO) failed");
  pkg_info info;
  memset(&info, 0, sizeof(info));
  info.name = pkgname;
  if (!packagelist_parse(packagelist_parse_callback, &info)) {
    error(1, errno, "packagelist_parse failed");
  }

  // Handle a multi-user data path
  if (userId > 0) {
    free(info.data_dir);
    if (asprintf(&info.data_dir, "/data/user/%d/%s", userId, pkgname) == -1) {
      error(1, errno, "asprintf failed");
    }
  }

  if (info.uid == 0) {
    error(1, 0, "unknown package: %s", pkgname);
  }
  if (setegid(old_egid) == -1) error(1, errno, "couldn't restore egid");

  // Verify that user id is not too big.
  if ((UID_MAX - info.uid) / AID_USER_OFFSET < (uid_t)userId) {
    error(1, 0, "user id too big: %d", userId);
  }

  // Calculate user app ID.
  uid_t userAppId = (AID_USER_OFFSET * userId) + info.uid;

  // Reject system packages.
  if (userAppId < AID_APP) {
    error(1, 0, "package not an application: %s", pkgname);
  }

  // Reject any non-debuggable package.
  if (!info.debuggable) {
    error(1, 0, "package not debuggable: %s", pkgname);
  }

  // Check that the data directory path is valid.
  if (!check_data_path(info.data_dir, userAppId)) {
    error(1, 0, "package has corrupt installation: %s", pkgname);
  }

  // Ensure that we change all real/effective/saved IDs at the
  // same time to avoid nasty surprises.
  uid_t uid = userAppId;
  uid_t gid = userAppId;
  ScopedMinijail j(minijail_new());
  minijail_change_uid(j.get(), uid);
  minijail_change_gid(j.get(), gid);
  minijail_keep_supplementary_gids(j.get());
  minijail_enter(j.get());

  std::string seinfo = std::string(info.seinfo) + ":fromRunAs";
  if (selinux_android_setcontext(uid, 0, seinfo.c_str(), pkgname) < 0) {
    error(1, errno, "couldn't set SELinux security context");
  }

  // cd into the data directory, and set $HOME correspondingly.
  if (TEMP_FAILURE_RETRY(chdir(info.data_dir)) == -1) {
    error(1, errno, "couldn't chdir to package's data directory");
  }
  setenv("HOME", info.data_dir, 1);

  // Reset parts of the environment, like su would.
  setenv("PATH", _PATH_DEFPATH, 1);
  unsetenv("IFS");

  // Set the user-specific parts for this user.
  passwd* pw = getpwuid(uid);
  setenv("LOGNAME", pw->pw_name, 1);
  setenv("SHELL", pw->pw_shell, 1);
  setenv("USER", pw->pw_name, 1);

  // User specified command for exec.
  if ((argc >= cmd_argv_offset + 1) &&
      (execvp(argv[cmd_argv_offset], argv+cmd_argv_offset) == -1)) {
    error(1, errno, "exec failed for %s", argv[cmd_argv_offset]);
  }

  // Default exec shell.
  execlp(_PATH_BSHELL, "sh", NULL);
  error(1, errno, "exec failed");
}