summaryrefslogtreecommitdiff
path: root/security/landlock/access.h
blob: f9eaa2f536866d883c5742f7e5da283860bd73d5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Landlock - Access types and helpers
 *
 * Copyright © 2016-2020 Mickaël Salaün <mic@digikod.net>
 * Copyright © 2018-2020 ANSSI
 * Copyright © 2024-2025 Microsoft Corporation
 */

#ifndef _SECURITY_LANDLOCK_ACCESS_H
#define _SECURITY_LANDLOCK_ACCESS_H

#include <linux/bitops.h>
#include <linux/build_bug.h>
#include <linux/kernel.h>
#include <uapi/linux/landlock.h>

#include "limits.h"

/*
 * All access rights that are denied by default whether they are handled or not
 * by a ruleset/layer.  This must be ORed with the .handled field of all
 * domain->layers[] entries when we need to get the absolute handled access
 * masks, see landlock_upgrade_handled_layer_config().
 */
/* clang-format off */
#define _LANDLOCK_ACCESS_FS_INITIALLY_DENIED ( \
	LANDLOCK_ACCESS_FS_REFER)
/* clang-format on */

/* clang-format off */
#define _LANDLOCK_ACCESS_FS_OPTIONAL ( \
	LANDLOCK_ACCESS_FS_TRUNCATE | \
	LANDLOCK_ACCESS_FS_IOCTL_DEV)
/* clang-format on */

typedef u32 access_mask_t;

/* Makes sure all filesystem access rights can be stored. */
static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS);
/* Makes sure all network access rights can be stored. */
static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_NET);
/* Makes sure all scoped rights can be stored. */
static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_SCOPE);
/* Makes sure all permissions can be stored. */
static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_PERMISSION);
/* Makes sure for_each_set_bit() and for_each_clear_bit() calls are OK. */
static_assert(sizeof(unsigned long) >= sizeof(access_mask_t));

/* Access and permission masks (bitfields only). */
struct access_masks {
	access_mask_t fs : LANDLOCK_NUM_ACCESS_FS;
	access_mask_t net : LANDLOCK_NUM_ACCESS_NET;
	access_mask_t scope : LANDLOCK_NUM_SCOPE;
	access_mask_t permissions : LANDLOCK_NUM_PERMISSION;
} __packed __aligned(sizeof(u32));

union access_masks_all {
	struct access_masks masks;
	u32 all;
};

/* Makes sure all fields are covered. */
static_assert(sizeof(typeof_member(union access_masks_all, masks)) ==
	      sizeof(typeof_member(union access_masks_all, all)));

/**
 * struct permission_masks - Per-permission member bitmasks
 */
struct permission_masks {
	/**
	 * @ns_types: Namespace type member mask, indexed in FOR_EACH_NS_TYPE()
	 * order.
	 */
	u64 ns_types : LANDLOCK_NUM_NAMESPACE_TYPE;
	/**
	 * @caps: Capability member mask, indexed by CAP_* values.
	 */
	u64 caps : LANDLOCK_NUM_CAPABILITY;
} __packed __aligned(sizeof(u64));

static_assert(sizeof(struct permission_masks) == sizeof(u64));
/* All permission_masks bitfields must fit in a single u64. */
static_assert(LANDLOCK_NUM_CAPABILITY + LANDLOCK_NUM_NAMESPACE_TYPE <=
	      BITS_PER_TYPE(u64));

/**
 * struct layer_config - Per-layer access configuration
 *
 * A ruleset stores one mutable layer and a domain stores a flexible array of
 * immutable layers.  Unlike filesystem and network access rights, namespace
 * types and capabilities use flat bitmasks because their keyspaces are small
 * and bounded.
 */
struct layer_config {
	/**
	 * @allowed: Members allowed by each handled permission.
	 */
	struct permission_masks allowed;
	/**
	 * @handled: Bitmask of access rights and permissions handled (i.e.
	 * restricted) by this layer.
	 */
	struct access_masks handled;
};

