drm: bridge: dw-hdmi: set ddc scl clock rate according to dts
[firefly-linux-kernel-4.4.55.git] / drivers / md / dm-android-verity.c
index 999e75bf2ba00fa804219593cdc265861370b0b9..bb6c1285e499b466b3d5d2b216eb52e3c50f3965 100644 (file)
@@ -59,8 +59,7 @@ static struct target_type android_verity_target = {
        .dtr                    = verity_dtr,
        .map                    = verity_map,
        .status                 = verity_status,
-       .ioctl                  = verity_ioctl,
-       .merge                  = verity_merge,
+       .prepare_ioctl          = verity_prepare_ioctl,
        .iterate_devices        = verity_iterate_devices,
        .io_hints               = verity_io_hints,
 };
@@ -267,10 +266,7 @@ static inline int validate_fec_header(struct fec_header *header, u64 offset)
                le32_to_cpu(header->version) != FEC_VERSION ||
                le32_to_cpu(header->size) != sizeof(struct fec_header) ||
                le32_to_cpu(header->roots) == 0 ||
-               le32_to_cpu(header->roots) >= FEC_RSM ||
-               offset < le32_to_cpu(header->fec_size) ||
-               offset - le32_to_cpu(header->fec_size) !=
-               le64_to_cpu(header->inp_size))
+               le32_to_cpu(header->roots) >= FEC_RSM)
                return -EINVAL;
 
        return 0;
@@ -365,12 +361,38 @@ static int find_size(dev_t dev, u64 *device_size)
        return 0;
 }
 
