Deleted Added
full compact
mac_mls.c (104546) mac_mls.c (105606)
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed by Robert Watson for the TrustedBSD Project.
7 *
8 * This software was developed for the FreeBSD Project in part by NAI Labs,
9 * the Security Research Division of Network Associates, Inc. under
10 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
11 * CHATS research program.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. The names of the authors may not be used to endorse or promote
22 * products derived from this software without specific prior written
23 * permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed by Robert Watson for the TrustedBSD Project.
7 *
8 * This software was developed for the FreeBSD Project in part by NAI Labs,
9 * the Security Research Division of Network Associates, Inc. under
10 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
11 * CHATS research program.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. The names of the authors may not be used to endorse or promote
22 * products derived from this software without specific prior written
23 * permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 *
37 * $FreeBSD: head/sys/security/mac_mls/mac_mls.c 104546 2002-10-06 02:46:26Z rwatson $
37 * $FreeBSD: head/sys/security/mac_mls/mac_mls.c 105606 2002-10-21 04:15:40Z rwatson $
38 */
39
40/*
41 * Developed by the TrustedBSD Project.
42 * MLS fixed label mandatory confidentiality policy.
43 */
44
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/acl.h>
48#include <sys/conf.h>
49#include <sys/kernel.h>
50#include <sys/mac.h>
51#include <sys/malloc.h>
52#include <sys/mount.h>
53#include <sys/proc.h>
54#include <sys/systm.h>
55#include <sys/sysproto.h>
56#include <sys/sysent.h>
57#include <sys/vnode.h>
58#include <sys/file.h>
59#include <sys/socket.h>
60#include <sys/socketvar.h>
61#include <sys/pipe.h>
62#include <sys/sysctl.h>
63
64#include <fs/devfs/devfs.h>
65
66#include <net/bpfdesc.h>
67#include <net/if.h>
68#include <net/if_types.h>
69#include <net/if_var.h>
70
71#include <netinet/in.h>
72#include <netinet/ip_var.h>
73
74#include <vm/vm.h>
75
76#include <sys/mac_policy.h>
77
78#include <security/mac_mls/mac_mls.h>
79
80SYSCTL_DECL(_security_mac);
81
82SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
83 "TrustedBSD mac_mls policy controls");
84
85static int mac_mls_enabled = 0;
86SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
87 &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
88TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
89
90static int destroyed_not_inited;
91SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
92 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
93
38 */
39
40/*
41 * Developed by the TrustedBSD Project.
42 * MLS fixed label mandatory confidentiality policy.
43 */
44
45#include <sys/types.h>
46#include <sys/param.h>
47#include <sys/acl.h>
48#include <sys/conf.h>
49#include <sys/kernel.h>
50#include <sys/mac.h>
51#include <sys/malloc.h>
52#include <sys/mount.h>
53#include <sys/proc.h>
54#include <sys/systm.h>
55#include <sys/sysproto.h>
56#include <sys/sysent.h>
57#include <sys/vnode.h>
58#include <sys/file.h>
59#include <sys/socket.h>
60#include <sys/socketvar.h>
61#include <sys/pipe.h>
62#include <sys/sysctl.h>
63
64#include <fs/devfs/devfs.h>
65
66#include <net/bpfdesc.h>
67#include <net/if.h>
68#include <net/if_types.h>
69#include <net/if_var.h>
70
71#include <netinet/in.h>
72#include <netinet/ip_var.h>
73
74#include <vm/vm.h>
75
76#include <sys/mac_policy.h>
77
78#include <security/mac_mls/mac_mls.h>
79
80SYSCTL_DECL(_security_mac);
81
82SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
83 "TrustedBSD mac_mls policy controls");
84
85static int mac_mls_enabled = 0;
86SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
87 &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
88TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
89
90static int destroyed_not_inited;
91SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
92 &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
93
94static int ptys_equal = 0;
95SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
96 &ptys_equal, 0, "Label pty devices as mls/equal on create");
97TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
98
94static int mac_mls_revocation_enabled = 0;
95SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
96 &mac_mls_revocation_enabled, 0, "Revoke access to objects on relabel");
97TUNABLE_INT("security.mac.mls.revocation_enabled",
98 &mac_mls_revocation_enabled);
99
100static int mac_mls_slot;
101#define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
102
103MALLOC_DEFINE(M_MACMLS, "mls label", "MAC/MLS labels");
104
105static int mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
106 struct label *vnodelabel, mode_t acc_mode);
107
108static struct mac_mls *
109mls_alloc(int flag)
110{
111 struct mac_mls *mac_mls;
112
113 mac_mls = malloc(sizeof(struct mac_mls), M_MACMLS, M_ZERO | flag);
114
115 return (mac_mls);
116}
117
118static void
119mls_free(struct mac_mls *mac_mls)
120{
121
122 if (mac_mls != NULL)
123 free(mac_mls, M_MACMLS);
124 else
125 atomic_add_int(&destroyed_not_inited, 1);
126}
127
128static int
129mac_mls_dominate_element(struct mac_mls_element *a,
130 struct mac_mls_element *b)
131{
132
133 switch(a->mme_type) {
134 case MAC_MLS_TYPE_EQUAL:
135 case MAC_MLS_TYPE_HIGH:
136 return (1);
137
138 case MAC_MLS_TYPE_LOW:
139 switch (b->mme_type) {
140 case MAC_MLS_TYPE_LEVEL:
141 case MAC_MLS_TYPE_HIGH:
142 return (0);
143
144 case MAC_MLS_TYPE_EQUAL:
145 case MAC_MLS_TYPE_LOW:
146 return (1);
147
148 default:
149 panic("mac_mls_dominate_element: b->mme_type invalid");
150 }
151
152 case MAC_MLS_TYPE_LEVEL:
153 switch (b->mme_type) {
154 case MAC_MLS_TYPE_EQUAL:
155 case MAC_MLS_TYPE_LOW:
156 return (1);
157
158 case MAC_MLS_TYPE_HIGH:
159 return (0);
160
161 case MAC_MLS_TYPE_LEVEL:
162 return (a->mme_level >= b->mme_level);
163
164 default:
165 panic("mac_mls_dominate_element: b->mme_type invalid");
166 }
167
168 default:
169 panic("mac_mls_dominate_element: a->mme_type invalid");
170 }
171
172 return (0);
173}
174
175static int
176mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
177{
178
179 return (mac_mls_dominate_element(&rangeb->mm_rangehigh,
180 &rangea->mm_rangehigh) &&
181 mac_mls_dominate_element(&rangea->mm_rangelow,
182 &rangeb->mm_rangelow));
183}
184
185static int
186mac_mls_single_in_range(struct mac_mls *single, struct mac_mls *range)
187{
188
189 KASSERT((single->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
190 ("mac_mls_single_in_range: a not single"));
191 KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
192 ("mac_mls_single_in_range: b not range"));
193
194 return (mac_mls_dominate_element(&range->mm_rangehigh,
195 &single->mm_single) &&
196 mac_mls_dominate_element(&single->mm_single,
197 &range->mm_rangelow));
198
199 return (1);
200}
201
202static int
203mac_mls_dominate_single(struct mac_mls *a, struct mac_mls *b)
204{
205 KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
206 ("mac_mls_dominate_single: a not single"));
207 KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
208 ("mac_mls_dominate_single: b not single"));
209
210 return (mac_mls_dominate_element(&a->mm_single, &b->mm_single));
211}
212
213static int
214mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
215{
216
217 if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
218 b->mme_type == MAC_MLS_TYPE_EQUAL)
219 return (1);
220
221 return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
222}
223
224static int
225mac_mls_equal_single(struct mac_mls *a, struct mac_mls *b)
226{
227
228 KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
229 ("mac_mls_equal_single: a not single"));
230 KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
231 ("mac_mls_equal_single: b not single"));
232
233 return (mac_mls_equal_element(&a->mm_single, &b->mm_single));
234}
235
236static int
237mac_mls_valid(struct mac_mls *mac_mls)
238{
239
240 if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
241 switch (mac_mls->mm_single.mme_type) {
242 case MAC_MLS_TYPE_LEVEL:
243 break;
244
245 case MAC_MLS_TYPE_EQUAL:
246 case MAC_MLS_TYPE_HIGH:
247 case MAC_MLS_TYPE_LOW:
248 if (mac_mls->mm_single.mme_level != 0)
249 return (EINVAL);
250 break;
251
252 default:
253 return (EINVAL);
254 }
255 } else {
256 if (mac_mls->mm_single.mme_type != MAC_MLS_TYPE_UNDEF)
257 return (EINVAL);
258 }
259
260 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
261 switch (mac_mls->mm_rangelow.mme_type) {
262 case MAC_MLS_TYPE_LEVEL:
263 break;
264
265 case MAC_MLS_TYPE_EQUAL:
266 case MAC_MLS_TYPE_HIGH:
267 case MAC_MLS_TYPE_LOW:
268 if (mac_mls->mm_rangelow.mme_level != 0)
269 return (EINVAL);
270 break;
271
272 default:
273 return (EINVAL);
274 }
275
276 switch (mac_mls->mm_rangehigh.mme_type) {
277 case MAC_MLS_TYPE_LEVEL:
278 break;
279
280 case MAC_MLS_TYPE_EQUAL:
281 case MAC_MLS_TYPE_HIGH:
282 case MAC_MLS_TYPE_LOW:
283 if (mac_mls->mm_rangehigh.mme_level != 0)
284 return (EINVAL);
285 break;
286
287 default:
288 return (EINVAL);
289 }
290 if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh,
291 &mac_mls->mm_rangelow))
292 return (EINVAL);
293 } else {
294 if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
295 mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
296 return (EINVAL);
297 }
298
299 return (0);
300}
301
302static void
303mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow,
304 u_short levellow, u_short typehigh, u_short levelhigh)
305{
306
307 mac_mls->mm_rangelow.mme_type = typelow;
308 mac_mls->mm_rangelow.mme_level = levellow;
309 mac_mls->mm_rangehigh.mme_type = typehigh;
310 mac_mls->mm_rangehigh.mme_level = levelhigh;
311 mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
312}
313
314static void
315mac_mls_set_single(struct mac_mls *mac_mls, u_short type, u_short level)
316{
317
318 mac_mls->mm_single.mme_type = type;
319 mac_mls->mm_single.mme_level = level;
320 mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE;
321}
322
323static void
324mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
325{
326 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
327 ("mac_mls_copy_range: labelfrom not range"));
328
329 labelto->mm_rangelow = labelfrom->mm_rangelow;
330 labelto->mm_rangehigh = labelfrom->mm_rangehigh;
331 labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
332}
333
334static void
335mac_mls_copy_single(struct mac_mls *labelfrom, struct mac_mls *labelto)
336{
337
338 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
339 ("mac_mls_copy_single: labelfrom not single"));
340
341 labelto->mm_single = labelfrom->mm_single;
342 labelto->mm_flags |= MAC_MLS_FLAG_SINGLE;
343}
344
345static void
346mac_mls_copy_single_to_range(struct mac_mls *labelfrom,
347 struct mac_mls *labelto)
348{
349
350 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
351 ("mac_mls_copy_single_to_range: labelfrom not single"));
352
353 labelto->mm_rangelow = labelfrom->mm_single;
354 labelto->mm_rangehigh = labelfrom->mm_single;
355 labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
356}
357
358/*
359 * Policy module operations.
360 */
361static void
362mac_mls_destroy(struct mac_policy_conf *conf)
363{
364
365}
366
367static void
368mac_mls_init(struct mac_policy_conf *conf)
369{
370
371}
372
373/*
374 * Label operations.
375 */
376static void
377mac_mls_init_label(struct label *label)
378{
379
380 SLOT(label) = mls_alloc(M_WAITOK);
381}
382
383static int
384mac_mls_init_label_waitcheck(struct label *label, int flag)
385{
386
387 SLOT(label) = mls_alloc(flag);
388 if (SLOT(label) == NULL)
389 return (ENOMEM);
390
391 return (0);
392}
393
394static void
395mac_mls_destroy_label(struct label *label)
396{
397
398 mls_free(SLOT(label));
399 SLOT(label) = NULL;
400}
401
402static int
403mac_mls_externalize(struct label *label, struct mac *extmac)
404{
405 struct mac_mls *mac_mls;
406
407 mac_mls = SLOT(label);
408
409 if (mac_mls == NULL) {
410 printf("mac_mls_externalize: NULL pointer\n");
411 return (0);
412 }
413
414 extmac->m_mls = *mac_mls;
415
416 return (0);
417}
418
419static int
420mac_mls_internalize(struct label *label, struct mac *extmac)
421{
422 struct mac_mls *mac_mls;
423 int error;
424
425 mac_mls = SLOT(label);
426
427 error = mac_mls_valid(mac_mls);
428 if (error)
429 return (error);
430
431 *mac_mls = extmac->m_mls;
432
433 return (0);
434}
435
436/*
437 * Labeling event operations: file system objects, and things that look
438 * a lot like file system objects.
439 */
440static void
441mac_mls_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent,
442 struct label *label)
443{
444 struct mac_mls *mac_mls;
445 int mls_type;
446
447 mac_mls = SLOT(label);
448 if (strcmp(dev->si_name, "null") == 0 ||
449 strcmp(dev->si_name, "zero") == 0 ||
450 strcmp(dev->si_name, "random") == 0 ||
451 strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
452 mls_type = MAC_MLS_TYPE_EQUAL;
453 else if (strcmp(dev->si_name, "kmem") == 0 ||
454 strcmp(dev->si_name, "mem") == 0)
455 mls_type = MAC_MLS_TYPE_HIGH;
99static int mac_mls_revocation_enabled = 0;
100SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
101 &mac_mls_revocation_enabled, 0, "Revoke access to objects on relabel");
102TUNABLE_INT("security.mac.mls.revocation_enabled",
103 &mac_mls_revocation_enabled);
104
105static int mac_mls_slot;
106#define SLOT(l) ((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
107
108MALLOC_DEFINE(M_MACMLS, "mls label", "MAC/MLS labels");
109
110static int mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
111 struct label *vnodelabel, mode_t acc_mode);
112
113static struct mac_mls *
114mls_alloc(int flag)
115{
116 struct mac_mls *mac_mls;
117
118 mac_mls = malloc(sizeof(struct mac_mls), M_MACMLS, M_ZERO | flag);
119
120 return (mac_mls);
121}
122
123static void
124mls_free(struct mac_mls *mac_mls)
125{
126
127 if (mac_mls != NULL)
128 free(mac_mls, M_MACMLS);
129 else
130 atomic_add_int(&destroyed_not_inited, 1);
131}
132
133static int
134mac_mls_dominate_element(struct mac_mls_element *a,
135 struct mac_mls_element *b)
136{
137
138 switch(a->mme_type) {
139 case MAC_MLS_TYPE_EQUAL:
140 case MAC_MLS_TYPE_HIGH:
141 return (1);
142
143 case MAC_MLS_TYPE_LOW:
144 switch (b->mme_type) {
145 case MAC_MLS_TYPE_LEVEL:
146 case MAC_MLS_TYPE_HIGH:
147 return (0);
148
149 case MAC_MLS_TYPE_EQUAL:
150 case MAC_MLS_TYPE_LOW:
151 return (1);
152
153 default:
154 panic("mac_mls_dominate_element: b->mme_type invalid");
155 }
156
157 case MAC_MLS_TYPE_LEVEL:
158 switch (b->mme_type) {
159 case MAC_MLS_TYPE_EQUAL:
160 case MAC_MLS_TYPE_LOW:
161 return (1);
162
163 case MAC_MLS_TYPE_HIGH:
164 return (0);
165
166 case MAC_MLS_TYPE_LEVEL:
167 return (a->mme_level >= b->mme_level);
168
169 default:
170 panic("mac_mls_dominate_element: b->mme_type invalid");
171 }
172
173 default:
174 panic("mac_mls_dominate_element: a->mme_type invalid");
175 }
176
177 return (0);
178}
179
180static int
181mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
182{
183
184 return (mac_mls_dominate_element(&rangeb->mm_rangehigh,
185 &rangea->mm_rangehigh) &&
186 mac_mls_dominate_element(&rangea->mm_rangelow,
187 &rangeb->mm_rangelow));
188}
189
190static int
191mac_mls_single_in_range(struct mac_mls *single, struct mac_mls *range)
192{
193
194 KASSERT((single->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
195 ("mac_mls_single_in_range: a not single"));
196 KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
197 ("mac_mls_single_in_range: b not range"));
198
199 return (mac_mls_dominate_element(&range->mm_rangehigh,
200 &single->mm_single) &&
201 mac_mls_dominate_element(&single->mm_single,
202 &range->mm_rangelow));
203
204 return (1);
205}
206
207static int
208mac_mls_dominate_single(struct mac_mls *a, struct mac_mls *b)
209{
210 KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
211 ("mac_mls_dominate_single: a not single"));
212 KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
213 ("mac_mls_dominate_single: b not single"));
214
215 return (mac_mls_dominate_element(&a->mm_single, &b->mm_single));
216}
217
218static int
219mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
220{
221
222 if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
223 b->mme_type == MAC_MLS_TYPE_EQUAL)
224 return (1);
225
226 return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
227}
228
229static int
230mac_mls_equal_single(struct mac_mls *a, struct mac_mls *b)
231{
232
233 KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
234 ("mac_mls_equal_single: a not single"));
235 KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
236 ("mac_mls_equal_single: b not single"));
237
238 return (mac_mls_equal_element(&a->mm_single, &b->mm_single));
239}
240
241static int
242mac_mls_valid(struct mac_mls *mac_mls)
243{
244
245 if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
246 switch (mac_mls->mm_single.mme_type) {
247 case MAC_MLS_TYPE_LEVEL:
248 break;
249
250 case MAC_MLS_TYPE_EQUAL:
251 case MAC_MLS_TYPE_HIGH:
252 case MAC_MLS_TYPE_LOW:
253 if (mac_mls->mm_single.mme_level != 0)
254 return (EINVAL);
255 break;
256
257 default:
258 return (EINVAL);
259 }
260 } else {
261 if (mac_mls->mm_single.mme_type != MAC_MLS_TYPE_UNDEF)
262 return (EINVAL);
263 }
264
265 if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
266 switch (mac_mls->mm_rangelow.mme_type) {
267 case MAC_MLS_TYPE_LEVEL:
268 break;
269
270 case MAC_MLS_TYPE_EQUAL:
271 case MAC_MLS_TYPE_HIGH:
272 case MAC_MLS_TYPE_LOW:
273 if (mac_mls->mm_rangelow.mme_level != 0)
274 return (EINVAL);
275 break;
276
277 default:
278 return (EINVAL);
279 }
280
281 switch (mac_mls->mm_rangehigh.mme_type) {
282 case MAC_MLS_TYPE_LEVEL:
283 break;
284
285 case MAC_MLS_TYPE_EQUAL:
286 case MAC_MLS_TYPE_HIGH:
287 case MAC_MLS_TYPE_LOW:
288 if (mac_mls->mm_rangehigh.mme_level != 0)
289 return (EINVAL);
290 break;
291
292 default:
293 return (EINVAL);
294 }
295 if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh,
296 &mac_mls->mm_rangelow))
297 return (EINVAL);
298 } else {
299 if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
300 mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
301 return (EINVAL);
302 }
303
304 return (0);
305}
306
307static void
308mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow,
309 u_short levellow, u_short typehigh, u_short levelhigh)
310{
311
312 mac_mls->mm_rangelow.mme_type = typelow;
313 mac_mls->mm_rangelow.mme_level = levellow;
314 mac_mls->mm_rangehigh.mme_type = typehigh;
315 mac_mls->mm_rangehigh.mme_level = levelhigh;
316 mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
317}
318
319static void
320mac_mls_set_single(struct mac_mls *mac_mls, u_short type, u_short level)
321{
322
323 mac_mls->mm_single.mme_type = type;
324 mac_mls->mm_single.mme_level = level;
325 mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE;
326}
327
328static void
329mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
330{
331 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
332 ("mac_mls_copy_range: labelfrom not range"));
333
334 labelto->mm_rangelow = labelfrom->mm_rangelow;
335 labelto->mm_rangehigh = labelfrom->mm_rangehigh;
336 labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
337}
338
339static void
340mac_mls_copy_single(struct mac_mls *labelfrom, struct mac_mls *labelto)
341{
342
343 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
344 ("mac_mls_copy_single: labelfrom not single"));
345
346 labelto->mm_single = labelfrom->mm_single;
347 labelto->mm_flags |= MAC_MLS_FLAG_SINGLE;
348}
349
350static void
351mac_mls_copy_single_to_range(struct mac_mls *labelfrom,
352 struct mac_mls *labelto)
353{
354
355 KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
356 ("mac_mls_copy_single_to_range: labelfrom not single"));
357
358 labelto->mm_rangelow = labelfrom->mm_single;
359 labelto->mm_rangehigh = labelfrom->mm_single;
360 labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
361}
362
363/*
364 * Policy module operations.
365 */
366static void
367mac_mls_destroy(struct mac_policy_conf *conf)
368{
369
370}
371
372static void
373mac_mls_init(struct mac_policy_conf *conf)
374{
375
376}
377
378/*
379 * Label operations.
380 */
381static void
382mac_mls_init_label(struct label *label)
383{
384
385 SLOT(label) = mls_alloc(M_WAITOK);
386}
387
388static int
389mac_mls_init_label_waitcheck(struct label *label, int flag)
390{
391
392 SLOT(label) = mls_alloc(flag);
393 if (SLOT(label) == NULL)
394 return (ENOMEM);
395
396 return (0);
397}
398
399static void
400mac_mls_destroy_label(struct label *label)
401{
402
403 mls_free(SLOT(label));
404 SLOT(label) = NULL;
405}
406
407static int
408mac_mls_externalize(struct label *label, struct mac *extmac)
409{
410 struct mac_mls *mac_mls;
411
412 mac_mls = SLOT(label);
413
414 if (mac_mls == NULL) {
415 printf("mac_mls_externalize: NULL pointer\n");
416 return (0);
417 }
418
419 extmac->m_mls = *mac_mls;
420
421 return (0);
422}
423
424static int
425mac_mls_internalize(struct label *label, struct mac *extmac)
426{
427 struct mac_mls *mac_mls;
428 int error;
429
430 mac_mls = SLOT(label);
431
432 error = mac_mls_valid(mac_mls);
433 if (error)
434 return (error);
435
436 *mac_mls = extmac->m_mls;
437
438 return (0);
439}
440
441/*
442 * Labeling event operations: file system objects, and things that look
443 * a lot like file system objects.
444 */
445static void
446mac_mls_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent,
447 struct label *label)
448{
449 struct mac_mls *mac_mls;
450 int mls_type;
451
452 mac_mls = SLOT(label);
453 if (strcmp(dev->si_name, "null") == 0 ||
454 strcmp(dev->si_name, "zero") == 0 ||
455 strcmp(dev->si_name, "random") == 0 ||
456 strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
457 mls_type = MAC_MLS_TYPE_EQUAL;
458 else if (strcmp(dev->si_name, "kmem") == 0 ||
459 strcmp(dev->si_name, "mem") == 0)
460 mls_type = MAC_MLS_TYPE_HIGH;
461 else if (ptys_equal &&
462 (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
463 strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
464 mls_type = MAC_MLS_TYPE_EQUAL;
456 else
457 mls_type = MAC_MLS_TYPE_LOW;
458 mac_mls_set_single(mac_mls, mls_type, 0);
459}
460
461static void
462mac_mls_create_devfs_directory(char *dirname, int dirnamelen,
463 struct devfs_dirent *devfs_dirent, struct label *label)
464{
465 struct mac_mls *mac_mls;
466
467 mac_mls = SLOT(label);
468 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
469}
470
471static void
472mac_mls_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
473 struct label *ddlabel, struct devfs_dirent *de, struct label *delabel)
474{
475 struct mac_mls *source, *dest;
476
477 source = SLOT(&cred->cr_label);
478 dest = SLOT(delabel);
479
480 mac_mls_copy_single(source, dest);
481}
482
483static void
484mac_mls_create_devfs_vnode(struct devfs_dirent *devfs_dirent,
485 struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
486{
487 struct mac_mls *source, *dest;
488
489 source = SLOT(direntlabel);
490 dest = SLOT(vnodelabel);
491 mac_mls_copy_single(source, dest);
492}
493
494static void
495mac_mls_create_vnode(struct ucred *cred, struct vnode *parent,
496 struct label *parentlabel, struct vnode *child, struct label *childlabel)
497{
498 struct mac_mls *source, *dest;
499
500 source = SLOT(&cred->cr_label);
501 dest = SLOT(childlabel);
502
503 mac_mls_copy_single(source, dest);
504}
505
506static void
507mac_mls_create_mount(struct ucred *cred, struct mount *mp,
508 struct label *mntlabel, struct label *fslabel)
509{
510 struct mac_mls *source, *dest;
511
512 source = SLOT(&cred->cr_label);
513 dest = SLOT(mntlabel);
514 mac_mls_copy_single(source, dest);
515 dest = SLOT(fslabel);
516 mac_mls_copy_single(source, dest);
517}
518
519static void
520mac_mls_create_root_mount(struct ucred *cred, struct mount *mp,
521 struct label *mntlabel, struct label *fslabel)
522{
523 struct mac_mls *mac_mls;
524
525 /* Always mount root as high integrity. */
526 mac_mls = SLOT(fslabel);
527 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
528 mac_mls = SLOT(mntlabel);
529 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
530}
531
532static void
533mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp,
534 struct label *vnodelabel, struct label *label)
535{
536 struct mac_mls *source, *dest;
537
538 source = SLOT(label);
539 dest = SLOT(vnodelabel);
540
541 mac_mls_copy_single(source, dest);
542}
543
544static void
545mac_mls_update_devfsdirent(struct devfs_dirent *devfs_dirent,
546 struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
547{
548 struct mac_mls *source, *dest;
549
550 source = SLOT(vnodelabel);
551 dest = SLOT(direntlabel);
552
553 mac_mls_copy_single(source, dest);
554}
555
556static void
557mac_mls_update_procfsvnode(struct vnode *vp, struct label *vnodelabel,
558 struct ucred *cred)
559{
560 struct mac_mls *source, *dest;
561
562 source = SLOT(&cred->cr_label);
563 dest = SLOT(vnodelabel);
564
565 /*
566 * Only copy the single, not the range, since vnodes only have
567 * a single.
568 */
569 mac_mls_copy_single(source, dest);
570}
571
572static int
573mac_mls_update_vnode_from_externalized(struct vnode *vp,
574 struct label *vnodelabel, struct mac *extmac)
575{
576 struct mac_mls *source, *dest;
577 int error;
578
579 source = &extmac->m_mls;
580 dest = SLOT(vnodelabel);
581
582 error = mac_mls_valid(source);
583 if (error)
584 return (error);
585
586 if ((source->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
587 return (EINVAL);
588
589 mac_mls_copy_single(source, dest);
590
591 return (0);
592}
593
594static void
595mac_mls_update_vnode_from_mount(struct vnode *vp, struct label *vnodelabel,
596 struct mount *mp, struct label *fslabel)
597{
598 struct mac_mls *source, *dest;
599
600 source = SLOT(fslabel);
601 dest = SLOT(vnodelabel);
602
603 mac_mls_copy_single(source, dest);
604}
605
606/*
607 * Labeling event operations: IPC object.
608 */
609static void
610mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
611 struct mbuf *m, struct label *mbuflabel)
612{
613 struct mac_mls *source, *dest;
614
615 source = SLOT(socketlabel);
616 dest = SLOT(mbuflabel);
617
618 mac_mls_copy_single(source, dest);
619}
620
621static void
622mac_mls_create_socket(struct ucred *cred, struct socket *socket,
623 struct label *socketlabel)
624{
625 struct mac_mls *source, *dest;
626
627 source = SLOT(&cred->cr_label);
628 dest = SLOT(socketlabel);
629
630 mac_mls_copy_single(source, dest);
631 mac_mls_copy_single_to_range(source, dest);
632}
633
634static void
635mac_mls_create_pipe(struct ucred *cred, struct pipe *pipe,
636 struct label *pipelabel)
637{
638 struct mac_mls *source, *dest;
639
640 source = SLOT(&cred->cr_label);
641 dest = SLOT(pipelabel);
642
643 mac_mls_copy_single(source, dest);
644}
645
646static void
647mac_mls_create_socket_from_socket(struct socket *oldsocket,
648 struct label *oldsocketlabel, struct socket *newsocket,
649 struct label *newsocketlabel)
650{
651 struct mac_mls *source, *dest;
652
653 source = SLOT(oldsocketlabel);
654 dest = SLOT(newsocketlabel);
655
656 mac_mls_copy_single(source, dest);
657 mac_mls_copy_range(source, dest);
658}
659
660static void
661mac_mls_relabel_socket(struct ucred *cred, struct socket *socket,
662 struct label *socketlabel, struct label *newlabel)
663{
664 struct mac_mls *source, *dest;
665
666 source = SLOT(newlabel);
667 dest = SLOT(socketlabel);
668
669 mac_mls_copy_single(source, dest);
670 mac_mls_copy_range(source, dest);
671}
672
673static void
674mac_mls_relabel_pipe(struct ucred *cred, struct pipe *pipe,
675 struct label *pipelabel, struct label *newlabel)
676{
677 struct mac_mls *source, *dest;
678
679 source = SLOT(newlabel);
680 dest = SLOT(pipelabel);
681
682 mac_mls_copy_single(source, dest);
683}
684
685static void
686mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
687 struct socket *socket, struct label *socketpeerlabel)
688{
689 struct mac_mls *source, *dest;
690
691 source = SLOT(mbuflabel);
692 dest = SLOT(socketpeerlabel);
693
694 mac_mls_copy_single(source, dest);
695}
696
697/*
698 * Labeling event operations: network objects.
699 */
700static void
701mac_mls_set_socket_peer_from_socket(struct socket *oldsocket,
702 struct label *oldsocketlabel, struct socket *newsocket,
703 struct label *newsocketpeerlabel)
704{
705 struct mac_mls *source, *dest;
706
707 source = SLOT(oldsocketlabel);
708 dest = SLOT(newsocketpeerlabel);
709
710 mac_mls_copy_single(source, dest);
711}
712
713static void
714mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
715 struct label *bpflabel)
716{
717 struct mac_mls *source, *dest;
718
719 source = SLOT(&cred->cr_label);
720 dest = SLOT(bpflabel);
721
722 mac_mls_copy_single(source, dest);
723}
724
725static void
726mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
727{
728 struct mac_mls *dest;
729 int level;
730
731 dest = SLOT(ifnetlabel);
732
733 if (ifnet->if_type == IFT_LOOP)
734 level = MAC_MLS_TYPE_EQUAL;
735 else
736 level = MAC_MLS_TYPE_LOW;
737
738 mac_mls_set_single(dest, level, 0);
739 mac_mls_set_range(dest, level, 0, level, 0);
740}
741
742static void
743mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
744 struct ipq *ipq, struct label *ipqlabel)
745{
746 struct mac_mls *source, *dest;
747
748 source = SLOT(fragmentlabel);
749 dest = SLOT(ipqlabel);
750
751 mac_mls_copy_single(source, dest);
752}
753
754static void
755mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
756 struct mbuf *datagram, struct label *datagramlabel)
757{
758 struct mac_mls *source, *dest;
759
760 source = SLOT(ipqlabel);
761 dest = SLOT(datagramlabel);
762
763 /* Just use the head, since we require them all to match. */
764 mac_mls_copy_single(source, dest);
765}
766
767static void
768mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
769 struct mbuf *fragment, struct label *fragmentlabel)
770{
771 struct mac_mls *source, *dest;
772
773 source = SLOT(datagramlabel);
774 dest = SLOT(fragmentlabel);
775
776 mac_mls_copy_single(source, dest);
777}
778
779static void
780mac_mls_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
781 struct label *oldmbuflabel, struct mbuf *newmbuf,
782 struct label *newmbuflabel)
783{
784 struct mac_mls *source, *dest;
785
786 source = SLOT(oldmbuflabel);
787 dest = SLOT(newmbuflabel);
788
789 mac_mls_copy_single(source, dest);
790}
791
792static void
793mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
794 struct mbuf *mbuf, struct label *mbuflabel)
795{
796 struct mac_mls *dest;
797
798 dest = SLOT(mbuflabel);
799
800 mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0);
801}
802
803static void
804mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
805 struct mbuf *mbuf, struct label *mbuflabel)
806{
807 struct mac_mls *source, *dest;
808
809 source = SLOT(bpflabel);
810 dest = SLOT(mbuflabel);
811
812 mac_mls_copy_single(source, dest);
813}
814
815static void
816mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
817 struct mbuf *m, struct label *mbuflabel)
818{
819 struct mac_mls *source, *dest;
820
821 source = SLOT(ifnetlabel);
822 dest = SLOT(mbuflabel);
823
824 mac_mls_copy_single(source, dest);
825}
826
827static void
828mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
829 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
830 struct mbuf *newmbuf, struct label *newmbuflabel)
831{
832 struct mac_mls *source, *dest;
833
834 source = SLOT(oldmbuflabel);
835 dest = SLOT(newmbuflabel);
836
837 mac_mls_copy_single(source, dest);
838}
839
840static void
841mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
842 struct mbuf *newmbuf, struct label *newmbuflabel)
843{
844 struct mac_mls *source, *dest;
845
846 source = SLOT(oldmbuflabel);
847 dest = SLOT(newmbuflabel);
848
849 mac_mls_copy_single(source, dest);
850}
851
852static int
853mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
854 struct ipq *ipq, struct label *ipqlabel)
855{
856 struct mac_mls *a, *b;
857
858 a = SLOT(ipqlabel);
859 b = SLOT(fragmentlabel);
860
861 return (mac_mls_equal_single(a, b));
862}
863
864static void
865mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
866 struct label *ifnetlabel, struct label *newlabel)
867{
868 struct mac_mls *source, *dest;
869
870 source = SLOT(newlabel);
871 dest = SLOT(ifnetlabel);
872
873 mac_mls_copy_single(source, dest);
874 mac_mls_copy_range(source, dest);
875}
876
877static void
878mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
879 struct ipq *ipq, struct label *ipqlabel)
880{
881
882 /* NOOP: we only accept matching labels, so no need to update */
883}
884
885/*
886 * Labeling event operations: processes.
887 */
888static void
889mac_mls_create_cred(struct ucred *cred_parent, struct ucred *cred_child)
890{
891 struct mac_mls *source, *dest;
892
893 source = SLOT(&cred_parent->cr_label);
894 dest = SLOT(&cred_child->cr_label);
895
896 mac_mls_copy_single(source, dest);
897 mac_mls_copy_range(source, dest);
898}
899
900static void
901mac_mls_execve_transition(struct ucred *old, struct ucred *new,
902 struct vnode *vp, struct mac *vnodelabel)
903{
904 struct mac_mls *source, *dest;
905
906 source = SLOT(&old->cr_label);
907 dest = SLOT(&new->cr_label);
908
909 mac_mls_copy_single(source, dest);
910 mac_mls_copy_range(source, dest);
911}
912
913static int
914mac_mls_execve_will_transition(struct ucred *old, struct vnode *vp,
915 struct mac *vnodelabel)
916{
917
918 return (0);
919}
920
921static void
922mac_mls_create_proc0(struct ucred *cred)
923{
924 struct mac_mls *dest;
925
926 dest = SLOT(&cred->cr_label);
927
928 mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0);
929 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, MAC_MLS_TYPE_HIGH, 0);
930}
931
932static void
933mac_mls_create_proc1(struct ucred *cred)
934{
935 struct mac_mls *dest;
936
937 dest = SLOT(&cred->cr_label);
938
939 mac_mls_set_single(dest, MAC_MLS_TYPE_LOW, 0);
940 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, MAC_MLS_TYPE_HIGH, 0);
941}
942
943static void
944mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel)
945{
946 struct mac_mls *source, *dest;
947
948 source = SLOT(newlabel);
949 dest = SLOT(&cred->cr_label);
950
951 mac_mls_copy_single(source, dest);
952 mac_mls_copy_range(source, dest);
953}
954
955/*
956 * Access control checks.
957 */
958static int
959mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
960 struct ifnet *ifnet, struct label *ifnetlabel)
961{
962 struct mac_mls *a, *b;
963
964 if (!mac_mls_enabled)
965 return (0);
966
967 a = SLOT(bpflabel);
968 b = SLOT(ifnetlabel);
969
970 if (mac_mls_equal_single(a, b))
971 return (0);
972 return (EACCES);
973}
974
975static int
976mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
977{
978 struct mac_mls *subj, *new;
979
980 subj = SLOT(&cred->cr_label);
981 new = SLOT(newlabel);
982
983 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH)
984 return (EINVAL);
985
986 /*
987 * XXX: Allow processes with root privilege to set labels outside
988 * their range, so suid things like "su" work. This WILL go away
989 * when we figure out the 'correct' solution...
990 */
991 if (!suser_cred(cred, 0))
992 return (0);
993
994 /*
995 * The new single must be in the old range.
996 */
997 if (!mac_mls_single_in_range(new, subj))
998 return (EPERM);
999
1000 /*
1001 * The new range must be in the old range.
1002 */
1003 if (!mac_mls_range_in_range(new, subj))
1004 return (EPERM);
1005
1006 /*
1007 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1008 */
1009
1010 return (0);
1011}
1012
1013
1014static int
1015mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
1016{
1017 struct mac_mls *subj, *obj;
1018
1019 if (!mac_mls_enabled)
1020 return (0);
1021
1022 subj = SLOT(&u1->cr_label);
1023 obj = SLOT(&u2->cr_label);
1024
1025 /* XXX: range */
1026 if (!mac_mls_dominate_single(subj, obj))
1027 return (ESRCH);
1028
1029 return (0);
1030}
1031
1032static int
1033mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1034 struct label *ifnetlabel, struct label *newlabel)
1035{
1036 struct mac_mls *subj, *new;
1037
1038 subj = SLOT(&cred->cr_label);
1039 new = SLOT(newlabel);
1040
1041 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH)
1042 return (EINVAL);
1043
1044 /* XXX: privilege model here? */
1045
1046 return (suser_cred(cred, 0));
1047}
1048
1049static int
1050mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1051 struct mbuf *m, struct label *mbuflabel)
1052{
1053 struct mac_mls *p, *i;
1054
1055 if (!mac_mls_enabled)
1056 return (0);
1057
1058 p = SLOT(mbuflabel);
1059 i = SLOT(ifnetlabel);
1060
1061 return (mac_mls_single_in_range(p, i) ? 0 : EACCES);
1062}
1063
1064static int
1065mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp,
1066 struct label *mntlabel)
1067{
1068 struct mac_mls *subj, *obj;
1069
1070 if (!mac_mls_enabled)
1071 return (0);
1072
1073 subj = SLOT(&cred->cr_label);
1074 obj = SLOT(mntlabel);
1075
1076 if (!mac_mls_dominate_single(subj, obj))
1077 return (EACCES);
1078
1079 return (0);
1080}
1081
1082static int
1083mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1084 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1085{
1086
1087 if(!mac_mls_enabled)
1088 return (0);
1089
1090 /* XXX: This will be implemented soon... */
1091
1092 return (0);
1093}
1094
1095static int
1096mac_mls_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
1097 struct label *pipelabel)
1098{
1099 struct mac_mls *subj, *obj;
1100
1101 if (!mac_mls_enabled)
1102 return (0);
1103
1104 subj = SLOT(&cred->cr_label);
1105 obj = SLOT((pipelabel));
1106
1107 if (!mac_mls_dominate_single(subj, obj))
1108 return (EACCES);
1109
1110 return (0);
1111}
1112
1113static int
1114mac_mls_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1115 struct label *pipelabel)
1116{
1117 struct mac_mls *subj, *obj;
1118
1119 if (!mac_mls_enabled)
1120 return (0);
1121
1122 subj = SLOT(&cred->cr_label);
1123 obj = SLOT((pipelabel));
1124
1125 if (!mac_mls_dominate_single(subj, obj))
1126 return (EACCES);
1127
1128 return (0);
1129}
1130
1131static int
1132mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1133 struct label *pipelabel, struct label *newlabel)
1134{
1135 struct mac_mls *subj, *obj, *new;
1136
1137 new = SLOT(newlabel);
1138 subj = SLOT(&cred->cr_label);
1139 obj = SLOT(pipelabel);
1140
1141 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1142 return (EINVAL);
1143
1144 /*
1145 * To relabel a pipe, the old pipe label must be in the subject
1146 * range.
1147 */
1148 if (!mac_mls_single_in_range(obj, subj))
1149 return (EPERM);
1150
1151 /*
1152 * To relabel a pipe, the new pipe label must be in the subject
1153 * range.
1154 */
1155 if (!mac_mls_single_in_range(new, subj))
1156 return (EPERM);
1157
1158 /*
1159 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1160 */
1161
1162 return (0);
1163}
1164
1165static int
1166mac_mls_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
1167 struct label *pipelabel)
1168{
1169 struct mac_mls *subj, *obj;
1170
1171 if (!mac_mls_enabled)
1172 return (0);
1173
1174 subj = SLOT(&cred->cr_label);
1175 obj = SLOT((pipelabel));
1176
1177 if (!mac_mls_dominate_single(subj, obj))
1178 return (EACCES);
1179
1180 return (0);
1181}
1182
1183static int
1184mac_mls_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1185 struct label *pipelabel)
1186{
1187 struct mac_mls *subj, *obj;
1188
1189 if (!mac_mls_enabled)
1190 return (0);
1191
1192 subj = SLOT(&cred->cr_label);
1193 obj = SLOT((pipelabel));
1194
1195 if (!mac_mls_dominate_single(obj, subj))
1196 return (EACCES);
1197
1198 return (0);
1199}
1200
1201static int
1202mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc)
1203{
1204 struct mac_mls *subj, *obj;
1205
1206 if (!mac_mls_enabled)
1207 return (0);
1208
1209 subj = SLOT(&cred->cr_label);
1210 obj = SLOT(&proc->p_ucred->cr_label);
1211
1212 /* XXX: range checks */
1213 if (!mac_mls_dominate_single(subj, obj))
1214 return (ESRCH);
1215 if (!mac_mls_dominate_single(obj, subj))
1216 return (EACCES);
1217
1218 return (0);
1219}
1220
1221static int
1222mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc)
1223{
1224 struct mac_mls *subj, *obj;
1225
1226 if (!mac_mls_enabled)
1227 return (0);
1228
1229 subj = SLOT(&cred->cr_label);
1230 obj = SLOT(&proc->p_ucred->cr_label);
1231
1232 /* XXX: range checks */
1233 if (!mac_mls_dominate_single(subj, obj))
1234 return (ESRCH);
1235 if (!mac_mls_dominate_single(obj, subj))
1236 return (EACCES);
1237
1238 return (0);
1239}
1240
1241static int
1242mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1243{
1244 struct mac_mls *subj, *obj;
1245
1246 if (!mac_mls_enabled)
1247 return (0);
1248
1249 subj = SLOT(&cred->cr_label);
1250 obj = SLOT(&proc->p_ucred->cr_label);
1251
1252 /* XXX: range checks */
1253 if (!mac_mls_dominate_single(subj, obj))
1254 return (ESRCH);
1255 if (!mac_mls_dominate_single(obj, subj))
1256 return (EACCES);
1257
1258 return (0);
1259}
1260
1261static int
1262mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel,
1263 struct mbuf *m, struct label *mbuflabel)
1264{
1265 struct mac_mls *p, *s;
1266
1267 if (!mac_mls_enabled)
1268 return (0);
1269
1270 p = SLOT(mbuflabel);
1271 s = SLOT(socketlabel);
1272
1273 return (mac_mls_equal_single(p, s) ? 0 : EACCES);
1274}
1275
1276static int
1277mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket,
1278 struct label *socketlabel, struct label *newlabel)
1279{
1280 struct mac_mls *subj, *obj, *new;
1281
1282 new = SLOT(newlabel);
1283 subj = SLOT(&cred->cr_label);
1284 obj = SLOT(socketlabel);
1285
1286 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1287 return (EINVAL);
1288
1289 /*
1290 * To relabel a socket, the old socket label must be in the subject
1291 * range.
1292 */
1293 if (!mac_mls_single_in_range(obj, subj))
1294 return (EPERM);
1295
1296 /*
1297 * To relabel a socket, the new socket label must be in the subject
1298 * range.
1299 */
1300 if (!mac_mls_single_in_range(new, subj))
1301 return (EPERM);
1302
1303 /*
1304 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1305 */
1306
1307 return (0);
1308}
1309
1310static int
1311mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket,
1312 struct label *socketlabel)
1313{
1314 struct mac_mls *subj, *obj;
1315
1316 if (!mac_mls_enabled)
1317 return (0);
1318
1319 subj = SLOT(&cred->cr_label);
1320 obj = SLOT(socketlabel);
1321
1322 if (!mac_mls_dominate_single(subj, obj))
1323 return (ENOENT);
1324
1325 return (0);
1326}
1327
1328static int
1329mac_mls_check_vnode_access(struct ucred *cred, struct vnode *vp,
1330 struct label *label, mode_t flags)
1331{
1332
1333 return (mac_mls_check_vnode_open(cred, vp, label, flags));
1334}
1335
1336static int
1337mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
1338 struct label *dlabel)
1339{
1340 struct mac_mls *subj, *obj;
1341
1342 if (!mac_mls_enabled)
1343 return (0);
1344
1345 subj = SLOT(&cred->cr_label);
1346 obj = SLOT(dlabel);
1347
1348 if (!mac_mls_dominate_single(subj, obj))
1349 return (EACCES);
1350
1351 return (0);
1352}
1353
1354static int
1355mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
1356 struct label *dlabel)
1357{
1358 struct mac_mls *subj, *obj;
1359
1360 if (!mac_mls_enabled)
1361 return (0);
1362
1363 subj = SLOT(&cred->cr_label);
1364 obj = SLOT(dlabel);
1365
1366 if (!mac_mls_dominate_single(subj, obj))
1367 return (EACCES);
1368
1369 return (0);
1370}
1371
1372static int
1373mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1374 struct label *dlabel, struct componentname *cnp, struct vattr *vap)
1375{
1376 struct mac_mls *subj, *obj;
1377
1378 if (!mac_mls_enabled)
1379 return (0);
1380
1381 subj = SLOT(&cred->cr_label);
1382 obj = SLOT(dlabel);
1383
1384 if (!mac_mls_dominate_single(obj, subj))
1385 return (EACCES);
1386
1387 return (0);
1388}
1389
1390static int
1391mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
1392 struct label *dlabel, struct vnode *vp, struct label *label,
1393 struct componentname *cnp)
1394{
1395 struct mac_mls *subj, *obj;
1396
1397 if (!mac_mls_enabled)
1398 return (0);
1399
1400 subj = SLOT(&cred->cr_label);
1401 obj = SLOT(dlabel);
1402
1403 if (!mac_mls_dominate_single(obj, subj))
1404 return (EACCES);
1405
1406 obj = SLOT(label);
1407
1408 if (!mac_mls_dominate_single(obj, subj))
1409 return (EACCES);
1410
1411 return (0);
1412}
1413
1414static int
1415mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1416 struct label *label, acl_type_t type)
1417{
1418 struct mac_mls *subj, *obj;
1419
1420 if (!mac_mls_enabled)
1421 return (0);
1422
1423 subj = SLOT(&cred->cr_label);
1424 obj = SLOT(label);
1425
1426 if (!mac_mls_dominate_single(obj, subj))
1427 return (EACCES);
1428
1429 return (0);
1430}
1431
1432static int
1433mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1434 struct label *label)
1435{
1436 struct mac_mls *subj, *obj;
1437
1438 if (!mac_mls_enabled)
1439 return (0);
1440
1441 subj = SLOT(&cred->cr_label);
1442 obj = SLOT(label);
1443
1444 if (!mac_mls_dominate_single(subj, obj))
1445 return (EACCES);
1446
1447 return (0);
1448}
1449
1450static int
1451mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
1452 struct label *label, acl_type_t type)
1453{
1454 struct mac_mls *subj, *obj;
1455
1456 if (!mac_mls_enabled)
1457 return (0);
1458
1459 subj = SLOT(&cred->cr_label);
1460 obj = SLOT(label);
1461
1462 if (!mac_mls_dominate_single(subj, obj))
1463 return (EACCES);
1464
1465 return (0);
1466}
1467
1468static int
1469mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1470 struct label *label, int attrnamespace, const char *name, struct uio *uio)
1471{
1472 struct mac_mls *subj, *obj;
1473
1474 if (!mac_mls_enabled)
1475 return (0);
1476
1477 subj = SLOT(&cred->cr_label);
1478 obj = SLOT(label);
1479
1480 if (!mac_mls_dominate_single(subj, obj))
1481 return (EACCES);
1482
1483 return (0);
1484}
1485
1486static int
1487mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1488 struct label *dlabel, struct vnode *vp, struct label *label,
1489 struct componentname *cnp)
1490{
1491 struct mac_mls *subj, *obj;
1492
1493 if (!mac_mls_enabled)
1494 return (0);
1495
1496 subj = SLOT(&cred->cr_label);
1497 obj = SLOT(dlabel);
1498
1499 if (!mac_mls_dominate_single(obj, subj))
1500 return (EACCES);
1501
1502 obj = SLOT(dlabel);
1503 if (!mac_mls_dominate_single(obj, subj))
1504 return (EACCES);
1505
1506 return (0);
1507}
1508
1509static int
1510mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1511 struct label *dlabel, struct componentname *cnp)
1512{
1513 struct mac_mls *subj, *obj;
1514
1515 if (!mac_mls_enabled)
1516 return (0);
1517
1518 subj = SLOT(&cred->cr_label);
1519 obj = SLOT(dlabel);
1520
1521 if (!mac_mls_dominate_single(subj, obj))
1522 return (EACCES);
1523
1524 return (0);
1525}
1526
1527static int
1528mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
1529 struct label *label, int prot)
1530{
1531 struct mac_mls *subj, *obj;
1532
1533 /*
1534 * Rely on the use of open()-time protections to handle
1535 * non-revocation cases.
1536 */
1537 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1538 return (0);
1539
1540 subj = SLOT(&cred->cr_label);
1541 obj = SLOT(label);
1542
1543 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
1544 if (!mac_mls_dominate_single(subj, obj))
1545 return (EACCES);
1546 }
1547 if (prot & VM_PROT_WRITE) {
1548 if (!mac_mls_dominate_single(obj, subj))
1549 return (EACCES);
1550 }
1551
1552 return (0);
1553}
1554
1555static int
1556mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
1557 struct label *vnodelabel, mode_t acc_mode)
1558{
1559 struct mac_mls *subj, *obj;
1560
1561 if (!mac_mls_enabled)
1562 return (0);
1563
1564 subj = SLOT(&cred->cr_label);
1565 obj = SLOT(vnodelabel);
1566
1567 /* XXX privilege override for admin? */
1568 if (acc_mode & (VREAD | VEXEC | VSTAT)) {
1569 if (!mac_mls_dominate_single(subj, obj))
1570 return (EACCES);
1571 }
1572 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
1573 if (!mac_mls_dominate_single(obj, subj))
1574 return (EACCES);
1575 }
1576
1577 return (0);
1578}
1579
1580static int
1581mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1582 struct vnode *vp, struct label *label)
1583{
1584 struct mac_mls *subj, *obj;
1585
1586 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1587 return (0);
1588
1589 subj = SLOT(&active_cred->cr_label);
1590 obj = SLOT(label);
1591
1592 if (!mac_mls_dominate_single(subj, obj))
1593 return (EACCES);
1594
1595 return (0);
1596}
1597
1598static int
1599mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1600 struct vnode *vp, struct label *label)
1601{
1602 struct mac_mls *subj, *obj;
1603
1604 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1605 return (0);
1606
1607 subj = SLOT(&active_cred->cr_label);
1608 obj = SLOT(label);
1609
1610 if (!mac_mls_dominate_single(subj, obj))
1611 return (EACCES);
1612
1613 return (0);
1614}
1615
1616static int
1617mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
1618 struct label *dlabel)
1619{
1620 struct mac_mls *subj, *obj;
1621
1622 if (!mac_mls_enabled)
1623 return (0);
1624
1625 subj = SLOT(&cred->cr_label);
1626 obj = SLOT(dlabel);
1627
1628 if (!mac_mls_dominate_single(subj, obj))
1629 return (EACCES);
1630
1631 return (0);
1632}
1633
1634static int
1635mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
1636 struct label *vnodelabel)
1637{
1638 struct mac_mls *subj, *obj;
1639
1640 if (!mac_mls_enabled)
1641 return (0);
1642
1643 subj = SLOT(&cred->cr_label);
1644 obj = SLOT(vnodelabel);
1645
1646 if (!mac_mls_dominate_single(subj, obj))
1647 return (EACCES);
1648
1649 return (0);
1650}
1651
1652static int
1653mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1654 struct label *vnodelabel, struct label *newlabel)
1655{
1656 struct mac_mls *old, *new, *subj;
1657
1658 old = SLOT(vnodelabel);
1659 new = SLOT(newlabel);
1660 subj = SLOT(&cred->cr_label);
1661
1662 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1663 return (EINVAL);
1664
1665 /*
1666 * To relabel a vnode, the old vnode label must be in the subject
1667 * range.
1668 */
1669 if (!mac_mls_single_in_range(old, subj))
1670 return (EPERM);
1671
1672 /*
1673 * To relabel a vnode, the new vnode label must be in the subject
1674 * range.
1675 */
1676 if (!mac_mls_single_in_range(new, subj))
1677 return (EPERM);
1678
1679 /*
1680 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1681 */
1682
1683 return (suser_cred(cred, 0));
1684}
1685
1686
1687static int
1688mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1689 struct label *dlabel, struct vnode *vp, struct label *label,
1690 struct componentname *cnp)
1691{
1692 struct mac_mls *subj, *obj;
1693
1694 if (!mac_mls_enabled)
1695 return (0);
1696
1697 subj = SLOT(&cred->cr_label);
1698 obj = SLOT(dlabel);
1699
1700 if (!mac_mls_dominate_single(obj, subj))
1701 return (EACCES);
1702
1703 obj = SLOT(label);
1704
1705 if (!mac_mls_dominate_single(obj, subj))
1706 return (EACCES);
1707
1708 return (0);
1709}
1710
1711static int
1712mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1713 struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
1714 struct componentname *cnp)
1715{
1716 struct mac_mls *subj, *obj;
1717
1718 if (!mac_mls_enabled)
1719 return (0);
1720
1721 subj = SLOT(&cred->cr_label);
1722 obj = SLOT(dlabel);
1723
1724 if (!mac_mls_dominate_single(obj, subj))
1725 return (EACCES);
1726
1727 if (vp != NULL) {
1728 obj = SLOT(label);
1729
1730 if (!mac_mls_dominate_single(obj, subj))
1731 return (EACCES);
1732 }
1733
1734 return (0);
1735}
1736
1737static int
1738mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
1739 struct label *label)
1740{
1741 struct mac_mls *subj, *obj;
1742
1743 if (!mac_mls_enabled)
1744 return (0);
1745
1746 subj = SLOT(&cred->cr_label);
1747 obj = SLOT(label);
1748
1749 if (!mac_mls_dominate_single(obj, subj))
1750 return (EACCES);
1751
1752 return (0);
1753}
1754
1755static int
1756mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
1757 struct label *label, acl_type_t type, struct acl *acl)
1758{
1759 struct mac_mls *subj, *obj;
1760
1761 if (!mac_mls_enabled)
1762 return (0);
1763
1764 subj = SLOT(&cred->cr_label);
1765 obj = SLOT(label);
1766
1767 if (!mac_mls_dominate_single(obj, subj))
1768 return (EACCES);
1769
1770 return (0);
1771}
1772
1773static int
1774mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1775 struct label *vnodelabel, int attrnamespace, const char *name,
1776 struct uio *uio)
1777{
1778 struct mac_mls *subj, *obj;
1779
1780 if (!mac_mls_enabled)
1781 return (0);
1782
1783 subj = SLOT(&cred->cr_label);
1784 obj = SLOT(vnodelabel);
1785
1786 if (!mac_mls_dominate_single(obj, subj))
1787 return (EACCES);
1788
1789 /* XXX: protect the MAC EA in a special way? */
1790
1791 return (0);
1792}
1793
1794static int
1795mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
1796 struct label *vnodelabel, u_long flags)
1797{
1798 struct mac_mls *subj, *obj;
1799
1800 if (!mac_mls_enabled)
1801 return (0);
1802
1803 subj = SLOT(&cred->cr_label);
1804 obj = SLOT(vnodelabel);
1805
1806 if (!mac_mls_dominate_single(obj, subj))
1807 return (EACCES);
1808
1809 return (0);
1810}
1811
1812static int
1813mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
1814 struct label *vnodelabel, mode_t mode)
1815{
1816 struct mac_mls *subj, *obj;
1817
1818 if (!mac_mls_enabled)
1819 return (0);
1820
1821 subj = SLOT(&cred->cr_label);
1822 obj = SLOT(vnodelabel);
1823
1824 if (!mac_mls_dominate_single(obj, subj))
1825 return (EACCES);
1826
1827 return (0);
1828}
1829
1830static int
1831mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
1832 struct label *vnodelabel, uid_t uid, gid_t gid)
1833{
1834 struct mac_mls *subj, *obj;
1835
1836 if (!mac_mls_enabled)
1837 return (0);
1838
1839 subj = SLOT(&cred->cr_label);
1840 obj = SLOT(vnodelabel);
1841
1842 if (!mac_mls_dominate_single(obj, subj))
1843 return (EACCES);
1844
1845 return (0);
1846}
1847
1848static int
1849mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1850 struct label *vnodelabel, struct timespec atime, struct timespec mtime)
1851{
1852 struct mac_mls *subj, *obj;
1853
1854 if (!mac_mls_enabled)
1855 return (0);
1856
1857 subj = SLOT(&cred->cr_label);
1858 obj = SLOT(vnodelabel);
1859
1860 if (!mac_mls_dominate_single(obj, subj))
1861 return (EACCES);
1862
1863 return (0);
1864}
1865
1866static int
1867mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1868 struct vnode *vp, struct label *vnodelabel)
1869{
1870 struct mac_mls *subj, *obj;
1871
1872 if (!mac_mls_enabled)
1873 return (0);
1874
1875 subj = SLOT(&active_cred->cr_label);
1876 obj = SLOT(vnodelabel);
1877
1878 if (!mac_mls_dominate_single(subj, obj))
1879 return (EACCES);
1880
1881 return (0);
1882}
1883
1884static int
1885mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1886 struct vnode *vp, struct label *label)
1887{
1888 struct mac_mls *subj, *obj;
1889
1890 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1891 return (0);
1892
1893 subj = SLOT(&active_cred->cr_label);
1894 obj = SLOT(label);
1895
1896 if (!mac_mls_dominate_single(obj, subj))
1897 return (EACCES);
1898
1899 return (0);
1900}
1901
1902static struct mac_policy_op_entry mac_mls_ops[] =
1903{
1904 { MAC_DESTROY,
1905 (macop_t)mac_mls_destroy },
1906 { MAC_INIT,
1907 (macop_t)mac_mls_init },
1908 { MAC_INIT_BPFDESC_LABEL,
1909 (macop_t)mac_mls_init_label },
1910 { MAC_INIT_CRED_LABEL,
1911 (macop_t)mac_mls_init_label },
1912 { MAC_INIT_DEVFSDIRENT_LABEL,
1913 (macop_t)mac_mls_init_label },
1914 { MAC_INIT_IFNET_LABEL,
1915 (macop_t)mac_mls_init_label },
1916 { MAC_INIT_IPQ_LABEL,
1917 (macop_t)mac_mls_init_label },
1918 { MAC_INIT_MBUF_LABEL,
1919 (macop_t)mac_mls_init_label_waitcheck },
1920 { MAC_INIT_MOUNT_LABEL,
1921 (macop_t)mac_mls_init_label },
1922 { MAC_INIT_MOUNT_FS_LABEL,
1923 (macop_t)mac_mls_init_label },
1924 { MAC_INIT_PIPE_LABEL,
1925 (macop_t)mac_mls_init_label },
1926 { MAC_INIT_SOCKET_LABEL,
1927 (macop_t)mac_mls_init_label_waitcheck },
1928 { MAC_INIT_SOCKET_PEER_LABEL,
1929 (macop_t)mac_mls_init_label_waitcheck },
1930 { MAC_INIT_TEMP_LABEL,
1931 (macop_t)mac_mls_init_label },
1932 { MAC_INIT_VNODE_LABEL,
1933 (macop_t)mac_mls_init_label },
1934 { MAC_DESTROY_BPFDESC_LABEL,
1935 (macop_t)mac_mls_destroy_label },
1936 { MAC_DESTROY_CRED_LABEL,
1937 (macop_t)mac_mls_destroy_label },
1938 { MAC_DESTROY_DEVFSDIRENT_LABEL,
1939 (macop_t)mac_mls_destroy_label },
1940 { MAC_DESTROY_IFNET_LABEL,
1941 (macop_t)mac_mls_destroy_label },
1942 { MAC_DESTROY_IPQ_LABEL,
1943 (macop_t)mac_mls_destroy_label },
1944 { MAC_DESTROY_MBUF_LABEL,
1945 (macop_t)mac_mls_destroy_label },
1946 { MAC_DESTROY_MOUNT_LABEL,
1947 (macop_t)mac_mls_destroy_label },
1948 { MAC_DESTROY_MOUNT_FS_LABEL,
1949 (macop_t)mac_mls_destroy_label },
1950 { MAC_DESTROY_PIPE_LABEL,
1951 (macop_t)mac_mls_destroy_label },
1952 { MAC_DESTROY_SOCKET_LABEL,
1953 (macop_t)mac_mls_destroy_label },
1954 { MAC_DESTROY_SOCKET_PEER_LABEL,
1955 (macop_t)mac_mls_destroy_label },
1956 { MAC_DESTROY_TEMP_LABEL,
1957 (macop_t)mac_mls_destroy_label },
1958 { MAC_DESTROY_VNODE_LABEL,
1959 (macop_t)mac_mls_destroy_label },
1960 { MAC_EXTERNALIZE,
1961 (macop_t)mac_mls_externalize },
1962 { MAC_INTERNALIZE,
1963 (macop_t)mac_mls_internalize },
1964 { MAC_CREATE_DEVFS_DEVICE,
1965 (macop_t)mac_mls_create_devfs_device },
1966 { MAC_CREATE_DEVFS_DIRECTORY,
1967 (macop_t)mac_mls_create_devfs_directory },
1968 { MAC_CREATE_DEVFS_SYMLINK,
1969 (macop_t)mac_mls_create_devfs_symlink },
1970 { MAC_CREATE_DEVFS_VNODE,
1971 (macop_t)mac_mls_create_devfs_vnode },
1972 { MAC_CREATE_VNODE,
1973 (macop_t)mac_mls_create_vnode },
1974 { MAC_CREATE_MOUNT,
1975 (macop_t)mac_mls_create_mount },
1976 { MAC_CREATE_ROOT_MOUNT,
1977 (macop_t)mac_mls_create_root_mount },
1978 { MAC_RELABEL_VNODE,
1979 (macop_t)mac_mls_relabel_vnode },
1980 { MAC_UPDATE_DEVFSDIRENT,
1981 (macop_t)mac_mls_update_devfsdirent },
1982 { MAC_UPDATE_PROCFSVNODE,
1983 (macop_t)mac_mls_update_procfsvnode },
1984 { MAC_UPDATE_VNODE_FROM_EXTERNALIZED,
1985 (macop_t)mac_mls_update_vnode_from_externalized },
1986 { MAC_UPDATE_VNODE_FROM_MOUNT,
1987 (macop_t)mac_mls_update_vnode_from_mount },
1988 { MAC_CREATE_MBUF_FROM_SOCKET,
1989 (macop_t)mac_mls_create_mbuf_from_socket },
1990 { MAC_CREATE_PIPE,
1991 (macop_t)mac_mls_create_pipe },
1992 { MAC_CREATE_SOCKET,
1993 (macop_t)mac_mls_create_socket },
1994 { MAC_CREATE_SOCKET_FROM_SOCKET,
1995 (macop_t)mac_mls_create_socket_from_socket },
1996 { MAC_RELABEL_PIPE,
1997 (macop_t)mac_mls_relabel_pipe },
1998 { MAC_RELABEL_SOCKET,
1999 (macop_t)mac_mls_relabel_socket },
2000 { MAC_SET_SOCKET_PEER_FROM_MBUF,
2001 (macop_t)mac_mls_set_socket_peer_from_mbuf },
2002 { MAC_SET_SOCKET_PEER_FROM_SOCKET,
2003 (macop_t)mac_mls_set_socket_peer_from_socket },
2004 { MAC_CREATE_BPFDESC,
2005 (macop_t)mac_mls_create_bpfdesc },
2006 { MAC_CREATE_DATAGRAM_FROM_IPQ,
2007 (macop_t)mac_mls_create_datagram_from_ipq },
2008 { MAC_CREATE_FRAGMENT,
2009 (macop_t)mac_mls_create_fragment },
2010 { MAC_CREATE_IFNET,
2011 (macop_t)mac_mls_create_ifnet },
2012 { MAC_CREATE_IPQ,
2013 (macop_t)mac_mls_create_ipq },
2014 { MAC_CREATE_MBUF_FROM_MBUF,
2015 (macop_t)mac_mls_create_mbuf_from_mbuf },
2016 { MAC_CREATE_MBUF_LINKLAYER,
2017 (macop_t)mac_mls_create_mbuf_linklayer },
2018 { MAC_CREATE_MBUF_FROM_BPFDESC,
2019 (macop_t)mac_mls_create_mbuf_from_bpfdesc },
2020 { MAC_CREATE_MBUF_FROM_IFNET,
2021 (macop_t)mac_mls_create_mbuf_from_ifnet },
2022 { MAC_CREATE_MBUF_MULTICAST_ENCAP,
2023 (macop_t)mac_mls_create_mbuf_multicast_encap },
2024 { MAC_CREATE_MBUF_NETLAYER,
2025 (macop_t)mac_mls_create_mbuf_netlayer },
2026 { MAC_FRAGMENT_MATCH,
2027 (macop_t)mac_mls_fragment_match },
2028 { MAC_RELABEL_IFNET,
2029 (macop_t)mac_mls_relabel_ifnet },
2030 { MAC_UPDATE_IPQ,
2031 (macop_t)mac_mls_update_ipq },
2032 { MAC_CREATE_CRED,
2033 (macop_t)mac_mls_create_cred },
2034 { MAC_EXECVE_TRANSITION,
2035 (macop_t)mac_mls_execve_transition },
2036 { MAC_EXECVE_WILL_TRANSITION,
2037 (macop_t)mac_mls_execve_will_transition },
2038 { MAC_CREATE_PROC0,
2039 (macop_t)mac_mls_create_proc0 },
2040 { MAC_CREATE_PROC1,
2041 (macop_t)mac_mls_create_proc1 },
2042 { MAC_RELABEL_CRED,
2043 (macop_t)mac_mls_relabel_cred },
2044 { MAC_CHECK_BPFDESC_RECEIVE,
2045 (macop_t)mac_mls_check_bpfdesc_receive },
2046 { MAC_CHECK_CRED_RELABEL,
2047 (macop_t)mac_mls_check_cred_relabel },
2048 { MAC_CHECK_CRED_VISIBLE,
2049 (macop_t)mac_mls_check_cred_visible },
2050 { MAC_CHECK_IFNET_RELABEL,
2051 (macop_t)mac_mls_check_ifnet_relabel },
2052 { MAC_CHECK_IFNET_TRANSMIT,
2053 (macop_t)mac_mls_check_ifnet_transmit },
2054 { MAC_CHECK_MOUNT_STAT,
2055 (macop_t)mac_mls_check_mount_stat },
2056 { MAC_CHECK_PIPE_IOCTL,
2057 (macop_t)mac_mls_check_pipe_ioctl },
2058 { MAC_CHECK_PIPE_POLL,
2059 (macop_t)mac_mls_check_pipe_poll },
2060 { MAC_CHECK_PIPE_READ,
2061 (macop_t)mac_mls_check_pipe_read },
2062 { MAC_CHECK_PIPE_RELABEL,
2063 (macop_t)mac_mls_check_pipe_relabel },
2064 { MAC_CHECK_PIPE_STAT,
2065 (macop_t)mac_mls_check_pipe_stat },
2066 { MAC_CHECK_PIPE_WRITE,
2067 (macop_t)mac_mls_check_pipe_write },
2068 { MAC_CHECK_PROC_DEBUG,
2069 (macop_t)mac_mls_check_proc_debug },
2070 { MAC_CHECK_PROC_SCHED,
2071 (macop_t)mac_mls_check_proc_sched },
2072 { MAC_CHECK_PROC_SIGNAL,
2073 (macop_t)mac_mls_check_proc_signal },
2074 { MAC_CHECK_SOCKET_DELIVER,
2075 (macop_t)mac_mls_check_socket_deliver },
2076 { MAC_CHECK_SOCKET_RELABEL,
2077 (macop_t)mac_mls_check_socket_relabel },
2078 { MAC_CHECK_SOCKET_VISIBLE,
2079 (macop_t)mac_mls_check_socket_visible },
2080 { MAC_CHECK_VNODE_ACCESS,
2081 (macop_t)mac_mls_check_vnode_access },
2082 { MAC_CHECK_VNODE_CHDIR,
2083 (macop_t)mac_mls_check_vnode_chdir },
2084 { MAC_CHECK_VNODE_CHROOT,
2085 (macop_t)mac_mls_check_vnode_chroot },
2086 { MAC_CHECK_VNODE_CREATE,
2087 (macop_t)mac_mls_check_vnode_create },
2088 { MAC_CHECK_VNODE_DELETE,
2089 (macop_t)mac_mls_check_vnode_delete },
2090 { MAC_CHECK_VNODE_DELETEACL,
2091 (macop_t)mac_mls_check_vnode_deleteacl },
2092 { MAC_CHECK_VNODE_EXEC,
2093 (macop_t)mac_mls_check_vnode_exec },
2094 { MAC_CHECK_VNODE_GETACL,
2095 (macop_t)mac_mls_check_vnode_getacl },
2096 { MAC_CHECK_VNODE_GETEXTATTR,
2097 (macop_t)mac_mls_check_vnode_getextattr },
2098 { MAC_CHECK_VNODE_LINK,
2099 (macop_t)mac_mls_check_vnode_link },
2100 { MAC_CHECK_VNODE_LOOKUP,
2101 (macop_t)mac_mls_check_vnode_lookup },
2102 { MAC_CHECK_VNODE_MMAP,
2103 (macop_t)mac_mls_check_vnode_mmap },
2104 { MAC_CHECK_VNODE_MPROTECT,
2105 (macop_t)mac_mls_check_vnode_mmap },
2106 { MAC_CHECK_VNODE_OPEN,
2107 (macop_t)mac_mls_check_vnode_open },
2108 { MAC_CHECK_VNODE_POLL,
2109 (macop_t)mac_mls_check_vnode_poll },
2110 { MAC_CHECK_VNODE_READ,
2111 (macop_t)mac_mls_check_vnode_read },
2112 { MAC_CHECK_VNODE_READDIR,
2113 (macop_t)mac_mls_check_vnode_readdir },
2114 { MAC_CHECK_VNODE_READLINK,
2115 (macop_t)mac_mls_check_vnode_readlink },
2116 { MAC_CHECK_VNODE_RELABEL,
2117 (macop_t)mac_mls_check_vnode_relabel },
2118 { MAC_CHECK_VNODE_RENAME_FROM,
2119 (macop_t)mac_mls_check_vnode_rename_from },
2120 { MAC_CHECK_VNODE_RENAME_TO,
2121 (macop_t)mac_mls_check_vnode_rename_to },
2122 { MAC_CHECK_VNODE_REVOKE,
2123 (macop_t)mac_mls_check_vnode_revoke },
2124 { MAC_CHECK_VNODE_SETACL,
2125 (macop_t)mac_mls_check_vnode_setacl },
2126 { MAC_CHECK_VNODE_SETEXTATTR,
2127 (macop_t)mac_mls_check_vnode_setextattr },
2128 { MAC_CHECK_VNODE_SETFLAGS,
2129 (macop_t)mac_mls_check_vnode_setflags },
2130 { MAC_CHECK_VNODE_SETMODE,
2131 (macop_t)mac_mls_check_vnode_setmode },
2132 { MAC_CHECK_VNODE_SETOWNER,
2133 (macop_t)mac_mls_check_vnode_setowner },
2134 { MAC_CHECK_VNODE_SETUTIMES,
2135 (macop_t)mac_mls_check_vnode_setutimes },
2136 { MAC_CHECK_VNODE_STAT,
2137 (macop_t)mac_mls_check_vnode_stat },
2138 { MAC_CHECK_VNODE_WRITE,
2139 (macop_t)mac_mls_check_vnode_write },
2140 { MAC_OP_LAST, NULL }
2141};
2142
2143MAC_POLICY_SET(mac_mls_ops, trustedbsd_mac_mls, "TrustedBSD MAC/MLS",
2144 MPC_LOADTIME_FLAG_NOTLATE, &mac_mls_slot);
465 else
466 mls_type = MAC_MLS_TYPE_LOW;
467 mac_mls_set_single(mac_mls, mls_type, 0);
468}
469
470static void
471mac_mls_create_devfs_directory(char *dirname, int dirnamelen,
472 struct devfs_dirent *devfs_dirent, struct label *label)
473{
474 struct mac_mls *mac_mls;
475
476 mac_mls = SLOT(label);
477 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
478}
479
480static void
481mac_mls_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
482 struct label *ddlabel, struct devfs_dirent *de, struct label *delabel)
483{
484 struct mac_mls *source, *dest;
485
486 source = SLOT(&cred->cr_label);
487 dest = SLOT(delabel);
488
489 mac_mls_copy_single(source, dest);
490}
491
492static void
493mac_mls_create_devfs_vnode(struct devfs_dirent *devfs_dirent,
494 struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
495{
496 struct mac_mls *source, *dest;
497
498 source = SLOT(direntlabel);
499 dest = SLOT(vnodelabel);
500 mac_mls_copy_single(source, dest);
501}
502
503static void
504mac_mls_create_vnode(struct ucred *cred, struct vnode *parent,
505 struct label *parentlabel, struct vnode *child, struct label *childlabel)
506{
507 struct mac_mls *source, *dest;
508
509 source = SLOT(&cred->cr_label);
510 dest = SLOT(childlabel);
511
512 mac_mls_copy_single(source, dest);
513}
514
515static void
516mac_mls_create_mount(struct ucred *cred, struct mount *mp,
517 struct label *mntlabel, struct label *fslabel)
518{
519 struct mac_mls *source, *dest;
520
521 source = SLOT(&cred->cr_label);
522 dest = SLOT(mntlabel);
523 mac_mls_copy_single(source, dest);
524 dest = SLOT(fslabel);
525 mac_mls_copy_single(source, dest);
526}
527
528static void
529mac_mls_create_root_mount(struct ucred *cred, struct mount *mp,
530 struct label *mntlabel, struct label *fslabel)
531{
532 struct mac_mls *mac_mls;
533
534 /* Always mount root as high integrity. */
535 mac_mls = SLOT(fslabel);
536 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
537 mac_mls = SLOT(mntlabel);
538 mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0);
539}
540
541static void
542mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp,
543 struct label *vnodelabel, struct label *label)
544{
545 struct mac_mls *source, *dest;
546
547 source = SLOT(label);
548 dest = SLOT(vnodelabel);
549
550 mac_mls_copy_single(source, dest);
551}
552
553static void
554mac_mls_update_devfsdirent(struct devfs_dirent *devfs_dirent,
555 struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
556{
557 struct mac_mls *source, *dest;
558
559 source = SLOT(vnodelabel);
560 dest = SLOT(direntlabel);
561
562 mac_mls_copy_single(source, dest);
563}
564
565static void
566mac_mls_update_procfsvnode(struct vnode *vp, struct label *vnodelabel,
567 struct ucred *cred)
568{
569 struct mac_mls *source, *dest;
570
571 source = SLOT(&cred->cr_label);
572 dest = SLOT(vnodelabel);
573
574 /*
575 * Only copy the single, not the range, since vnodes only have
576 * a single.
577 */
578 mac_mls_copy_single(source, dest);
579}
580
581static int
582mac_mls_update_vnode_from_externalized(struct vnode *vp,
583 struct label *vnodelabel, struct mac *extmac)
584{
585 struct mac_mls *source, *dest;
586 int error;
587
588 source = &extmac->m_mls;
589 dest = SLOT(vnodelabel);
590
591 error = mac_mls_valid(source);
592 if (error)
593 return (error);
594
595 if ((source->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
596 return (EINVAL);
597
598 mac_mls_copy_single(source, dest);
599
600 return (0);
601}
602
603static void
604mac_mls_update_vnode_from_mount(struct vnode *vp, struct label *vnodelabel,
605 struct mount *mp, struct label *fslabel)
606{
607 struct mac_mls *source, *dest;
608
609 source = SLOT(fslabel);
610 dest = SLOT(vnodelabel);
611
612 mac_mls_copy_single(source, dest);
613}
614
615/*
616 * Labeling event operations: IPC object.
617 */
618static void
619mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
620 struct mbuf *m, struct label *mbuflabel)
621{
622 struct mac_mls *source, *dest;
623
624 source = SLOT(socketlabel);
625 dest = SLOT(mbuflabel);
626
627 mac_mls_copy_single(source, dest);
628}
629
630static void
631mac_mls_create_socket(struct ucred *cred, struct socket *socket,
632 struct label *socketlabel)
633{
634 struct mac_mls *source, *dest;
635
636 source = SLOT(&cred->cr_label);
637 dest = SLOT(socketlabel);
638
639 mac_mls_copy_single(source, dest);
640 mac_mls_copy_single_to_range(source, dest);
641}
642
643static void
644mac_mls_create_pipe(struct ucred *cred, struct pipe *pipe,
645 struct label *pipelabel)
646{
647 struct mac_mls *source, *dest;
648
649 source = SLOT(&cred->cr_label);
650 dest = SLOT(pipelabel);
651
652 mac_mls_copy_single(source, dest);
653}
654
655static void
656mac_mls_create_socket_from_socket(struct socket *oldsocket,
657 struct label *oldsocketlabel, struct socket *newsocket,
658 struct label *newsocketlabel)
659{
660 struct mac_mls *source, *dest;
661
662 source = SLOT(oldsocketlabel);
663 dest = SLOT(newsocketlabel);
664
665 mac_mls_copy_single(source, dest);
666 mac_mls_copy_range(source, dest);
667}
668
669static void
670mac_mls_relabel_socket(struct ucred *cred, struct socket *socket,
671 struct label *socketlabel, struct label *newlabel)
672{
673 struct mac_mls *source, *dest;
674
675 source = SLOT(newlabel);
676 dest = SLOT(socketlabel);
677
678 mac_mls_copy_single(source, dest);
679 mac_mls_copy_range(source, dest);
680}
681
682static void
683mac_mls_relabel_pipe(struct ucred *cred, struct pipe *pipe,
684 struct label *pipelabel, struct label *newlabel)
685{
686 struct mac_mls *source, *dest;
687
688 source = SLOT(newlabel);
689 dest = SLOT(pipelabel);
690
691 mac_mls_copy_single(source, dest);
692}
693
694static void
695mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
696 struct socket *socket, struct label *socketpeerlabel)
697{
698 struct mac_mls *source, *dest;
699
700 source = SLOT(mbuflabel);
701 dest = SLOT(socketpeerlabel);
702
703 mac_mls_copy_single(source, dest);
704}
705
706/*
707 * Labeling event operations: network objects.
708 */
709static void
710mac_mls_set_socket_peer_from_socket(struct socket *oldsocket,
711 struct label *oldsocketlabel, struct socket *newsocket,
712 struct label *newsocketpeerlabel)
713{
714 struct mac_mls *source, *dest;
715
716 source = SLOT(oldsocketlabel);
717 dest = SLOT(newsocketpeerlabel);
718
719 mac_mls_copy_single(source, dest);
720}
721
722static void
723mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
724 struct label *bpflabel)
725{
726 struct mac_mls *source, *dest;
727
728 source = SLOT(&cred->cr_label);
729 dest = SLOT(bpflabel);
730
731 mac_mls_copy_single(source, dest);
732}
733
734static void
735mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
736{
737 struct mac_mls *dest;
738 int level;
739
740 dest = SLOT(ifnetlabel);
741
742 if (ifnet->if_type == IFT_LOOP)
743 level = MAC_MLS_TYPE_EQUAL;
744 else
745 level = MAC_MLS_TYPE_LOW;
746
747 mac_mls_set_single(dest, level, 0);
748 mac_mls_set_range(dest, level, 0, level, 0);
749}
750
751static void
752mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
753 struct ipq *ipq, struct label *ipqlabel)
754{
755 struct mac_mls *source, *dest;
756
757 source = SLOT(fragmentlabel);
758 dest = SLOT(ipqlabel);
759
760 mac_mls_copy_single(source, dest);
761}
762
763static void
764mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
765 struct mbuf *datagram, struct label *datagramlabel)
766{
767 struct mac_mls *source, *dest;
768
769 source = SLOT(ipqlabel);
770 dest = SLOT(datagramlabel);
771
772 /* Just use the head, since we require them all to match. */
773 mac_mls_copy_single(source, dest);
774}
775
776static void
777mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
778 struct mbuf *fragment, struct label *fragmentlabel)
779{
780 struct mac_mls *source, *dest;
781
782 source = SLOT(datagramlabel);
783 dest = SLOT(fragmentlabel);
784
785 mac_mls_copy_single(source, dest);
786}
787
788static void
789mac_mls_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
790 struct label *oldmbuflabel, struct mbuf *newmbuf,
791 struct label *newmbuflabel)
792{
793 struct mac_mls *source, *dest;
794
795 source = SLOT(oldmbuflabel);
796 dest = SLOT(newmbuflabel);
797
798 mac_mls_copy_single(source, dest);
799}
800
801static void
802mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
803 struct mbuf *mbuf, struct label *mbuflabel)
804{
805 struct mac_mls *dest;
806
807 dest = SLOT(mbuflabel);
808
809 mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0);
810}
811
812static void
813mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
814 struct mbuf *mbuf, struct label *mbuflabel)
815{
816 struct mac_mls *source, *dest;
817
818 source = SLOT(bpflabel);
819 dest = SLOT(mbuflabel);
820
821 mac_mls_copy_single(source, dest);
822}
823
824static void
825mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
826 struct mbuf *m, struct label *mbuflabel)
827{
828 struct mac_mls *source, *dest;
829
830 source = SLOT(ifnetlabel);
831 dest = SLOT(mbuflabel);
832
833 mac_mls_copy_single(source, dest);
834}
835
836static void
837mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
838 struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
839 struct mbuf *newmbuf, struct label *newmbuflabel)
840{
841 struct mac_mls *source, *dest;
842
843 source = SLOT(oldmbuflabel);
844 dest = SLOT(newmbuflabel);
845
846 mac_mls_copy_single(source, dest);
847}
848
849static void
850mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
851 struct mbuf *newmbuf, struct label *newmbuflabel)
852{
853 struct mac_mls *source, *dest;
854
855 source = SLOT(oldmbuflabel);
856 dest = SLOT(newmbuflabel);
857
858 mac_mls_copy_single(source, dest);
859}
860
861static int
862mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
863 struct ipq *ipq, struct label *ipqlabel)
864{
865 struct mac_mls *a, *b;
866
867 a = SLOT(ipqlabel);
868 b = SLOT(fragmentlabel);
869
870 return (mac_mls_equal_single(a, b));
871}
872
873static void
874mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
875 struct label *ifnetlabel, struct label *newlabel)
876{
877 struct mac_mls *source, *dest;
878
879 source = SLOT(newlabel);
880 dest = SLOT(ifnetlabel);
881
882 mac_mls_copy_single(source, dest);
883 mac_mls_copy_range(source, dest);
884}
885
886static void
887mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
888 struct ipq *ipq, struct label *ipqlabel)
889{
890
891 /* NOOP: we only accept matching labels, so no need to update */
892}
893
894/*
895 * Labeling event operations: processes.
896 */
897static void
898mac_mls_create_cred(struct ucred *cred_parent, struct ucred *cred_child)
899{
900 struct mac_mls *source, *dest;
901
902 source = SLOT(&cred_parent->cr_label);
903 dest = SLOT(&cred_child->cr_label);
904
905 mac_mls_copy_single(source, dest);
906 mac_mls_copy_range(source, dest);
907}
908
909static void
910mac_mls_execve_transition(struct ucred *old, struct ucred *new,
911 struct vnode *vp, struct mac *vnodelabel)
912{
913 struct mac_mls *source, *dest;
914
915 source = SLOT(&old->cr_label);
916 dest = SLOT(&new->cr_label);
917
918 mac_mls_copy_single(source, dest);
919 mac_mls_copy_range(source, dest);
920}
921
922static int
923mac_mls_execve_will_transition(struct ucred *old, struct vnode *vp,
924 struct mac *vnodelabel)
925{
926
927 return (0);
928}
929
930static void
931mac_mls_create_proc0(struct ucred *cred)
932{
933 struct mac_mls *dest;
934
935 dest = SLOT(&cred->cr_label);
936
937 mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0);
938 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, MAC_MLS_TYPE_HIGH, 0);
939}
940
941static void
942mac_mls_create_proc1(struct ucred *cred)
943{
944 struct mac_mls *dest;
945
946 dest = SLOT(&cred->cr_label);
947
948 mac_mls_set_single(dest, MAC_MLS_TYPE_LOW, 0);
949 mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, MAC_MLS_TYPE_HIGH, 0);
950}
951
952static void
953mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel)
954{
955 struct mac_mls *source, *dest;
956
957 source = SLOT(newlabel);
958 dest = SLOT(&cred->cr_label);
959
960 mac_mls_copy_single(source, dest);
961 mac_mls_copy_range(source, dest);
962}
963
964/*
965 * Access control checks.
966 */
967static int
968mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
969 struct ifnet *ifnet, struct label *ifnetlabel)
970{
971 struct mac_mls *a, *b;
972
973 if (!mac_mls_enabled)
974 return (0);
975
976 a = SLOT(bpflabel);
977 b = SLOT(ifnetlabel);
978
979 if (mac_mls_equal_single(a, b))
980 return (0);
981 return (EACCES);
982}
983
984static int
985mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
986{
987 struct mac_mls *subj, *new;
988
989 subj = SLOT(&cred->cr_label);
990 new = SLOT(newlabel);
991
992 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH)
993 return (EINVAL);
994
995 /*
996 * XXX: Allow processes with root privilege to set labels outside
997 * their range, so suid things like "su" work. This WILL go away
998 * when we figure out the 'correct' solution...
999 */
1000 if (!suser_cred(cred, 0))
1001 return (0);
1002
1003 /*
1004 * The new single must be in the old range.
1005 */
1006 if (!mac_mls_single_in_range(new, subj))
1007 return (EPERM);
1008
1009 /*
1010 * The new range must be in the old range.
1011 */
1012 if (!mac_mls_range_in_range(new, subj))
1013 return (EPERM);
1014
1015 /*
1016 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1017 */
1018
1019 return (0);
1020}
1021
1022
1023static int
1024mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
1025{
1026 struct mac_mls *subj, *obj;
1027
1028 if (!mac_mls_enabled)
1029 return (0);
1030
1031 subj = SLOT(&u1->cr_label);
1032 obj = SLOT(&u2->cr_label);
1033
1034 /* XXX: range */
1035 if (!mac_mls_dominate_single(subj, obj))
1036 return (ESRCH);
1037
1038 return (0);
1039}
1040
1041static int
1042mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1043 struct label *ifnetlabel, struct label *newlabel)
1044{
1045 struct mac_mls *subj, *new;
1046
1047 subj = SLOT(&cred->cr_label);
1048 new = SLOT(newlabel);
1049
1050 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAGS_BOTH)
1051 return (EINVAL);
1052
1053 /* XXX: privilege model here? */
1054
1055 return (suser_cred(cred, 0));
1056}
1057
1058static int
1059mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1060 struct mbuf *m, struct label *mbuflabel)
1061{
1062 struct mac_mls *p, *i;
1063
1064 if (!mac_mls_enabled)
1065 return (0);
1066
1067 p = SLOT(mbuflabel);
1068 i = SLOT(ifnetlabel);
1069
1070 return (mac_mls_single_in_range(p, i) ? 0 : EACCES);
1071}
1072
1073static int
1074mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp,
1075 struct label *mntlabel)
1076{
1077 struct mac_mls *subj, *obj;
1078
1079 if (!mac_mls_enabled)
1080 return (0);
1081
1082 subj = SLOT(&cred->cr_label);
1083 obj = SLOT(mntlabel);
1084
1085 if (!mac_mls_dominate_single(subj, obj))
1086 return (EACCES);
1087
1088 return (0);
1089}
1090
1091static int
1092mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1093 struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1094{
1095
1096 if(!mac_mls_enabled)
1097 return (0);
1098
1099 /* XXX: This will be implemented soon... */
1100
1101 return (0);
1102}
1103
1104static int
1105mac_mls_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
1106 struct label *pipelabel)
1107{
1108 struct mac_mls *subj, *obj;
1109
1110 if (!mac_mls_enabled)
1111 return (0);
1112
1113 subj = SLOT(&cred->cr_label);
1114 obj = SLOT((pipelabel));
1115
1116 if (!mac_mls_dominate_single(subj, obj))
1117 return (EACCES);
1118
1119 return (0);
1120}
1121
1122static int
1123mac_mls_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1124 struct label *pipelabel)
1125{
1126 struct mac_mls *subj, *obj;
1127
1128 if (!mac_mls_enabled)
1129 return (0);
1130
1131 subj = SLOT(&cred->cr_label);
1132 obj = SLOT((pipelabel));
1133
1134 if (!mac_mls_dominate_single(subj, obj))
1135 return (EACCES);
1136
1137 return (0);
1138}
1139
1140static int
1141mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1142 struct label *pipelabel, struct label *newlabel)
1143{
1144 struct mac_mls *subj, *obj, *new;
1145
1146 new = SLOT(newlabel);
1147 subj = SLOT(&cred->cr_label);
1148 obj = SLOT(pipelabel);
1149
1150 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1151 return (EINVAL);
1152
1153 /*
1154 * To relabel a pipe, the old pipe label must be in the subject
1155 * range.
1156 */
1157 if (!mac_mls_single_in_range(obj, subj))
1158 return (EPERM);
1159
1160 /*
1161 * To relabel a pipe, the new pipe label must be in the subject
1162 * range.
1163 */
1164 if (!mac_mls_single_in_range(new, subj))
1165 return (EPERM);
1166
1167 /*
1168 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1169 */
1170
1171 return (0);
1172}
1173
1174static int
1175mac_mls_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
1176 struct label *pipelabel)
1177{
1178 struct mac_mls *subj, *obj;
1179
1180 if (!mac_mls_enabled)
1181 return (0);
1182
1183 subj = SLOT(&cred->cr_label);
1184 obj = SLOT((pipelabel));
1185
1186 if (!mac_mls_dominate_single(subj, obj))
1187 return (EACCES);
1188
1189 return (0);
1190}
1191
1192static int
1193mac_mls_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1194 struct label *pipelabel)
1195{
1196 struct mac_mls *subj, *obj;
1197
1198 if (!mac_mls_enabled)
1199 return (0);
1200
1201 subj = SLOT(&cred->cr_label);
1202 obj = SLOT((pipelabel));
1203
1204 if (!mac_mls_dominate_single(obj, subj))
1205 return (EACCES);
1206
1207 return (0);
1208}
1209
1210static int
1211mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc)
1212{
1213 struct mac_mls *subj, *obj;
1214
1215 if (!mac_mls_enabled)
1216 return (0);
1217
1218 subj = SLOT(&cred->cr_label);
1219 obj = SLOT(&proc->p_ucred->cr_label);
1220
1221 /* XXX: range checks */
1222 if (!mac_mls_dominate_single(subj, obj))
1223 return (ESRCH);
1224 if (!mac_mls_dominate_single(obj, subj))
1225 return (EACCES);
1226
1227 return (0);
1228}
1229
1230static int
1231mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc)
1232{
1233 struct mac_mls *subj, *obj;
1234
1235 if (!mac_mls_enabled)
1236 return (0);
1237
1238 subj = SLOT(&cred->cr_label);
1239 obj = SLOT(&proc->p_ucred->cr_label);
1240
1241 /* XXX: range checks */
1242 if (!mac_mls_dominate_single(subj, obj))
1243 return (ESRCH);
1244 if (!mac_mls_dominate_single(obj, subj))
1245 return (EACCES);
1246
1247 return (0);
1248}
1249
1250static int
1251mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1252{
1253 struct mac_mls *subj, *obj;
1254
1255 if (!mac_mls_enabled)
1256 return (0);
1257
1258 subj = SLOT(&cred->cr_label);
1259 obj = SLOT(&proc->p_ucred->cr_label);
1260
1261 /* XXX: range checks */
1262 if (!mac_mls_dominate_single(subj, obj))
1263 return (ESRCH);
1264 if (!mac_mls_dominate_single(obj, subj))
1265 return (EACCES);
1266
1267 return (0);
1268}
1269
1270static int
1271mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel,
1272 struct mbuf *m, struct label *mbuflabel)
1273{
1274 struct mac_mls *p, *s;
1275
1276 if (!mac_mls_enabled)
1277 return (0);
1278
1279 p = SLOT(mbuflabel);
1280 s = SLOT(socketlabel);
1281
1282 return (mac_mls_equal_single(p, s) ? 0 : EACCES);
1283}
1284
1285static int
1286mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket,
1287 struct label *socketlabel, struct label *newlabel)
1288{
1289 struct mac_mls *subj, *obj, *new;
1290
1291 new = SLOT(newlabel);
1292 subj = SLOT(&cred->cr_label);
1293 obj = SLOT(socketlabel);
1294
1295 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1296 return (EINVAL);
1297
1298 /*
1299 * To relabel a socket, the old socket label must be in the subject
1300 * range.
1301 */
1302 if (!mac_mls_single_in_range(obj, subj))
1303 return (EPERM);
1304
1305 /*
1306 * To relabel a socket, the new socket label must be in the subject
1307 * range.
1308 */
1309 if (!mac_mls_single_in_range(new, subj))
1310 return (EPERM);
1311
1312 /*
1313 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1314 */
1315
1316 return (0);
1317}
1318
1319static int
1320mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket,
1321 struct label *socketlabel)
1322{
1323 struct mac_mls *subj, *obj;
1324
1325 if (!mac_mls_enabled)
1326 return (0);
1327
1328 subj = SLOT(&cred->cr_label);
1329 obj = SLOT(socketlabel);
1330
1331 if (!mac_mls_dominate_single(subj, obj))
1332 return (ENOENT);
1333
1334 return (0);
1335}
1336
1337static int
1338mac_mls_check_vnode_access(struct ucred *cred, struct vnode *vp,
1339 struct label *label, mode_t flags)
1340{
1341
1342 return (mac_mls_check_vnode_open(cred, vp, label, flags));
1343}
1344
1345static int
1346mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
1347 struct label *dlabel)
1348{
1349 struct mac_mls *subj, *obj;
1350
1351 if (!mac_mls_enabled)
1352 return (0);
1353
1354 subj = SLOT(&cred->cr_label);
1355 obj = SLOT(dlabel);
1356
1357 if (!mac_mls_dominate_single(subj, obj))
1358 return (EACCES);
1359
1360 return (0);
1361}
1362
1363static int
1364mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
1365 struct label *dlabel)
1366{
1367 struct mac_mls *subj, *obj;
1368
1369 if (!mac_mls_enabled)
1370 return (0);
1371
1372 subj = SLOT(&cred->cr_label);
1373 obj = SLOT(dlabel);
1374
1375 if (!mac_mls_dominate_single(subj, obj))
1376 return (EACCES);
1377
1378 return (0);
1379}
1380
1381static int
1382mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1383 struct label *dlabel, struct componentname *cnp, struct vattr *vap)
1384{
1385 struct mac_mls *subj, *obj;
1386
1387 if (!mac_mls_enabled)
1388 return (0);
1389
1390 subj = SLOT(&cred->cr_label);
1391 obj = SLOT(dlabel);
1392
1393 if (!mac_mls_dominate_single(obj, subj))
1394 return (EACCES);
1395
1396 return (0);
1397}
1398
1399static int
1400mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
1401 struct label *dlabel, struct vnode *vp, struct label *label,
1402 struct componentname *cnp)
1403{
1404 struct mac_mls *subj, *obj;
1405
1406 if (!mac_mls_enabled)
1407 return (0);
1408
1409 subj = SLOT(&cred->cr_label);
1410 obj = SLOT(dlabel);
1411
1412 if (!mac_mls_dominate_single(obj, subj))
1413 return (EACCES);
1414
1415 obj = SLOT(label);
1416
1417 if (!mac_mls_dominate_single(obj, subj))
1418 return (EACCES);
1419
1420 return (0);
1421}
1422
1423static int
1424mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1425 struct label *label, acl_type_t type)
1426{
1427 struct mac_mls *subj, *obj;
1428
1429 if (!mac_mls_enabled)
1430 return (0);
1431
1432 subj = SLOT(&cred->cr_label);
1433 obj = SLOT(label);
1434
1435 if (!mac_mls_dominate_single(obj, subj))
1436 return (EACCES);
1437
1438 return (0);
1439}
1440
1441static int
1442mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1443 struct label *label)
1444{
1445 struct mac_mls *subj, *obj;
1446
1447 if (!mac_mls_enabled)
1448 return (0);
1449
1450 subj = SLOT(&cred->cr_label);
1451 obj = SLOT(label);
1452
1453 if (!mac_mls_dominate_single(subj, obj))
1454 return (EACCES);
1455
1456 return (0);
1457}
1458
1459static int
1460mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
1461 struct label *label, acl_type_t type)
1462{
1463 struct mac_mls *subj, *obj;
1464
1465 if (!mac_mls_enabled)
1466 return (0);
1467
1468 subj = SLOT(&cred->cr_label);
1469 obj = SLOT(label);
1470
1471 if (!mac_mls_dominate_single(subj, obj))
1472 return (EACCES);
1473
1474 return (0);
1475}
1476
1477static int
1478mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1479 struct label *label, int attrnamespace, const char *name, struct uio *uio)
1480{
1481 struct mac_mls *subj, *obj;
1482
1483 if (!mac_mls_enabled)
1484 return (0);
1485
1486 subj = SLOT(&cred->cr_label);
1487 obj = SLOT(label);
1488
1489 if (!mac_mls_dominate_single(subj, obj))
1490 return (EACCES);
1491
1492 return (0);
1493}
1494
1495static int
1496mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1497 struct label *dlabel, struct vnode *vp, struct label *label,
1498 struct componentname *cnp)
1499{
1500 struct mac_mls *subj, *obj;
1501
1502 if (!mac_mls_enabled)
1503 return (0);
1504
1505 subj = SLOT(&cred->cr_label);
1506 obj = SLOT(dlabel);
1507
1508 if (!mac_mls_dominate_single(obj, subj))
1509 return (EACCES);
1510
1511 obj = SLOT(dlabel);
1512 if (!mac_mls_dominate_single(obj, subj))
1513 return (EACCES);
1514
1515 return (0);
1516}
1517
1518static int
1519mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1520 struct label *dlabel, struct componentname *cnp)
1521{
1522 struct mac_mls *subj, *obj;
1523
1524 if (!mac_mls_enabled)
1525 return (0);
1526
1527 subj = SLOT(&cred->cr_label);
1528 obj = SLOT(dlabel);
1529
1530 if (!mac_mls_dominate_single(subj, obj))
1531 return (EACCES);
1532
1533 return (0);
1534}
1535
1536static int
1537mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
1538 struct label *label, int prot)
1539{
1540 struct mac_mls *subj, *obj;
1541
1542 /*
1543 * Rely on the use of open()-time protections to handle
1544 * non-revocation cases.
1545 */
1546 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1547 return (0);
1548
1549 subj = SLOT(&cred->cr_label);
1550 obj = SLOT(label);
1551
1552 if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
1553 if (!mac_mls_dominate_single(subj, obj))
1554 return (EACCES);
1555 }
1556 if (prot & VM_PROT_WRITE) {
1557 if (!mac_mls_dominate_single(obj, subj))
1558 return (EACCES);
1559 }
1560
1561 return (0);
1562}
1563
1564static int
1565mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
1566 struct label *vnodelabel, mode_t acc_mode)
1567{
1568 struct mac_mls *subj, *obj;
1569
1570 if (!mac_mls_enabled)
1571 return (0);
1572
1573 subj = SLOT(&cred->cr_label);
1574 obj = SLOT(vnodelabel);
1575
1576 /* XXX privilege override for admin? */
1577 if (acc_mode & (VREAD | VEXEC | VSTAT)) {
1578 if (!mac_mls_dominate_single(subj, obj))
1579 return (EACCES);
1580 }
1581 if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
1582 if (!mac_mls_dominate_single(obj, subj))
1583 return (EACCES);
1584 }
1585
1586 return (0);
1587}
1588
1589static int
1590mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1591 struct vnode *vp, struct label *label)
1592{
1593 struct mac_mls *subj, *obj;
1594
1595 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1596 return (0);
1597
1598 subj = SLOT(&active_cred->cr_label);
1599 obj = SLOT(label);
1600
1601 if (!mac_mls_dominate_single(subj, obj))
1602 return (EACCES);
1603
1604 return (0);
1605}
1606
1607static int
1608mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1609 struct vnode *vp, struct label *label)
1610{
1611 struct mac_mls *subj, *obj;
1612
1613 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1614 return (0);
1615
1616 subj = SLOT(&active_cred->cr_label);
1617 obj = SLOT(label);
1618
1619 if (!mac_mls_dominate_single(subj, obj))
1620 return (EACCES);
1621
1622 return (0);
1623}
1624
1625static int
1626mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
1627 struct label *dlabel)
1628{
1629 struct mac_mls *subj, *obj;
1630
1631 if (!mac_mls_enabled)
1632 return (0);
1633
1634 subj = SLOT(&cred->cr_label);
1635 obj = SLOT(dlabel);
1636
1637 if (!mac_mls_dominate_single(subj, obj))
1638 return (EACCES);
1639
1640 return (0);
1641}
1642
1643static int
1644mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
1645 struct label *vnodelabel)
1646{
1647 struct mac_mls *subj, *obj;
1648
1649 if (!mac_mls_enabled)
1650 return (0);
1651
1652 subj = SLOT(&cred->cr_label);
1653 obj = SLOT(vnodelabel);
1654
1655 if (!mac_mls_dominate_single(subj, obj))
1656 return (EACCES);
1657
1658 return (0);
1659}
1660
1661static int
1662mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1663 struct label *vnodelabel, struct label *newlabel)
1664{
1665 struct mac_mls *old, *new, *subj;
1666
1667 old = SLOT(vnodelabel);
1668 new = SLOT(newlabel);
1669 subj = SLOT(&cred->cr_label);
1670
1671 if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE)
1672 return (EINVAL);
1673
1674 /*
1675 * To relabel a vnode, the old vnode label must be in the subject
1676 * range.
1677 */
1678 if (!mac_mls_single_in_range(old, subj))
1679 return (EPERM);
1680
1681 /*
1682 * To relabel a vnode, the new vnode label must be in the subject
1683 * range.
1684 */
1685 if (!mac_mls_single_in_range(new, subj))
1686 return (EPERM);
1687
1688 /*
1689 * XXX: Don't permit EQUAL in a label unless the subject has EQUAL.
1690 */
1691
1692 return (suser_cred(cred, 0));
1693}
1694
1695
1696static int
1697mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1698 struct label *dlabel, struct vnode *vp, struct label *label,
1699 struct componentname *cnp)
1700{
1701 struct mac_mls *subj, *obj;
1702
1703 if (!mac_mls_enabled)
1704 return (0);
1705
1706 subj = SLOT(&cred->cr_label);
1707 obj = SLOT(dlabel);
1708
1709 if (!mac_mls_dominate_single(obj, subj))
1710 return (EACCES);
1711
1712 obj = SLOT(label);
1713
1714 if (!mac_mls_dominate_single(obj, subj))
1715 return (EACCES);
1716
1717 return (0);
1718}
1719
1720static int
1721mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1722 struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
1723 struct componentname *cnp)
1724{
1725 struct mac_mls *subj, *obj;
1726
1727 if (!mac_mls_enabled)
1728 return (0);
1729
1730 subj = SLOT(&cred->cr_label);
1731 obj = SLOT(dlabel);
1732
1733 if (!mac_mls_dominate_single(obj, subj))
1734 return (EACCES);
1735
1736 if (vp != NULL) {
1737 obj = SLOT(label);
1738
1739 if (!mac_mls_dominate_single(obj, subj))
1740 return (EACCES);
1741 }
1742
1743 return (0);
1744}
1745
1746static int
1747mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
1748 struct label *label)
1749{
1750 struct mac_mls *subj, *obj;
1751
1752 if (!mac_mls_enabled)
1753 return (0);
1754
1755 subj = SLOT(&cred->cr_label);
1756 obj = SLOT(label);
1757
1758 if (!mac_mls_dominate_single(obj, subj))
1759 return (EACCES);
1760
1761 return (0);
1762}
1763
1764static int
1765mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
1766 struct label *label, acl_type_t type, struct acl *acl)
1767{
1768 struct mac_mls *subj, *obj;
1769
1770 if (!mac_mls_enabled)
1771 return (0);
1772
1773 subj = SLOT(&cred->cr_label);
1774 obj = SLOT(label);
1775
1776 if (!mac_mls_dominate_single(obj, subj))
1777 return (EACCES);
1778
1779 return (0);
1780}
1781
1782static int
1783mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1784 struct label *vnodelabel, int attrnamespace, const char *name,
1785 struct uio *uio)
1786{
1787 struct mac_mls *subj, *obj;
1788
1789 if (!mac_mls_enabled)
1790 return (0);
1791
1792 subj = SLOT(&cred->cr_label);
1793 obj = SLOT(vnodelabel);
1794
1795 if (!mac_mls_dominate_single(obj, subj))
1796 return (EACCES);
1797
1798 /* XXX: protect the MAC EA in a special way? */
1799
1800 return (0);
1801}
1802
1803static int
1804mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
1805 struct label *vnodelabel, u_long flags)
1806{
1807 struct mac_mls *subj, *obj;
1808
1809 if (!mac_mls_enabled)
1810 return (0);
1811
1812 subj = SLOT(&cred->cr_label);
1813 obj = SLOT(vnodelabel);
1814
1815 if (!mac_mls_dominate_single(obj, subj))
1816 return (EACCES);
1817
1818 return (0);
1819}
1820
1821static int
1822mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
1823 struct label *vnodelabel, mode_t mode)
1824{
1825 struct mac_mls *subj, *obj;
1826
1827 if (!mac_mls_enabled)
1828 return (0);
1829
1830 subj = SLOT(&cred->cr_label);
1831 obj = SLOT(vnodelabel);
1832
1833 if (!mac_mls_dominate_single(obj, subj))
1834 return (EACCES);
1835
1836 return (0);
1837}
1838
1839static int
1840mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
1841 struct label *vnodelabel, uid_t uid, gid_t gid)
1842{
1843 struct mac_mls *subj, *obj;
1844
1845 if (!mac_mls_enabled)
1846 return (0);
1847
1848 subj = SLOT(&cred->cr_label);
1849 obj = SLOT(vnodelabel);
1850
1851 if (!mac_mls_dominate_single(obj, subj))
1852 return (EACCES);
1853
1854 return (0);
1855}
1856
1857static int
1858mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1859 struct label *vnodelabel, struct timespec atime, struct timespec mtime)
1860{
1861 struct mac_mls *subj, *obj;
1862
1863 if (!mac_mls_enabled)
1864 return (0);
1865
1866 subj = SLOT(&cred->cr_label);
1867 obj = SLOT(vnodelabel);
1868
1869 if (!mac_mls_dominate_single(obj, subj))
1870 return (EACCES);
1871
1872 return (0);
1873}
1874
1875static int
1876mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1877 struct vnode *vp, struct label *vnodelabel)
1878{
1879 struct mac_mls *subj, *obj;
1880
1881 if (!mac_mls_enabled)
1882 return (0);
1883
1884 subj = SLOT(&active_cred->cr_label);
1885 obj = SLOT(vnodelabel);
1886
1887 if (!mac_mls_dominate_single(subj, obj))
1888 return (EACCES);
1889
1890 return (0);
1891}
1892
1893static int
1894mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1895 struct vnode *vp, struct label *label)
1896{
1897 struct mac_mls *subj, *obj;
1898
1899 if (!mac_mls_enabled || !mac_mls_revocation_enabled)
1900 return (0);
1901
1902 subj = SLOT(&active_cred->cr_label);
1903 obj = SLOT(label);
1904
1905 if (!mac_mls_dominate_single(obj, subj))
1906 return (EACCES);
1907
1908 return (0);
1909}
1910
1911static struct mac_policy_op_entry mac_mls_ops[] =
1912{
1913 { MAC_DESTROY,
1914 (macop_t)mac_mls_destroy },
1915 { MAC_INIT,
1916 (macop_t)mac_mls_init },
1917 { MAC_INIT_BPFDESC_LABEL,
1918 (macop_t)mac_mls_init_label },
1919 { MAC_INIT_CRED_LABEL,
1920 (macop_t)mac_mls_init_label },
1921 { MAC_INIT_DEVFSDIRENT_LABEL,
1922 (macop_t)mac_mls_init_label },
1923 { MAC_INIT_IFNET_LABEL,
1924 (macop_t)mac_mls_init_label },
1925 { MAC_INIT_IPQ_LABEL,
1926 (macop_t)mac_mls_init_label },
1927 { MAC_INIT_MBUF_LABEL,
1928 (macop_t)mac_mls_init_label_waitcheck },
1929 { MAC_INIT_MOUNT_LABEL,
1930 (macop_t)mac_mls_init_label },
1931 { MAC_INIT_MOUNT_FS_LABEL,
1932 (macop_t)mac_mls_init_label },
1933 { MAC_INIT_PIPE_LABEL,
1934 (macop_t)mac_mls_init_label },
1935 { MAC_INIT_SOCKET_LABEL,
1936 (macop_t)mac_mls_init_label_waitcheck },
1937 { MAC_INIT_SOCKET_PEER_LABEL,
1938 (macop_t)mac_mls_init_label_waitcheck },
1939 { MAC_INIT_TEMP_LABEL,
1940 (macop_t)mac_mls_init_label },
1941 { MAC_INIT_VNODE_LABEL,
1942 (macop_t)mac_mls_init_label },
1943 { MAC_DESTROY_BPFDESC_LABEL,
1944 (macop_t)mac_mls_destroy_label },
1945 { MAC_DESTROY_CRED_LABEL,
1946 (macop_t)mac_mls_destroy_label },
1947 { MAC_DESTROY_DEVFSDIRENT_LABEL,
1948 (macop_t)mac_mls_destroy_label },
1949 { MAC_DESTROY_IFNET_LABEL,
1950 (macop_t)mac_mls_destroy_label },
1951 { MAC_DESTROY_IPQ_LABEL,
1952 (macop_t)mac_mls_destroy_label },
1953 { MAC_DESTROY_MBUF_LABEL,
1954 (macop_t)mac_mls_destroy_label },
1955 { MAC_DESTROY_MOUNT_LABEL,
1956 (macop_t)mac_mls_destroy_label },
1957 { MAC_DESTROY_MOUNT_FS_LABEL,
1958 (macop_t)mac_mls_destroy_label },
1959 { MAC_DESTROY_PIPE_LABEL,
1960 (macop_t)mac_mls_destroy_label },
1961 { MAC_DESTROY_SOCKET_LABEL,
1962 (macop_t)mac_mls_destroy_label },
1963 { MAC_DESTROY_SOCKET_PEER_LABEL,
1964 (macop_t)mac_mls_destroy_label },
1965 { MAC_DESTROY_TEMP_LABEL,
1966 (macop_t)mac_mls_destroy_label },
1967 { MAC_DESTROY_VNODE_LABEL,
1968 (macop_t)mac_mls_destroy_label },
1969 { MAC_EXTERNALIZE,
1970 (macop_t)mac_mls_externalize },
1971 { MAC_INTERNALIZE,
1972 (macop_t)mac_mls_internalize },
1973 { MAC_CREATE_DEVFS_DEVICE,
1974 (macop_t)mac_mls_create_devfs_device },
1975 { MAC_CREATE_DEVFS_DIRECTORY,
1976 (macop_t)mac_mls_create_devfs_directory },
1977 { MAC_CREATE_DEVFS_SYMLINK,
1978 (macop_t)mac_mls_create_devfs_symlink },
1979 { MAC_CREATE_DEVFS_VNODE,
1980 (macop_t)mac_mls_create_devfs_vnode },
1981 { MAC_CREATE_VNODE,
1982 (macop_t)mac_mls_create_vnode },
1983 { MAC_CREATE_MOUNT,
1984 (macop_t)mac_mls_create_mount },
1985 { MAC_CREATE_ROOT_MOUNT,
1986 (macop_t)mac_mls_create_root_mount },
1987 { MAC_RELABEL_VNODE,
1988 (macop_t)mac_mls_relabel_vnode },
1989 { MAC_UPDATE_DEVFSDIRENT,
1990 (macop_t)mac_mls_update_devfsdirent },
1991 { MAC_UPDATE_PROCFSVNODE,
1992 (macop_t)mac_mls_update_procfsvnode },
1993 { MAC_UPDATE_VNODE_FROM_EXTERNALIZED,
1994 (macop_t)mac_mls_update_vnode_from_externalized },
1995 { MAC_UPDATE_VNODE_FROM_MOUNT,
1996 (macop_t)mac_mls_update_vnode_from_mount },
1997 { MAC_CREATE_MBUF_FROM_SOCKET,
1998 (macop_t)mac_mls_create_mbuf_from_socket },
1999 { MAC_CREATE_PIPE,
2000 (macop_t)mac_mls_create_pipe },
2001 { MAC_CREATE_SOCKET,
2002 (macop_t)mac_mls_create_socket },
2003 { MAC_CREATE_SOCKET_FROM_SOCKET,
2004 (macop_t)mac_mls_create_socket_from_socket },
2005 { MAC_RELABEL_PIPE,
2006 (macop_t)mac_mls_relabel_pipe },
2007 { MAC_RELABEL_SOCKET,
2008 (macop_t)mac_mls_relabel_socket },
2009 { MAC_SET_SOCKET_PEER_FROM_MBUF,
2010 (macop_t)mac_mls_set_socket_peer_from_mbuf },
2011 { MAC_SET_SOCKET_PEER_FROM_SOCKET,
2012 (macop_t)mac_mls_set_socket_peer_from_socket },
2013 { MAC_CREATE_BPFDESC,
2014 (macop_t)mac_mls_create_bpfdesc },
2015 { MAC_CREATE_DATAGRAM_FROM_IPQ,
2016 (macop_t)mac_mls_create_datagram_from_ipq },
2017 { MAC_CREATE_FRAGMENT,
2018 (macop_t)mac_mls_create_fragment },
2019 { MAC_CREATE_IFNET,
2020 (macop_t)mac_mls_create_ifnet },
2021 { MAC_CREATE_IPQ,
2022 (macop_t)mac_mls_create_ipq },
2023 { MAC_CREATE_MBUF_FROM_MBUF,
2024 (macop_t)mac_mls_create_mbuf_from_mbuf },
2025 { MAC_CREATE_MBUF_LINKLAYER,
2026 (macop_t)mac_mls_create_mbuf_linklayer },
2027 { MAC_CREATE_MBUF_FROM_BPFDESC,
2028 (macop_t)mac_mls_create_mbuf_from_bpfdesc },
2029 { MAC_CREATE_MBUF_FROM_IFNET,
2030 (macop_t)mac_mls_create_mbuf_from_ifnet },
2031 { MAC_CREATE_MBUF_MULTICAST_ENCAP,
2032 (macop_t)mac_mls_create_mbuf_multicast_encap },
2033 { MAC_CREATE_MBUF_NETLAYER,
2034 (macop_t)mac_mls_create_mbuf_netlayer },
2035 { MAC_FRAGMENT_MATCH,
2036 (macop_t)mac_mls_fragment_match },
2037 { MAC_RELABEL_IFNET,
2038 (macop_t)mac_mls_relabel_ifnet },
2039 { MAC_UPDATE_IPQ,
2040 (macop_t)mac_mls_update_ipq },
2041 { MAC_CREATE_CRED,
2042 (macop_t)mac_mls_create_cred },
2043 { MAC_EXECVE_TRANSITION,
2044 (macop_t)mac_mls_execve_transition },
2045 { MAC_EXECVE_WILL_TRANSITION,
2046 (macop_t)mac_mls_execve_will_transition },
2047 { MAC_CREATE_PROC0,
2048 (macop_t)mac_mls_create_proc0 },
2049 { MAC_CREATE_PROC1,
2050 (macop_t)mac_mls_create_proc1 },
2051 { MAC_RELABEL_CRED,
2052 (macop_t)mac_mls_relabel_cred },
2053 { MAC_CHECK_BPFDESC_RECEIVE,
2054 (macop_t)mac_mls_check_bpfdesc_receive },
2055 { MAC_CHECK_CRED_RELABEL,
2056 (macop_t)mac_mls_check_cred_relabel },
2057 { MAC_CHECK_CRED_VISIBLE,
2058 (macop_t)mac_mls_check_cred_visible },
2059 { MAC_CHECK_IFNET_RELABEL,
2060 (macop_t)mac_mls_check_ifnet_relabel },
2061 { MAC_CHECK_IFNET_TRANSMIT,
2062 (macop_t)mac_mls_check_ifnet_transmit },
2063 { MAC_CHECK_MOUNT_STAT,
2064 (macop_t)mac_mls_check_mount_stat },
2065 { MAC_CHECK_PIPE_IOCTL,
2066 (macop_t)mac_mls_check_pipe_ioctl },
2067 { MAC_CHECK_PIPE_POLL,
2068 (macop_t)mac_mls_check_pipe_poll },
2069 { MAC_CHECK_PIPE_READ,
2070 (macop_t)mac_mls_check_pipe_read },
2071 { MAC_CHECK_PIPE_RELABEL,
2072 (macop_t)mac_mls_check_pipe_relabel },
2073 { MAC_CHECK_PIPE_STAT,
2074 (macop_t)mac_mls_check_pipe_stat },
2075 { MAC_CHECK_PIPE_WRITE,
2076 (macop_t)mac_mls_check_pipe_write },
2077 { MAC_CHECK_PROC_DEBUG,
2078 (macop_t)mac_mls_check_proc_debug },
2079 { MAC_CHECK_PROC_SCHED,
2080 (macop_t)mac_mls_check_proc_sched },
2081 { MAC_CHECK_PROC_SIGNAL,
2082 (macop_t)mac_mls_check_proc_signal },
2083 { MAC_CHECK_SOCKET_DELIVER,
2084 (macop_t)mac_mls_check_socket_deliver },
2085 { MAC_CHECK_SOCKET_RELABEL,
2086 (macop_t)mac_mls_check_socket_relabel },
2087 { MAC_CHECK_SOCKET_VISIBLE,
2088 (macop_t)mac_mls_check_socket_visible },
2089 { MAC_CHECK_VNODE_ACCESS,
2090 (macop_t)mac_mls_check_vnode_access },
2091 { MAC_CHECK_VNODE_CHDIR,
2092 (macop_t)mac_mls_check_vnode_chdir },
2093 { MAC_CHECK_VNODE_CHROOT,
2094 (macop_t)mac_mls_check_vnode_chroot },
2095 { MAC_CHECK_VNODE_CREATE,
2096 (macop_t)mac_mls_check_vnode_create },
2097 { MAC_CHECK_VNODE_DELETE,
2098 (macop_t)mac_mls_check_vnode_delete },
2099 { MAC_CHECK_VNODE_DELETEACL,
2100 (macop_t)mac_mls_check_vnode_deleteacl },
2101 { MAC_CHECK_VNODE_EXEC,
2102 (macop_t)mac_mls_check_vnode_exec },
2103 { MAC_CHECK_VNODE_GETACL,
2104 (macop_t)mac_mls_check_vnode_getacl },
2105 { MAC_CHECK_VNODE_GETEXTATTR,
2106 (macop_t)mac_mls_check_vnode_getextattr },
2107 { MAC_CHECK_VNODE_LINK,
2108 (macop_t)mac_mls_check_vnode_link },
2109 { MAC_CHECK_VNODE_LOOKUP,
2110 (macop_t)mac_mls_check_vnode_lookup },
2111 { MAC_CHECK_VNODE_MMAP,
2112 (macop_t)mac_mls_check_vnode_mmap },
2113 { MAC_CHECK_VNODE_MPROTECT,
2114 (macop_t)mac_mls_check_vnode_mmap },
2115 { MAC_CHECK_VNODE_OPEN,
2116 (macop_t)mac_mls_check_vnode_open },
2117 { MAC_CHECK_VNODE_POLL,
2118 (macop_t)mac_mls_check_vnode_poll },
2119 { MAC_CHECK_VNODE_READ,
2120 (macop_t)mac_mls_check_vnode_read },
2121 { MAC_CHECK_VNODE_READDIR,
2122 (macop_t)mac_mls_check_vnode_readdir },
2123 { MAC_CHECK_VNODE_READLINK,
2124 (macop_t)mac_mls_check_vnode_readlink },
2125 { MAC_CHECK_VNODE_RELABEL,
2126 (macop_t)mac_mls_check_vnode_relabel },
2127 { MAC_CHECK_VNODE_RENAME_FROM,
2128 (macop_t)mac_mls_check_vnode_rename_from },
2129 { MAC_CHECK_VNODE_RENAME_TO,
2130 (macop_t)mac_mls_check_vnode_rename_to },
2131 { MAC_CHECK_VNODE_REVOKE,
2132 (macop_t)mac_mls_check_vnode_revoke },
2133 { MAC_CHECK_VNODE_SETACL,
2134 (macop_t)mac_mls_check_vnode_setacl },
2135 { MAC_CHECK_VNODE_SETEXTATTR,
2136 (macop_t)mac_mls_check_vnode_setextattr },
2137 { MAC_CHECK_VNODE_SETFLAGS,
2138 (macop_t)mac_mls_check_vnode_setflags },
2139 { MAC_CHECK_VNODE_SETMODE,
2140 (macop_t)mac_mls_check_vnode_setmode },
2141 { MAC_CHECK_VNODE_SETOWNER,
2142 (macop_t)mac_mls_check_vnode_setowner },
2143 { MAC_CHECK_VNODE_SETUTIMES,
2144 (macop_t)mac_mls_check_vnode_setutimes },
2145 { MAC_CHECK_VNODE_STAT,
2146 (macop_t)mac_mls_check_vnode_stat },
2147 { MAC_CHECK_VNODE_WRITE,
2148 (macop_t)mac_mls_check_vnode_write },
2149 { MAC_OP_LAST, NULL }
2150};
2151
2152MAC_POLICY_SET(mac_mls_ops, trustedbsd_mac_mls, "TrustedBSD MAC/MLS",
2153 MPC_LOADTIME_FLAG_NOTLATE, &mac_mls_slot);