Commit d158847a authored by Mimi Zohar's avatar Mimi Zohar Committed by Linus Torvalds

ima: maintain memory size needed for serializing the measurement list

In preparation for serializing the binary_runtime_measurements, this
patch maintains the amount of memory required.

Link: http://lkml.kernel.org/r/1480554346-29071-5-git-send-email-zohar@linux.vnet.ibm.comSigned-off-by: default avatarMimi Zohar <zohar@linux.vnet.ibm.com>
Acked-by: default avatarDmitry Kasatkin <dmitry.kasatkin@gmail.com>
Cc: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Andreas Steffen <andreas.steffen@strongswan.org>
Cc: Josh Sklar <sklar@linux.vnet.ibm.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Baoquan He <bhe@redhat.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Stewart Smith <stewart@linux.vnet.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent dcfc5693
...@@ -27,6 +27,18 @@ config IMA ...@@ -27,6 +27,18 @@ config IMA
to learn more about IMA. to learn more about IMA.
If unsure, say N. If unsure, say N.
config IMA_KEXEC
bool "Enable carrying the IMA measurement list across a soft boot"
depends on IMA && TCG_TPM && HAVE_IMA_KEXEC
default n
help
TPM PCRs are only reset on a hard reboot. In order to validate
a TPM's quote after a soft boot, the IMA measurement list of the
running kernel must be saved and restored on boot.
Depending on the IMA policy, the measurement list can grow to
be very large.
config IMA_MEASURE_PCR_IDX config IMA_MEASURE_PCR_IDX
int int
depends on IMA depends on IMA
......
...@@ -143,6 +143,7 @@ void ima_print_digest(struct seq_file *m, u8 *digest, u32 size); ...@@ -143,6 +143,7 @@ void ima_print_digest(struct seq_file *m, u8 *digest, u32 size);
struct ima_template_desc *ima_template_desc_current(void); struct ima_template_desc *ima_template_desc_current(void);
int ima_restore_measurement_entry(struct ima_template_entry *entry); int ima_restore_measurement_entry(struct ima_template_entry *entry);
int ima_restore_measurement_list(loff_t bufsize, void *buf); int ima_restore_measurement_list(loff_t bufsize, void *buf);
unsigned long ima_get_binary_runtime_size(void);
int ima_init_template(void); int ima_init_template(void);
/* /*
......
...@@ -29,6 +29,11 @@ ...@@ -29,6 +29,11 @@
#define AUDIT_CAUSE_LEN_MAX 32 #define AUDIT_CAUSE_LEN_MAX 32
LIST_HEAD(ima_measurements); /* list of all measurements */ LIST_HEAD(ima_measurements); /* list of all measurements */
#ifdef CONFIG_IMA_KEXEC
static unsigned long binary_runtime_size;
#else
static unsigned long binary_runtime_size = ULONG_MAX;
#endif
/* key: inode (before secure-hashing a file) */ /* key: inode (before secure-hashing a file) */
struct ima_h_table ima_htable = { struct ima_h_table ima_htable = {
...@@ -64,6 +69,24 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value, ...@@ -64,6 +69,24 @@ static struct ima_queue_entry *ima_lookup_digest_entry(u8 *digest_value,
return ret; return ret;
} }
/*
* Calculate the memory required for serializing a single
* binary_runtime_measurement list entry, which contains a
* couple of variable length fields (e.g template name and data).
*/
static int get_binary_runtime_size(struct ima_template_entry *entry)
{
int size = 0;
size += sizeof(u32); /* pcr */
size += sizeof(entry->digest);
size += sizeof(int); /* template name size field */
size += strlen(entry->template_desc->name) + 1;
size += sizeof(entry->template_data_len);
size += entry->template_data_len;
return size;
}
/* ima_add_template_entry helper function: /* ima_add_template_entry helper function:
* - Add template entry to the measurement list and hash table, for * - Add template entry to the measurement list and hash table, for
* all entries except those carried across kexec. * all entries except those carried across kexec.
...@@ -91,9 +114,30 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, ...@@ -91,9 +114,30 @@ static int ima_add_digest_entry(struct ima_template_entry *entry,
key = ima_hash_key(entry->digest); key = ima_hash_key(entry->digest);
hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]); hlist_add_head_rcu(&qe->hnext, &ima_htable.queue[key]);
} }
if (binary_runtime_size != ULONG_MAX) {
int size;
size = get_binary_runtime_size(entry);
binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ?
binary_runtime_size + size : ULONG_MAX;
}
return 0; return 0;
} }
/*
* Return the amount of memory required for serializing the
* entire binary_runtime_measurement list, including the ima_kexec_hdr
* structure.
*/
unsigned long ima_get_binary_runtime_size(void)
{
if (binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr)))
return ULONG_MAX;
else
return binary_runtime_size + sizeof(struct ima_kexec_hdr);
};
static int ima_pcr_extend(const u8 *hash, int pcr) static int ima_pcr_extend(const u8 *hash, int pcr)
{ {
int result = 0; int result = 0;
...@@ -107,8 +151,13 @@ static int ima_pcr_extend(const u8 *hash, int pcr) ...@@ -107,8 +151,13 @@ static int ima_pcr_extend(const u8 *hash, int pcr)
return result; return result;
} }
/* Add template entry to the measurement list and hash table, /*
* and extend the pcr. * Add template entry to the measurement list and hash table, and
* extend the pcr.
*
* On systems which support carrying the IMA measurement list across
* kexec, maintain the total memory size required for serializing the
* binary_runtime_measurements.
*/ */
int ima_add_template_entry(struct ima_template_entry *entry, int violation, int ima_add_template_entry(struct ima_template_entry *entry, int violation,
const char *op, struct inode *inode, const char *op, struct inode *inode,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment