Commit | Line | Data |
---|---|---|
ae271c1b MS |
1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* | |
3 | * Landlock LSM - Ruleset management | |
4 | * | |
5 | * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net> | |
6 | * Copyright © 2018-2020 ANSSI | |
7 | */ | |
8 | ||
9 | #ifndef _SECURITY_LANDLOCK_RULESET_H | |
10 | #define _SECURITY_LANDLOCK_RULESET_H | |
11 | ||
5f2ff33e MS |
12 | #include <linux/bitops.h> |
13 | #include <linux/build_bug.h> | |
ae271c1b MS |
14 | #include <linux/mutex.h> |
15 | #include <linux/rbtree.h> | |
16 | #include <linux/refcount.h> | |
17 | #include <linux/workqueue.h> | |
18 | ||
5f2ff33e | 19 | #include "limits.h" |
ae271c1b MS |
20 | #include "object.h" |
21 | ||
5f2ff33e MS |
22 | typedef u16 access_mask_t; |
23 | /* Makes sure all filesystem access rights can be stored. */ | |
24 | static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS); | |
8ba0005f MS |
25 | /* Makes sure for_each_set_bit() and for_each_clear_bit() calls are OK. */ |
26 | static_assert(sizeof(unsigned long) >= sizeof(access_mask_t)); | |
5f2ff33e | 27 | |
75c542d6 MS |
28 | typedef u16 layer_mask_t; |
29 | /* Makes sure all layers can be checked. */ | |
30 | static_assert(BITS_PER_TYPE(layer_mask_t) >= LANDLOCK_MAX_NUM_LAYERS); | |
31 | ||
ae271c1b MS |
32 | /** |
33 | * struct landlock_layer - Access rights for a given layer | |
34 | */ | |
35 | struct landlock_layer { | |
36 | /** | |
37 | * @level: Position of this layer in the layer stack. | |
38 | */ | |
39 | u16 level; | |
40 | /** | |
41 | * @access: Bitfield of allowed actions on the kernel object. They are | |
42 | * relative to the object type (e.g. %LANDLOCK_ACTION_FS_READ). | |
43 | */ | |
5f2ff33e | 44 | access_mask_t access; |
ae271c1b MS |
45 | }; |
46 | ||
47 | /** | |
48 | * struct landlock_rule - Access rights tied to an object | |
49 | */ | |
50 | struct landlock_rule { | |
51 | /** | |
52 | * @node: Node in the ruleset's red-black tree. | |
53 | */ | |
54 | struct rb_node node; | |
55 | /** | |
56 | * @object: Pointer to identify a kernel object (e.g. an inode). This | |
57 | * is used as a key for this ruleset element. This pointer is set once | |
58 | * and never modified. It always points to an allocated object because | |
59 | * each rule increments the refcount of its object. | |
60 | */ | |
61 | struct landlock_object *object; | |
62 | /** | |
63 | * @num_layers: Number of entries in @layers. | |
64 | */ | |
65 | u32 num_layers; | |
66 | /** | |
67 | * @layers: Stack of layers, from the latest to the newest, implemented | |
68 | * as a flexible array member (FAM). | |
69 | */ | |
70 | struct landlock_layer layers[]; | |
71 | }; | |
72 | ||
73 | /** | |
74 | * struct landlock_hierarchy - Node in a ruleset hierarchy | |
75 | */ | |
76 | struct landlock_hierarchy { | |
77 | /** | |
78 | * @parent: Pointer to the parent node, or NULL if it is a root | |
79 | * Landlock domain. | |
80 | */ | |
81 | struct landlock_hierarchy *parent; | |
82 | /** | |
83 | * @usage: Number of potential children domains plus their parent | |
84 | * domain. | |
85 | */ | |
86 | refcount_t usage; | |
87 | }; | |
88 | ||
89 | /** | |
90 | * struct landlock_ruleset - Landlock ruleset | |
91 | * | |
92 | * This data structure must contain unique entries, be updatable, and quick to | |
93 | * match an object. | |
94 | */ | |
95 | struct landlock_ruleset { | |
96 | /** | |
97 | * @root: Root of a red-black tree containing &struct landlock_rule | |
98 | * nodes. Once a ruleset is tied to a process (i.e. as a domain), this | |
99 | * tree is immutable until @usage reaches zero. | |
100 | */ | |
101 | struct rb_root root; | |
102 | /** | |
103 | * @hierarchy: Enables hierarchy identification even when a parent | |
104 | * domain vanishes. This is needed for the ptrace protection. | |
105 | */ | |
106 | struct landlock_hierarchy *hierarchy; | |
107 | union { | |
108 | /** | |
109 | * @work_free: Enables to free a ruleset within a lockless | |
110 | * section. This is only used by | |
111 | * landlock_put_ruleset_deferred() when @usage reaches zero. | |
112 | * The fields @lock, @usage, @num_rules, @num_layers and | |
113 | * @fs_access_masks are then unused. | |
114 | */ | |
115 | struct work_struct work_free; | |
116 | struct { | |
117 | /** | |
118 | * @lock: Protects against concurrent modifications of | |
119 | * @root, if @usage is greater than zero. | |
120 | */ | |
121 | struct mutex lock; | |
122 | /** | |
123 | * @usage: Number of processes (i.e. domains) or file | |
124 | * descriptors referencing this ruleset. | |
125 | */ | |
126 | refcount_t usage; | |
127 | /** | |
128 | * @num_rules: Number of non-overlapping (i.e. not for | |
129 | * the same object) rules in this ruleset. | |
130 | */ | |
131 | u32 num_rules; | |
132 | /** | |
133 | * @num_layers: Number of layers that are used in this | |
134 | * ruleset. This enables to check that all the layers | |
135 | * allow an access request. A value of 0 identifies a | |
136 | * non-merged ruleset (i.e. not a domain). | |
137 | */ | |
138 | u32 num_layers; | |
139 | /** | |
140 | * @fs_access_masks: Contains the subset of filesystem | |
141 | * actions that are restricted by a ruleset. A domain | |
142 | * saves all layers of merged rulesets in a stack | |
143 | * (FAM), starting from the first layer to the last | |
144 | * one. These layers are used when merging rulesets, | |
145 | * for user space backward compatibility (i.e. | |
146 | * future-proof), and to properly handle merged | |
147 | * rulesets without overlapping access rights. These | |
148 | * layers are set once and never changed for the | |
149 | * lifetime of the ruleset. | |
150 | */ | |
5f2ff33e | 151 | access_mask_t fs_access_masks[]; |
ae271c1b MS |
152 | }; |
153 | }; | |
154 | }; | |
155 | ||
5f2ff33e MS |
156 | struct landlock_ruleset * |
157 | landlock_create_ruleset(const access_mask_t fs_access_mask); | |
ae271c1b MS |
158 | |
159 | void landlock_put_ruleset(struct landlock_ruleset *const ruleset); | |
160 | void landlock_put_ruleset_deferred(struct landlock_ruleset *const ruleset); | |
161 | ||
162 | int landlock_insert_rule(struct landlock_ruleset *const ruleset, | |
06a1c40a | 163 | struct landlock_object *const object, |
5f2ff33e | 164 | const access_mask_t access); |
ae271c1b | 165 | |
06a1c40a MS |
166 | struct landlock_ruleset * |
167 | landlock_merge_ruleset(struct landlock_ruleset *const parent, | |
168 | struct landlock_ruleset *const ruleset); | |
ae271c1b | 169 | |
06a1c40a MS |
170 | const struct landlock_rule * |
171 | landlock_find_rule(const struct landlock_ruleset *const ruleset, | |
172 | const struct landlock_object *const object); | |
ae271c1b MS |
173 | |
174 | static inline void landlock_get_ruleset(struct landlock_ruleset *const ruleset) | |
175 | { | |
176 | if (ruleset) | |
177 | refcount_inc(&ruleset->usage); | |
178 | } | |
179 | ||
180 | #endif /* _SECURITY_LANDLOCK_RULESET_H */ |