#define _LANDLOCK_LAYER_MASK_PADDING                              \
	(BITS_PER_TYPE(access_mask_t) - LANDLOCK_NUM_ACCESS_MAX - \
	 IS_ENABLED(CONFIG_SECURITY_LANDLOCK_LOG))

/**
 * struct layer_mask - The access rights and rule flags for a layer.
 *
 * This has a bit for each access rights and rule flags.  During access checks,
 * it is used to represent the access rights for each layer which still need to
 * be fulfilled.  When all bits are 0, the access request is considered to be
 * fulfilled.
 */
struct layer_mask {
	/**
	 * @access: The unfulfilled access rights for this layer.
	 */
	access_mask_t access : LANDLOCK_NUM_ACCESS_MAX;
#ifdef CONFIG_SECURITY_LANDLOCK_LOG
	/**
	 * @quiet: Whether we have encountered a rule with the quiet flag for
	 * this layer.  Used to control logging.
	 */
	access_mask_t quiet : 1;
#endif /* CONFIG_SECURITY_LANDLOCK_LOG */
	/**
	 * @__pad: Padding for the compiler's bitfield initialization.
	 */
	access_mask_t __pad : _LANDLOCK_LAYER_MASK_PADDING;
} __packed __aligned(sizeof(access_mask_t));

/*
 * Make sure that we don't increase the size of struct layer_mask when storing
 * rule flags.
 */
static_assert(sizeof(struct layer_mask) == sizeof(access_mask_t));

/**
 * struct layer_masks - An array of struct layer_mask, one per layer.
 */
struct layer_masks {
	/**
	 * @layers: The unfulfilled access rights for each layer.
	 */
	struct layer_mask layers[LANDLOCK_MAX_NUM_LAYERS];
};

/*
 * Tracks domains responsible of a denied access.  This avoids storing in each
 * object the full matrix of per-layer unfulfilled access rights, which is
 * required by update_request().
 *
 * Each nibble represents the layer index of the newest layer which denied a
 * certain access right.  For file system access rights, the upper four bits are
 * the index of the layer which denies LANDLOCK_ACCESS_FS_IOCTL_DEV and the
 * lower nibble represents LANDLOCK_ACCESS_FS_TRUNCATE.
 */
typedef u8 deny_masks_t;

/*
 * Makes sure all optional access rights can be tied to a layer index (cf.
 * get_deny_mask).
 */
static_assert(BITS_PER_TYPE(deny_masks_t) >=
	      (HWEIGHT(LANDLOCK_MAX_NUM_LAYERS - 1) *
	       HWEIGHT(_LANDLOCK_ACCESS_FS_OPTIONAL)));

/* LANDLOCK_MAX_NUM_LAYERS must be a power of two (cf. deny_masks_t assert). */
static_assert(HWEIGHT(LANDLOCK_MAX_NUM_LAYERS) == 1);

/* Upgrades with all initially denied by default access rights. */
static inline struct layer_config
landlock_upgrade_handled_layer_config(struct layer_config layer_config)
{
	/*
	 * All access rights that are denied by default whether they are
	 * explicitly handled or not.
	 */
	if (layer_config.handled.fs)
		layer_config.handled.fs |= _LANDLOCK_ACCESS_FS_INITIALLY_DENIED;

	return layer_config;
}

/* Checks the subset relation between access masks. */
static inline bool access_mask_subset(access_mask_t subset,
				      access_mask_t superset)
{
	return (subset | superset) == superset;
}

/* A bitmask that is large enough to hold set of optional accesses. */
typedef u8 optional_access_t;
static_assert(BITS_PER_TYPE(optional_access_t) >=
	      HWEIGHT(_LANDLOCK_ACCESS_FS_OPTIONAL));

#endif /* _SECURITY_LANDLOCK_ACCESS_H */