Loading fs_mgr/fs_mgr.c +69 −32 Original line number Original line Diff line number Diff line Loading @@ -113,6 +113,7 @@ static void check_fs(char *blk_device, char *fs_type, char *target) * fix the filesystem. * fix the filesystem. */ */ ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts); ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts); INFO("%s(): mount(%s,%s,%s)=%d\n", __func__, blk_device, target, fs_type, ret); if (!ret) { if (!ret) { umount(target); umount(target); } } Loading Loading @@ -190,16 +191,19 @@ static void fs_set_blk_ro(const char *blockdev) * sets the underlying block device to read-only if the mount is read-only. * sets the underlying block device to read-only if the mount is read-only. * See "man 2 mount" for return values. * See "man 2 mount" for return values. */ */ static int __mount(const char *source, const char *target, static int __mount(const char *source, const char *target, const struct fstab_rec *rec) const char *filesystemtype, unsigned long mountflags, const void *data) { { int ret = mount(source, target, filesystemtype, mountflags, data); unsigned long mountflags = rec->flags; int ret; int save_errno; ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options); save_errno = errno; INFO("%s(source=%s,target=%s,type=%s)=%d\n", __func__, source, target, rec->fs_type, ret); if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { fs_set_blk_ro(source); fs_set_blk_ro(source); } } errno = save_errno; return ret; return ret; } } Loading Loading @@ -232,13 +236,18 @@ static int device_is_debuggable() { return strcmp(value, "1") ? 0 : 1; return strcmp(value, "1") ? 0 : 1; } } /* 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. */ int fs_mgr_mount_all(struct fstab *fstab) int fs_mgr_mount_all(struct fstab *fstab) { { int i = 0; int i = 0, j = 0; int encryptable = 0; int encryptable = 0; int error_count = 0; int error_count = 0; int mret; int mret = -1; int mount_errno; int mount_errno = 0; const char *last_ok_mount_point = NULL; if (!fstab) { if (!fstab) { return -1; return -1; Loading @@ -261,11 +270,6 @@ int fs_mgr_mount_all(struct fstab *fstab) wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } } if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { 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_VERIFY) && if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && !device_is_debuggable()) { !device_is_debuggable()) { if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { Loading @@ -274,10 +278,41 @@ int fs_mgr_mount_all(struct fstab *fstab) } } } } mret = __mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, /* fstab->recs[i].fs_type, fstab->recs[i].flags, * Don't try to mount/encrypt the same mount point again. fstab->recs[i].fs_options); * Deal with alternate entries for the same point which are required to be all following * each other. */ if (last_ok_mount_point && !strcmp(last_ok_mount_point, fstab->recs[i].mount_point)) { INFO("%s(): skipping fstab dup mountpoint=%s rec[%d].fs_type=%s already mounted.\n", __func__, last_ok_mount_point, i, fstab->recs[i].fs_type); continue; } /* Hunt down an fstab entry for the same mount point that might succeed */ for (j = i; /* We required that fstab entries for the same mountpoint be consecutive */ j < fstab->num_entries && !strcmp(fstab->recs[i].mount_point, fstab->recs[j].mount_point); j++) { if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { check_fs(fstab->recs[j].blk_device, fstab->recs[j].fs_type, fstab->recs[j].mount_point); } mret = __mount(fstab->recs[j].blk_device, fstab->recs[j].mount_point, &fstab->recs[j]); if (!mret) { last_ok_mount_point = fstab->recs[j].mount_point; if (i != j) { INFO("%s(): some alternate mount worked for mount_point=%s fs_type=%s instead of fs_type=%s\n", __func__, last_ok_mount_point, fstab->recs[j].fs_type, fstab->recs[i].fs_type); i = j; /* We advance the recs index to the working entry */ } break; } else { /* back up errno for crypto decisions */ mount_errno = errno; } } /* Deal with encryptability. */ if (!mret) { if (!mret) { /* If this is encryptable, need to trigger encryption */ /* If this is encryptable, need to trigger encryption */ if ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT)) { if ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT)) { Loading @@ -294,24 +329,18 @@ int fs_mgr_mount_all(struct fstab *fstab) continue; continue; } } } } /* Success! Go get the next one */ /* Success! Go get the next one */ continue; continue; } } /* back up errno as partition_wipe clobbers the value */ mount_errno = errno; /* mount(2) returned an error, check if it's encryptable and deal with it */ /* mount(2) returned an error, check if it's encryptable and deal with it */ if (mount_errno != EBUSY && mount_errno != EACCES && if (mret && mount_errno != EBUSY && mount_errno != EACCES && (fstab->recs[i].fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT)) && (fstab->recs[i].fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT)) && !partition_wiped(fstab->recs[i].blk_device)) { !partition_wiped(fstab->recs[i].blk_device)) { /* Need to mount a tmpfs at this mountpoint for now, and set /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting * properties that vold will query later for decrypting */ */ if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs", if (fs_mgr_do_tmpfs_mount(fstab->recs[i].mount_point) < 0) { MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) { ERROR("Cannot mount tmpfs filesystem for encryptable fs at %s error: %s\n", fstab->recs[i].mount_point, strerror(errno)); ++error_count; ++error_count; continue; continue; } } Loading @@ -335,12 +364,16 @@ int fs_mgr_mount_all(struct fstab *fstab) /* If tmp_mount_point is non-null, mount the filesystem there. This is for the /* If tmp_mount_point is non-null, mount the filesystem there. This is for the * tmp mount we do to check the user password * tmp mount we do to check the user password * 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, 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) char *tmp_mount_point) { { int i = 0; int i = 0; int ret = -1; int ret = -1; int mount_errors = 0; int first_mount_errno = 0; char *m; char *m; if (!fstab) { if (!fstab) { Loading Loading @@ -386,19 +419,23 @@ int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, } else { } else { m = fstab->recs[i].mount_point; m = fstab->recs[i].mount_point; } } if (__mount(n_blk_device, m, fstab->recs[i].fs_type, if (__mount(n_blk_device, m, &fstab->recs[i])) { fstab->recs[i].flags, fstab->recs[i].fs_options)) { if (!first_mount_errno) first_mount_errno = errno; ERROR("Cannot mount filesystem on %s at %s options: %s error: %s\n", mount_errors++; n_blk_device, m, fstab->recs[i].fs_options, strerror(errno)); continue; goto out; } else { } else { ret = 0; ret = 0; goto out; goto out; } } } } if (mount_errors) { ERROR("Cannot mount filesystem on %s at %s. error: %s\n", n_blk_device, m, strerror(first_mount_errno)); ret = -1; } else { /* We didn't find a match, say so and return an error */ /* We didn't find a match, say so and return an error */ ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); } out: out: return ret; return ret; Loading fs_mgr/fs_mgr_fstab.c +26 −4 Original line number Original line Diff line number Diff line Loading @@ -367,25 +367,47 @@ int fs_mgr_add_entry(struct fstab *fstab, return 0; return 0; } } struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path) /* * Returns the 1st matching fstab_rec that follows the start_rec. * start_rec is the result of a previous search or NULL. */ struct fstab_rec *fs_mgr_get_entry_for_mount_point_after(struct fstab_rec *start_rec, struct fstab *fstab, const char *path) { { int i; int i; if (!fstab) { if (!fstab) { return NULL; return NULL; } } if (start_rec) { for (i = 0; i < fstab->num_entries; i++) { for (i = 0; i < fstab->num_entries; i++) { if (&fstab->recs[i] == start_rec) { i++; break; } } } else { i = 0; } for (; i < fstab->num_entries; i++) { int len = strlen(fstab->recs[i].mount_point); int len = strlen(fstab->recs[i].mount_point); if (strncmp(path, fstab->recs[i].mount_point, len) == 0 && if (strncmp(path, fstab->recs[i].mount_point, len) == 0 && (path[len] == '\0' || path[len] == '/')) { (path[len] == '\0' || path[len] == '/')) { return &fstab->recs[i]; return &fstab->recs[i]; } } } } return NULL; return NULL; } } /* * Returns the 1st matching mount point. * There might be more. To look for others, use fs_mgr_get_entry_for_mount_point_after() * and give the fstab_rec from the previous search. */ struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path) { return fs_mgr_get_entry_for_mount_point_after(NULL, fstab, path); } int fs_mgr_is_voldmanaged(struct fstab_rec *fstab) int fs_mgr_is_voldmanaged(struct fstab_rec *fstab) { { return fstab->fs_mgr_flags & MF_VOLDMANAGED; return fstab->fs_mgr_flags & MF_VOLDMANAGED; Loading fs_mgr/include/fs_mgr.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,11 @@ extern "C" { extern "C" { #endif #endif /* * The entries must be kept in the same order as they were seen in the fstab. * Unless explicitly requested, a lookup on mount point should always * return the 1st one. */ struct fstab { struct fstab { int num_entries; int num_entries; struct fstab_rec *recs; struct fstab_rec *recs; Loading Loading
fs_mgr/fs_mgr.c +69 −32 Original line number Original line Diff line number Diff line Loading @@ -113,6 +113,7 @@ static void check_fs(char *blk_device, char *fs_type, char *target) * fix the filesystem. * fix the filesystem. */ */ ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts); ret = mount(blk_device, target, fs_type, tmpmnt_flags, tmpmnt_opts); INFO("%s(): mount(%s,%s,%s)=%d\n", __func__, blk_device, target, fs_type, ret); if (!ret) { if (!ret) { umount(target); umount(target); } } Loading Loading @@ -190,16 +191,19 @@ static void fs_set_blk_ro(const char *blockdev) * sets the underlying block device to read-only if the mount is read-only. * sets the underlying block device to read-only if the mount is read-only. * See "man 2 mount" for return values. * See "man 2 mount" for return values. */ */ static int __mount(const char *source, const char *target, static int __mount(const char *source, const char *target, const struct fstab_rec *rec) const char *filesystemtype, unsigned long mountflags, const void *data) { { int ret = mount(source, target, filesystemtype, mountflags, data); unsigned long mountflags = rec->flags; int ret; int save_errno; ret = mount(source, target, rec->fs_type, mountflags, rec->fs_options); save_errno = errno; INFO("%s(source=%s,target=%s,type=%s)=%d\n", __func__, source, target, rec->fs_type, ret); if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { if ((ret == 0) && (mountflags & MS_RDONLY) != 0) { fs_set_blk_ro(source); fs_set_blk_ro(source); } } errno = save_errno; return ret; return ret; } } Loading Loading @@ -232,13 +236,18 @@ static int device_is_debuggable() { return strcmp(value, "1") ? 0 : 1; return strcmp(value, "1") ? 0 : 1; } } /* 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. */ int fs_mgr_mount_all(struct fstab *fstab) int fs_mgr_mount_all(struct fstab *fstab) { { int i = 0; int i = 0, j = 0; int encryptable = 0; int encryptable = 0; int error_count = 0; int error_count = 0; int mret; int mret = -1; int mount_errno; int mount_errno = 0; const char *last_ok_mount_point = NULL; if (!fstab) { if (!fstab) { return -1; return -1; Loading @@ -261,11 +270,6 @@ int fs_mgr_mount_all(struct fstab *fstab) wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); wait_for_file(fstab->recs[i].blk_device, WAIT_TIMEOUT); } } if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { 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_VERIFY) && if ((fstab->recs[i].fs_mgr_flags & MF_VERIFY) && !device_is_debuggable()) { !device_is_debuggable()) { if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { if (fs_mgr_setup_verity(&fstab->recs[i]) < 0) { Loading @@ -274,10 +278,41 @@ int fs_mgr_mount_all(struct fstab *fstab) } } } } mret = __mount(fstab->recs[i].blk_device, fstab->recs[i].mount_point, /* fstab->recs[i].fs_type, fstab->recs[i].flags, * Don't try to mount/encrypt the same mount point again. fstab->recs[i].fs_options); * Deal with alternate entries for the same point which are required to be all following * each other. */ if (last_ok_mount_point && !strcmp(last_ok_mount_point, fstab->recs[i].mount_point)) { INFO("%s(): skipping fstab dup mountpoint=%s rec[%d].fs_type=%s already mounted.\n", __func__, last_ok_mount_point, i, fstab->recs[i].fs_type); continue; } /* Hunt down an fstab entry for the same mount point that might succeed */ for (j = i; /* We required that fstab entries for the same mountpoint be consecutive */ j < fstab->num_entries && !strcmp(fstab->recs[i].mount_point, fstab->recs[j].mount_point); j++) { if (fstab->recs[i].fs_mgr_flags & MF_CHECK) { check_fs(fstab->recs[j].blk_device, fstab->recs[j].fs_type, fstab->recs[j].mount_point); } mret = __mount(fstab->recs[j].blk_device, fstab->recs[j].mount_point, &fstab->recs[j]); if (!mret) { last_ok_mount_point = fstab->recs[j].mount_point; if (i != j) { INFO("%s(): some alternate mount worked for mount_point=%s fs_type=%s instead of fs_type=%s\n", __func__, last_ok_mount_point, fstab->recs[j].fs_type, fstab->recs[i].fs_type); i = j; /* We advance the recs index to the working entry */ } break; } else { /* back up errno for crypto decisions */ mount_errno = errno; } } /* Deal with encryptability. */ if (!mret) { if (!mret) { /* If this is encryptable, need to trigger encryption */ /* If this is encryptable, need to trigger encryption */ if ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT)) { if ((fstab->recs[i].fs_mgr_flags & MF_FORCECRYPT)) { Loading @@ -294,24 +329,18 @@ int fs_mgr_mount_all(struct fstab *fstab) continue; continue; } } } } /* Success! Go get the next one */ /* Success! Go get the next one */ continue; continue; } } /* back up errno as partition_wipe clobbers the value */ mount_errno = errno; /* mount(2) returned an error, check if it's encryptable and deal with it */ /* mount(2) returned an error, check if it's encryptable and deal with it */ if (mount_errno != EBUSY && mount_errno != EACCES && if (mret && mount_errno != EBUSY && mount_errno != EACCES && (fstab->recs[i].fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT)) && (fstab->recs[i].fs_mgr_flags & (MF_CRYPT | MF_FORCECRYPT)) && !partition_wiped(fstab->recs[i].blk_device)) { !partition_wiped(fstab->recs[i].blk_device)) { /* Need to mount a tmpfs at this mountpoint for now, and set /* Need to mount a tmpfs at this mountpoint for now, and set * properties that vold will query later for decrypting * properties that vold will query later for decrypting */ */ if (mount("tmpfs", fstab->recs[i].mount_point, "tmpfs", if (fs_mgr_do_tmpfs_mount(fstab->recs[i].mount_point) < 0) { MS_NOATIME | MS_NOSUID | MS_NODEV, CRYPTO_TMPFS_OPTIONS) < 0) { ERROR("Cannot mount tmpfs filesystem for encryptable fs at %s error: %s\n", fstab->recs[i].mount_point, strerror(errno)); ++error_count; ++error_count; continue; continue; } } Loading @@ -335,12 +364,16 @@ int fs_mgr_mount_all(struct fstab *fstab) /* If tmp_mount_point is non-null, mount the filesystem there. This is for the /* If tmp_mount_point is non-null, mount the filesystem there. This is for the * tmp mount we do to check the user password * tmp mount we do to check the user password * 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, 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) char *tmp_mount_point) { { int i = 0; int i = 0; int ret = -1; int ret = -1; int mount_errors = 0; int first_mount_errno = 0; char *m; char *m; if (!fstab) { if (!fstab) { Loading Loading @@ -386,19 +419,23 @@ int fs_mgr_do_mount(struct fstab *fstab, char *n_name, char *n_blk_device, } else { } else { m = fstab->recs[i].mount_point; m = fstab->recs[i].mount_point; } } if (__mount(n_blk_device, m, fstab->recs[i].fs_type, if (__mount(n_blk_device, m, &fstab->recs[i])) { fstab->recs[i].flags, fstab->recs[i].fs_options)) { if (!first_mount_errno) first_mount_errno = errno; ERROR("Cannot mount filesystem on %s at %s options: %s error: %s\n", mount_errors++; n_blk_device, m, fstab->recs[i].fs_options, strerror(errno)); continue; goto out; } else { } else { ret = 0; ret = 0; goto out; goto out; } } } } if (mount_errors) { ERROR("Cannot mount filesystem on %s at %s. error: %s\n", n_blk_device, m, strerror(first_mount_errno)); ret = -1; } else { /* We didn't find a match, say so and return an error */ /* We didn't find a match, say so and return an error */ ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); ERROR("Cannot find mount point %s in fstab\n", fstab->recs[i].mount_point); } out: out: return ret; return ret; Loading
fs_mgr/fs_mgr_fstab.c +26 −4 Original line number Original line Diff line number Diff line Loading @@ -367,25 +367,47 @@ int fs_mgr_add_entry(struct fstab *fstab, return 0; return 0; } } struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path) /* * Returns the 1st matching fstab_rec that follows the start_rec. * start_rec is the result of a previous search or NULL. */ struct fstab_rec *fs_mgr_get_entry_for_mount_point_after(struct fstab_rec *start_rec, struct fstab *fstab, const char *path) { { int i; int i; if (!fstab) { if (!fstab) { return NULL; return NULL; } } if (start_rec) { for (i = 0; i < fstab->num_entries; i++) { for (i = 0; i < fstab->num_entries; i++) { if (&fstab->recs[i] == start_rec) { i++; break; } } } else { i = 0; } for (; i < fstab->num_entries; i++) { int len = strlen(fstab->recs[i].mount_point); int len = strlen(fstab->recs[i].mount_point); if (strncmp(path, fstab->recs[i].mount_point, len) == 0 && if (strncmp(path, fstab->recs[i].mount_point, len) == 0 && (path[len] == '\0' || path[len] == '/')) { (path[len] == '\0' || path[len] == '/')) { return &fstab->recs[i]; return &fstab->recs[i]; } } } } return NULL; return NULL; } } /* * Returns the 1st matching mount point. * There might be more. To look for others, use fs_mgr_get_entry_for_mount_point_after() * and give the fstab_rec from the previous search. */ struct fstab_rec *fs_mgr_get_entry_for_mount_point(struct fstab *fstab, const char *path) { return fs_mgr_get_entry_for_mount_point_after(NULL, fstab, path); } int fs_mgr_is_voldmanaged(struct fstab_rec *fstab) int fs_mgr_is_voldmanaged(struct fstab_rec *fstab) { { return fstab->fs_mgr_flags & MF_VOLDMANAGED; return fstab->fs_mgr_flags & MF_VOLDMANAGED; Loading
fs_mgr/include/fs_mgr.h +5 −0 Original line number Original line Diff line number Diff line Loading @@ -24,6 +24,11 @@ extern "C" { extern "C" { #endif #endif /* * The entries must be kept in the same order as they were seen in the fstab. * Unless explicitly requested, a lookup on mount point should always * return the 1st one. */ struct fstab { struct fstab { int num_entries; int num_entries; struct fstab_rec *recs; struct fstab_rec *recs; Loading