Merge tag 'for-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux...
[sfrench/cifs-2.6.git] / security / integrity / ima / ima_template.c
index da8cf2d3fd647fb87c82ae1b5e782fa226d85d9e..1e89e2d3851f997f5f455c3e82f9854932b3280b 100644 (file)
@@ -301,6 +301,7 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc,
                                     int template_data_size,
                                     struct ima_template_entry **entry)
 {
+       struct tpm_digest *digests;
        int ret = 0;
        int i;
 
@@ -309,11 +310,21 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc,
        if (!*entry)
                return -ENOMEM;
 
+       digests = kcalloc(NR_BANKS(ima_tpm_chip) + ima_extra_slots,
+                         sizeof(*digests), GFP_NOFS);
+       if (!digests) {
+               kfree(*entry);
+               return -ENOMEM;
+       }
+
+       (*entry)->digests = digests;
+
        ret = ima_parse_buf(template_data, template_data + template_data_size,
                            NULL, template_desc->num_fields,
                            (*entry)->template_data, NULL, NULL,
                            ENFORCE_FIELDS | ENFORCE_BUFEND, "template data");
        if (ret < 0) {
+               kfree((*entry)->digests);
                kfree(*entry);
                return ret;
        }
@@ -346,6 +357,7 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc,
 int ima_restore_measurement_list(loff_t size, void *buf)
 {
        char template_name[MAX_TEMPLATE_NAME_LEN];
+       unsigned char zero[TPM_DIGEST_SIZE] = { 0 };
 
        struct ima_kexec_hdr *khdr = buf;
        struct ima_field_data hdr[HDR__LAST] = {
@@ -445,8 +457,17 @@ int ima_restore_measurement_list(loff_t size, void *buf)
                if (ret < 0)
                        break;
 
-               memcpy(entry->digest, hdr[HDR_DIGEST].data,
-                      hdr[HDR_DIGEST].len);
+               if (memcmp(hdr[HDR_DIGEST].data, zero, sizeof(zero))) {
+                       ret = ima_calc_field_array_hash(
+                                               &entry->template_data[0],
+                                               entry);
+                       if (ret < 0) {
+                               pr_err("cannot calculate template digest\n");
+                               ret = -EINVAL;
+                               break;
+                       }
+               }
+
                entry->pcr = !ima_canonical_fmt ? *(hdr[HDR_PCR].data) :
                             le32_to_cpu(*(hdr[HDR_PCR].data));
                ret = ima_restore_measurement_entry(entry);