summaryrefslogtreecommitdiffstats
path: root/security/landlock/ruleset.h
diff options
context:
space:
mode:
authorSteven Rostedt <rostedt@goodmis.org>2026-09-02 09:55:01 -0400
committerSteven Rostedt <rostedt@goodmis.org>2026-09-02 11:08:21 -0400
commit4617721c502b2ddaa4e324e86da4997edf738fa5 (patch)
tree350aa83b47da0b574a814795392b20b0bed83cbc /security/landlock/ruleset.h
downloadlinux-stable-4617721c502b2ddaa4e324e86da4997edf738fa5.tar.gz
linux-stable-4617721c502b2ddaa4e324e86da4997edf738fa5.zip
ftrace: Synchronize the initialization of ftrace_opsgrafted
There's some internal state that ftrace_ops needs to have set, but since it can be declared outside of the ftrace.c code, it calls ftrace_ops_init() on the ops in every global function. The issue is that if two tasks call it on the same ops at the same time it is possible to have the initialization of one corrupt the initialization of the other call. Create a ops_mutex to use to synchronize every initialization of the ftrace_ops. The mutex is taken within checking the ftrace_ops flag that states it was initializied but the flag is checked again after the mutex has been taken. Checking first outside the mutex allows it to shortcut having to take the mutex. But then the check needs to be done again after the mute is taken in case of races. Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260902095501.6b59af20@gandalf.local.home Fixes: f04f24fb7e48d ("ftrace, kprobes: Fix a deadlock on ftrace_regex_lock") Reported-by: sashiko-bot@kernel.org Close: https://lore.kernel.org/all/20260829025528.49A831F000E9@smtp.kernel.org/ Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'security/landlock/ruleset.h')
-rw-r--r--security/landlock/ruleset.h250
1 files changed, 250 insertions, 0 deletions
diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h
new file mode 100644
index 000000000..b536fa042
--- /dev/null
+++ b/security/landlock/ruleset.h
@@ -0,0 +1,250 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Landlock LSM - Ruleset management
+ *
+ * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net>
+ * Copyright © 2018-2020 ANSSI
+ * Copyright © 2026 Cloudflare, Inc.
+ */
+
+#ifndef _SECURITY_LANDLOCK_RULESET_H
+#define _SECURITY_LANDLOCK_RULESET_H
+
+#include <linux/cleanup.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/rbtree.h>
+#include <linux/refcount.h>
+
+#include "access.h"
+#include "limits.h"
+#include "object.h"
+
+/**
+ * struct landlock_layer - Access rights for a given layer
+ */
+struct landlock_layer {
+ /**
+ * @level: Position of this layer in the layer stack. Starts from 1.
+ */
+ u8 level;
+ /**
+ * @flags: Bitfield for special flags attached to this rule.
+ */
+ struct {
+ /**
+ * @flags.quiet: Suppresses denial logs for the object covered by
+ * this rule in this domain. For filesystem rules, this inherits
+ * down the file hierarchy.
+ */
+ u8 quiet : 1;
+ } flags;
+ /**
+ * @access: Bitfield of allowed actions on the kernel object. They are
+ * relative to the object type (e.g. %LANDLOCK_ACTION_FS_READ).
+ */
+ access_mask_t access;
+};
+
+/**
+ * union landlock_key - Key of a ruleset's red-black tree
+ */
+union landlock_key {
+ /**
+ * @object: Pointer to identify a kernel object (e.g. an inode).
+ */
+ struct landlock_object *object;
+ /**
+ * @data: Raw data to identify an arbitrary 32-bit value
+ * (e.g. a TCP port).
+ */
+ uintptr_t data;
+};
+
+/**
+ * enum landlock_key_type - Type of &union landlock_key
+ */
+enum landlock_key_type {
+ /**
+ * @LANDLOCK_KEY_INODE: Type of &landlock_rules.root_inode's node keys.
+ */
+ LANDLOCK_KEY_INODE = 1,
+ /**
+ * @LANDLOCK_KEY_NET_PORT: Type of &landlock_rules.root_net_port's node
+ * keys.
+ */
+ LANDLOCK_KEY_NET_PORT,
+};
+
+/**
+ * struct landlock_id - Unique rule identifier for a ruleset
+ */
+struct landlock_id {
+ /**
+ * @key: Identifies either a kernel object (e.g. an inode) or
+ * a raw value (e.g. a TCP port).
+ */
+ union landlock_key key;
+ /**
+ * @type: Type of a landlock_ruleset's root tree.
+ */
+ const enum landlock_key_type type;
+};
+
+/**
+ * struct landlock_rule - Access rights tied to an object
+ */
+struct landlock_rule {
+ /**
+ * @node: Node in the ruleset's red-black tree.
+ */
+ struct rb_node node;
+ /**
+ * @key: A union to identify either a kernel object (e.g. an inode) or
+ * a raw data value (e.g. a network socket port). This is used as a key
+ * for this ruleset element. The pointer is set once and never
+ * modified. It always points to an allocated object because each rule
+ * increments the refcount of its object.
+ */
+ union landlock_key key;
+ /**
+ * @num_layers: Number of entries in @layers.
+ */
+ u32 num_layers;
+ /**
+ * @layers: Stack of layers, from the latest to the newest, implemented
+ * as a flexible array member (FAM).
+ */
+ struct landlock_layer layers[] __counted_by(num_layers);
+};
+
+/**
+ * struct landlock_rules - Red-black tree storage for Landlock rules
+ *
+ * This structure holds the rule trees shared by both rulesets and domains.
+ */
+struct landlock_rules {
+ /**
+ * @root_inode: Root of a red-black tree containing &struct
+ * landlock_rule nodes with inode object. Immutable for domains.
+ */
+ struct rb_root root_inode;
+
+#if IS_ENABLED(CONFIG_INET)
+ /**
+ * @root_net_port: Root of a red-black tree containing &struct
+ * landlock_rule nodes with network port. Immutable for domains.
+ */
+ struct rb_root root_net_port;
+#endif /* IS_ENABLED(CONFIG_INET) */
+
+ /**
+ * @num_rules: Number of non-overlapping (i.e. not for the same object)
+ * rules in this tree storage.
+ */
+ u32 num_rules;
+};
+
+/**
+ * struct landlock_ruleset - Landlock ruleset
+ *
+ * This data structure must contain unique entries, be updatable, and quick to
+ * match an object.
+ */
+struct landlock_ruleset {
+ /**
+ * @rules: Red-black tree storage for rules.
+ */
+ struct landlock_rules rules;
+ /**
+ * @lock: Protects against concurrent modifications of @rules, if @usage
+ * is greater than zero.
+ */
+ struct mutex lock;
+ /**
+ * @usage: Number of file descriptors referencing this ruleset.
+ */
+ refcount_t usage;
+
+#ifdef CONFIG_TRACEPOINTS
+ /**
+ * @version: Counter incremented on each successful
+ * landlock_add_rule(2), including when it only extends an existing
+ * rule's access rights. Used by tracepoints to correlate a domain with
+ * the exact ruleset state it was created from. Protected by @lock.
+ */
+ u32 version;
+ /**
+ * @id: Unique identifier for this ruleset, used for tracing.
+ */
+ u64 id;
+#endif /* CONFIG_TRACEPOINTS */
+
+ /**
+ * @quiet_masks: Stores the quiet flags for an unmerged ruleset. For a
+ * merged domain, this is stored in each layer's struct
+ * landlock_hierarchy instead.
+ */
+ struct access_masks quiet_masks;
+ /**
+ * @handled_masks: Contains the subset of filesystem and network actions
+ * that are handled by this ruleset.
+ */
+ struct access_masks handled_masks;
+};
+
+struct landlock_ruleset *
+landlock_create_ruleset(const access_mask_t access_mask_fs,
+ const access_mask_t access_mask_net,
+ const access_mask_t scope_mask);
+
+void landlock_put_ruleset(struct landlock_ruleset *const ruleset);
+
+DEFINE_FREE(landlock_put_ruleset, struct landlock_ruleset *,
+ if (!IS_ERR_OR_NULL(_T)) landlock_put_ruleset(_T))
+
+int landlock_insert_rule(struct landlock_ruleset *const ruleset,
+ const struct landlock_id id,
+ const access_mask_t access, const u32 flags);
+
+int landlock_store_rule(struct landlock_rules *const rules,
+ const struct landlock_id id,
+ const struct landlock_layer (*layers)[],
+ const size_t num_layers);
+
+void landlock_free_rules(struct landlock_rules *const rules);
+
+/**
+ * landlock_get_rule_root - Get the root of a rule tree by key type
+ *
+ * @rules: The rules storage to look up.
+ * @key_type: The type of key to select the tree for.
+ *
+ * Return: A pointer to the rb_root, or ERR_PTR(-EINVAL) on unknown type.
+ */
+static inline struct rb_root *
+landlock_get_rule_root(struct landlock_rules *const rules,
+ const enum landlock_key_type key_type)
+{
+ switch (key_type) {
+ case LANDLOCK_KEY_INODE:
+ return &rules->root_inode;
+
+#if IS_ENABLED(CONFIG_INET)
+ case LANDLOCK_KEY_NET_PORT:
+ return &rules->root_net_port;
+#endif /* IS_ENABLED(CONFIG_INET) */
+
+ default:
+ WARN_ON_ONCE(1);
+ return ERR_PTR(-EINVAL);
+ }
+}
+
+static inline void landlock_get_ruleset(struct landlock_ruleset *const ruleset)
+{
+ if (ruleset)
+ refcount_inc(&ruleset->usage);
+}
+
+#endif /* _SECURITY_LANDLOCK_RULESET_H */