@@ -361,11 +361,81 @@ void dm_ima_measure_on_table_clear(struct mapped_device *md, bool new_map)
return;
}
+/*
+ * Measure IMA data on device rename
+ */
+void dm_ima_measure_on_device_rename(struct mapped_device *md)
+{
+ char *old_device_data = NULL, *new_device_data = NULL, *combined_device_data = NULL;
+ char *new_dev_name = NULL, *new_dev_uuid = NULL;
+ unsigned int noio_flag;
+ sector_t capacity;
+
+ noio_flag = memalloc_noio_save();
+ new_device_data = kzalloc(DM_IMA_DEVICE_BUF_LEN, GFP_KERNEL);
+ memalloc_noio_restore(noio_flag);
+
+ if (!new_device_data)
+ return;
+
+ noio_flag = memalloc_noio_save();
+ new_dev_name = kzalloc(DM_NAME_LEN*2, GFP_KERNEL);
+ memalloc_noio_restore(noio_flag);
+ if (!new_dev_name)
+ goto error;
+
+ memalloc_noio_restore(noio_flag);
+ new_dev_uuid = kzalloc(DM_UUID_LEN*2, GFP_KERNEL);
+ memalloc_noio_restore(noio_flag);
+ if (!new_dev_uuid)
+ goto error;
+
+ if (dm_copy_name_and_uuid(md, new_dev_name, new_dev_uuid))
+ goto error;
+
+ fix_separator_chars(&new_dev_name);
+ fix_separator_chars(&new_dev_uuid);
+
+ noio_flag = memalloc_noio_save();
+ combined_device_data = kzalloc(DM_IMA_DEVICE_BUF_LEN * 2, GFP_KERNEL);
+ memalloc_noio_restore(noio_flag);
+
+ if (!combined_device_data)
+ goto error;
+
+ capacity = get_capacity(md->disk);
+
+ old_device_data = md->ima.device_data;
+
+ scnprintf(new_device_data, DM_IMA_DEVICE_BUF_LEN,
+ "name=%s;uuid=%s;capacity=%llu;major=%d;minor=%d;minor_count=%d;num_targets=%u;",
+ new_dev_name, new_dev_uuid, capacity, md->disk->major, md->disk->first_minor,
+ md->disk->minors, md->ima.num_targets);
+ md->ima.device_data = new_device_data;
+ md->ima.device_data_len = strlen(new_device_data);
+
+ scnprintf(combined_device_data, DM_IMA_DEVICE_BUF_LEN * 2, "%snew_name=%s;new_uuid=%s;",
+ old_device_data, new_dev_name, new_dev_uuid);
+
+ dm_ima_measure_data("device_rename", combined_device_data, strlen(combined_device_data));
+
+ goto exit;
+
+error:
+ kfree(new_device_data);
+exit:
+ kfree(combined_device_data);
+ kfree(old_device_data);
+ kfree(new_dev_name);
+ kfree(new_dev_uuid);
+}
+
#else
void dm_ima_measure_on_table_load(struct dm_table *table, unsigned int status_flags) {}
void dm_ima_measure_on_device_resume(struct mapped_device *md, bool swap) {}
void dm_ima_measure_on_device_remove(struct mapped_device *md) {}
void dm_ima_measure_on_table_clear(struct mapped_device *md, bool new_map) {}
+void dm_ima_measure_on_device_rename(struct mapped_device *md) {}
#endif
MODULE_AUTHOR("Tushar Sugandhi <tusharsu@linux.microsoft.com>");
MODULE_DESCRIPTION("Enables IMA measurements for DM targets");
@@ -36,5 +36,6 @@ void dm_ima_measure_on_table_load(struct dm_table *table, unsigned int status_fl
void dm_ima_measure_on_device_resume(struct mapped_device *md, bool swap);
void dm_ima_measure_on_device_remove(struct mapped_device *md);
void dm_ima_measure_on_table_clear(struct mapped_device *md, bool new_map);
+void dm_ima_measure_on_device_rename(struct mapped_device *md);
#endif /*DM_IMA_H*/
@@ -486,6 +486,9 @@ static struct mapped_device *dm_hash_rename(struct dm_ioctl *param,
param->flags |= DM_UEVENT_GENERATED_FLAG;
md = hc->md;
+
+ dm_ima_measure_on_device_rename(md);
+
up_write(&_hash_lock);
kfree(old_name);
A given block device is identified by it's name and UUID. However, both these parameters can be renamed. For an external attestation service to correctly attest a given device, it needs to keep track of these rename events. Fix if there are any separator characters in the new name/UUID. Update the device data for IMA with the new values. Measure both old device data and the new device name/UUID parameters in the same IMA measurement event, so that the old and new values can be connected later. Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com> --- drivers/md/dm-ima.c | 70 +++++++++++++++++++++++++++++++++++++++++++ drivers/md/dm-ima.h | 1 + drivers/md/dm-ioctl.c | 3 ++ 3 files changed, 74 insertions(+)