Deleted Added
full compact
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson and Ilmar Habibulin for the
8 * TrustedBSD Project.
9 *
10 * This software was developed for the FreeBSD Project in part by Network
11 * Associates Laboratories, the Security Research Division of Network
12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13 * as part of the DARPA CHATS research program.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/security/mac/mac_vfs.c 121507 2003-10-25 15:28:20Z rwatson $");
38__FBSDID("$FreeBSD: head/sys/security/mac/mac_vfs.c 122159 2003-11-06 03:42:43Z rwatson $");
39
40#include "opt_mac.h"
41#include "opt_devfs.h"
42
43#include <sys/param.h>
44#include <sys/condvar.h>
45#include <sys/extattr.h>
46#include <sys/imgact.h>
47#include <sys/kernel.h>
48#include <sys/lock.h>
49#include <sys/malloc.h>
50#include <sys/mutex.h>
51#include <sys/mac.h>
52#include <sys/proc.h>
53#include <sys/sbuf.h>
54#include <sys/systm.h>
55#include <sys/vnode.h>
56#include <sys/mount.h>
57#include <sys/file.h>
58#include <sys/namei.h>
59#include <sys/sysctl.h>
60
61#include <vm/vm.h>
62#include <vm/pmap.h>
63#include <vm/vm_map.h>
64#include <vm/vm_object.h>
65
66#include <sys/mac_policy.h>
67
68#include <fs/devfs/devfs.h>
69
70#include <security/mac/mac_internal.h>
71
72/*
73 * Warn about EA transactions only the first time they happen.
74 * Weak coherency, no locking.
75 */
76static int ea_warn_once = 0;
77
78static int mac_enforce_fs = 1;
79SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
80 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
81TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
82
83#ifdef MAC_DEBUG
84static int mac_debug_label_fallback = 0;
85SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
86 &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
87 "when label is corrupted.");
88TUNABLE_INT("security.mac.debug_label_fallback",
89 &mac_debug_label_fallback);
90
91static unsigned int nmacmounts, nmacvnodes, nmacdevfsdirents;
92SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
93 &nmacmounts, 0, "number of mounts in use");
94SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
95 &nmacvnodes, 0, "number of vnodes in use");
96SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
97 &nmacdevfsdirents, 0, "number of devfs dirents inuse");
98#endif
99
100static int mac_setlabel_vnode_extattr(struct ucred *cred,
101 struct vnode *vp, struct label *intlabel);
102
103void
104mac_init_devfsdirent(struct devfs_dirent *de)
105{
106
107 mac_init_label(&de->de_label);
108 MAC_PERFORM(init_devfsdirent_label, &de->de_label);
109 MAC_DEBUG_COUNTER_INC(&nmacdevfsdirents);
110}
111
112void
113mac_init_mount(struct mount *mp)
114{
115
116 mac_init_label(&mp->mnt_mntlabel);
117 mac_init_label(&mp->mnt_fslabel);
118 MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
119 MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
120 MAC_DEBUG_COUNTER_INC(&nmacmounts);
121}
122
123void
124mac_init_vnode_label(struct label *label)
125{
126
127 mac_init_label(label);
128 MAC_PERFORM(init_vnode_label, label);
129 MAC_DEBUG_COUNTER_INC(&nmacvnodes);
130}
131
132void
133mac_init_vnode(struct vnode *vp)
134{
135
136 mac_init_vnode_label(&vp->v_label);
137}
138
139void
140mac_destroy_devfsdirent(struct devfs_dirent *de)
141{
142
143 MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
144 mac_destroy_label(&de->de_label);
145 MAC_DEBUG_COUNTER_DEC(&nmacdevfsdirents);
146}
147
148void
149mac_destroy_mount(struct mount *mp)
150{
151
152 MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
153 MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
154 mac_destroy_label(&mp->mnt_fslabel);
155 mac_destroy_label(&mp->mnt_mntlabel);
156 MAC_DEBUG_COUNTER_DEC(&nmacmounts);
157}
158
159void
160mac_destroy_vnode_label(struct label *label)
161{
162
163 MAC_PERFORM(destroy_vnode_label, label);
164 mac_destroy_label(label);
165 MAC_DEBUG_COUNTER_DEC(&nmacvnodes);
166}
167
168void
169mac_destroy_vnode(struct vnode *vp)
170{
171
172 mac_destroy_vnode_label(&vp->v_label);
173}
174
175void
176mac_copy_vnode_label(struct label *src, struct label *dest)
177{
178
179 MAC_PERFORM(copy_vnode_label, src, dest);
180}
181
182int
183mac_externalize_vnode_label(struct label *label, char *elements,
184 char *outbuf, size_t outbuflen, int flags)
184 char *outbuf, size_t outbuflen)
185{
186 int error;
187
188 MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
189
190 return (error);
191}
192
193int
194mac_internalize_vnode_label(struct label *label, char *string)
195{
196 int error;
197
198 MAC_INTERNALIZE(vnode, label, string);
199
200 return (error);
201}
202
203void
204mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
205 struct vnode *vp)
206{
207
208 MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
209 &vp->v_label);
210}
211
212void
213mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
214 struct vnode *vp)
215{
216
217 MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
218 &de->de_label, vp, &vp->v_label);
219}
220
221int
222mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
223{
224 int error;
225
226 ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
227
228 MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
229 &vp->v_label);
230
231 return (error);
232}
233
234void
235mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
236{
237
238 MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
239 &vp->v_label);
240}
241
242int
243mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
244 struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
245{
246 int error;
247
248 ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
249 ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
250
251 error = VOP_OPENEXTATTR(vp, cred, curthread);
252 if (error == EOPNOTSUPP) {
253 /* XXX: Optionally abort if transactions not supported. */
254 if (ea_warn_once == 0) {
255 printf("Warning: transactions not supported "
256 "in EA write.\n");
257 ea_warn_once = 1;
258 }
259 } else if (error)
260 return (error);
261
262 MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
263 dvp, &dvp->v_label, vp, &vp->v_label, cnp);
264
265 if (error) {
266 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
267 return (error);
268 }
269
270 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
271
272 if (error == EOPNOTSUPP)
273 error = 0; /* XXX */
274
275 return (error);
276}
277
278static int
279mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
280 struct label *intlabel)
281{
282 int error;
283
284 ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
285
286 error = VOP_OPENEXTATTR(vp, cred, curthread);
287 if (error == EOPNOTSUPP) {
288 /* XXX: Optionally abort if transactions not supported. */
289 if (ea_warn_once == 0) {
290 printf("Warning: transactions not supported "
291 "in EA write.\n");
292 ea_warn_once = 1;
293 }
294 } else if (error)
295 return (error);
296
297 MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
298
299 if (error) {
300 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
301 return (error);
302 }
303
304 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
305
306 if (error == EOPNOTSUPP)
307 error = 0; /* XXX */
308
309 return (error);
310}
311
312void
313mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
314 struct label *interpvnodelabel, struct image_params *imgp)
315{
316
317 ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
318
319 if (!mac_enforce_process && !mac_enforce_fs)
320 return;
321
322 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
323 interpvnodelabel, imgp, imgp->execlabel);
324}
325
326int
327mac_execve_will_transition(struct ucred *old, struct vnode *vp,
328 struct label *interpvnodelabel, struct image_params *imgp)
329{
330 int result;
331
332 ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
333
334 if (!mac_enforce_process && !mac_enforce_fs)
335 return (0);
336
337 result = 0;
338 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
339 interpvnodelabel, imgp, imgp->execlabel);
340
341 return (result);
342}
343
344int
345mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
346{
347 int error;
348
349 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
350
351 if (!mac_enforce_fs)
352 return (0);
353
354 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
355 return (error);
356}
357
358int
359mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
360{
361 int error;
362
363 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
364
365 if (!mac_enforce_fs)
366 return (0);
367
368 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
369 return (error);
370}
371
372int
373mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
374{
375 int error;
376
377 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
378
379 if (!mac_enforce_fs)
380 return (0);
381
382 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
383 return (error);
384}
385
386int
387mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
388 struct componentname *cnp, struct vattr *vap)
389{
390 int error;
391
392 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
393
394 if (!mac_enforce_fs)
395 return (0);
396
397 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
398 return (error);
399}
400
401int
402mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
403 struct componentname *cnp)
404{
405 int error;
406
407 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
408 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
409
410 if (!mac_enforce_fs)
411 return (0);
412
413 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
414 &vp->v_label, cnp);
415 return (error);
416}
417
418int
419mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
420 acl_type_t type)
421{
422 int error;
423
424 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
425
426 if (!mac_enforce_fs)
427 return (0);
428
429 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
430 return (error);
431}
432
433int
434mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
435 int attrnamespace, const char *name)
436{
437 int error;
438
439 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr");
440
441 if (!mac_enforce_fs)
442 return (0);
443
444 MAC_CHECK(check_vnode_deleteextattr, cred, vp, &vp->v_label,
445 attrnamespace, name);
446 return (error);
447}
448
449int
450mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
451 struct image_params *imgp)
452{
453 int error;
454
455 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
456
457 if (!mac_enforce_process && !mac_enforce_fs)
458 return (0);
459
460 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
461 imgp->execlabel);
462
463 return (error);
464}
465
466int
467mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
468{
469 int error;
470
471 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
472
473 if (!mac_enforce_fs)
474 return (0);
475
476 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
477 return (error);
478}
479
480int
481mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
482 int attrnamespace, const char *name, struct uio *uio)
483{
484 int error;
485
486 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
487
488 if (!mac_enforce_fs)
489 return (0);
490
491 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
492 attrnamespace, name, uio);
493 return (error);
494}
495
496int
497mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
498 struct vnode *vp, struct componentname *cnp)
499{
500 int error;
501
502 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
503 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
504
505 if (!mac_enforce_fs)
506 return (0);
507
508 MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
509 &vp->v_label, cnp);
510 return (error);
511}
512
513int
514mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
515 int attrnamespace)
516{
517 int error;
518
519 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr");
520
521 if (!mac_enforce_fs)
522 return (0);
523
524 MAC_CHECK(check_vnode_listextattr, cred, vp, &vp->v_label,
525 attrnamespace);
526 return (error);
527}
528
529int
530mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
531 struct componentname *cnp)
532{
533 int error;
534
535 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
536
537 if (!mac_enforce_fs)
538 return (0);
539
540 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
541 return (error);
542}
543
544int
545mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
546{
547 int error;
548
549 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
550
551 if (!mac_enforce_fs || !mac_enforce_vm)
552 return (0);
553
554 MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
555 return (error);
556}
557
558void
559mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
560{
561 int result = *prot;
562
563 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
564
565 if (!mac_enforce_fs || !mac_enforce_vm)
566 return;
567
568 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
569 &result);
570
571 *prot = result;
572}
573
574int
575mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
576{
577 int error;
578
579 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
580
581 if (!mac_enforce_fs || !mac_enforce_vm)
582 return (0);
583
584 MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
585 return (error);
586}
587
588int
589mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
590{
591 int error;
592
593 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
594
595 if (!mac_enforce_fs)
596 return (0);
597
598 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
599 return (error);
600}
601
602int
603mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
604 struct vnode *vp)
605{
606 int error;
607
608 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
609
610 if (!mac_enforce_fs)
611 return (0);
612
613 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
614 &vp->v_label);
615
616 return (error);
617}
618
619int
620mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
621 struct vnode *vp)
622{
623 int error;
624
625 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
626
627 if (!mac_enforce_fs)
628 return (0);
629
630 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
631 &vp->v_label);
632
633 return (error);
634}
635
636int
637mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
638{
639 int error;
640
641 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
642
643 if (!mac_enforce_fs)
644 return (0);
645
646 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
647 return (error);
648}
649
650int
651mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
652{
653 int error;
654
655 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
656
657 if (!mac_enforce_fs)
658 return (0);
659
660 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
661 return (error);
662}
663
664static int
665mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
666 struct label *newlabel)
667{
668 int error;
669
670 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
671
672 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
673
674 return (error);
675}
676
677int
678mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
679 struct vnode *vp, struct componentname *cnp)
680{
681 int error;
682
683 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
684 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
685
686 if (!mac_enforce_fs)
687 return (0);
688
689 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
690 &vp->v_label, cnp);
691 return (error);
692}
693
694int
695mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
696 struct vnode *vp, int samedir, struct componentname *cnp)
697{
698 int error;
699
700 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
701 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
702
703 if (!mac_enforce_fs)
704 return (0);
705
706 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
707 vp != NULL ? &vp->v_label : NULL, samedir, cnp);
708 return (error);
709}
710
711int
712mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
713{
714 int error;
715
716 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
717
718 if (!mac_enforce_fs)
719 return (0);
720
721 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
722 return (error);
723}
724
725int
726mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
727 struct acl *acl)
728{
729 int error;
730
731 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
732
733 if (!mac_enforce_fs)
734 return (0);
735
736 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
737 return (error);
738}
739
740int
741mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
742 int attrnamespace, const char *name, struct uio *uio)
743{
744 int error;
745
746 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
747
748 if (!mac_enforce_fs)
749 return (0);
750
751 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
752 attrnamespace, name, uio);
753 return (error);
754}
755
756int
757mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
758{
759 int error;
760
761 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
762
763 if (!mac_enforce_fs)
764 return (0);
765
766 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
767 return (error);
768}
769
770int
771mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
772{
773 int error;
774
775 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
776
777 if (!mac_enforce_fs)
778 return (0);
779
780 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
781 return (error);
782}
783
784int
785mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
786 gid_t gid)
787{
788 int error;
789
790 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
791
792 if (!mac_enforce_fs)
793 return (0);
794
795 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
796 return (error);
797}
798
799int
800mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
801 struct timespec atime, struct timespec mtime)
802{
803 int error;
804
805 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
806
807 if (!mac_enforce_fs)
808 return (0);
809
810 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
811 mtime);
812 return (error);
813}
814
815int
816mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
817 struct vnode *vp)
818{
819 int error;
820
821 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
822
823 if (!mac_enforce_fs)
824 return (0);
825
826 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
827 &vp->v_label);
828 return (error);
829}
830
831int
832mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
833 struct vnode *vp)
834{
835 int error;
836
837 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
838
839 if (!mac_enforce_fs)
840 return (0);
841
842 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
843 &vp->v_label);
844
845 return (error);
846}
847
848void
849mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
850{
851
852 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
853}
854
855void
856mac_create_mount(struct ucred *cred, struct mount *mp)
857{
858
859 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
860 &mp->mnt_fslabel);
861}
862
863void
864mac_create_root_mount(struct ucred *cred, struct mount *mp)
865{
866
867 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
868 &mp->mnt_fslabel);
869}
870
871int
872mac_check_mount_stat(struct ucred *cred, struct mount *mount)
873{
874 int error;
875
876 if (!mac_enforce_fs)
877 return (0);
878
879 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
880
881 return (error);
882}
883
884void
885mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
886{
887
888 MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
889}
890
891void
892mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
893 struct devfs_dirent *dd, struct devfs_dirent *de)
894{
895
896 MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
897 &de->de_label);
898}
899
900void
901mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
902 struct devfs_dirent *de)
903{
904
905 MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
906 &de->de_label);
907}
908
909/*
910 * Implementation of VOP_SETLABEL() that relies on extended attributes
911 * to store label data. Can be referenced by filesystems supporting
912 * extended attributes.
913 */
914int
915vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
916{
917 struct vnode *vp = ap->a_vp;
918 struct label *intlabel = ap->a_label;
919 int error;
920
921 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
922
923 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
924 return (EOPNOTSUPP);
925
926 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
927 if (error)
928 return (error);
929
930 mac_relabel_vnode(ap->a_cred, vp, intlabel);
931
932 return (0);
933}
934
935int
936vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
937{
938 int error;
939
940 if (vp->v_mount == NULL) {
941 /* printf("vn_setlabel: null v_mount\n"); */
942 if (vp->v_type != VNON)
943 printf("vn_setlabel: null v_mount with non-VNON\n");
944 return (EBADF);
945 }
946
947 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
948 return (EOPNOTSUPP);
949
950 /*
951 * Multi-phase commit. First check the policies to confirm the
952 * change is OK. Then commit via the filesystem. Finally,
953 * update the actual vnode label. Question: maybe the filesystem
954 * should update the vnode at the end as part of VOP_SETLABEL()?
955 */
956 error = mac_check_vnode_relabel(cred, vp, intlabel);
957 if (error)
958 return (error);
959
960 /*
961 * VADMIN provides the opportunity for the filesystem to make
962 * decisions about who is and is not able to modify labels
963 * and protections on files. This might not be right. We can't
964 * assume VOP_SETLABEL() will do it, because we might implement
965 * that as part of vop_stdsetlabel_ea().
966 */
967 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
968 if (error)
969 return (error);
970
971 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
972 if (error)
973 return (error);
974
975 return (0);
976}