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

Commit a7947755 authored by Bill Yi's avatar Bill Yi
Browse files

Merge remote-tracking branch 'goog/stage-aosp-master' into HEAD

parents 3a763771 422a5128
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@
#include <string>
#include <vector>

#include <android-base/parseint.h>
#include <android-base/strings.h>

#include "sysdeps.h"
@@ -144,11 +143,9 @@ class BugreportStandardStreamsCallback : public StandardStreamsCallbackInterface
            //
            size_t idx1 = line.rfind(BUGZ_PROGRESS_PREFIX) + strlen(BUGZ_PROGRESS_PREFIX);
            size_t idx2 = line.rfind(BUGZ_PROGRESS_SEPARATOR);
            int progress, total;
            if (android::base::ParseInt(line.substr(idx1, (idx2 - idx1)), &progress) &&
                android::base::ParseInt(line.substr(idx2 + 1), &total)) {
            int progress = std::stoi(line.substr(idx1, (idx2 - idx1)));
            int total = std::stoi(line.substr(idx2 + 1));
            br_->UpdateProgress(line_message_, progress, total);
            }
        } else {
            invalid_lines_.push_back(line);
        }
+62 −12
Original line number Diff line number Diff line
@@ -185,6 +185,16 @@ out:
   return allowed;
}

static bool pid_contains_tid(pid_t pid, pid_t tid) {
  char task_path[PATH_MAX];
  if (snprintf(task_path, PATH_MAX, "/proc/%d/task/%d", pid, tid) >= PATH_MAX) {
    ALOGE("debuggerd: task path overflow (pid = %d, tid = %d)\n", pid, tid);
    exit(1);
  }

  return access(task_path, F_OK) == 0;
}

