@@ -204,6 +204,7 @@ struct ima_namespace {
struct integrity_iint_tree *iint_tree;
struct list_head *measurements;
atomic_long_t ml_len; /* number of stored measurements in the list */
+ atomic_long_t violations;
} __randomize_layout;
extern struct ima_namespace init_ima_ns;
@@ -193,7 +193,6 @@ extern spinlock_t ima_queue_lock;
struct ima_h_table {
atomic_long_t len; /* number of stored measurements in the list */
- atomic_long_t violations;
struct hlist_head queue[IMA_MEASURE_HTABLE_SIZE];
};
extern struct ima_h_table ima_htable;
@@ -151,7 +151,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
event_data.ns_id = get_ns_id(ima_ns);
/* can overflow, only indicator */
- atomic_long_inc(&ima_htable.violations);
+ atomic_long_inc(&ima_ns->violations);
result = ima_alloc_init_template(&event_data, &entry, NULL);
if (result < 0) {
@@ -51,10 +51,23 @@ static ssize_t ima_show_htable_violations(struct file *filp,
char __user *buf,
size_t count, loff_t *ppos)
{
- return ima_show_htable_value(buf, count, ppos, &ima_htable.violations);
+ struct ima_namespace *ima_ns = get_current_ns();
+
+ return ima_show_htable_value(buf, count, ppos, &ima_ns->violations);
+}
+
+static int ima_open_htable_violations(struct inode *inode, struct file *file)
+{
+ struct ima_namespace *ima_ns = get_current_ns();
+
+ if (!ns_capable(ima_ns->user_ns, CAP_SYS_ADMIN))
+ return -EPERM;
+
+ return 0;
}
static const struct file_operations ima_htable_violations_ops = {
+ .open = ima_open_htable_violations,
.read = ima_show_htable_violations,
.llseek = generic_file_llseek,
};
@@ -76,7 +89,6 @@ static ssize_t ima_show_measurements_count(struct file *filp,
struct ima_namespace *ima_ns = get_current_ns();
return ima_show_htable_value(buf, count, ppos, &ima_ns->ml_len);
-
}
static const struct file_operations ima_measurements_count_ops = {
@@ -552,7 +564,7 @@ int __init ima_fs_init(void)
goto out;
violations =
- securityfs_create_file("violations", S_IRUSR | S_IRGRP,
+ securityfs_create_file("violations", S_IRUSR | S_IRGRP | S_IROTH,
ima_dir, NULL, &ima_htable_violations_ops);
if (IS_ERR(violations))
goto out;
@@ -37,6 +37,7 @@ struct ima_namespace init_ima_ns = {
.iint_tree = &init_iint_tree,
.measurements = &ima_measurements,
.ml_len = ATOMIC_LONG_INIT(0),
+ .violations = ATOMIC_LONG_INIT(0),
};
EXPORT_SYMBOL(init_ima_ns);
@@ -127,6 +127,7 @@ static struct ima_namespace *clone_ima_ns(struct user_namespace *user_ns,
ns->ucounts = ucounts;
ns->frozen = false;
atomic_long_set(&ns->ml_len, 0);
+ atomic_long_set(&ns->violations, 0);
rwlock_init(&ns->iint_tree->lock);
ns->iint_tree->root = RB_ROOT;
@@ -34,7 +34,6 @@ static unsigned long binary_runtime_size = ULONG_MAX;
/* key: inode (before secure-hashing a file) */
struct ima_h_table ima_htable = {
.len = ATOMIC_LONG_INIT(0),
- .violations = ATOMIC_LONG_INIT(0),
.queue[0 ... IMA_MEASURE_HTABLE_SIZE - 1] = HLIST_HEAD_INIT
};