Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/security/mac/mac_prison.c
96295 views
1
/*-
2
* Copyright (c) 2025 Kyle Evans <[email protected]>
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*/
6
7
#include <sys/cdefs.h>
8
#include "opt_mac.h"
9
10
#include <sys/param.h>
11
#include <sys/condvar.h>
12
#include <sys/imgact.h>
13
#include <sys/jail.h>
14
#include <sys/kernel.h>
15
#include <sys/lock.h>
16
#include <sys/malloc.h>
17
#include <sys/mutex.h>
18
#include <sys/mac.h>
19
#include <sys/proc.h>
20
#include <sys/sbuf.h>
21
#include <sys/sdt.h>
22
#include <sys/systm.h>
23
#include <sys/vnode.h>
24
#include <sys/mount.h>
25
#include <sys/file.h>
26
#include <sys/namei.h>
27
#include <sys/sysctl.h>
28
29
#include <security/mac/mac_framework.h>
30
#include <security/mac/mac_internal.h>
31
#include <security/mac/mac_policy.h>
32
33
void
34
mac_prison_label_free(struct label *label)
35
{
36
if (label == NULL)
37
return;
38
39
MAC_POLICY_PERFORM_NOSLEEP(prison_destroy_label, label);
40
mac_labelzone_free(label);
41
}
42
43
struct label *
44
mac_prison_label_alloc(int flag)
45
{
46
struct label *label;
47
int error;
48
49
label = mac_labelzone_alloc(flag);
50
if (label == NULL)
51
return (NULL);
52
53
if (flag & M_WAITOK)
54
MAC_POLICY_CHECK(prison_init_label, label, flag);
55
else
56
MAC_POLICY_CHECK_NOSLEEP(prison_init_label, label, flag);
57
if (error) {
58
mac_prison_label_free(label);
59
return (NULL);
60
}
61
return (label);
62
}
63
64
/*
65
* The caller's expecting us to return with the prison locked if we were
66
* successful, since we're also setting pr->pr_label. On error, it remains
67
* unlocked.
68
*/
69
int
70
mac_prison_init(struct prison *pr, int flag)
71
{
72
struct label *prlabel;
73
74
mtx_assert(&pr->pr_mtx, MA_NOTOWNED);
75
if ((mac_labeled & MPC_OBJECT_PRISON) == 0) {
76
mtx_lock(&pr->pr_mtx);
77
pr->pr_label = NULL;
78
return (0);
79
}
80
81
prlabel = mac_prison_label_alloc(flag);
82
if (prlabel == NULL) {
83
KASSERT((flag & M_WAITOK) == 0,
84
("MAC policy prison_init_label failed under M_WAITOK"));
85
return (ENOMEM);
86
}
87
88
mtx_lock(&pr->pr_mtx);
89
pr->pr_label = prlabel;
90
return (0);
91
}
92
93
void
94
mac_prison_destroy(struct prison *pr)
95
{
96
mtx_assert(&pr->pr_mtx, MA_OWNED);
97
mac_prison_label_free(pr->pr_label);
98
pr->pr_label = NULL;
99
}
100
101
void
102
mac_prison_copy_label(struct label *src, struct label *dest)
103
{
104
105
MAC_POLICY_PERFORM_NOSLEEP(prison_copy_label, src, dest);
106
}
107
108
int
109
mac_prison_externalize_label(struct label *label, char *elements,
110
char *outbuf, size_t outbuflen)
111
{
112
int error;
113
114
MAC_POLICY_EXTERNALIZE(prison, label, elements, outbuf, outbuflen);
115
return (error);
116
}
117
118
int
119
mac_prison_internalize_label(struct label *label, char *string)
120
{
121
int error;
122
123
MAC_POLICY_INTERNALIZE(prison, label, string);
124
return (error);
125
}
126
127
void
128
mac_prison_relabel(struct ucred *cred, struct prison *pr,
129
struct label *newlabel)
130
{
131
mtx_assert(&pr->pr_mtx, MA_OWNED);
132
MAC_POLICY_PERFORM_NOSLEEP(prison_relabel, cred, pr, pr->pr_label,
133
newlabel);
134
}
135
136
int
137
mac_prison_label_set(struct ucred *cred, struct prison *pr,
138
struct label *label)
139
{
140
int error;
141
142
mtx_assert(&pr->pr_mtx, MA_OWNED);
143
144
error = mac_prison_check_relabel(cred, pr, label);
145
if (error)
146
return (error);
147
148
mac_prison_relabel(cred, pr, label);
149
150
return (0);
151
}
152
153
MAC_CHECK_PROBE_DEFINE4(prison_check_relabel, "struct ucred *",
154
"struct prison *", "struct label *", "struct label *");
155
int
156
mac_prison_check_relabel(struct ucred *cred, struct prison *pr,
157
struct label *newlabel)
158
{
159
int error;
160
161
mtx_assert(&pr->pr_mtx, MA_OWNED);
162
MAC_POLICY_CHECK_NOSLEEP(prison_check_relabel, cred, pr,
163
pr->pr_label, newlabel);
164
MAC_CHECK_PROBE4(prison_check_relabel, error, cred, pr,
165
pr->pr_label, newlabel);
166
167
return (error);
168
}
169
170
MAC_CHECK_PROBE_DEFINE3(prison_check_attach, "struct ucred *",
171
"struct prison *", "struct label *");
172
int
173
mac_prison_check_attach(struct ucred *cred, struct prison *pr)
174
{
175
int error;
176
177
MAC_POLICY_CHECK_NOSLEEP(prison_check_attach, cred, pr, pr->pr_label);
178
MAC_CHECK_PROBE3(prison_check_attach, error, cred, pr, pr->pr_label);
179
180
return (error);
181
}
182
183
MAC_CHECK_PROBE_DEFINE3(prison_check_create, "struct ucred *",
184
"struct vfsoptlist *", "int");
185
int
186
mac_prison_check_create(struct ucred *cred, struct vfsoptlist *opts,
187
int flags)
188
{
189
int error;
190
191
MAC_POLICY_CHECK_NOSLEEP(prison_check_create, cred, opts, flags);
192
MAC_CHECK_PROBE3(prison_check_create, error, cred, opts, flags);
193
194
return (error);
195
}
196
197
MAC_CHECK_PROBE_DEFINE5(prison_check_get, "struct ucred *",
198
"struct prison *", "struct label *", "struct vfsoptlist *", "int");
199
int
200
mac_prison_check_get(struct ucred *cred, struct prison *pr,
201
struct vfsoptlist *opts, int flags)
202
{
203
int error;
204
205
MAC_POLICY_CHECK_NOSLEEP(prison_check_get, cred, pr, pr->pr_label,
206
opts, flags);
207
MAC_CHECK_PROBE5(prison_check_get, error, cred, pr, pr->pr_label, opts,
208
flags);
209
210
return (error);
211
}
212
213
MAC_CHECK_PROBE_DEFINE5(prison_check_set, "struct ucred *",
214
"struct prison *", "struct label *", "struct vfsoptlist *", "int");
215
int
216
mac_prison_check_set(struct ucred *cred, struct prison *pr,
217
struct vfsoptlist *opts, int flags)
218
{
219
int error;
220
221
MAC_POLICY_CHECK_NOSLEEP(prison_check_set, cred, pr, pr->pr_label,
222
opts, flags);
223
MAC_CHECK_PROBE5(prison_check_set, error, cred, pr, pr->pr_label, opts,
224
flags);
225
226
return (error);
227
}
228
229
MAC_CHECK_PROBE_DEFINE3(prison_check_remove, "struct ucred *",
230
"struct prison *", "struct label *");
231
int
232
mac_prison_check_remove(struct ucred *cred, struct prison *pr)
233
{
234
int error;
235
236
MAC_POLICY_CHECK_NOSLEEP(prison_check_remove, cred, pr, pr->pr_label);
237
MAC_CHECK_PROBE3(prison_check_remove, error, cred, pr, pr->pr_label);
238
239
return (error);
240
}
241
242
void
243
mac_prison_created(struct ucred *cred, struct prison *pr)
244
{
245
246
MAC_POLICY_PERFORM(prison_created, cred, pr, pr->pr_label);
247
}
248
249
void
250
mac_prison_attached(struct ucred *cred, struct prison *pr, struct proc *p)
251
{
252
253
MAC_POLICY_PERFORM(prison_attached, cred, pr, pr->pr_label, p,
254
p->p_label);
255
}
256
257