static int read_request(int fd, debugger_request_t* out_request) {
  ucred cr;
  socklen_t len = sizeof(cr);
@@ -227,16 +237,13 @@ static int read_request(int fd, debugger_request_t* out_request) {

  if (msg.action == DEBUGGER_ACTION_CRASH) {
    // Ensure that the tid reported by the crashing process is valid.
    char buf[64];
    struct stat s;
    snprintf(buf, sizeof buf, "/proc/%d/task/%d", out_request->pid, out_request->tid);
    if (stat(buf, &s)) {
      ALOGE("tid %d does not exist in pid %d. ignoring debug request\n",
          out_request->tid, out_request->pid);
    // This check needs to happen again after ptracing the requested thread to prevent a race.
    if (!pid_contains_tid(out_request->pid, out_request->tid)) {
      ALOGE("tid %d does not exist in pid %d. ignoring debug request\n", out_request->tid,
            out_request->pid);
      return -1;
    }
  } else if (cr.uid == 0
            || (cr.uid == AID_SYSTEM && msg.action == DEBUGGER_ACTION_DUMP_BACKTRACE)) {
  } else if (cr.uid == 0 || (cr.uid == AID_SYSTEM && msg.action == DEBUGGER_ACTION_DUMP_BACKTRACE)) {
    // Only root or system can ask us to attach to any process and dump it explicitly.
    // However, system is only allowed to collect backtraces but cannot dump tombstones.
    status = get_process_info(out_request->tid, &out_request->pid,
@@ -413,10 +420,31 @@ static void redirect_to_32(int fd, debugger_request_t* request) {
}
#endif

// Attach to a thread, and verify that it's still a member of the given process
static bool ptrace_attach_thread(pid_t pid, pid_t tid) {
  if (ptrace(PTRACE_ATTACH, tid, 0, 0) != 0) {
    return false;
  }

  // Make sure that the task we attached to is actually part of the pid we're dumping.
  if (!pid_contains_tid(pid, tid)) {
    if (ptrace(PTRACE_DETACH, tid, 0, 0) != 0) {
      ALOGE("debuggerd: failed to detach from thread '%d'", tid);
      exit(1);
    }
    return false;
  }

  return true;
}

static void ptrace_siblings(pid_t pid, pid_t main_tid, pid_t ignore_tid, std::set<pid_t>& tids) {
  char task_path[64];
  char task_path[PATH_MAX];

  snprintf(task_path, sizeof(task_path), "/proc/%d/task", pid);
  if (snprintf(task_path, PATH_MAX, "/proc/%d/task", pid) >= PATH_MAX) {
    ALOGE("debuggerd: task path overflow (pid = %d)\n", pid);
    abort();
  }

  std::unique_ptr<DIR, int (*)(DIR*)> d(opendir(task_path), closedir);

@@ -443,7 +471,7 @@ static void ptrace_siblings(pid_t pid, pid_t main_tid, pid_t ignore_tid, std::se
      continue;
    }

    if (ptrace(PTRACE_ATTACH, tid, 0, 0) < 0) {
    if (!ptrace_attach_thread(pid, tid)) {
      ALOGE("debuggerd: ptrace attach to %d failed: %s", tid, strerror(errno));
      continue;
    }
@@ -572,11 +600,33 @@ static void worker_process(int fd, debugger_request_t& request) {
  // debugger_signal_handler().

  // Attach to the target process.
  if (ptrace(PTRACE_ATTACH, request.tid, 0, 0) != 0) {
  if (!ptrace_attach_thread(request.pid, request.tid)) {
    ALOGE("debuggerd: ptrace attach failed: %s", strerror(errno));
    exit(1);
  }

  // DEBUGGER_ACTION_CRASH requests can come from arbitrary processes and the tid field in the
  // request is sent from the other side. If an attacker can cause a process to be spawned with the
  // pid of their process, they could trick debuggerd into dumping that process by exiting after
  // sending the request. Validate the trusted request.uid/gid to defend against this.
  if (request.action == DEBUGGER_ACTION_CRASH) {
    pid_t pid;
    uid_t uid;
    gid_t gid;
    if (get_process_info(request.tid, &pid, &uid, &gid) != 0) {
      ALOGE("debuggerd: failed to get process info for tid '%d'", request.tid);
      exit(1);
    }

    if (pid != request.pid || uid != request.uid || gid != request.gid) {
      ALOGE(
        "debuggerd: attached task %d does not match request: "
        "expected pid=%d,uid=%d,gid=%d, actual pid=%d,uid=%d,gid=%d",
        request.tid, request.pid, request.uid, request.gid, pid, uid, gid);
      exit(1);
    }
  }

  // Don't attach to the sibling threads if we want to attach gdb.
  // Supposedly, it makes the process less reliable.
  bool attach_gdb = should_attach_gdb(request);
+3 −109
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/swap.h>
@@ -39,7 +38,6 @@
#include <ext4_utils/ext4_sb.h>
#include <ext4_utils/ext4_utils.h>
#include <ext4_utils/wipe.h>
#include <linux/fs.h>
#include <linux/loop.h>
#include <logwrap/logwrap.h>
#include <private/android_filesystem_config.h>
@@ -54,7 +52,6 @@
#define E2FSCK_BIN      "/system/bin/e2fsck"
#define F2FS_FSCK_BIN  "/system/bin/fsck.f2fs"
#define MKSWAP_BIN      "/system/bin/mkswap"
#define TUNE2FS_BIN     "/system/bin/tune2fs"

#define FSCK_LOG_FILE   "/dev/fscklogs/log"

@@ -183,99 +180,6 @@ static void check_fs(char *blk_device, char *fs_type, char *target)
    return;
}

/* Function to read the primary superblock */
static int read_super_block(int fd, struct ext4_super_block *sb)
{
    off64_t ret;

    ret = lseek64(fd, 1024, SEEK_SET);
    if (ret < 0)
        return ret;

    ret = read(fd, sb, sizeof(*sb));
    if (ret < 0)
        return ret;
    if (ret != sizeof(*sb))
        return ret;

    return 0;
}

static ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
{
    return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
            le32_to_cpu(es->s_blocks_count_lo);
}

static ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
{
    return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
            le32_to_cpu(es->s_r_blocks_count_lo);
}

static void do_reserved_size(char *blk_device, char *fs_type, struct fstab_rec *rec)
{
    /* Check for the types of filesystems we know how to check */
    if (!strcmp(fs_type, "ext2") || !strcmp(fs_type, "ext3") || !strcmp(fs_type, "ext4")) {
        /*
         * Some system images do not have tune2fs for licensing reasons
         * Detect these and skip reserve blocks.
         */
        if (access(TUNE2FS_BIN, X_OK)) {
            ERROR("Not running %s on %s (executable not in system image)\n",
                  TUNE2FS_BIN, blk_device);
        } else {
            INFO("Running %s on %s\n", TUNE2FS_BIN, blk_device);

            int status = 0;
            int ret = 0;
            unsigned long reserved_blocks = 0;
            int fd = TEMP_FAILURE_RETRY(open(blk_device, O_RDONLY | O_CLOEXEC));
            if (fd >= 0) {
                struct ext4_super_block sb;
                ret = read_super_block(fd, &sb);
                if (ret < 0) {
                    ERROR("Can't read '%s' super block: %s\n", blk_device, strerror(errno));
                    goto out;
                }
                reserved_blocks = rec->reserved_size / EXT4_BLOCK_SIZE(&sb);
                unsigned long reserved_threshold = ext4_blocks_count(&sb) * 0.02;
                if (reserved_threshold < reserved_blocks) {
                    WARNING("Reserved blocks %lu is too large\n", reserved_blocks);
                    reserved_blocks = reserved_threshold;
                }

                if (ext4_r_blocks_count(&sb) == reserved_blocks) {
                    INFO("Have reserved same blocks\n");
                    goto out;
                }
            } else {
                ERROR("Failed to open '%s': %s\n", blk_device, strerror(errno));
                return;
            }

            char buf[16] = {0};
            snprintf(buf, sizeof (buf), "-r %lu", reserved_blocks);
            char *tune2fs_argv[] = {
                TUNE2FS_BIN,
                buf,
                blk_device,
            };

            ret = android_fork_execvp_ext(ARRAY_SIZE(tune2fs_argv), tune2fs_argv,
                                          &status, true, LOG_KLOG | LOG_FILE,
                                          true, NULL, NULL, 0);

            if (ret < 0) {
                /* No need to check for error in fork, we can't really handle it now */
                ERROR("Failed trying to run %s\n", TUNE2FS_BIN);
            }
      out:
            close(fd);
        }
    }
}

static void remove_trailing_slashes(char *n)
{
    int len;
@@ -338,7 +242,7 @@ static int __mount(const char *source, const char *target, const struct fstab_re
    return ret;
}

static int fs_match(const char *in1, const char *in2)
static int fs_match(char *in1, char *in2)
{
    char *n1;
    char *n2;
@@ -421,12 +325,6 @@ static int mount_with_alternatives(struct fstab *fstab, int start_idx, int *end_
                check_fs(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
                         fstab->recs[i].mount_point);
            }

            if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
                do_reserved_size(fstab->recs[i].blk_device, fstab->recs[i].fs_type,
                                 &fstab->recs[i]);
            }

            if (!__mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, &fstab->recs[i])) {
                *attempted_idx = i;
                mounted = 1;
@@ -754,7 +652,7 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
 * If multiple fstab entries are to be mounted on "n_name", it will try to mount each one
 * in turn, and stop on 1st success, or no more match.
 */
int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device,
                    char *tmp_mount_point)
{
    int i = 0;
@@ -792,10 +690,6 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
                     fstab->recs[i].mount_point);
        }

        if (fstab->recs[i].fs_mgr_flags & MF_RESERVEDSIZE) {
            do_reserved_size(n_blk_device, fstab->recs[i].fs_type, &fstab->recs[i]);
        }

        if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
            int rc = fs_mgr_setup_verity(&fstab->recs[i]);
            if (__android_log_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
+39 −24
Original line number Diff line number Diff line
@@ -33,12 +33,12 @@ struct fs_mgr_flag_values {
    int swap_prio;
    int max_comp_streams;
    unsigned int zram_size;
    uint64_t reserved_size;
    unsigned int file_encryption_mode;
};

struct flag_list {
    const char *name;
    unsigned flag;
    unsigned int flag;
};

static struct flag_list mount_flags[] = {
@@ -65,7 +65,7 @@ static struct flag_list fs_mgr_flags[] = {
    { "check",       MF_CHECK },
    { "encryptable=",MF_CRYPT },
    { "forceencrypt=",MF_FORCECRYPT },
    { "fileencryption",MF_FILEENCRYPTION },
    { "fileencryption=",MF_FILEENCRYPTION },
    { "forcefdeorfbe=",MF_FORCEFDEORFBE },
    { "nonremovable",MF_NONREMOVABLE },
    { "voldmanaged=",MF_VOLDMANAGED},
@@ -81,11 +81,19 @@ static struct flag_list fs_mgr_flags[] = {
    { "slotselect",  MF_SLOTSELECT },
    { "nofail",      MF_NOFAIL },
    { "latemount",   MF_LATEMOUNT },
    { "reservedsize=", MF_RESERVEDSIZE },
    { "defaults",    0 },
    { 0,             0 },
};

#define EM_SOFTWARE 1
#define EM_ICE      2

static struct flag_list encryption_modes[] = {
    {"software", EM_SOFTWARE},
    {"ice", EM_ICE},
    {0, 0}
};

static uint64_t calculate_zram_size(unsigned int percentage)
{
    uint64_t total;
@@ -99,20 +107,6 @@ static uint64_t calculate_zram_size(unsigned int percentage)
    return total;
}

static uint64_t parse_size(const char *arg)
{
    char *endptr;
    uint64_t size = strtoull(arg, &endptr, 10);
    if (*endptr == 'k' || *endptr == 'K')
        size *= 1024LL;
    else if (*endptr == 'm' || *endptr == 'M')
        size *= 1024LL * 1024LL;
    else if (*endptr == 'g' || *endptr == 'G')
        size *= 1024LL * 1024LL * 1024LL;

    return size;
}

static int parse_flags(char *flags, struct flag_list *fl,
                       struct fs_mgr_flag_values *flag_vals,
                       char *fs_options, int fs_options_len)
@@ -166,6 +160,21 @@ static int parse_flags(char *flags, struct flag_list *fl,
                     * location of the keys.  Get it and return it.
                     */
                    flag_vals->key_loc = strdup(strchr(p, '=') + 1);
                    flag_vals->file_encryption_mode = EM_SOFTWARE;
                } else if ((fl[i].flag == MF_FILEENCRYPTION) && flag_vals) {
                    /* The fileencryption flag is followed by an = and the
                     * type of the encryption.  Get it and return it.
                     */
                    const struct flag_list *j;
                    const char *mode = strchr(p, '=') + 1;
                    for (j = encryption_modes; j->name; ++j) {
                        if (!strcmp(mode, j->name)) {
                            flag_vals->file_encryption_mode = j->flag;
                        }
                    }
                    if (flag_vals->file_encryption_mode == 0) {
                        ERROR("Unknown file encryption mode: %s\n", mode);
                    }
                } else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
                    /* The length flag is followed by an = and the
                     * size of the partition.  Get it and return it.
@@ -207,11 +216,6 @@ static int parse_flags(char *flags, struct flag_list *fl,
                        flag_vals->zram_size = calculate_zram_size(val);
                    else
                        flag_vals->zram_size = val;
                } else if ((fl[i].flag == MF_RESERVEDSIZE) && flag_vals) {
                    /* The reserved flag is followed by an = and the
                     * reserved size of the partition.  Get it and return it.
                     */
                    flag_vals->reserved_size = parse_size(strchr(p, '=') + 1);
                }
                break;
            }
@@ -356,7 +360,7 @@ struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
        fstab->recs[cnt].swap_prio = flag_vals.swap_prio;
        fstab->recs[cnt].max_comp_streams = flag_vals.max_comp_streams;
        fstab->recs[cnt].zram_size = flag_vals.zram_size;
        fstab->recs[cnt].reserved_size = flag_vals.reserved_size;
        fstab->recs[cnt].file_encryption_mode = flag_vals.file_encryption_mode;
        cnt++;
    }
    /* If an A/B partition, modify block device to be the real block device */
@@ -515,6 +519,17 @@ int fs_mgr_is_file_encrypted(const struct fstab_rec *fstab)
    return fstab->fs_mgr_flags & MF_FILEENCRYPTION;
}

const char* fs_mgr_get_file_encryption_mode(const struct fstab_rec *fstab)
{
    const struct flag_list *j;
    for (j = encryption_modes; j->name; ++j) {
        if (fstab->file_encryption_mode == j->flag) {
            return j->name;
        }
    }
    return NULL;
}

int fs_mgr_is_convertible_to_fbe(const struct fstab_rec *fstab)
{
    return fstab->fs_mgr_flags & MF_FORCEFDEORFBE;
+9 −14
Original line number Diff line number Diff line
@@ -14,17 +14,12 @@
 * limitations under the License.
 */

#define _GNU_SOURCE

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <libgen.h>
#include "fs_mgr_priv.h"

#ifdef _LIBGEN_H
#warning "libgen.h must not be included"
#endif

char *me = "";

static void usage(void)
@@ -37,10 +32,10 @@ static void usage(void)
 * and exit the program, do not return to the caller.
 * Return the number of argv[] entries consumed.
 */
static void parse_options(int argc, char * const argv[], int *a_flag, int *u_flag, int *n_flag,
                     const char **n_name, const char **n_blk_dev)
static void parse_options(int argc, char *argv[], int *a_flag, int *u_flag, int *n_flag,
                     char **n_name, char **n_blk_dev)
{
    me = basename(argv[0]);
    me = basename(strdup(argv[0]));

    if (argc <= 1) {
        usage();
@@ -80,14 +75,14 @@ static void parse_options(int argc, char * const argv[], int *a_flag, int *u_fla
    return;
}

int main(int argc, char * const argv[])
int main(int argc, char *argv[])
{
    int a_flag=0;
    int u_flag=0;
    int n_flag=0;
    const char *n_name=NULL;
    const char *n_blk_dev=NULL;
    const char *fstab_file=NULL;
    char *n_name=NULL;
    char *n_blk_dev=NULL;
    char *fstab_file=NULL;
    struct fstab *fstab=NULL;

    klog_set_level(6);
@@ -102,7 +97,7 @@ int main(int argc, char * const argv[])
    if (a_flag) {
        return fs_mgr_mount_all(fstab, MOUNT_MODE_DEFAULT);
    } else if (n_flag) {
        return fs_mgr_do_mount(fstab, n_name, (char *)n_blk_dev, 0);
        return fs_mgr_do_mount(fstab, n_name, n_blk_dev, 0);
    } else if (u_flag) {
        return fs_mgr_unmount_all(fstab);
    } else {
Loading