Exemplo n.º 1
0
static const char* find_block_device(const char* path, bool* encryptable,
                                     bool* encrypted, bool* f2fs_fs) {
    // Look for a volume whose mount point is the prefix of path and
    // return its block device.  Set encrypted if it's currently
    // encrypted.

    // ensure f2fs_fs is set to false first.
    *f2fs_fs = false;

    for (int i = 0; i < fstab->num_entries; ++i) {
        struct fstab_rec* v = &fstab->recs[i];
        if (!v->mount_point) {
            continue;
        }
        int len = strlen(v->mount_point);
        if (strncmp(path, v->mount_point, len) == 0 &&
            (path[len] == '/' || path[len] == 0)) {
            *encrypted = false;
            *encryptable = false;
            if (fs_mgr_is_encryptable(v) || fs_mgr_is_file_encrypted(v)) {
                *encryptable = true;
                if (android::base::GetProperty("ro.crypto.state", "") == "encrypted") {
                    *encrypted = true;
                }
            }
            if (strcmp(v->fs_type, "f2fs") == 0) {
                *f2fs_fs = true;
            }
            return v->blk_device;
        }
    }

    return NULL;
}
static const char* find_block_device(const char* path, bool* encryptable, bool* encrypted) {
    // Look for a volume whose mount point is the prefix of path and
    // return its block device.  Set encrypted if it's currently
    // encrypted.
    for (int i = 0; i < fstab->num_entries; ++i) {
        struct fstab_rec* v = &fstab->recs[i];
        if (!v->mount_point) {
            continue;
        }
        int len = strlen(v->mount_point);
        if (strncmp(path, v->mount_point, len) == 0 &&
            (path[len] == '/' || path[len] == 0)) {
            *encrypted = false;
            *encryptable = false;
            if (fs_mgr_is_encryptable(v) || fs_mgr_is_file_encrypted(v)) {
                *encryptable = true;
                char buffer[PROPERTY_VALUE_MAX+1];
                if (property_get("ro.crypto.state", buffer, "") &&
                    strcmp(buffer, "encrypted") == 0) {
                    *encrypted = true;
                }
            }
            return v->blk_device;
        }
    }

    return NULL;
}
Exemplo n.º 3
0
// Check to see if a mountable volume has encryption requirements
static int handle_encryptable(struct fstab *fstab, const struct fstab_rec* rec)
{
    /* If this is block encryptable, need to trigger encryption */
    if (   (rec->fs_mgr_flags & MF_FORCECRYPT)
        || (device_is_force_encrypted() && fs_mgr_is_encryptable(rec))) {
        if (umount(rec->mount_point) == 0) {
            return FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION;
        } else {
            WARNING("Could not umount %s (%s) - allow continue unencrypted\n",
                    rec->mount_point, strerror(errno));
            return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
        }
    }

    // Deal with file level encryption
    if (rec->fs_mgr_flags & MF_FILEENCRYPTION) {
        // Default or not yet initialized encryption requires no more work here
        if (!e4crypt_non_default_key(rec->mount_point)) {
            INFO("%s is default file encrypted\n", rec->mount_point);
            return FS_MGR_MNTALL_DEV_DEFAULT_FILE_ENCRYPTED;
        }

        INFO("%s is non-default file encrypted\n", rec->mount_point);

        // Uses non-default key, so must unmount and set up temp file system
        if (umount(rec->mount_point)) {
            ERROR("Failed to umount %s - rebooting\n", rec->mount_point);
            return FS_MGR_MNTALL_FAIL;
        }

        if (fs_mgr_do_tmpfs_mount(rec->mount_point) != 0) {
            ERROR("Failed to mount a tmpfs at %s\n", rec->mount_point);
            return FS_MGR_MNTALL_FAIL;
        }

        // Mount data temporarily so we can access unencrypted dir
        char tmp_mnt[PATH_MAX];
        strlcpy(tmp_mnt, rec->mount_point, sizeof(tmp_mnt));
        strlcat(tmp_mnt, "/tmp_mnt", sizeof(tmp_mnt));
        if (mkdir(tmp_mnt, 0700)) {
            ERROR("Failed to create temp mount point\n");
            return FS_MGR_MNTALL_FAIL;
        }

        if (fs_mgr_do_mount(fstab, rec->mount_point,
                            rec->blk_device, tmp_mnt)) {
            ERROR("Error temp mounting encrypted file system\n");
            return FS_MGR_MNTALL_FAIL;
        }

        return FS_MGR_MNTALL_DEV_NON_DEFAULT_FILE_ENCRYPTED;
    }

    return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
}
Exemplo n.º 4
0
static bool needs_block_encryption(const struct fstab_rec* rec)
{
    if (device_is_force_encrypted() && fs_mgr_is_encryptable(rec)) return true;
    if (rec->fs_mgr_flags & MF_FORCECRYPT) return true;
    if (rec->fs_mgr_flags & MF_CRYPT) {
        /* Check for existence of convert_fde breadcrumb file */
        char convert_fde_name[PATH_MAX];
        snprintf(convert_fde_name, sizeof(convert_fde_name),
                 "%s/misc/vold/convert_fde", rec->mount_point);
        if (access(convert_fde_name, F_OK) == 0) return true;
    }
    if (rec->fs_mgr_flags & MF_FORCEFDEORFBE) {
        /* Check for absence of convert_fbe breadcrumb file */
        char convert_fbe_name[PATH_MAX];
        snprintf(convert_fbe_name, sizeof(convert_fbe_name),
                 "%s/convert_fbe", rec->mount_point);
        if (access(convert_fbe_name, F_OK) != 0) return true;
    }
    return false;
}
Exemplo n.º 5
0
// Check to see if a mountable volume has encryption requirements
static int handle_encryptable(const struct fstab_rec* rec)
{
    /* If this is block encryptable, need to trigger encryption */
    if (needs_block_encryption(rec)) {
        if (umount(rec->mount_point) == 0) {
            return FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION;
        } else {
            WARNING("Could not umount %s (%s) - allow continue unencrypted\n",
                    rec->mount_point, strerror(errno));
            return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
        }
    } else if (rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE)) {
    // Deal with file level encryption
        INFO("%s is file encrypted\n", rec->mount_point);
        return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED;
    } else if (fs_mgr_is_encryptable(rec)) {
        return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
    } else {
        return FS_MGR_MNTALL_DEV_NOT_ENCRYPTABLE;
    }
}
Exemplo n.º 6
0
/* 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;
    }
}
Exemplo n.º 7
0
/* 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;
    }
}
Exemplo n.º 8
0
/* 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;
    }
}
Exemplo n.º 9
0
/* 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;
    }
}
Exemplo n.º 10
0
int format_volume(const char* volume) {
    Volume* v = volume_for_path(volume);
    if (v == NULL) {
        LOGE("unknown volume \"%s\"\n", volume);
        return -1;
    }
    if (strcmp(v->fs_type, "ramdisk") == 0) {
        // you can't format the ramdisk.
        LOGE("can't format_volume \"%s\"", volume);
        return -1;
    }
    if (strcmp(v->mount_point, volume) != 0) {
        LOGE("can't give path \"%s\" to format_volume\n", volume);
        return -1;
    }

    if (ensure_path_unmounted(volume) != 0) {
        LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
        return -1;
    }

    if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0) {
        mtd_scan_partitions();
        const MtdPartition* partition = mtd_find_partition_by_name(v->blk_device);
        if (partition == NULL) {
            LOGE("format_volume: no MTD partition \"%s\"\n", v->blk_device);
            return -1;
        }

        MtdWriteContext *write = mtd_write_partition(partition);
        if (write == NULL) {
            LOGW("format_volume: can't open MTD \"%s\"\n", v->blk_device);
            return -1;
        } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
            LOGW("format_volume: can't erase MTD \"%s\"\n", v->blk_device);
            mtd_write_close(write);
            return -1;
        } else if (mtd_write_close(write)) {
            LOGW("format_volume: can't close MTD \"%s\"\n", v->blk_device);
            return -1;
        }
        return 0;
    }

    if (strcmp(v->fs_type, "ext4") == 0) {
        if (fs_mgr_is_encryptable(v) &&
            (v->length == 0) &&
            (v->key_loc != NULL) &&
            !strcmp(v->key_loc, KEY_IN_FOOTER)) {
            if (get_block_device_size(v->blk_device, &v->length) == 0) {
                v->length -= CRYPT_FOOTER_OFFSET;
            }
        }

        int result = make_ext4fs(v->blk_device, v->length, volume, sehandle);
        if (result != 0) {
            LOGE("format_volume: make_extf4fs failed on %s\n", v->blk_device);
            return -1;
        }
        return 0;
    }
#ifdef USE_UBIFS
    if (strcmp(v->fs_type, "ubifs") == 0) {
        int ret;
        LOGW("formating by ubiVolumeFormat");
        ret = ubiVolumeFormat(v->blk_device);
        if (ret != 0) {
            LOGE("ubiVolumeFormat return error:%d", ret);
            return -1;
        }
            return 0;
    }
#endif

    LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
    return -1;
}