Skip to content

Commit

Permalink
ima: Store the measurement again when appraising a modsig
Browse files Browse the repository at this point in the history
If the IMA template contains the "modsig" or "d-modsig" field, then the
modsig should be added to the measurement list when the file is appraised.

And that is what normally happens, but if a measurement rule caused a file
containing a modsig to be measured before a different rule causes it to be
appraised, the resulting measurement entry will not contain the modsig
because it is only fetched during appraisal. When the appraisal rule
triggers, it won't store a new measurement containing the modsig because
the file was already measured.

We need to detect that situation and store an additional measurement with
the modsig. This is done by adding an IMA_MEASURE action flag if we read a
modsig and the IMA template contains a modsig field.

Suggested-by: Mimi Zohar <zohar@linux.ibm.com>
Signed-off-by: Thiago Jung Bauermann <bauerman@linux.ibm.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
  • Loading branch information
bauermann authored and mimizohar committed Aug 5, 2019
1 parent 3878d50 commit e509225
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 7 deletions.
1 change: 1 addition & 0 deletions security/integrity/ima/ima.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ int template_desc_init_fields(const char *template_fmt,
int *num_fields);
struct ima_template_desc *ima_template_desc_current(void);
struct ima_template_desc *lookup_template_desc(const char *name);
bool ima_template_has_modsig(const struct ima_template_desc *ima_template);
int ima_restore_measurement_entry(struct ima_template_entry *entry);
int ima_restore_measurement_list(loff_t bufsize, void *buf);
int ima_measurements_show(struct seq_file *m, void *v);
Expand Down
19 changes: 15 additions & 4 deletions security/integrity/ima/ima_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,14 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
char digest[IMA_MAX_DIGEST_SIZE];
} hash;

/*
* Always collect the modsig, because IMA might have already collected
* the file digest without collecting the modsig in a previous
* measurement rule.
*/
if (modsig)
ima_collect_modsig(modsig, buf, size);

if (iint->flags & IMA_COLLECTED)
goto out;

Expand Down Expand Up @@ -252,9 +260,6 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
memcpy(iint->ima_hash, &hash, length);
iint->version = i_version;

if (modsig)
ima_collect_modsig(modsig, buf, size);

/* Possibly temporary failure due to type of read (eg. O_DIRECT) */
if (!result)
iint->flags |= IMA_COLLECTED;
Expand Down Expand Up @@ -304,7 +309,13 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
.modsig = modsig };
int violation = 0;

if (iint->measured_pcrs & (0x1 << pcr))
/*
* We still need to store the measurement in the case of MODSIG because
* we only have its contents to put in the list at the time of
* appraisal, but a file measurement from earlier might already exist in
* the measurement list.
*/
if (iint->measured_pcrs & (0x1 << pcr) && !modsig)
return;

result = ima_alloc_init_template(&event_data, &entry, template_desc);
Expand Down
15 changes: 12 additions & 3 deletions security/integrity/ima/ima_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,9 +307,18 @@ static int process_measurement(struct file *file, const struct cred *cred,
/* read 'security.ima' */
xattr_len = ima_read_xattr(file_dentry(file), &xattr_value);

/* Read the appended modsig if allowed by the policy. */
if (iint->flags & IMA_MODSIG_ALLOWED)
ima_read_modsig(func, buf, size, &modsig);
/*
* Read the appended modsig if allowed by the policy, and allow
* an additional measurement list entry, if needed, based on the
* template format and whether the file was already measured.
*/
if (iint->flags & IMA_MODSIG_ALLOWED) {
rc = ima_read_modsig(func, buf, size, &modsig);

if (!rc && ima_template_has_modsig(template_desc) &&
iint->flags & IMA_MEASURED)
action |= IMA_MEASURE;
}
}

hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
Expand Down
19 changes: 19 additions & 0 deletions security/integrity/ima/ima_template.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,25 @@ static const struct ima_template_field supported_fields[] = {

static struct ima_template_desc *ima_template;

/**
* ima_template_has_modsig - Check whether template has modsig-related fields.
* @ima_template: IMA template to check.
*
* Tells whether the given template has fields referencing a file's appended
* signature.
*/
bool ima_template_has_modsig(const struct ima_template_desc *ima_template)
{
int i;

for (i = 0; i < ima_template->num_fields; i++)
if (!strcmp(ima_template->fields[i]->field_id, "modsig") ||
!strcmp(ima_template->fields[i]->field_id, "d-modsig"))
return true;

return false;
}

static int __init ima_template_setup(char *str)
{
struct ima_template_desc *template_desc;
Expand Down

0 comments on commit e509225

Please sign in to comment.