-static struct android_metadata *extract_metadata(dev_t dev,
-                               struct fec_header *fec)
+static int verify_header(struct android_metadata_header *header)
+{
+       int retval = -EINVAL;
+
+       if (is_userdebug() && le32_to_cpu(header->magic_number) ==
+                       VERITY_METADATA_MAGIC_DISABLE)
+               return VERITY_STATE_DISABLE;
+
+       if (!(le32_to_cpu(header->magic_number) ==
+                       VERITY_METADATA_MAGIC_NUMBER) ||
+                       (le32_to_cpu(header->magic_number) ==
+                       VERITY_METADATA_MAGIC_DISABLE)) {
+               DMERR("Incorrect magic number");
+               return retval;
+       }
+
+       if (le32_to_cpu(header->protocol_version) !=
+                       VERITY_METADATA_VERSION) {
+               DMERR("Unsupported version %u",
+                       le32_to_cpu(header->protocol_version));
+               return retval;
+       }
+
+       return 0;
+}
+
+static int extract_metadata(dev_t dev, struct fec_header *fec,
+                               struct android_metadata **metadata,
+                               bool *verity_enabled)
 {
        struct block_device *bdev;
        struct android_metadata_header *header;
-       struct android_metadata *uninitialized_var(metadata);
        int i;
        u32 table_length, copy_length, offset;
        u64 metadata_offset;
@@ -381,7 +403,7 @@ static struct android_metadata *extract_metadata(dev_t dev,
 
        if (IS_ERR_OR_NULL(bdev)) {
                DMERR("blkdev_get_by_dev failed");
-               return ERR_CAST(bdev);
+               return -ENODEV;
        }
 
        find_metadata_offset(fec, bdev, &metadata_offset);
@@ -399,7 +421,6 @@ static struct android_metadata *extract_metadata(dev_t dev,
                (1 << SECTOR_SHIFT), VERITY_METADATA_SIZE);
        if (err) {
                DMERR("Error while reading verity metadata");
-               metadata = ERR_PTR(err);
                goto blkdev_release;
        }
 
@@ -418,24 +439,42 @@ static struct android_metadata *extract_metadata(dev_t dev,
                le32_to_cpu(header->protocol_version),
                le32_to_cpu(header->table_length));
 
-       metadata = kzalloc(sizeof(*metadata), GFP_KERNEL);
-       if (!metadata) {
+       err = verify_header(header);
+
+       if (err == VERITY_STATE_DISABLE) {
+               DMERR("Mounting root with verity disabled");
+               *verity_enabled = false;
+               /* we would still have to read the metadata to figure out
+                * the data blocks size. Or may be could map the entire
+                * partition similar to mounting the device.
+                *
+                * Reset error as well as the verity_enabled flag is changed.
+                */
+               err = 0;
+       } else if (err)
+               goto free_header;
+
+       *metadata = kzalloc(sizeof(**metadata), GFP_KERNEL);
+       if (!*metadata) {
                DMERR("kzalloc for metadata failed");
                err = -ENOMEM;
                goto free_header;
        }
 
-       metadata->header = header;
+       (*metadata)->header = header;
        table_length = le32_to_cpu(header->table_length);
 
        if (table_length == 0 ||
                table_length > (VERITY_METADATA_SIZE -
-                       sizeof(struct android_metadata_header)))
+                       sizeof(struct android_metadata_header))) {
+               DMERR("table_length too long");
+               err = -EINVAL;
                goto free_metadata;
+       }
 
-       metadata->verity_table = kzalloc(table_length + 1, GFP_KERNEL);
+       (*metadata)->verity_table = kzalloc(table_length + 1, GFP_KERNEL);
 
-       if (!metadata->verity_table) {
+       if (!(*metadata)->verity_table) {
                DMERR("kzalloc verity_table failed");
                err = -ENOMEM;
                goto free_metadata;
@@ -443,13 +482,15 @@ static struct android_metadata *extract_metadata(dev_t dev,
 
        if (sizeof(struct android_metadata_header) +
                        table_length <= PAGE_SIZE) {
-               memcpy(metadata->verity_table, page_address(payload.page_io[0])
+               memcpy((*metadata)->verity_table,
+                       page_address(payload.page_io[0])
                        + sizeof(struct android_metadata_header),
                        table_length);
        } else {
                copy_length = PAGE_SIZE -
                        sizeof(struct android_metadata_header);
-               memcpy(metadata->verity_table, page_address(payload.page_io[0])
+               memcpy((*metadata)->verity_table,
+                       page_address(payload.page_io[0])
                        + sizeof(struct android_metadata_header),
                        copy_length);
                table_length -= copy_length;
@@ -457,13 +498,13 @@ static struct android_metadata *extract_metadata(dev_t dev,
                i = 1;
                while (table_length != 0) {
                        if (table_length > PAGE_SIZE) {
-                               memcpy(metadata->verity_table + offset,
+                               memcpy((*metadata)->verity_table + offset,
                                        page_address(payload.page_io[i]),
                                        PAGE_SIZE);
                                offset += PAGE_SIZE;
                                table_length -= PAGE_SIZE;
                        } else {
-                               memcpy(metadata->verity_table + offset,
+                               memcpy((*metadata)->verity_table + offset,
                                        page_address(payload.page_io[i]),
                                        table_length);
                                table_length = 0;
@@ -471,25 +512,23 @@ static struct android_metadata *extract_metadata(dev_t dev,
                        i++;
                }
        }
-       metadata->verity_table[table_length] = '\0';
+       (*metadata)->verity_table[table_length] = '\0';
 
+       DMINFO("verity_table: %s", (*metadata)->verity_table);
        goto free_payload;
 
 free_metadata:
-       kfree(metadata);
+       kfree(*metadata);
 free_header:
        kfree(header);
-       metadata = ERR_PTR(err);
 free_payload:
        for (i = 0; i < payload.number_of_pages; i++)
                if (payload.page_io[i])
                        __free_page(payload.page_io[i]);
        kfree(payload.page_io);
-
-       DMINFO("verity_table: %s", metadata->verity_table);
 blkdev_release:
        blkdev_put(bdev, FMODE_READ);
-       return metadata;
+       return err;
 }
 
 /* helper functions to extract properties from dts */
@@ -522,34 +561,6 @@ static int verity_mode(void)
        return DM_VERITY_MODE_EIO;
 }
 
-static int verify_header(struct android_metadata_header *header)
-{
-       int retval = -EINVAL;
-
-       if (is_userdebug() && le32_to_cpu(header->magic_number) ==
-               VERITY_METADATA_MAGIC_DISABLE) {
-               retval = VERITY_STATE_DISABLE;
-               return retval;
-       }
-
-       if (!(le32_to_cpu(header->magic_number) ==
-               VERITY_METADATA_MAGIC_NUMBER) ||
-               (le32_to_cpu(header->magic_number) ==
-               VERITY_METADATA_MAGIC_DISABLE)) {
-               DMERR("Incorrect magic number");
-               return retval;
-       }
-
-       if (le32_to_cpu(header->protocol_version) !=
-               VERITY_METADATA_VERSION) {
-               DMERR("Unsupported version %u",
-                       le32_to_cpu(header->protocol_version));
-               return retval;
-       }
-
-       return 0;
-}
-
 static int verify_verity_signature(char *key_id,
                struct android_metadata *metadata)
 {
@@ -622,8 +633,7 @@ static int add_as_linear_device(struct dm_target *ti, char *dev)
        android_verity_target.dtr = dm_linear_dtr,
        android_verity_target.map = dm_linear_map,
        android_verity_target.status = dm_linear_status,
-       android_verity_target.ioctl = dm_linear_ioctl,
-       android_verity_target.merge = dm_linear_merge,
+       android_verity_target.prepare_ioctl = dm_linear_prepare_ioctl,
        android_verity_target.iterate_devices = dm_linear_iterate_devices,
        android_verity_target.io_hints = NULL;
 
@@ -649,7 +659,7 @@ static int add_as_linear_device(struct dm_target *ti, char *dev)
 static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
 {
        dev_t uninitialized_var(dev);
-       struct android_metadata *uninitialized_var(metadata);
+       struct android_metadata *metadata = NULL;
        int err = 0, i, mode;
        char *key_id, *table_ptr, dummy, *target_device,
        *verity_table_args[VERITY_TABLE_ARGS + 2 + VERITY_TABLE_OPT_FEC_ARGS];
@@ -661,7 +671,7 @@ static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        struct fec_ecc_metadata uninitialized_var(ecc);
        char buf[FEC_ARG_LENGTH], *buf_ptr;
        unsigned long long tmpll;
-       u64 device_size;
+       u64  uninitialized_var(device_size);
 
        if (argc == 1) {
                /* Use the default keyid */
@@ -717,26 +727,11 @@ static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
                return -EINVAL;
        }
 
-       metadata = extract_metadata(dev, &fec);
+       err = extract_metadata(dev, &fec, &metadata, &verity_enabled);
 
-       if (IS_ERR(metadata)) {
+       if (err) {
                DMERR("Error while extracting metadata");
                handle_error();
-               return -EINVAL;
-       }
-
-       err = verify_header(metadata->header);
-
-       if (err == VERITY_STATE_DISABLE) {
-               DMERR("Mounting root with verity disabled");
-               verity_enabled = false;
-               /* we would still have to parse the args to figure out
-                * the data blocks size. Or may be could map the entire
-                * partition similar to mounting the device.
-                */
-       } else if (err) {
-               DMERR("Verity header handle error");
-               handle_error();
                goto free_metadata;
        }
 
@@ -869,8 +864,10 @@ static int android_verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        }
 
 free_metadata:
-       kfree(metadata->header);
-       kfree(metadata->verity_table);
+       if (metadata) {
+               kfree(metadata->header);
+               kfree(metadata->verity_table);
+       }
        kfree(metadata);
        return err;
 }
@@ -894,7 +891,7 @@ static int __init dm_android_verity_init(void)
        }
 
        file = debugfs_create_bool("target_added", S_IRUGO, debug_dir,
-                               (u32 *)&target_added);
+                               &target_added);
 
        if (IS_ERR_OR_NULL(file)) {
                DMERR("Cannot create android_verity debugfs directory: %ld",
@@ -904,7 +901,7 @@ static int __init dm_android_verity_init(void)
        }
 
        file = debugfs_create_bool("verity_enabled", S_IRUGO, debug_dir,
-                               (u32 *)&verity_enabled);
+                               &verity_enabled);
 
        if (IS_ERR_OR_NULL(file)) {
                DMERR("Cannot create android_verity debugfs directory: %ld",