projects/linux·blob master · refs

332 lines · 9.7 KiB

1/* SPDX-License-Identifier: GPL-2.0-only */
2/*
3 * Landlock - Domain management
4 *
5 * Copyright © 2016-2020 Mickaël Salaün <[email protected]>
6 * Copyright © 2018-2020 ANSSI
7 * Copyright © 2024-2025 Microsoft Corporation
8 * Copyright © 2026 Cloudflare, Inc.
9 */
10
11#ifndef _SECURITY_LANDLOCK_DOMAIN_H
12#define _SECURITY_LANDLOCK_DOMAIN_H
13
14#include <linux/cleanup.h>
15#include <linux/limits.h>
16#include <linux/mm.h>
17#include <linux/path.h>
18#include <linux/pid.h>
19#include <linux/refcount.h>
20#include <linux/sched.h>
21#include <linux/slab.h>
22#include <linux/workqueue.h>
23
24#include "access.h"
25#include "log.h"
26#include "ruleset.h"
27
28enum landlock_log_status {
29 /*
30 * Hierarchy whose creation event has not been emitted, so it is not yet
31 * observable from user space. A hierarchy is born in this state (the
32 * zero value, so a partially initialized hierarchy defaults to "not
33 * observable") and leaves it when landlock_restrict_self() emits its
34 * creation event, right after the merge and before the thread-sync
35 * wait. No trace free_domain event (and no audit deallocation record)
36 * fires while a hierarchy is in this state, so a hierarchy that never
37 * became observable (e.g. its initialization failed) is freed silently.
38 * A domain aborted by a thread-sync failure already emitted its
39 * creation event, so it is no longer UNCOMMITTED and does fire
40 * free_domain.
41 */
42 LANDLOCK_LOG_UNCOMMITTED = 0,
43 LANDLOCK_LOG_PENDING,
44 LANDLOCK_LOG_RECORDED,
45 LANDLOCK_LOG_DISABLED,
46};
47
48/**
49 * struct landlock_details - Domain's creation information
50 *
51 * Rarely accessed, mainly when logging the first domain's denial.
52 *
53 * The contained pointers are initialized at the domain creation time and never
54 * changed again.
55 */
56struct landlock_details {
57 /**
58 * @pid: PID of the task that initially restricted itself. It still
59 * identifies the same task. Keeping a reference to this PID ensures that
60 * it will not be recycled.
61 */
62 struct pid *pid;
63 /**
64 * @uid: UID of the task that initially restricted itself, at creation time.
65 */
66 uid_t uid;
67 /**
68 * @comm: Command line of the task that initially restricted itself, at
69 * creation time. Always NULL terminated.
70 */
71 char comm[TASK_COMM_LEN];
72 /**
73 * @exe_path: Executable path of the task that initially restricted
74 * itself, at creation time. Always NULL terminated, and never greater
75 * than LANDLOCK_PATH_MAX_SIZE.
76 */
77 char exe_path[];
78};
79
80/* Adds 11 extra characters for the potential " (deleted)" suffix. */
81#define LANDLOCK_PATH_MAX_SIZE (PATH_MAX + 11)
82
83/* Makes sure the greatest landlock_details can be allocated. */
84static_assert(struct_size_t(struct landlock_details, exe_path,
85 LANDLOCK_PATH_MAX_SIZE) <= KMALLOC_MAX_SIZE);
86
87/**
88 * struct landlock_hierarchy - Node in a domain hierarchy
89 */
90struct landlock_hierarchy {
91 /**
92 * @parent: Pointer to the parent node, or NULL if it is a root
93 * Landlock domain.
94 */
95 struct landlock_hierarchy *parent;
96 /**
97 * @usage: Number of potential children domains plus their parent
98 * domain.
99 */
100 refcount_t usage;
101
102#ifdef CONFIG_SECURITY_LANDLOCK_LOG
103 /**
104 * @log_status: Whether this domain should be logged or not. Because
105 * concurrent log entries may be created at the same time, it is still
106 * possible to have several domain records of the same domain.
107 */
108 enum landlock_log_status log_status;
109 /**
110 * @num_denials: Number of access requests denied by this domain.
111 * Masked (i.e. never logged) denials are still counted.
112 */
113 atomic64_t num_denials;
114 /**
115 * @id: Landlock domain ID, set once at domain creation time.
116 */
117 u64 id;
118 /**
119 * @details: Information about the related domain.
120 */
121 const struct landlock_details *details;
122 /**
123 * @log_same_exec: Set if the domain is *not* configured with
124 * %LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF. Set to true by default.
125 */
126 u32 log_same_exec : 1,
127 /**
128 * @log_new_exec: Set if the domain is configured with
129 * %LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON. Set to false by default.
130 */
131 log_new_exec : 1;
132 /**
133 * @quiet_masks: Bitmasks of access that should be quieted (i.e. not
134 * logged) if the related object is marked as quiet.
135 */
136 struct access_masks quiet_masks;
137#endif /* CONFIG_SECURITY_LANDLOCK_LOG */
138};
139
140#ifdef CONFIG_SECURITY_LANDLOCK_LOG
141
142deny_masks_t
143landlock_get_deny_masks(const access_mask_t all_existing_optional_access,
144 const access_mask_t optional_access,
145 const struct layer_masks *const masks);
146
147optional_access_t landlock_get_quiet_optional_accesses(
148 const access_mask_t all_existing_optional_access,
149 const deny_masks_t deny_masks, const struct layer_masks *const masks);
150
151int landlock_init_hierarchy_log(struct landlock_hierarchy *const hierarchy);
152
153static inline void
154landlock_free_hierarchy_details(struct landlock_hierarchy *const hierarchy)
155{
156 if (!hierarchy || !hierarchy->details)
157 return;
158
159 put_pid(hierarchy->details->pid);
160 kfree(hierarchy->details);
161}
162
163#else /* CONFIG_SECURITY_LANDLOCK_LOG */
164
165static inline int
166landlock_init_hierarchy_log(struct landlock_hierarchy *const hierarchy)
167{
168 return 0;
169}
170
171static inline void
172landlock_free_hierarchy_details(struct landlock_hierarchy *const hierarchy)
173{
174}
175
176#endif /* CONFIG_SECURITY_LANDLOCK_LOG */
177
178static inline void
179landlock_get_hierarchy(struct landlock_hierarchy *const hierarchy)
180{
181 if (hierarchy)
182 refcount_inc(&hierarchy->usage);
183}
184
185static inline void landlock_put_hierarchy(struct landlock_hierarchy *hierarchy)
186{
187 while (hierarchy && refcount_dec_and_test(&hierarchy->usage)) {
188 const struct landlock_hierarchy *const freeme = hierarchy;
189
190 landlock_log_free_domain(hierarchy);
191 landlock_free_hierarchy_details(hierarchy);
192 hierarchy = hierarchy->parent;
193 kfree(freeme);
194 }
195}
196
197/**
198 * struct landlock_domain - Immutable Landlock domain
199 *
200 * A domain is created from a ruleset by landlock_merge_ruleset() and enforced
201 * on a task. Once created, its rules and access masks are immutable. Unlike
202 * &struct landlock_ruleset, a domain has no lock field.
203 */
204struct landlock_domain {
205 /**
206 * @rules: Red-black tree storage for rules.
207 */
208 struct landlock_rules rules;
209 /**
210 * @hierarchy: Enables hierarchy identification even when a parent
211 * domain vanishes. This is needed for the ptrace and scope
212 * restrictions.
213 */
214 struct landlock_hierarchy *hierarchy;
215 union {
216 /**
217 * @work_free: Enables to free a domain within a lockless
218 * section. This is only used by landlock_put_domain_deferred()
219 * when @usage reaches zero. The fields @usage, @num_layers and
220 * @handled_masks are then unused.
221 */
222 struct work_struct work_free;
223 struct {
224 /**
225 * @usage: Number of credentials referencing this
226 * domain.
227 */
228 refcount_t usage;
229 /**
230 * @num_layers: Number of layers that are used in this
231 * domain. This enables to check that all the layers
232 * allow an access request.
233 */
234 u32 num_layers;
235 /**
236 * @handled_masks: Contains the subset of filesystem and
237 * network actions that are restricted by a domain. A
238 * domain saves all layers of merged rulesets in a stack
239 * (FAM), starting from the first layer to the last one.
240 * These layers are used when merging rulesets, for user
241 * space backward compatibility (i.e. future-proof), and
242 * to properly handle merged rulesets without
243 * overlapping access rights. These layers are set once
244 * and never changed for the lifetime of the domain.
245 *
246 * Not annotated with __counted_by(num_layers): clang
247 * miscomputes the counter address for a FAM nested in
248 * an anonymous struct within a union, which trips
249 * FORTIFY:
250 * https://github.com/llvm/llvm-project/pull/228309
251 */
252 struct access_masks handled_masks[];
253 };
254 };
255};
256
257static inline access_mask_t
258landlock_get_fs_access_mask(const struct landlock_domain *const domain,
259 const u16 layer_level)
260{
261 /* Handles all initially denied by default access rights. */
262 return domain->handled_masks[layer_level].fs |
263 _LANDLOCK_ACCESS_FS_INITIALLY_DENIED;
264}
265
266static inline access_mask_t
267landlock_get_net_access_mask(const struct landlock_domain *const domain,
268 const u16 layer_level)
269{
270 return domain->handled_masks[layer_level].net;
271}
272
273static inline access_mask_t
274landlock_get_scope_mask(const struct landlock_domain *const domain,
275 const u16 layer_level)
276{
277 return domain->handled_masks[layer_level].scope;
278}
279
280/**
281 * landlock_union_access_masks - Return all access rights handled in the
282 * domain
283 *
284 * @domain: Landlock domain
285 *
286 * Return: An access_masks result of the OR of all the domain's access masks.
287 */
288static inline struct access_masks
289landlock_union_access_masks(const struct landlock_domain *const domain)
290{
291 union access_masks_all matches = {};
292 size_t layer_level;
293
294 for (layer_level = 0; layer_level < domain->num_layers; layer_level++) {
295 union access_masks_all layer = {
296 .masks = domain->handled_masks[layer_level],
297 };
298
299 matches.all |= layer.all;
300 }
301
302 return matches.masks;
303}
304
305void landlock_put_domain(struct landlock_domain *const domain);
306void landlock_put_domain_deferred(struct landlock_domain *const domain);
307
308DEFINE_FREE(landlock_put_domain, struct landlock_domain *,
309 if (!IS_ERR_OR_NULL(_T)) landlock_put_domain(_T))
310
311struct landlock_domain *
312landlock_merge_ruleset(struct landlock_domain *const parent,
313 struct landlock_ruleset *const ruleset);
314
315bool landlock_unmask_layers(const struct landlock_domain *const domain,
316 const struct landlock_id id,
317 struct layer_masks *masks,
318 const struct landlock_rule **matched_rule);
319
320access_mask_t
321landlock_init_layer_masks(const struct landlock_domain *const domain,
322 const access_mask_t access_request,
323 struct layer_masks *masks,
324 const enum landlock_key_type key_type);
325
326static inline void landlock_get_domain(struct landlock_domain *const domain)
327{
328 if (domain)
329 refcount_inc(&domain->usage);
330}
331
332#endif /* _SECURITY_LANDLOCK_DOMAIN_H */