diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 8363ba38499256d116d2e557823c4616ae01edfe..9df26a2b75ba692ee9d164fb14317779a117ca16 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -266,7 +266,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, xattr_len, NULL}; int violation = 0; - if (iint->flags & IMA_MEASURED) + if (iint->measured_pcrs & (0x1 << pcr)) return; result = ima_alloc_init_template(&event_data, &entry); @@ -277,8 +277,10 @@ void ima_store_measurement(struct integrity_iint_cache *iint, } result = ima_store_template(entry, violation, inode, filename, pcr); - if (!result || result == -EEXIST) + if (!result || result == -EEXIST) { iint->flags |= IMA_MEASURED; + iint->measured_pcrs |= (0x1 << pcr); + } if (result < 0) ima_free_template_entry(entry); } diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index fe8e92360d77fd3649ef7662d6c76b3a038e7c01..4b9b4a4e1b89ced4167c3a318580b46ae23f2621 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -370,6 +370,7 @@ static void ima_reset_appraise_flags(struct inode *inode, int digsig) return; iint->flags &= ~IMA_DONE_MASK; + iint->measured_pcrs = 0; if (digsig) iint->flags |= IMA_DIGSIG; return; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 3627afdc932e6b2b63a632a48b04a787c8e45303..596ef616ac2183fe1eb65a4899b9941af48b67db 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -125,6 +125,7 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint, if ((iint->version != inode->i_version) || (iint->flags & IMA_NEW_FILE)) { iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE); + iint->measured_pcrs = 0; if (iint->flags & IMA_APPRAISE) ima_update_xattr(iint, file); } @@ -210,7 +211,11 @@ static int process_measurement(struct file *file, char *buf, loff_t size, */ iint->flags |= action; action &= IMA_DO_MASK; - action &= ~((iint->flags & IMA_DONE_MASK) >> 1); + action &= ~((iint->flags & (IMA_DONE_MASK ^ IMA_MEASURED)) >> 1); + + /* If target pcr is already measured, unset IMA_MEASURE action */ + if ((action & IMA_MEASURE) && (iint->measured_pcrs & (0x1 << pcr))) + action ^= IMA_MEASURE; /* Nothing to do, just return existing appraised status */ if (!action) {