Loading fs_mgr/fs_mgr_fstab.c +10 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ struct fs_mgr_flag_values { char *key_loc; char *verity_loc; long long part_length; char *label; int partnum; Loading Loading @@ -107,6 +108,14 @@ 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); } else if ((fl[i].flag == MF_VERIFY) && flag_vals) { /* If the verify flag is followed by an = and the * location for the verity state, get it and return it. */ char *start = strchr(p, '='); if (start) { flag_vals->verity_loc = strdup(start + 1); } } else if ((fl[i].flag == MF_FORCECRYPT) && flag_vals) { /* The forceencrypt flag is followed by an = and the * location of the keys. Get it and return it. Loading Loading @@ -291,6 +300,7 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path) fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, &flag_vals, NULL, 0); fstab->recs[cnt].key_loc = flag_vals.key_loc; fstab->recs[cnt].verity_loc = flag_vals.verity_loc; fstab->recs[cnt].length = flag_vals.part_length; fstab->recs[cnt].label = flag_vals.label; fstab->recs[cnt].partnum = flag_vals.partnum; Loading fs_mgr/fs_mgr_verity.c +185 −62 Original line number Diff line number Diff line Loading @@ -47,16 +47,23 @@ #define VERITY_METADATA_SIZE 32768 #define VERITY_TABLE_RSA_KEY "/verity_key" #define METADATA_MAGIC 0x01564c54 #define METADATA_TAG_MAX_LENGTH 63 #define METADATA_EOD "eod" #define VERITY_STATE_TAG "verity_state" #define VERITY_STATE_HEADER 0x83c0ae9d #define VERITY_STATE_VERSION 1 #define VERITY_KMSG_RESTART "dm-verity device corrupted" #define VERITY_KMSG_BUFSIZE 1024 #define __STRINGIFY(x) #x #define STRINGIFY(x) __STRINGIFY(x) struct verity_state { uint32_t header; uint32_t version; uint32_t size; int32_t mode; }; Loading Loading @@ -453,83 +460,151 @@ static int was_verity_restart() return 0; } static int write_verity_state(const char *fname, off64_t offset, int32_t mode) static int metadata_add(FILE *fp, long start, const char *tag, unsigned int length, off64_t *offset) { int fd; if (TEMP_FAILURE_RETRY(fseek(fp, start, SEEK_SET)) < 0 || TEMP_FAILURE_RETRY(fprintf(fp, "%s %u\n", tag, length)) < 0) { return -1; } *offset = ftell(fp); if (TEMP_FAILURE_RETRY(fseek(fp, length, SEEK_CUR)) < 0 || TEMP_FAILURE_RETRY(fprintf(fp, METADATA_EOD " 0\n")) < 0) { return -1; } return 0; } static int metadata_find(const char *fname, const char *stag, unsigned int slength, off64_t *offset) { FILE *fp = NULL; char tag[METADATA_TAG_MAX_LENGTH + 1]; int rc = -1; int n; long start = 0x4000; /* skip cryptfs metadata area */ uint32_t magic; unsigned int length = 0; struct verity_state s = { VERITY_STATE_HEADER, VERITY_STATE_VERSION, sizeof(struct verity_state), mode }; if (!fname) { return -1; } fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC)); fp = TEMP_FAILURE_RETRY(fopen(fname, "r+")); if (fd == -1) { if (!fp) { ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); goto out; } if (TEMP_FAILURE_RETRY(lseek64(fd, offset, SEEK_SET)) < 0) { ERROR("Failed to seek %s to %" PRIu64 " (%s)\n", fname, offset, strerror(errno)); /* check magic */ if (TEMP_FAILURE_RETRY(fseek(fp, start, SEEK_SET)) < 0 || TEMP_FAILURE_RETRY(fread(&magic, sizeof(magic), 1, fp)) != 1) { ERROR("Failed to read magic from %s (%s)\n", fname, strerror(errno)); goto out; } if (TEMP_FAILURE_RETRY(write(fd, &s, sizeof(s))) != sizeof(s)) { ERROR("Failed to write %zu bytes to %s (%s)\n", sizeof(s), fname, strerror(errno)); if (magic != METADATA_MAGIC) { magic = METADATA_MAGIC; if (TEMP_FAILURE_RETRY(fseek(fp, start, SEEK_SET)) < 0 || TEMP_FAILURE_RETRY(fwrite(&magic, sizeof(magic), 1, fp)) != 1) { ERROR("Failed to write magic to %s (%s)\n", fname, strerror(errno)); goto out; } rc = metadata_add(fp, start + sizeof(magic), stag, slength, offset); if (rc < 0) { ERROR("Failed to add metadata to %s: %s\n", fname, strerror(errno)); } goto out; } start += sizeof(magic); while (1) { n = TEMP_FAILURE_RETRY(fscanf(fp, "%" STRINGIFY(METADATA_TAG_MAX_LENGTH) "s %u\n", tag, &length)); if (n == 2 && strcmp(tag, METADATA_EOD)) { /* found a tag */ start = ftell(fp); if (!strcmp(tag, stag) && length == slength) { *offset = start; rc = 0; goto out; } start += length; if (TEMP_FAILURE_RETRY(fseek(fp, length, SEEK_CUR)) < 0) { ERROR("Failed to seek %s (%s)\n", fname, strerror(errno)); goto out; } } else { rc = metadata_add(fp, start, stag, slength, offset); if (rc < 0) { ERROR("Failed to write metadata to %s: %s\n", fname, strerror(errno)); } goto out; } } out: if (fd != -1) { TEMP_FAILURE_RETRY(close(fd)); if (fp) { TEMP_FAILURE_RETRY(fflush(fp)); TEMP_FAILURE_RETRY(fclose(fp)); } return rc; } static int get_verity_state_location(char *location, off64_t *offset) static int write_verity_state(const char *fname, off64_t offset, int32_t mode) { char state_off[PROPERTY_VALUE_MAX]; int fd; int rc = -1; struct verity_state s = { VERITY_STATE_HEADER, VERITY_STATE_VERSION, mode }; if (property_get("ro.verity.state.location", location, NULL) <= 0) { return -1; } fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC)); if (*location != '/' || access(location, R_OK | W_OK) == -1) { ERROR("Failed to access verity state %s (%s)\n", location, strerror(errno)); return -1; if (fd == -1) { ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); goto out; } *offset = 0; if (TEMP_FAILURE_RETRY(pwrite64(fd, &s, sizeof(s), offset)) != sizeof(s)) { ERROR("Failed to write %zu bytes to %s to offset %" PRIu64 " (%s)\n", sizeof(s), fname, offset, strerror(errno)); goto out; } if (property_get("ro.verity.state.offset", state_off, NULL) > 0) { *offset = strtoll(state_off, NULL, 0); rc = 0; if (errno == ERANGE || errno == EINVAL) { ERROR("Invalid value in ro.verity.state.offset (%s)\n", state_off); return -1; } out: if (fd != -1) { TEMP_FAILURE_RETRY(close(fd)); } return 0; return rc; } int fs_mgr_load_verity_state(int *mode) static int load_verity_state(struct fstab_rec *fstab, int *mode) { char fname[PROPERTY_VALUE_MAX]; int fd = -1; int rc = -1; off64_t offset = 0; struct verity_state s; if (get_verity_state_location(fname, &offset) < 0) { /* location for dm-verity state is not specified, fall back to * default behavior: return -EIO for corrupted blocks */ if (metadata_find(fstab->verity_loc, VERITY_STATE_TAG, sizeof(s), &offset) < 0) { /* fall back to stateless behavior */ *mode = VERITY_MODE_EIO; rc = 0; goto out; Loading @@ -539,28 +614,27 @@ int fs_mgr_load_verity_state(int *mode) /* device was restarted after dm-verity detected a corrupted * block, so switch to logging mode */ *mode = VERITY_MODE_LOGGING; rc = write_verity_state(fname, offset, *mode); rc = write_verity_state(fstab->verity_loc, offset, *mode); goto out; } fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC)); fd = TEMP_FAILURE_RETRY(open(fstab->verity_loc, O_RDONLY | O_CLOEXEC)); if (fd == -1) { ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); goto out; } if (TEMP_FAILURE_RETRY(lseek64(fd, offset, SEEK_SET)) < 0) { ERROR("Failed to seek %s to %" PRIu64 " (%s)\n", fname, offset, strerror(errno)); ERROR("Failed to open %s (%s)\n", fstab->verity_loc, strerror(errno)); goto out; } if (TEMP_FAILURE_RETRY(read(fd, &s, sizeof(s))) != sizeof(s)) { ERROR("Failed to read %zu bytes from %s (%s)\n", sizeof(s), fname, strerror(errno)); if (TEMP_FAILURE_RETRY(pread64(fd, &s, sizeof(s), offset)) != sizeof(s)) { ERROR("Failed to read %zu bytes from %s offset %" PRIu64 " (%s)\n", sizeof(s), fstab->verity_loc, offset, strerror(errno)); goto out; } if (s.header != VERITY_STATE_HEADER) { /* space allocated, but no state written. write default state */ *mode = VERITY_MODE_DEFAULT; rc = write_verity_state(fstab->verity_loc, offset, *mode); goto out; } Loading @@ -569,11 +643,6 @@ int fs_mgr_load_verity_state(int *mode) goto out; } if (s.size != sizeof(s)) { ERROR("Unexpected verity state size (%u)\n", s.size); goto out; } if (s.mode < VERITY_MODE_EIO || s.mode > VERITY_MODE_LAST) { ERROR("Unsupported verity mode (%u)\n", s.mode); Loading @@ -591,13 +660,61 @@ out: return rc; } int fs_mgr_load_verity_state(int *mode) { char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; char propbuf[PROPERTY_VALUE_MAX]; int rc = -1; int i; struct fstab *fstab = NULL; *mode = VERITY_MODE_DEFAULT; property_get("ro.hardware", propbuf, ""); snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); fstab = fs_mgr_read_fstab(fstab_filename); if (!fstab) { ERROR("Failed to read %s\n", fstab_filename); goto out; } for (i = 0; i < fstab->num_entries; i++) { if (!fs_mgr_is_verified(&fstab->recs[i])) { continue; } rc = load_verity_state(&fstab->recs[i], mode); if (rc < 0) { continue; } /* if any of the verified partitions are in logging mode, return */ if (*mode == VERITY_MODE_LOGGING) { rc = 0; goto out; } } /* if there were multiple partitions, all in non-logging mode, return the * state of the last one */ rc = 0; out: if (fstab) { fs_mgr_free_fstab(fstab); } return rc; } int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) { _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE]; char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; char *mount_point; char propbuf[PROPERTY_VALUE_MAX]; char state_loc[PROPERTY_VALUE_MAX]; char *status; int fd = -1; int i; Loading @@ -606,10 +723,6 @@ int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) struct dm_ioctl *io = (struct dm_ioctl *) buffer; struct fstab *fstab = NULL; if (get_verity_state_location(state_loc, &offset) < 0) { goto out; } fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)); if (fd == -1) { Loading @@ -632,6 +745,11 @@ int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) continue; } if (metadata_find(fstab->recs[i].verity_loc, VERITY_STATE_TAG, sizeof(struct verity_state), &offset) < 0) { continue; } mount_point = basename(fstab->recs[i].mount_point); verity_ioctl_init(io, mount_point, 0); Loading @@ -644,7 +762,8 @@ int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) status = &buffer[io->data_start + sizeof(struct dm_target_spec)]; if (*status == 'C') { rc = write_verity_state(state_loc, offset, VERITY_MODE_LOGGING); rc = write_verity_state(fstab->recs[i].verity_loc, offset, VERITY_MODE_LOGGING); if (rc == -1) { goto out; Loading Loading @@ -732,8 +851,12 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { goto out; } if (fs_mgr_load_verity_state(&mode) < 0) { mode = VERITY_MODE_RESTART; /* default dm-verity mode */ if (load_verity_state(fstab, &mode) < 0) { /* if accessing or updating the state failed, switch to the default * safe mode. This makes sure the device won't end up in an endless * restart loop, and no corrupted data will be exposed to userspace * without a warning. */ mode = VERITY_MODE_EIO; } INFO("Enabling dm-verity for %s (mode %d)\n", mount_point, mode); Loading fs_mgr/include/fs_mgr.h +2 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,8 @@ enum verity_mode { VERITY_MODE_EIO = 0, VERITY_MODE_LOGGING = 1, VERITY_MODE_RESTART = 2, VERITY_MODE_LAST = VERITY_MODE_RESTART VERITY_MODE_LAST = VERITY_MODE_RESTART, VERITY_MODE_DEFAULT = VERITY_MODE_RESTART }; /* Loading Loading
fs_mgr/fs_mgr_fstab.c +10 −0 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ struct fs_mgr_flag_values { char *key_loc; char *verity_loc; long long part_length; char *label; int partnum; Loading Loading @@ -107,6 +108,14 @@ 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); } else if ((fl[i].flag == MF_VERIFY) && flag_vals) { /* If the verify flag is followed by an = and the * location for the verity state, get it and return it. */ char *start = strchr(p, '='); if (start) { flag_vals->verity_loc = strdup(start + 1); } } else if ((fl[i].flag == MF_FORCECRYPT) && flag_vals) { /* The forceencrypt flag is followed by an = and the * location of the keys. Get it and return it. Loading Loading @@ -291,6 +300,7 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path) fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags, &flag_vals, NULL, 0); fstab->recs[cnt].key_loc = flag_vals.key_loc; fstab->recs[cnt].verity_loc = flag_vals.verity_loc; fstab->recs[cnt].length = flag_vals.part_length; fstab->recs[cnt].label = flag_vals.label; fstab->recs[cnt].partnum = flag_vals.partnum; Loading
fs_mgr/fs_mgr_verity.c +185 −62 Original line number Diff line number Diff line Loading @@ -47,16 +47,23 @@ #define VERITY_METADATA_SIZE 32768 #define VERITY_TABLE_RSA_KEY "/verity_key" #define METADATA_MAGIC 0x01564c54 #define METADATA_TAG_MAX_LENGTH 63 #define METADATA_EOD "eod" #define VERITY_STATE_TAG "verity_state" #define VERITY_STATE_HEADER 0x83c0ae9d #define VERITY_STATE_VERSION 1 #define VERITY_KMSG_RESTART "dm-verity device corrupted" #define VERITY_KMSG_BUFSIZE 1024 #define __STRINGIFY(x) #x #define STRINGIFY(x) __STRINGIFY(x) struct verity_state { uint32_t header; uint32_t version; uint32_t size; int32_t mode; }; Loading Loading @@ -453,83 +460,151 @@ static int was_verity_restart() return 0; } static int write_verity_state(const char *fname, off64_t offset, int32_t mode) static int metadata_add(FILE *fp, long start, const char *tag, unsigned int length, off64_t *offset) { int fd; if (TEMP_FAILURE_RETRY(fseek(fp, start, SEEK_SET)) < 0 || TEMP_FAILURE_RETRY(fprintf(fp, "%s %u\n", tag, length)) < 0) { return -1; } *offset = ftell(fp); if (TEMP_FAILURE_RETRY(fseek(fp, length, SEEK_CUR)) < 0 || TEMP_FAILURE_RETRY(fprintf(fp, METADATA_EOD " 0\n")) < 0) { return -1; } return 0; } static int metadata_find(const char *fname, const char *stag, unsigned int slength, off64_t *offset) { FILE *fp = NULL; char tag[METADATA_TAG_MAX_LENGTH + 1]; int rc = -1; int n; long start = 0x4000; /* skip cryptfs metadata area */ uint32_t magic; unsigned int length = 0; struct verity_state s = { VERITY_STATE_HEADER, VERITY_STATE_VERSION, sizeof(struct verity_state), mode }; if (!fname) { return -1; } fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC)); fp = TEMP_FAILURE_RETRY(fopen(fname, "r+")); if (fd == -1) { if (!fp) { ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); goto out; } if (TEMP_FAILURE_RETRY(lseek64(fd, offset, SEEK_SET)) < 0) { ERROR("Failed to seek %s to %" PRIu64 " (%s)\n", fname, offset, strerror(errno)); /* check magic */ if (TEMP_FAILURE_RETRY(fseek(fp, start, SEEK_SET)) < 0 || TEMP_FAILURE_RETRY(fread(&magic, sizeof(magic), 1, fp)) != 1) { ERROR("Failed to read magic from %s (%s)\n", fname, strerror(errno)); goto out; } if (TEMP_FAILURE_RETRY(write(fd, &s, sizeof(s))) != sizeof(s)) { ERROR("Failed to write %zu bytes to %s (%s)\n", sizeof(s), fname, strerror(errno)); if (magic != METADATA_MAGIC) { magic = METADATA_MAGIC; if (TEMP_FAILURE_RETRY(fseek(fp, start, SEEK_SET)) < 0 || TEMP_FAILURE_RETRY(fwrite(&magic, sizeof(magic), 1, fp)) != 1) { ERROR("Failed to write magic to %s (%s)\n", fname, strerror(errno)); goto out; } rc = metadata_add(fp, start + sizeof(magic), stag, slength, offset); if (rc < 0) { ERROR("Failed to add metadata to %s: %s\n", fname, strerror(errno)); } goto out; } start += sizeof(magic); while (1) { n = TEMP_FAILURE_RETRY(fscanf(fp, "%" STRINGIFY(METADATA_TAG_MAX_LENGTH) "s %u\n", tag, &length)); if (n == 2 && strcmp(tag, METADATA_EOD)) { /* found a tag */ start = ftell(fp); if (!strcmp(tag, stag) && length == slength) { *offset = start; rc = 0; goto out; } start += length; if (TEMP_FAILURE_RETRY(fseek(fp, length, SEEK_CUR)) < 0) { ERROR("Failed to seek %s (%s)\n", fname, strerror(errno)); goto out; } } else { rc = metadata_add(fp, start, stag, slength, offset); if (rc < 0) { ERROR("Failed to write metadata to %s: %s\n", fname, strerror(errno)); } goto out; } } out: if (fd != -1) { TEMP_FAILURE_RETRY(close(fd)); if (fp) { TEMP_FAILURE_RETRY(fflush(fp)); TEMP_FAILURE_RETRY(fclose(fp)); } return rc; } static int get_verity_state_location(char *location, off64_t *offset) static int write_verity_state(const char *fname, off64_t offset, int32_t mode) { char state_off[PROPERTY_VALUE_MAX]; int fd; int rc = -1; struct verity_state s = { VERITY_STATE_HEADER, VERITY_STATE_VERSION, mode }; if (property_get("ro.verity.state.location", location, NULL) <= 0) { return -1; } fd = TEMP_FAILURE_RETRY(open(fname, O_WRONLY | O_SYNC | O_CLOEXEC)); if (*location != '/' || access(location, R_OK | W_OK) == -1) { ERROR("Failed to access verity state %s (%s)\n", location, strerror(errno)); return -1; if (fd == -1) { ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); goto out; } *offset = 0; if (TEMP_FAILURE_RETRY(pwrite64(fd, &s, sizeof(s), offset)) != sizeof(s)) { ERROR("Failed to write %zu bytes to %s to offset %" PRIu64 " (%s)\n", sizeof(s), fname, offset, strerror(errno)); goto out; } if (property_get("ro.verity.state.offset", state_off, NULL) > 0) { *offset = strtoll(state_off, NULL, 0); rc = 0; if (errno == ERANGE || errno == EINVAL) { ERROR("Invalid value in ro.verity.state.offset (%s)\n", state_off); return -1; } out: if (fd != -1) { TEMP_FAILURE_RETRY(close(fd)); } return 0; return rc; } int fs_mgr_load_verity_state(int *mode) static int load_verity_state(struct fstab_rec *fstab, int *mode) { char fname[PROPERTY_VALUE_MAX]; int fd = -1; int rc = -1; off64_t offset = 0; struct verity_state s; if (get_verity_state_location(fname, &offset) < 0) { /* location for dm-verity state is not specified, fall back to * default behavior: return -EIO for corrupted blocks */ if (metadata_find(fstab->verity_loc, VERITY_STATE_TAG, sizeof(s), &offset) < 0) { /* fall back to stateless behavior */ *mode = VERITY_MODE_EIO; rc = 0; goto out; Loading @@ -539,28 +614,27 @@ int fs_mgr_load_verity_state(int *mode) /* device was restarted after dm-verity detected a corrupted * block, so switch to logging mode */ *mode = VERITY_MODE_LOGGING; rc = write_verity_state(fname, offset, *mode); rc = write_verity_state(fstab->verity_loc, offset, *mode); goto out; } fd = TEMP_FAILURE_RETRY(open(fname, O_RDONLY | O_CLOEXEC)); fd = TEMP_FAILURE_RETRY(open(fstab->verity_loc, O_RDONLY | O_CLOEXEC)); if (fd == -1) { ERROR("Failed to open %s (%s)\n", fname, strerror(errno)); goto out; } if (TEMP_FAILURE_RETRY(lseek64(fd, offset, SEEK_SET)) < 0) { ERROR("Failed to seek %s to %" PRIu64 " (%s)\n", fname, offset, strerror(errno)); ERROR("Failed to open %s (%s)\n", fstab->verity_loc, strerror(errno)); goto out; } if (TEMP_FAILURE_RETRY(read(fd, &s, sizeof(s))) != sizeof(s)) { ERROR("Failed to read %zu bytes from %s (%s)\n", sizeof(s), fname, strerror(errno)); if (TEMP_FAILURE_RETRY(pread64(fd, &s, sizeof(s), offset)) != sizeof(s)) { ERROR("Failed to read %zu bytes from %s offset %" PRIu64 " (%s)\n", sizeof(s), fstab->verity_loc, offset, strerror(errno)); goto out; } if (s.header != VERITY_STATE_HEADER) { /* space allocated, but no state written. write default state */ *mode = VERITY_MODE_DEFAULT; rc = write_verity_state(fstab->verity_loc, offset, *mode); goto out; } Loading @@ -569,11 +643,6 @@ int fs_mgr_load_verity_state(int *mode) goto out; } if (s.size != sizeof(s)) { ERROR("Unexpected verity state size (%u)\n", s.size); goto out; } if (s.mode < VERITY_MODE_EIO || s.mode > VERITY_MODE_LAST) { ERROR("Unsupported verity mode (%u)\n", s.mode); Loading @@ -591,13 +660,61 @@ out: return rc; } int fs_mgr_load_verity_state(int *mode) { char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; char propbuf[PROPERTY_VALUE_MAX]; int rc = -1; int i; struct fstab *fstab = NULL; *mode = VERITY_MODE_DEFAULT; property_get("ro.hardware", propbuf, ""); snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf); fstab = fs_mgr_read_fstab(fstab_filename); if (!fstab) { ERROR("Failed to read %s\n", fstab_filename); goto out; } for (i = 0; i < fstab->num_entries; i++) { if (!fs_mgr_is_verified(&fstab->recs[i])) { continue; } rc = load_verity_state(&fstab->recs[i], mode); if (rc < 0) { continue; } /* if any of the verified partitions are in logging mode, return */ if (*mode == VERITY_MODE_LOGGING) { rc = 0; goto out; } } /* if there were multiple partitions, all in non-logging mode, return the * state of the last one */ rc = 0; out: if (fstab) { fs_mgr_free_fstab(fstab); } return rc; } int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) { _Alignas(struct dm_ioctl) char buffer[DM_BUF_SIZE]; char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)]; char *mount_point; char propbuf[PROPERTY_VALUE_MAX]; char state_loc[PROPERTY_VALUE_MAX]; char *status; int fd = -1; int i; Loading @@ -606,10 +723,6 @@ int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) struct dm_ioctl *io = (struct dm_ioctl *) buffer; struct fstab *fstab = NULL; if (get_verity_state_location(state_loc, &offset) < 0) { goto out; } fd = TEMP_FAILURE_RETRY(open("/dev/device-mapper", O_RDWR | O_CLOEXEC)); if (fd == -1) { Loading @@ -632,6 +745,11 @@ int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) continue; } if (metadata_find(fstab->recs[i].verity_loc, VERITY_STATE_TAG, sizeof(struct verity_state), &offset) < 0) { continue; } mount_point = basename(fstab->recs[i].mount_point); verity_ioctl_init(io, mount_point, 0); Loading @@ -644,7 +762,8 @@ int fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback) status = &buffer[io->data_start + sizeof(struct dm_target_spec)]; if (*status == 'C') { rc = write_verity_state(state_loc, offset, VERITY_MODE_LOGGING); rc = write_verity_state(fstab->recs[i].verity_loc, offset, VERITY_MODE_LOGGING); if (rc == -1) { goto out; Loading Loading @@ -732,8 +851,12 @@ int fs_mgr_setup_verity(struct fstab_rec *fstab) { goto out; } if (fs_mgr_load_verity_state(&mode) < 0) { mode = VERITY_MODE_RESTART; /* default dm-verity mode */ if (load_verity_state(fstab, &mode) < 0) { /* if accessing or updating the state failed, switch to the default * safe mode. This makes sure the device won't end up in an endless * restart loop, and no corrupted data will be exposed to userspace * without a warning. */ mode = VERITY_MODE_EIO; } INFO("Enabling dm-verity for %s (mode %d)\n", mount_point, mode); Loading
fs_mgr/include/fs_mgr.h +2 −1 Original line number Diff line number Diff line Loading @@ -36,7 +36,8 @@ enum verity_mode { VERITY_MODE_EIO = 0, VERITY_MODE_LOGGING = 1, VERITY_MODE_RESTART = 2, VERITY_MODE_LAST = VERITY_MODE_RESTART VERITY_MODE_LAST = VERITY_MODE_RESTART, VERITY_MODE_DEFAULT = VERITY_MODE_RESTART }; /* Loading