ima: Introduce per binary measurements list type binary_runtime_size value

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 <roberto.sassu@huawei.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
This commit is contained in:
Roberto Sassu 2026-06-05 19:22:28 +02:00 committed by Mimi Zohar
parent 2fcebcd2aa
commit 8f19da70f7
3 changed files with 32 additions and 15 deletions

View File

@ -319,7 +319,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);

View File

@ -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_records[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;

View File

@ -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
atomic_long_t ima_num_records[BINARY__LAST] = {
@ -128,6 +130,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.
@ -160,13 +176,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;
}
@ -175,12 +185,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)