From: Roberto Sassu <[email protected]> Make binary_runtime_size as an array, to have separate counters per binary measurements list type. Currently, define the BINARY type for the existing binary measurements list.
Introduce ima_update_binary_runtime_size() to facilitate updating a binary_runtime_size value with a given binary measurement list type. Also add the binary measurements list type parameter to ima_get_binary_runtime_size(), to retrieve the desired value. Retrieving the value is now done under the ima_extend_list_mutex, since there can be concurrent updates. No functional change (except for the mutex usage, that fixes the concurrency issue): the BINARY array element is equivalent to the old binary_runtime_size. Link: https://github.com/linux-integrity/linux/issues/1 Signed-off-by: Roberto Sassu <[email protected]> --- security/integrity/ima/ima.h | 2 +- security/integrity/ima/ima_kexec.c | 5 ++-- security/integrity/ima/ima_queue.c | 40 +++++++++++++++++++++--------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 199237e2d2e3..97b7d6024b5d 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -318,7 +318,7 @@ 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); int __init ima_init_htable(void); -unsigned long ima_get_binary_runtime_size(void); +unsigned long ima_get_binary_runtime_size(enum binary_lists binary_list); int ima_init_template(void); void ima_init_template_list(void); int __init ima_init_digests(void); diff --git a/security/integrity/ima/ima_kexec.c b/security/integrity/ima/ima_kexec.c index 40962dc0ca86..44ebefbdcab0 100644 --- a/security/integrity/ima/ima_kexec.c +++ b/security/integrity/ima/ima_kexec.c @@ -42,7 +42,7 @@ void ima_measure_kexec_event(const char *event_name) long len; int n; - buf_size = ima_get_binary_runtime_size(); + buf_size = ima_get_binary_runtime_size(BINARY); len = atomic_long_read(&ima_num_entries[BINARY]); n = scnprintf(ima_kexec_event, IMA_KEXEC_EVENT_LEN, @@ -159,7 +159,8 @@ void ima_add_kexec_buffer(struct kimage *image) else extra_memory = CONFIG_IMA_KEXEC_EXTRA_MEMORY_KB * 1024; - binary_runtime_size = ima_get_binary_runtime_size() + extra_memory; + binary_runtime_size = ima_get_binary_runtime_size(BINARY) + + extra_memory; if (binary_runtime_size >= ULONG_MAX - PAGE_SIZE) kexec_segment_size = ULONG_MAX; diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index 952172a4905d..b6d10dceb669 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c @@ -27,9 +27,11 @@ static struct tpm_digest *digests; LIST_HEAD(ima_measurements); /* list of all measurements */ #ifdef CONFIG_IMA_KEXEC -static unsigned long binary_runtime_size; +static unsigned long binary_runtime_size[BINARY__LAST]; #else -static unsigned long binary_runtime_size = ULONG_MAX; +static unsigned long binary_runtime_size[BINARY__LAST] = { + [0 ... BINARY__LAST - 1] = ULONG_MAX +}; #endif /* num of stored measurements in the list */ @@ -131,6 +133,20 @@ static int get_binary_runtime_size(struct ima_template_entry *entry) return size; } +static void ima_update_binary_runtime_size(struct ima_template_entry *entry, + enum binary_lists binary_list) +{ + int size; + + if (binary_runtime_size[binary_list] == ULONG_MAX) + return; + + size = get_binary_runtime_size(entry); + binary_runtime_size[binary_list] = + (binary_runtime_size[binary_list] < ULONG_MAX - size) ? + binary_runtime_size[binary_list] + size : ULONG_MAX; +} + /* ima_add_template_entry helper function: * - Add template entry to the measurement list and hash table, for * all entries except those carried across kexec. @@ -163,13 +179,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, hlist_add_head_rcu(&qe->hnext, &htable[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; - } + ima_update_binary_runtime_size(entry, BINARY); return 0; } @@ -178,12 +188,18 @@ static int ima_add_digest_entry(struct ima_template_entry *entry, * entire binary_runtime_measurement list, including the ima_kexec_hdr * structure. */ -unsigned long ima_get_binary_runtime_size(void) +unsigned long ima_get_binary_runtime_size(enum binary_lists binary_list) { - if (binary_runtime_size >= (ULONG_MAX - sizeof(struct ima_kexec_hdr))) + unsigned long val; + + mutex_lock(&ima_extend_list_mutex); + val = binary_runtime_size[binary_list]; + mutex_unlock(&ima_extend_list_mutex); + + if (val >= (ULONG_MAX - sizeof(struct ima_kexec_hdr))) return ULONG_MAX; else - return binary_runtime_size + sizeof(struct ima_kexec_hdr); + return val + sizeof(struct ima_kexec_hdr); } static int ima_pcr_extend(struct tpm_digest *digests_arg, int pcr) -- 2.43.0

