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.com
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Acked-by: Dmitry 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: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Mimi Zohar 2016-12-19 16:22:42 -08:00 committed by Linus Torvalds
parent dcfc56937b
commit d158847ae8
3 changed files with 64 additions and 2 deletions

View File

@ -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

View File

@ -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);
/* /*

View File

@ -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,
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,
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)
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,