dm ima: add version info to dm related events in ima log
authorTushar Sugandhi <tusharsu@linux.microsoft.com>
Fri, 13 Aug 2021 21:37:57 +0000 (14:37 -0700)
committerMike Snitzer <snitzer@redhat.com>
Fri, 20 Aug 2021 19:59:47 +0000 (15:59 -0400)
The DM events present in the ima log contain various attributes in the
key=value format.  The attributes' names/values may change in future,
and new attributes may also get added.  The attestation server needs
some versioning to determine which attributes are supported and are
expected in the ima log.

Add version information to the DM events present in the ima log to
help attestation servers to correctly process the attributes across
different versions.

Signed-off-by: Tushar Sugandhi <tusharsu@linux.microsoft.com>
Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
drivers/md/dm-ima.c
drivers/md/dm-ima.h

index d4184ff28ccaf321d73ee795c13236e002c15a1f..22faf0698d097b774ae040aa5bb6aa70db58ef69 100644 (file)
@@ -168,6 +168,7 @@ static int dm_ima_alloc_and_copy_capacity_str(struct mapped_device *md, char **c
 void dm_ima_reset_data(struct mapped_device *md)
 {
        memset(&(md->ima), 0, sizeof(md->ima));
+       md->ima.dm_version_str_len = strlen(DM_IMA_VERSION_STR);
 }
 
 /*
@@ -223,6 +224,9 @@ void dm_ima_measure_on_table_load(struct dm_table *table, unsigned int status_fl
        if (r)
                goto error;
 
+       memcpy(ima_buf + l, DM_IMA_VERSION_STR, table->md->ima.dm_version_str_len);
+       l += table->md->ima.dm_version_str_len;
+
        device_data_buf_len = strlen(device_data_buf);
        memcpy(ima_buf + l, device_data_buf, device_data_buf_len);
        l += device_data_buf_len;
@@ -280,6 +284,9 @@ void dm_ima_measure_on_table_load(struct dm_table *table, unsigned int status_fl
                         * prefix, so that multiple records from the same table_load for
                         * a given device can be linked together.
                         */
+                       memcpy(ima_buf + l, DM_IMA_VERSION_STR, table->md->ima.dm_version_str_len);
+                       l += table->md->ima.dm_version_str_len;
+
                        memcpy(ima_buf + l, device_data_buf, device_data_buf_len);
                        l += device_data_buf_len;
 
@@ -367,6 +374,7 @@ void dm_ima_measure_on_device_resume(struct mapped_device *md, bool swap)
        unsigned int active_len = strlen(active), capacity_len = 0;
        unsigned int l = 0;
        bool noio = true;
+       bool nodata = true;
        int r;
 
        device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, GFP_KERNEL, noio);
@@ -377,6 +385,9 @@ void dm_ima_measure_on_device_resume(struct mapped_device *md, bool swap)
        if (r)
                goto error;
 
+       memcpy(device_table_data + l, DM_IMA_VERSION_STR, md->ima.dm_version_str_len);
+       l += md->ima.dm_version_str_len;
+
        if (swap) {
                if (md->ima.active_table.hash != md->ima.inactive_table.hash)
                        kfree(md->ima.active_table.hash);
@@ -412,8 +423,11 @@ void dm_ima_measure_on_device_resume(struct mapped_device *md, bool swap)
        }
 
        if (md->ima.active_table.device_metadata) {
-               l = md->ima.active_table.device_metadata_len;
-               memcpy(device_table_data, md->ima.active_table.device_metadata, l);
+               memcpy(device_table_data + l, md->ima.active_table.device_metadata,
+                      md->ima.active_table.device_metadata_len);
+               l += md->ima.active_table.device_metadata_len;
+
+               nodata = false;
        }
 
        if (md->ima.active_table.hash) {
@@ -426,16 +440,18 @@ void dm_ima_measure_on_device_resume(struct mapped_device *md, bool swap)
 
                memcpy(device_table_data + l, ";", 1);
                l++;
+
+               nodata = false;
        }
 
-       if (!l) {
+       if (nodata) {
                r = dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio);
                if (r)
                        goto error;
 
                scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN,
-                         "name=%s,uuid=%s;device_resume=no_data;",
-                         dev_name, dev_uuid);
+                         "%sname=%s,uuid=%s;device_resume=no_data;",
+                         DM_IMA_VERSION_STR, dev_name, dev_uuid);
                l += strlen(device_table_data);
 
        }
@@ -472,6 +488,7 @@ void dm_ima_measure_on_device_remove(struct mapped_device *md, bool remove_all)
        unsigned int capacity_len = 0;
        unsigned int l = 0;
        bool noio = true;
+       bool nodata = true;
        int r;
 
        device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN*2, GFP_KERNEL, noio);
@@ -484,6 +501,9 @@ void dm_ima_measure_on_device_remove(struct mapped_device *md, bool remove_all)
                goto exit;
        }
 
