|
From: Roberto S. <rob...@po...> - 2010-04-20 16:03:40
|
Description of the issue:
There is a variety of criteria that can be used to determine if a file must be
measured or not; an useful feature of recent versions of IMA is the ability
of take measure decisions depending on the label assigned by a "Mandatory
Access Control" to a process which is accessing a file or depending on the
object label itself.
In general these data, i.e. the subject and the object labels, can be used
during the "Remote Attestation" by a verifier to better evaluate if a trust
relationship should be established with the remote peer: for example if
it wants to check the integrity only of the sshd server, it can
examine the executable and libraries mapped in the process assigned memory by
selecting, from the list of measurements with enhanced format, the rows
with subject label "sshd_t".
This is just a possible check that can be done: to evaluate the integrity
of a generic software component, the verifier must know what Mandatory Access
Control is being executed on the remote system and the relative policy since
the latter is where labels and rules are defined.
The current format of the measurement list is:
| PCR extended | template digest | ima | event digest | event name |
Solution proposed:
The new format proposed adds two new fields:
| PCR extended | template digest | ima | event digest | event name | subject label | object label |
The added data is retrieved in "ima_store_measurement" by calling the function
"security_secid_to_secctx".
Since the template digest is obtained by performing the SHA1 of "event digest"
and "event name", in the patched code even the two added fields have been
included in the hash operation.
In this patch a new kernel parameter has been introduced, "ima_report_format", to
specify the format that IMA will use for the measurement list. Allowed values are:
- "ima": select the current format [default];
- "ima-ng": select the new format with MAC labels.
This patch set applies to kernel 2.6.32 series and 2.6.33 series.
Signed-off-by: Roberto Sassu <rob...@po...>
Acked-by: Gianluca Ramunno <ra...@po...>
Acked-by: Mimi Zohar <zo...@us...>
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e2c7487..19c268f 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -970,6 +970,16 @@ and is between 256 and 4096 characters. It is defined in the file
programs exec'd, files mmap'd for exec, and all files
opened for read by uid=0.
+ ima_report_format=
+ [IMA]
+ Format: { "ima" | "ima-ng" }
+ default: "ima"
+ Select the format of the measurement list displayed
+ through the securityfs filesystem. The first value
+ means the actual format is kept; the second one adds
+ to each item of the list the subject and object MAC
+ labels, if existent.
+
in2000= [HW,SCSI]
See header of drivers/scsi/in2000.c.
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 47fb65d..10f2410 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -1,9 +1,12 @@
/*
* Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ * Copyright (C) 2009-2010 Politecnico di Torino, Italy,
+ * TORSEC group -- http://security.polito.it
*
* Authors:
* Reiner Sailer <sa...@wa...>
* Mimi Zohar <zo...@us...>
+ * Roberto Sassu <rob...@po...>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -30,19 +33,28 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
/* digest size for IMA, fits SHA1 or MD5 */
#define IMA_DIGEST_SIZE 20
#define IMA_EVENT_NAME_LEN_MAX 255
+#define IMA_LABEL_LEN_MAX 127
#define IMA_HASH_BITS 9
#define IMA_MEASURE_HTABLE_SIZE (1 << IMA_HASH_BITS)
+#define IMA_REPORT_FORMAT_CURRENT 0
+#define IMA_REPORT_FORMAT_CURRENT_LEN offsetof(struct ima_template_data, subj_label)
+#define IMA_REPORT_FORMAT_NG 1
+#define IMA_REPORT_FORMAT_NG_LEN sizeof(struct ima_template_data)
+
/* set during initialization */
extern int ima_initialized;
extern int ima_used_chip;
extern char *ima_hash;
+extern int ima_format;
/* IMA inode template definition */
struct ima_template_data {
u8 digest[IMA_DIGEST_SIZE]; /* sha1/md5 measurement hash */
char file_name[IMA_EVENT_NAME_LEN_MAX + 1]; /* name + \0 */
+ char subj_label[IMA_LABEL_LEN_MAX + 1]; /* subj_label + \0 */
+ char obj_label[IMA_LABEL_LEN_MAX + 1]; /* obj_label + \0 */
};
struct ima_template_entry {
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 2a5e0bc..9848212 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -1,7 +1,11 @@
/*
* Copyright (C) 2008 IBM Corporation
+ * Copyright (C) 2009-2010 Politecnico di Torino, Italy,
+ * TORSEC group -- http://security.polito.it
*
- * Author: Mimi Zohar <zo...@us...>
+ * Authors:
+ * Mimi Zohar <zo...@us...>
+ * Roberto Sassu <rob...@po...>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -171,7 +175,13 @@ void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
struct inode *inode = file->f_dentry->d_inode;
struct ima_template_entry *entry;
int violation = 0;
-
+ char *subj_label = NULL;
+ char *obj_label = NULL;
+ int obj_label_len = 0;
+ int subj_label_len = 0;
+ struct task_struct *tsk = current;
+ u32 osid, sid;
+
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
@@ -181,6 +191,22 @@ void ima_store_measurement(struct ima_iint_cache *iint, struct file *file,
memset(&entry->template, 0, sizeof(entry->template));
memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE);
strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
+
+ if (file->f_dentry->d_inode) {
+ security_inode_getsecid(file->f_dentry->d_inode, &osid);
+ if (!security_secid_to_secctx(osid, &obj_label, &obj_label_len)) {
+ strncpy(entry->template.obj_label, obj_label, obj_label_len < IMA_LABEL_LEN_MAX ?
+ obj_label_len : IMA_LABEL_LEN_MAX);
+ security_release_secctx(obj_label, obj_label_len);
+ }
+ }
+
+ security_task_getsecid(tsk, &sid);
+ if (!security_secid_to_secctx(sid, &subj_label, &subj_label_len)) {
+ strncpy(entry->template.subj_label, subj_label, subj_label_len < IMA_LABEL_LEN_MAX ?
+ subj_label_len : IMA_LABEL_LEN_MAX);
+ security_release_secctx(subj_label, subj_label_len);
+ }
result = ima_store_template(entry, violation, inode);
if (!result)
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 46642a1..9f1dc9b 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -96,9 +96,19 @@ int ima_calc_template_hash(int template_len, void *template, char *digest)
rc = init_desc(&desc);
if (rc != 0)
return rc;
+
+ sg_init_table(sg, 1);
- sg_init_one(sg, template, template_len);
- rc = crypto_hash_update(&desc, sg, template_len);
+ sg_set_buf(sg, template, IMA_REPORT_FORMAT_CURRENT_LEN);
+ rc = crypto_hash_update(&desc, sg, IMA_REPORT_FORMAT_CURRENT_LEN);
+ if (ima_format == IMA_REPORT_FORMAT_CURRENT)
+ goto hash_final;
+
+ sg_set_buf(sg, template + IMA_REPORT_FORMAT_CURRENT_LEN,
+ IMA_REPORT_FORMAT_NG_LEN - IMA_REPORT_FORMAT_CURRENT_LEN);
+ rc = crypto_hash_update(&desc, sg, IMA_REPORT_FORMAT_NG_LEN - IMA_REPORT_FORMAT_CURRENT_LEN);
+
+hash_final:
if (!rc)
rc = crypto_hash_final(&desc, digest);
crypto_free_hash(desc.tfm);
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 0c72c9c..a6c0f0a 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -1,10 +1,13 @@
/*
* Copyright (C) 2005,2006,2007,2008 IBM Corporation
+ * Copyright (C) 2009-2010 Politecnico di Torino, Italy,
+ * TORSEC group -- http://security.polito.it
*
* Authors:
* Kylene Hall <kj...@us...>
* Reiner Sailer <sa...@us...>
* Mimi Zohar <zo...@us...>
+ * Roberto Sassu <rob...@po...>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -26,6 +29,18 @@
static int valid_policy = 1;
#define TMPBUFLEN 12
+
+int ima_format = IMA_REPORT_FORMAT_CURRENT;
+
+static int __init ima_report_format_setup(char *str)
+{
+ if (strncmp(str, "ima-ng", 6) == 0)
+ ima_format = IMA_REPORT_FORMAT_NG;
+ return 1;
+}
+__setup("ima_report_format=", ima_report_format_setup);
+
+
static ssize_t ima_show_htable_value(char __user *buf, size_t count,
loff_t *ppos, atomic_long_t *val)
{
@@ -177,11 +192,20 @@ void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show)
{
struct ima_template_data *entry = e;
int namelen;
-
+ int obj_label_len = strlen(entry->obj_label);
+ int subj_label_len = strlen(entry->subj_label);
+
switch (show) {
case IMA_SHOW_ASCII:
ima_print_digest(m, entry->digest);
- seq_printf(m, " %s\n", entry->file_name);
+ seq_printf(m, " %s", entry->file_name);
+ if (ima_format == IMA_REPORT_FORMAT_NG) {
+ if (subj_label_len)
+ seq_printf(m, " %s", entry->subj_label);
+ if (obj_label_len)
+ seq_printf(m, " %s", entry->obj_label);
+ }
+ seq_printf(m, "\n");
break;
case IMA_SHOW_BINARY:
ima_putc(m, entry->digest, IMA_DIGEST_SIZE);
@@ -189,6 +213,14 @@ void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show)
namelen = strlen(entry->file_name);
ima_putc(m, &namelen, sizeof namelen);
ima_putc(m, entry->file_name, namelen);
+ if (ima_format == IMA_REPORT_FORMAT_NG) {
+ ima_putc(m, &subj_label_len, sizeof subj_label_len);
+ if (subj_label_len)
+ ima_putc(m, entry->subj_label, subj_label_len);
+ ima_putc(m, &obj_label_len, sizeof obj_label_len);
+ if (obj_label_len)
+ ima_putc(m, entry->obj_label, obj_label_len);
+ }
default:
break;
}
|