@@ -180,6 +180,8 @@ struct ima_h_table {
};
extern struct ima_h_table ima_htable;
+extern wait_queue_head_t ima_htable_wait;
+
static inline unsigned int ima_hash_key(u8 *digest)
{
/* there is no point in taking a hash of part of a digest */
@@ -21,6 +21,7 @@
#include <linux/rcupdate.h>
#include <linux/parser.h>
#include <linux/vmalloc.h>
+#include <linux/poll.h>
#include "ima.h"
@@ -198,11 +199,31 @@ static int ima_measurements_open(struct inode *inode, struct file *file)
return seq_open(file, &ima_measurments_seqops);
}
+static __poll_t ima_measurements_poll(struct file *file, poll_table *wait)
+{
+ struct seq_file *seq = file->private_data;
+ /* always allow reading */
+ __poll_t mask = EPOLLIN | EPOLLRDNORM;
+ int event;
+
+ poll_wait(file, &ima_htable_wait, wait);
+
+ event = atomic_long_read(&ima_htable.len);
+
+ if (seq->poll_event != event) {
+ seq->poll_event = event;
+ mask |= EPOLLERR | EPOLLPRI;
+ }
+
+ return mask;
+}
+
static const struct file_operations ima_measurements_ops = {
.open = ima_measurements_open,
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
+ .poll = ima_measurements_poll,
};
void ima_print_digest(struct seq_file *m, u8 *digest, u32 size)
@@ -269,6 +290,7 @@ static const struct file_operations ima_ascii_measurements_ops = {
.read = seq_read,
.llseek = seq_lseek,
.release = seq_release,
+ .poll = ima_measurements_poll,
};
static ssize_t ima_read_policy(char *path)
@@ -38,6 +38,9 @@ struct ima_h_table ima_htable = {
.queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] = HLIST_HEAD_INIT
};
+/* wait queue for polling changes in ima_htable */
+DECLARE_WAIT_QUEUE_HEAD(ima_htable_wait);
+
/* mutex protects atomicity of extending measurement list
* and extending the TPM PCR aggregate. Since tpm_extend can take
* long (and the tpm driver uses a mutex), we can't use the spinlock.
@@ -119,6 +122,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry,
binary_runtime_size = (binary_runtime_size < ULONG_MAX - size) ?
binary_runtime_size + size : ULONG_MAX;
}
+
return 0;
}
@@ -193,9 +197,11 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
tpmresult);
audit_cause = tpm_audit_cause;
audit_info = 0;
- }
+ } else
+ wake_up_interruptible(&ima_htable_wait);
out:
mutex_unlock(&ima_extend_list_mutex);
+
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename,
op, audit_cause, result, audit_info);
return result;
Currently it's not possible to efficiently monitor changes to the IMA runtime measurement list with poll(). While ascii_runtime_measurement file is pollable with POLLIN, it returns immediately even if there is no change to the list, and thus cannot be used as a wait condition in a loop. This patch makes it possible to poll the file in a similar fashion to the sysfs files: POLLIN is still always signalled, while POLLPRI will also be signalled on actual changes made to the list. Signed-off-by: Daiki Ueno <dueno@redhat.com> --- v2: moved wake_up_interruptible() call after PCR extend and expanded the patch description to cover the use-case, suggested by Mimi. --- security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_fs.c | 22 ++++++++++++++++++++++ security/integrity/ima/ima_queue.c | 8 +++++++- 3 files changed, 31 insertions(+), 1 deletion(-)