+       memcpy(device_table_data + l, DM_IMA_VERSION_STR, md->ima.dm_version_str_len);
+       l += md->ima.dm_version_str_len;
+
        if (md->ima.active_table.device_metadata) {
                memcpy(device_table_data + l, device_active_str, device_active_len);
                l += device_active_len;
@@ -491,6 +511,8 @@ void dm_ima_measure_on_device_remove(struct mapped_device *md, bool remove_all)
                memcpy(device_table_data + l, md->ima.active_table.device_metadata,
                       md->ima.active_table.device_metadata_len);
                l += md->ima.active_table.device_metadata_len;
+
+               nodata = false;
        }
 
        if (md->ima.inactive_table.device_metadata) {
@@ -500,6 +522,8 @@ void dm_ima_measure_on_device_remove(struct mapped_device *md, bool remove_all)
                memcpy(device_table_data + l, md->ima.inactive_table.device_metadata,
                       md->ima.inactive_table.device_metadata_len);
                l += md->ima.inactive_table.device_metadata_len;
+
+               nodata = false;
        }
 
        if (md->ima.active_table.hash) {
@@ -512,6 +536,8 @@ void dm_ima_measure_on_device_remove(struct mapped_device *md, bool remove_all)
 
                memcpy(device_table_data + l, ",", 1);
                l++;
+
+               nodata = false;
        }
 
        if (md->ima.inactive_table.hash) {
@@ -524,19 +550,21 @@ void dm_ima_measure_on_device_remove(struct mapped_device *md, bool remove_all)
 
                memcpy(device_table_data + l, ",", 1);
                l++;
+
+               nodata = false;
        }
        /*
         * In case both active and inactive tables, and corresponding
         * device metadata is cleared/missing - record the name and uuid
         * in IMA measurements.
         */
-       if (!l) {
+       if (nodata) {
                if (dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio))
                        goto error;
 
                scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN,
-                         "name=%s,uuid=%s;device_remove=no_data;",
-                         dev_name, dev_uuid);
+                         "%sname=%s,uuid=%s;device_remove=no_data;",
+                         DM_IMA_VERSION_STR, dev_name, dev_uuid);
                l += strlen(device_table_data);
        }
 
@@ -582,6 +610,7 @@ void dm_ima_measure_on_table_clear(struct mapped_device *md, bool new_map)
        char inactive_str[] = "inactive_table_hash=";
        unsigned int inactive_len = strlen(inactive_str);
        bool noio = true;
+       bool nodata = true;
        int r;
 
        device_table_data = dm_ima_alloc(DM_IMA_DEVICE_BUF_LEN, GFP_KERNEL, noio);
@@ -592,6 +621,9 @@ void dm_ima_measure_on_table_clear(struct mapped_device *md, bool new_map)
        if (r)
                goto error1;
 
+       memcpy(device_table_data + l, DM_IMA_VERSION_STR, md->ima.dm_version_str_len);
+       l += md->ima.dm_version_str_len;
+
        if (md->ima.inactive_table.device_metadata_len &&
            md->ima.inactive_table.hash_len) {
                memcpy(device_table_data + l, md->ima.inactive_table.device_metadata,
@@ -608,14 +640,17 @@ void dm_ima_measure_on_table_clear(struct mapped_device *md, bool new_map)
 
                memcpy(device_table_data + l, ";", 1);
                l++;
+
+               nodata = false;
        }
 
-       if (!l) {
+       if (nodata) {
                if (dm_ima_alloc_and_copy_name_uuid(md, &dev_name, &dev_uuid, noio))
                        goto error2;
 
                scnprintf(device_table_data, DM_IMA_DEVICE_BUF_LEN,
-                         "name=%s,uuid=%s;table_clear=no_data;", dev_name, dev_uuid);
+                         "%sname=%s,uuid=%s;table_clear=no_data;",
+                          DM_IMA_VERSION_STR, dev_name, dev_uuid);
                l += strlen(device_table_data);
        }
 
@@ -694,8 +729,9 @@ void dm_ima_measure_on_device_rename(struct mapped_device *md)
        md->ima.active_table.device_metadata = new_device_data;
        md->ima.active_table.device_metadata_len = strlen(new_device_data);
 
-       scnprintf(combined_device_data, DM_IMA_DEVICE_BUF_LEN * 2, "%snew_name=%s,new_uuid=%s;%s",
-                 old_device_data, new_dev_name, new_dev_uuid, capacity_str);
+       scnprintf(combined_device_data, DM_IMA_DEVICE_BUF_LEN * 2,
+                 "%s%snew_name=%s,new_uuid=%s;%s", DM_IMA_VERSION_STR, old_device_data,
+                 new_dev_name, new_dev_uuid, capacity_str);
 
        dm_ima_measure_data("device_rename", combined_device_data, strlen(combined_device_data),
                            noio);
index 0731a51565d6a0f9ae7878d49355b20e045c5e18..b8c3b614670be271c80f4d46938d68b4c66963eb 100644 (file)
 #define DM_IMA_DEVICE_CAPACITY_BUF_LEN 128
 #define DM_IMA_TABLE_HASH_ALG          "sha256"
 
+#define __dm_ima_stringify(s) #s
+#define __dm_ima_str(s) __dm_ima_stringify(s)
+
+#define DM_IMA_VERSION_STR "dm_version="       \
+       __dm_ima_str(DM_VERSION_MAJOR) "."      \
+       __dm_ima_str(DM_VERSION_MINOR) "."      \
+       __dm_ima_str(DM_VERSION_PATCHLEVEL) ";"
+
 #ifdef CONFIG_IMA
 
 struct dm_ima_device_table_metadata {
@@ -46,6 +54,7 @@ struct dm_ima_device_table_metadata {
 struct dm_ima_measurements {
        struct dm_ima_device_table_metadata active_table;
        struct dm_ima_device_table_metadata inactive_table;
+       unsigned int dm_version_str_len;
 };
 
 void dm_ima_reset_data(struct mapped_device *md);