Hi Lakshmi,I'll make this change.
On Wed, 2020-11-11 at 12:59 -0800, Lakshmi Ramasubramanian wrote:
The default IMA template for measuring buffer should be 'ima-buf' - so
that the measured buffer is correctly included in the IMA measurement
log entry. But the default IMA template used for all policy rules is
the value set for CONFIG_IMA_DEFAULT_TEMPLATE if the policy rule does
not specify a template.
The second sentence defines the current status. The first sentence
describes the problem. I would reverse the sentence order.
^measuring buffer -> buffer measurements
IMA does not take into account the template
requirements of different rules when choosing a default template for
a given policy rule. This breaks the buffer measurement if the template
is not provided as part of the rule because the default template could
be different than 'ima-buf'.
Does the above paragraph add anything new? Instead describe the
problem. Perhaps something like:
With the default template format, buffer measurements are added to the
measurement list, but do not include the buffer data, making it
difficult, if not impossible, to validate. Including "ima-buf"
template records in the measurement list by default, should not impact
existing attestation servers without "ima-buf" template support.
Will remove the above paragraph.
For example, the following IMA policy rule enables measuring
the command line arguments passed to the new kernel on kexec system call.
measure func=KEXEC_CMDLINE
The IMA template selected should be 'ima-buf' to have the measured
command line arguments included in the IMA measurement log entry.
Instead the default IMA template is selected, which could be different
than 'ima-buf'.
When upstreaming a new type of measurement, including an example
provides how to validate the new template data. Not every patch
description requires an example.
I will initialize the buf template in ima_init_template() per your comment below. Will move the check for template right after the check for the IMA policy flag.
Initialize a global 'ima-buf' template and select that template,
by default, for measuring buffer.
Good.
Signed-off-by: Lakshmi Ramasubramanian <nramas@xxxxxxxxxxxxxxxxxxx>
---
security/integrity/ima/ima.h | 1 +
security/integrity/ima/ima_main.c | 17 +++++------------
security/integrity/ima/ima_policy.c | 2 +-
security/integrity/ima/ima_template.c | 25 +++++++++++++++++++++++++
4 files changed, 32 insertions(+), 13 deletions(-)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 6ebefec616e4..8e8b1e3cb847 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -156,6 +156,7 @@ int template_desc_init_fields(const char *template_fmt,
const struct ima_template_field ***fields,
int *num_fields);
struct ima_template_desc *ima_template_desc_current(void);
+struct ima_template_desc *ima_template_desc_buf(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);
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index a962b23e0429..3646ae763ba9 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -413,7 +413,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
*/
int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot)
{
- struct ima_template_desc *template;
+ struct ima_template_desc *template = NULL;
struct file *file = vma->vm_file;
char filename[NAME_MAX];
char *pathbuf = NULL;
@@ -802,7 +802,7 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
.filename = eventname,
.buf = buf,
.buf_len = size};
- struct ima_template_desc *template = NULL;
+ struct ima_template_desc *template = ima_template_desc_buf();
struct {
struct ima_digest_data hdr;
char digest[IMA_MAX_DIGEST_SIZE];
@@ -833,16 +833,9 @@ void process_buffer_measurement(struct inode *inode, const void *buf, int size,
pcr = CONFIG_IMA_MEASURE_PCR_IDX;
if (!template) {
- template = lookup_template_desc("ima-buf");
- ret = template_desc_init_fields(template->fmt,
- &(template->fields),
- &(template->num_fields));
- if (ret < 0) {
- pr_err("template %s init failed, result: %d\n",
- (strlen(template->name) ?
- template->name : template->fmt), ret);
- return;
- }
+ ret = -EINVAL;
+ audit_cause = "ima_template_desc_buf";
+ goto out;
Normally a test follows the variable assignment, but in this case, the
check is being deferred in case there isn't a policy rule.
}
iint.ima_hash = &hash.hdr;
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 9b5adeaa47fc..823a0c1379cb 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -628,7 +628,7 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
struct ima_rule_entry *entry;
int action = 0, actmask = flags | (flags << 1);
- if (template_desc)
+ if (template_desc && !*template_desc)
*template_desc = ima_template_desc_current();
rcu_read_lock();
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index 1e89e2d3851f..e53fce2c1610 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -55,6 +55,7 @@ static const struct ima_template_field supported_fields[] = {
#define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf|d-modisg|modsig")
static struct ima_template_desc *ima_template;
+static struct ima_template_desc *ima_buf_template;
/**
* ima_template_has_modsig - Check whether template has modsig-related fields.
@@ -252,6 +253,30 @@ struct ima_template_desc *ima_template_desc_current(void)
return ima_template;
}
+struct ima_template_desc *ima_template_desc_buf(void)
+{
+ struct ima_template_desc *template = NULL;
+ int ret = 0;
+
+ if (ima_buf_template)
+ return ima_buf_template;
+
+ ima_init_template_list();
+ template = lookup_template_desc("ima-buf");
+ if (!template)
+ return NULL;
+
+ ret = template_desc_init_fields(template->fmt,
+ &(template->fields),
+ &(template->num_fields));
+ if (ret)
+ return NULL;
Instead of initializing the fields here, maybe it should be done in
ima_init_template()? That would remove the deferred !template test in
process_buffer_measurement() and would also simplify this function.
+
+ ima_buf_template = template;
+
+ return ima_buf_template;
+}
+
int __init ima_init_template(void)
{
struct ima_template_desc *template = ima_template_desc_current();