Loading adb/bugreport.cpp +3 −6 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ #include <string> #include <vector> #include <android-base/parseint.h> #include <android-base/strings.h> #include "sysdeps.h" Loading Loading @@ -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); } Loading debuggerd/debuggerd.cpp +62 −12 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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, Loading Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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); Loading fs_mgr/fs_mgr.c +3 −109 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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> Loading @@ -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" Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading fs_mgr/fs_mgr_fstab.c +39 −24 Original line number Diff line number Diff line Loading @@ -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[] = { Loading @@ -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}, Loading @@ -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; Loading @@ -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) Loading Loading @@ -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. Loading Loading @@ -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; } Loading Loading @@ -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 */ Loading Loading @@ -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; Loading fs_mgr/fs_mgr_main.c +9 −14 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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(); Loading Loading @@ -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); Loading @@ -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 Loading
adb/bugreport.cpp +3 −6 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ #include <string> #include <vector> #include <android-base/parseint.h> #include <android-base/strings.h> #include "sysdeps.h" Loading Loading @@ -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); } Loading
debuggerd/debuggerd.cpp +62 −12 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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, Loading Loading @@ -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); Loading @@ -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; } Loading Loading @@ -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); Loading
fs_mgr/fs_mgr.c +3 −109 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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> Loading @@ -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" Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) { Loading
fs_mgr/fs_mgr_fstab.c +39 −24 Original line number Diff line number Diff line Loading @@ -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[] = { Loading @@ -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}, Loading @@ -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; Loading @@ -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) Loading Loading @@ -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. Loading Loading @@ -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; } Loading Loading @@ -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 */ Loading Loading @@ -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; Loading
fs_mgr/fs_mgr_main.c +9 −14 Original line number Diff line number Diff line Loading @@ -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) Loading @@ -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(); Loading Loading @@ -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); Loading @@ -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