Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/security/mac_partition/mac_partition.c
39481 views
1
/*-
2
* Copyright (c) 1999-2002, 2007-2008 Robert N. M. Watson
3
* Copyright (c) 2001-2002 Networks Associates Technology, Inc.
4
* Copyright (c) 2006 SPARTA, Inc.
5
* Copyright (c) 2008 Apple Inc.
6
* All rights reserved.
7
*
8
* This software was developed by Robert Watson for the TrustedBSD Project.
9
*
10
* This software was developed for the FreeBSD Project in part by Network
11
* Associates Laboratories, the Security Research Division of Network
12
* Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13
* as part of the DARPA CHATS research program.
14
*
15
* This software was enhanced by SPARTA ISSO under SPAWAR contract
16
* N66001-04-C-6019 ("SEFOS").
17
*
18
* Redistribution and use in source and binary forms, with or without
19
* modification, are permitted provided that the following conditions
20
* are met:
21
* 1. Redistributions of source code must retain the above copyright
22
* notice, this list of conditions and the following disclaimer.
23
* 2. Redistributions in binary form must reproduce the above copyright
24
* notice, this list of conditions and the following disclaimer in the
25
* documentation and/or other materials provided with the distribution.
26
*
27
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37
* SUCH DAMAGE.
38
*/
39
40
/*
41
* Developed by the TrustedBSD Project.
42
*
43
* Experiment with a partition-like model.
44
*/
45
46
#include <sys/param.h>
47
#include <sys/kernel.h>
48
#include <sys/module.h>
49
#include <sys/priv.h>
50
#include <sys/proc.h>
51
#include <sys/sbuf.h>
52
#include <sys/socket.h>
53
#include <sys/socketvar.h>
54
#include <sys/systm.h>
55
#include <sys/sysctl.h>
56
57
#include <net/route.h>
58
#include <netinet/in.h>
59
#include <netinet/in_pcb.h>
60
61
#include <security/mac/mac_policy.h>
62
#include <security/mac_partition/mac_partition.h>
63
64
static SYSCTL_NODE(_security_mac, OID_AUTO, partition,
65
CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
66
"TrustedBSD mac_partition policy controls");
67
68
static int partition_enabled = 1;
69
SYSCTL_INT(_security_mac_partition, OID_AUTO, enabled, CTLFLAG_RW,
70
&partition_enabled, 0, "Enforce partition policy");
71
72
static int partition_slot;
73
#define SLOT(l) mac_label_get((l), partition_slot)
74
#define SLOT_SET(l, v) mac_label_set((l), partition_slot, (v))
75
76
static int
77
partition_check(struct label *subject, struct label *object)
78
{
79
80
if (partition_enabled == 0)
81
return (0);
82
83
if (subject == NULL)
84
return (0);
85
86
if (SLOT(subject) == 0)
87
return (0);
88
89
/*
90
* If the object label hasn't been allocated, then it's effectively
91
* not in a partition, and we know the subject is as it has a label
92
* and it's not 0, so reject.
93
*/
94
if (object == NULL)
95
return (EPERM);
96
97
if (SLOT(subject) == SLOT(object))
98
return (0);
99
100
return (EPERM);
101
}
102
103
/*
104
* Object-specific entry points are sorted alphabetically by object type name
105
* and then by operation.
106
*/
107
static int
108
partition_cred_check_relabel(struct ucred *cred, struct label *newlabel)
109
{
110
int error;
111
112
error = 0;
113
114
/*
115
* Treat "0" as a no-op request because it reflects an unset
116
* partition label. If we ever want to support switching back to an
117
* unpartitioned state for a process, we'll need to differentiate the
118
* "not in a partition" and "no partition defined during internalize"
119
* conditions.
120
*/
121
if (SLOT(newlabel) != 0) {
122
/*
123
* Require BSD privilege in order to change the partition.
124
* Originally we also required that the process not be in a
125
* partition in the first place, but this didn't interact
126
* well with sendmail.
127
*/
128
error = priv_check_cred(cred, PRIV_MAC_PARTITION);
129
}
130
131
return (error);
132
}
133
134
static int
135
partition_cred_check_visible(struct ucred *cr1, struct ucred *cr2)
136
{
137
int error;
138
139
error = partition_check(cr1->cr_label, cr2->cr_label);
140
141
return (error == 0 ? 0 : ESRCH);
142
}
143
144
static void
145
partition_cred_copy_label(struct label *src, struct label *dest)
146
{
147
148
if (src != NULL && dest != NULL)
149
SLOT_SET(dest, SLOT(src));
150
else if (dest != NULL)
151
SLOT_SET(dest, 0);
152
}
153
154
static void
155
partition_cred_create_init(struct ucred *cred)
156
{
157
158
SLOT_SET(cred->cr_label, 0);
159
}
160
161
static void
162
partition_cred_create_swapper(struct ucred *cred)
163
{
164
165
SLOT_SET(cred->cr_label, 0);
166
}
167
168
static void
169
partition_cred_destroy_label(struct label *label)
170
{
171
172
SLOT_SET(label, 0);
173
}
174
175
static int
176
partition_cred_externalize_label(struct label *label, char *element_name,
177
struct sbuf *sb, int *claimed)
178
{
179
180
if (strcmp(MAC_PARTITION_LABEL_NAME, element_name) != 0)
181
return (0);
182
183
(*claimed)++;
184
185
if (label != NULL) {
186
if (sbuf_printf(sb, "%jd", (intmax_t)SLOT(label)) == -1)
187
return (EINVAL);
188
} else {
189
if (sbuf_printf(sb, "0") == -1)
190
return (EINVAL);
191
}
192
return (0);
193
}
194
195
static void
196
partition_cred_init_label(struct label *label)
197
{
198
199
SLOT_SET(label, 0);
200
}
201
202
static int
203
partition_cred_internalize_label(struct label *label, char *element_name,
204
char *element_data, int *claimed)
205
{
206
207
if (strcmp(MAC_PARTITION_LABEL_NAME, element_name) != 0)
208
return (0);
209
210
(*claimed)++;
211
SLOT_SET(label, strtol(element_data, NULL, 10));
212
return (0);
213
}
214
215
static void
216
partition_cred_relabel(struct ucred *cred, struct label *newlabel)
217
{
218
219
if (newlabel != NULL && SLOT(newlabel) != 0)
220
SLOT_SET(cred->cr_label, SLOT(newlabel));
221
}
222
223
static int
224
partition_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
225
struct label *inplabel)
226
{
227
int error;
228
229
error = partition_check(cred->cr_label, inp->inp_cred->cr_label);
230
231
return (error ? ENOENT : 0);
232
}
233
234
static int
235
partition_proc_check_debug(struct ucred *cred, struct proc *p)
236
{
237
int error;
238
239
error = partition_check(cred->cr_label, p->p_ucred->cr_label);
240
241
return (error ? ESRCH : 0);
242
}
243
244
static int
245
partition_proc_check_sched(struct ucred *cred, struct proc *p)
246
{
247
int error;
248
249
error = partition_check(cred->cr_label, p->p_ucred->cr_label);
250
251
return (error ? ESRCH : 0);
252
}
253
254
static int
255
partition_proc_check_signal(struct ucred *cred, struct proc *p,
256
int signum)
257
{
258
int error;
259
260
error = partition_check(cred->cr_label, p->p_ucred->cr_label);
261
262
return (error ? ESRCH : 0);
263
}
264
265
static int
266
partition_socket_check_visible(struct ucred *cred, struct socket *so,
267
struct label *solabel)
268
{
269
int error;
270
271
error = partition_check(cred->cr_label, so->so_cred->cr_label);
272
273
return (error ? ENOENT : 0);
274
}
275
276
static int
277
partition_vnode_check_exec(struct ucred *cred, struct vnode *vp,
278
struct label *vplabel, struct image_params *imgp,
279
struct label *execlabel)
280
{
281
282
if (execlabel != NULL) {
283
/*
284
* We currently don't permit labels to be changed at
285
* exec-time as part of the partition model, so disallow
286
* non-NULL partition label changes in execlabel.
287
*/
288
if (SLOT(execlabel) != 0)
289
return (EINVAL);
290
}
291
292
return (0);
293
}
294
295
static struct mac_policy_ops partition_ops =
296
{
297
.mpo_cred_check_relabel = partition_cred_check_relabel,
298
.mpo_cred_check_visible = partition_cred_check_visible,
299
.mpo_cred_copy_label = partition_cred_copy_label,
300
.mpo_cred_create_init = partition_cred_create_init,
301
.mpo_cred_create_swapper = partition_cred_create_swapper,
302
.mpo_cred_destroy_label = partition_cred_destroy_label,
303
.mpo_cred_externalize_label = partition_cred_externalize_label,
304
.mpo_cred_init_label = partition_cred_init_label,
305
.mpo_cred_internalize_label = partition_cred_internalize_label,
306
.mpo_cred_relabel = partition_cred_relabel,
307
.mpo_inpcb_check_visible = partition_inpcb_check_visible,
308
.mpo_proc_check_debug = partition_proc_check_debug,
309
.mpo_proc_check_sched = partition_proc_check_sched,
310
.mpo_proc_check_signal = partition_proc_check_signal,
311
.mpo_socket_check_visible = partition_socket_check_visible,
312
.mpo_vnode_check_exec = partition_vnode_check_exec,
313
};
314
315
MAC_POLICY_SET(&partition_ops, mac_partition, "TrustedBSD MAC/Partition",
316
MPC_LOADTIME_FLAG_UNLOADOK, &partition_slot);
317
318