/* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. */ int fs_mgr_mount_all(struct fstab *fstab) { int i = 0; int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; int error_count = 0; int mret = -1; int mount_errno = 0; int attempted_idx = -1; if (!fstab) { return -1; } for (i = 0; i < fstab->num_entries; i++) { /* Don't mount entries that are managed by vold */ if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { continue; } /* Skip swap and raw partition entries such as boot, recovery, etc */ if (!strcmp(fstab->recs[i].fs_type, "swap") || !strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { continue; } ERROR("[xiaolei] : blk device name %s\n", fstab->recs[i].blk_device); #ifdef MTK_UBIFS_SUPPORT if (!strcmp(fstab->recs[i].fs_type, "ubifs")) { char tmp[80]; int n = ubi_attach_mtd(fstab->recs[i].blk_device + 5); if (n < 0) { return -1; } n = sprintf(tmp, "/dev/ubi%d_0", n); free(fstab->recs[i].blk_device); fstab->recs[i].blk_device = malloc(n+1); sprintf(fstab->recs[i].blk_device, "%s", tmp); ERROR("debug : ubifs blk_device %s", fstab->recs[i].blk_device); } #endif if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && !device_is_debuggable()) { if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { ERROR("Could not set up verified partition, skipping!\n"); continue; } } int last_idx_inspected; mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx, encryptable); i = last_idx_inspected; mount_errno = errno; /* Deal with encryptability. */ if (!mret) { /* If this is encryptable, need to trigger encryption */ if ((fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT)) { if (umount(fstab->recs[attempted_idx].mount_point) == 0) { if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION; } else { ERROR("Only one encryptable/encrypted partition supported\n"); encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } } else { INFO("Could not umount %s - allow continue unencrypted\n", fstab->recs[attempted_idx].mount_point); continue; } } /* Success! Go get the next one */ continue; } /* mount(2) returned an error, check if it's encryptable and deal with it */ if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { if(partition_wiped(fstab->recs[attempted_idx].blk_device)) { ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; continue; } else { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { ++error_count; continue; } } encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } else { ERROR("Failed to mount an un-encryptable or wiped partition on" "%s at %s options: %s error: %s\n", fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); ++error_count; continue; } } if (error_count) { return -1; } else { return encryptable; } }
/* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. */ int fs_mgr_mount_all(struct fstab *fstab) { int i = 0; int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; int error_count = 0; int mret = -1; int mount_errno = 0; int attempted_idx = -1; if (!fstab) { return -1; } for (i = 0; i < fstab->num_entries; i++) { /* Don't mount entries that are managed by vold */ if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { continue; } /* Skip swap and raw partition entries such as boot, recovery, etc */ if (!strcmp(fstab->recs[i].fs_type, "swap") || !strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { continue; } /* Translate LABEL= file system labels into block devices */ if (!strcmp(fstab->recs[i].fs_type, "ext2") || !strcmp(fstab->recs[i].fs_type, "ext3") || !strcmp(fstab->recs[i].fs_type, "ext4")) { int tret = translate_ext_labels(&fstab->recs[i]); if (tret < 0) { ERROR("Could not translate label to block device\n"); continue; } } if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) { int rc = fs_mgr_setup_verity(&fstab->recs[i]); if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { INFO("Verity disabled"); } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { ERROR("Could not set up verified partition, skipping!\n"); continue; } } int last_idx_inspected; mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx); i = last_idx_inspected; mount_errno = errno; /* Deal with encryptability. */ if (!mret) { int status = handle_encryptable(fstab, &fstab->recs[attempted_idx]); if (status == FS_MGR_MNTALL_FAIL) { /* Fatal error - no point continuing */ return status; } if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { // Log and continue ERROR("Only one encryptable/encrypted partition supported\n"); } encryptable = status; } /* Success! Go get the next one */ continue; } /* mount(2) returned an error, check if it's encryptable and deal with it */ if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { if(partition_wiped(fstab->recs[attempted_idx].blk_device)) { ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; continue; } else { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { ++error_count; continue; } } encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } else { ERROR("Failed to mount an un-encryptable or wiped partition on" "%s at %s options: %s error: %s\n", fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); ++error_count; continue; } } if (error_count) { return -1; } else { return encryptable; } }
/* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. */ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode) { int i = 0; int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE; int error_count = 0; int mret = -1; int mount_errno = 0; int attempted_idx = -1; if (!fstab) { return -1; } for (i = 0; i < fstab->num_entries; i++) { /* Don't mount entries that are managed by vold or not for the mount mode*/ if ((fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) || ((mount_mode == MOUNT_MODE_LATE) && !fs_mgr_is_latemount(&fstab->recs[i])) || ((mount_mode == MOUNT_MODE_EARLY) && fs_mgr_is_latemount(&fstab->recs[i]))) { continue; } /* Skip swap and raw partition entries such as boot, recovery, etc */ if (!strcmp(fstab->recs[i].fs_type, "swap") || !strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { continue; } /* Skip mounting the root partition, as it will already have been mounted */ if (!strcmp(fstab->recs[i].mount_point, "/")) { if ((fstab->recs[i].fs_mgr_flags & MS_RDONLY) != 0) { fs_mgr_set_blk_ro(fstab->recs[i].blk_device); } continue; } /* Translate LABEL= file system labels into block devices */ if (!strcmp(fstab->recs[i].fs_type, "ext2") || !strcmp(fstab->recs[i].fs_type, "ext3") || !strcmp(fstab->recs[i].fs_type, "ext4")) { int tret = translate_ext_labels(&fstab->recs[i]); if (tret < 0) { ERROR("Could not translate label to block device\n"); continue; } } if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } 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) { INFO("Verity disabled"); } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { ERROR("Could not set up verified partition, skipping!\n"); continue; } } int last_idx_inspected; int top_idx = i; mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx); i = last_idx_inspected; mount_errno = errno; /* Deal with encryptability. */ if (!mret) { int status = handle_encryptable(&fstab->recs[attempted_idx]); if (status == FS_MGR_MNTALL_FAIL) { /* Fatal error - no point continuing */ return status; } if (status != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { if (encryptable != FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE) { // Log and continue ERROR("Only one encryptable/encrypted partition supported\n"); } encryptable = status; } /* Success! Go get the next one */ continue; } /* mount(2) returned an error, handle the encryptable/formattable case */ bool wiped = partition_wiped(fstab->recs[top_idx].blk_device); bool crypt_footer = false; if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) { /* top_idx and attempted_idx point at the same partition, but sometimes * at two different lines in the fstab. Use the top one for formatting * as that is the preferred one. */ ERROR("%s(): %s is wiped and %s %s is formattable. Format it.\n", __func__, fstab->recs[top_idx].blk_device, fstab->recs[top_idx].mount_point, fstab->recs[top_idx].fs_type); if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) && strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) { int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY); if (fd >= 0) { INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc); wipe_block_device(fd, get_file_size(fd)); close(fd); } else { ERROR("%s(): %s wouldn't open (%s)\n", __func__, fstab->recs[top_idx].key_loc, strerror(errno)); } } else if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) && !strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) { crypt_footer = true; } if (fs_mgr_do_format(&fstab->recs[top_idx], crypt_footer) == 0) { /* Let's replay the mount actions. */ i = top_idx - 1; continue; } else { ERROR("%s(): Format failed. Suggest recovery...\n", __func__); encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; continue; } } if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { if (wiped) { ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; continue; } else { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { ++error_count; continue; } } encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } else { if (fs_mgr_is_nofail(&fstab->recs[attempted_idx])) { ERROR("Ignoring failure to mount an un-encryptable or wiped partition on" "%s at %s options: %s error: %s\n", fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); } else { ERROR("Failed to mount an un-encryptable or wiped partition on" "%s at %s options: %s error: %s\n", fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); ++error_count; } continue; } } if (error_count) { return -1; } else { return encryptable; } }
/* When multiple fstab records share the same mount_point, it will * try to mount each one in turn, and ignore any duplicates after a * first successful mount. * Returns -1 on error, and FS_MGR_MNTALL_* otherwise. */ int fs_mgr_mount_all(struct fstab *fstab) { int i = 0; int encryptable = FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; int error_count = 0; int mret = -1; int mount_errno = 0; int attempted_idx = -1; if (!fstab) { return -1; } for (i = 0; i < fstab->num_entries; i++) { /* Don't mount entries that are managed by vold */ if (fstab->recs[i].fs_mgr_flags & (MF_VOLDMANAGED | MF_RECOVERYONLY)) { continue; } /* Skip swap and raw partition entries such as boot, recovery, etc */ if (!strcmp(fstab->recs[i].fs_type, "swap") || !strcmp(fstab->recs[i].fs_type, "emmc") || !strcmp(fstab->recs[i].fs_type, "mtd")) { continue; } if (fstab->recs[i].fs_mgr_flags & MF_WAIT) { wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && device_is_secure()) { int rc = fs_mgr_setup_verity(&fstab->recs[i]); if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) { INFO("Verity disabled"); } else if (rc != FS_MGR_SETUP_VERITY_SUCCESS) { ERROR("Could not set up verified partition, skipping!\n"); continue; } } int last_idx_inspected; int top_idx = i; mret = mount_with_alternatives(fstab, i, &last_idx_inspected, &attempted_idx); i = last_idx_inspected; mount_errno = errno; /* Deal with encryptability. */ if (!mret) { /* If this is encryptable, need to trigger encryption */ if ( (fstab->recs[attempted_idx].fs_mgr_flags & MF_FORCECRYPT) || (device_is_force_encrypted() && fs_mgr_is_encryptable(&fstab->recs[attempted_idx]))) { if (umount(fstab->recs[attempted_idx].mount_point) == 0) { if (encryptable == FS_MGR_MNTALL_DEV_NOT_ENCRYPTED) { ERROR("Will try to encrypt %s %s\n", fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION; } else { ERROR("Only one encryptable/encrypted partition supported\n"); encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } } else { INFO("Could not umount %s - allow continue unencrypted\n", fstab->recs[attempted_idx].mount_point); continue; } } /* Success! Go get the next one */ continue; } /* mount(2) returned an error, handle the encryptable/formattable case */ bool wiped = partition_wiped(fstab->recs[top_idx].blk_device); if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_formattable(&fstab->recs[top_idx]) && wiped) { /* top_idx and attempted_idx point at the same partition, but sometimes * at two different lines in the fstab. Use the top one for formatting * as that is the preferred one. */ ERROR("%s(): %s is wiped and %s %s is formattable. Format it.\n", __func__, fstab->recs[top_idx].blk_device, fstab->recs[top_idx].mount_point, fstab->recs[top_idx].fs_type); if (fs_mgr_is_encryptable(&fstab->recs[top_idx]) && strcmp(fstab->recs[top_idx].key_loc, KEY_IN_FOOTER)) { int fd = open(fstab->recs[top_idx].key_loc, O_WRONLY, 0644); if (fd >= 0) { INFO("%s(): also wipe %s\n", __func__, fstab->recs[top_idx].key_loc); wipe_block_device(fd, get_file_size(fd)); close(fd); } else { ERROR("%s(): %s wouldn't open (%s)\n", __func__, fstab->recs[top_idx].key_loc, strerror(errno)); } } if (fs_mgr_do_format(&fstab->recs[top_idx]) == 0) { /* Let's replay the mount actions. */ i = top_idx - 1; continue; } } if (mret && mount_errno != EBUSY && mount_errno != EACCES && fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) { if (wiped) { ERROR("%s(): %s is wiped and %s %s is encryptable. Suggest recovery...\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); encryptable = FS_MGR_MNTALL_DEV_NEEDS_RECOVERY; continue; } else { /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting */ ERROR("%s(): possibly an encryptable blkdev %s for mount %s type %s )\n", __func__, fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_type); if (fs_mgr_do_tmpfs_mount(fstab->recs[attempted_idx].mount_point) < 0) { ++error_count; continue; } } encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED; } else { ERROR("Failed to mount an un-encryptable or wiped partition on" "%s at %s options: %s error: %s\n", fstab->recs[attempted_idx].blk_device, fstab->recs[attempted_idx].mount_point, fstab->recs[attempted_idx].fs_options, strerror(mount_errno)); ++error_count; continue; } } if (error_count) { return -1; } else { return encryptable; } }