summaryrefslogtreecommitdiff
path: root/security/landlock/domain.h
diff options
context:
space:
mode:
Diffstat (limited to 'security/landlock/domain.h')
-rw-r--r--security/landlock/domain.h86
1 files changed, 86 insertions, 0 deletions
diff --git a/security/landlock/domain.h b/security/landlock/domain.h
index f8df7103bd3d..2c6f04da3628 100644
--- a/security/landlock/domain.h
+++ b/security/landlock/domain.h
@@ -10,8 +10,62 @@
#ifndef _SECURITY_LANDLOCK_DOMAIN_H
#define _SECURITY_LANDLOCK_DOMAIN_H
+#include <linux/limits.h>
#include <linux/mm.h>
+#include <linux/path.h>
+#include <linux/pid.h>
#include <linux/refcount.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include "audit.h"
+
+enum landlock_log_status {
+ LANDLOCK_LOG_PENDING = 0,
+ LANDLOCK_LOG_RECORDED,
+};
+
+/**
+ * struct landlock_details - Domain's creation information
+ *
+ * Rarely accessed, mainly when logging the first domain's denial.
+ *
+ * The contained pointers are initialized at the domain creation time and never
+ * changed again. Contrary to most other Landlock object types, this one is
+ * not allocated with GFP_KERNEL_ACCOUNT because its size may not be under the
+ * caller's control (e.g. unknown exe_path) and the data is not explicitly
+ * requested nor used by tasks.
+ */
+struct landlock_details {
+ /**
+ * @pid: PID of the task that initially restricted itself. It still
+ * identifies the same task. Keeping a reference to this PID ensures that
+ * it will not be recycled.
+ */
+ struct pid *pid;
+ /**
+ * @uid: UID of the task that initially restricted itself, at creation time.
+ */
+ uid_t uid;
+ /**
+ * @comm: Command line of the task that initially restricted itself, at
+ * creation time. Always NULL terminated.
+ */
+ char comm[TASK_COMM_LEN];
+ /**
+ * @exe_path: Executable path of the task that initially restricted
+ * itself, at creation time. Always NULL terminated, and never greater
+ * than LANDLOCK_PATH_MAX_SIZE.
+ */
+ char exe_path[];
+};
+
+/* Adds 11 extra characters for the potential " (deleted)" suffix. */
+#define LANDLOCK_PATH_MAX_SIZE (PATH_MAX + 11)
+
+/* Makes sure the greatest landlock_details can be allocated. */
+static_assert(struct_size_t(struct landlock_details, exe_path,
+ LANDLOCK_PATH_MAX_SIZE) <= KMALLOC_MAX_SIZE);
/**
* struct landlock_hierarchy - Node in a domain hierarchy
@@ -30,9 +84,24 @@ struct landlock_hierarchy {
#ifdef CONFIG_AUDIT
/**
+ * @log_status: Whether this domain should be logged or not. Because
+ * concurrent log entries may be created at the same time, it is still
+ * possible to have several domain records of the same domain.
+ */
+ enum landlock_log_status log_status;
+ /**
+ * @num_denials: Number of access requests denied by this domain.
+ * Masked (i.e. never logged) denials are still counted.
+ */
+ atomic64_t num_denials;
+ /**
* @id: Landlock domain ID, sets once at domain creation time.
*/
u64 id;
+ /**
+ * @details: Information about the related domain.
+ */
+ const struct landlock_details *details;
#endif /* CONFIG_AUDIT */
};
@@ -40,6 +109,16 @@ struct landlock_hierarchy {
int landlock_init_hierarchy_log(struct landlock_hierarchy *const hierarchy);
+static inline void
+landlock_free_hierarchy_details(struct landlock_hierarchy *const hierarchy)
+{
+ if (WARN_ON_ONCE(!hierarchy || !hierarchy->details))
+ return;
+
+ put_pid(hierarchy->details->pid);
+ kfree(hierarchy->details);
+}
+
#else /* CONFIG_AUDIT */
static inline int
@@ -48,6 +127,11 @@ landlock_init_hierarchy_log(struct landlock_hierarchy *const hierarchy)
return 0;
}
+static inline void
+landlock_free_hierarchy_details(struct landlock_hierarchy *const hierarchy)
+{
+}
+
#endif /* CONFIG_AUDIT */
static inline void
@@ -62,6 +146,8 @@ static inline void landlock_put_hierarchy(struct landlock_hierarchy *hierarchy)
while (hierarchy && refcount_dec_and_test(&hierarchy->usage)) {
const struct landlock_hierarchy *const freeme = hierarchy;
+ landlock_log_drop_domain(hierarchy);
+ landlock_free_hierarchy_details(hierarchy);
hierarchy = hierarchy->parent;
kfree(freeme);
}