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: releng/5.2/sys/security/mac/mac_vfs.c 122524 2003-11-12 03:14:31Z 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 */
76 static int ea_warn_once = 0;
77
78 static int mac_enforce_fs = 1;
79 SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
80 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
81 TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
82
83 #ifdef MAC_DEBUG
84 static int mac_debug_label_fallback = 0;
85 SYSCTL_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.");
88 TUNABLE_INT("security.mac.debug_label_fallback",
89 &mac_debug_label_fallback);
90
91 static unsigned int nmacmounts, nmacvnodes, nmacdevfsdirents;
92 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
93 &nmacmounts, 0, "number of mounts in use");
94 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
95 &nmacvnodes, 0, "number of vnodes in use");
96 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
97 &nmacdevfsdirents, 0, "number of devfs dirents inuse");
98 #endif
99
100 static int mac_setlabel_vnode_extattr(struct ucred *cred,
101 struct vnode *vp, struct label *intlabel);
102
103 static struct label *
104 mac_devfsdirent_label_alloc(void)
105 {
106 struct label *label;
107
108 label = mac_labelzone_alloc(M_WAITOK);
109 MAC_PERFORM(init_devfsdirent_label, label);
110 MAC_DEBUG_COUNTER_INC(&nmacdevfsdirents);
111 return (label);
112 }
113
114 void
115 mac_init_devfsdirent(struct devfs_dirent *de)
116 {
117
118 de->de_label = mac_devfsdirent_label_alloc();
119 }
120
121 static struct label *
122 mac_mount_label_alloc(void)
123 {
124 struct label *label;
125
126 label = mac_labelzone_alloc(M_WAITOK);
127 MAC_PERFORM(init_mount_label, label);
128 MAC_DEBUG_COUNTER_INC(&nmacmounts);
129 return (label);
130 }
131
132 static struct label *
133 mac_mount_fs_label_alloc(void)
134 {
135 struct label *label;
136
137 label = mac_labelzone_alloc(M_WAITOK);
138 MAC_PERFORM(init_mount_fs_label, label);
139 MAC_DEBUG_COUNTER_INC(&nmacmounts);
140 return (label);
141 }
142
143 void
144 mac_init_mount(struct mount *mp)
145 {
146
147 mp->mnt_mntlabel = mac_mount_label_alloc();
148 mp->mnt_fslabel = mac_mount_fs_label_alloc();
149 }
150
151 struct label *
152 mac_vnode_label_alloc(void)
153 {
154 struct label *label;
155
156 label = mac_labelzone_alloc(M_WAITOK);
157 MAC_PERFORM(init_vnode_label, label);
158 MAC_DEBUG_COUNTER_INC(&nmacvnodes);
159 return (label);
160 }
161
162 void
163 mac_init_vnode(struct vnode *vp)
164 {
165
166 vp->v_label = mac_vnode_label_alloc();
167 }
168
169 static void
170 mac_devfsdirent_label_free(struct label *label)
171 {
172
173 MAC_PERFORM(destroy_devfsdirent_label, label);
174 mac_labelzone_free(label);
175 MAC_DEBUG_COUNTER_DEC(&nmacdevfsdirents);
176 }
177
178 void
179 mac_destroy_devfsdirent(struct devfs_dirent *de)
180 {
181
182 mac_devfsdirent_label_free(de->de_label);
183 de->de_label = NULL;
184 }
185
186 static void
187 mac_mount_label_free(struct label *label)
188 {
189
190 MAC_PERFORM(destroy_mount_label, label);
191 mac_labelzone_free(label);
192 MAC_DEBUG_COUNTER_DEC(&nmacmounts);
193 }
194
195 static void
196 mac_mount_fs_label_free(struct label *label)
197 {
198
199 MAC_PERFORM(destroy_mount_fs_label, label);
200 mac_labelzone_free(label);
201 MAC_DEBUG_COUNTER_DEC(&nmacmounts);
202 }
203
204 void
205 mac_destroy_mount(struct mount *mp)
206 {
207
208 mac_mount_fs_label_free(mp->mnt_fslabel);
209 mp->mnt_fslabel = NULL;
210 mac_mount_label_free(mp->mnt_mntlabel);
211 mp->mnt_mntlabel = NULL;
212 }
213
214 void
215 mac_vnode_label_free(struct label *label)
216 {
217
218 MAC_PERFORM(destroy_vnode_label, label);
219 mac_labelzone_free(label);
220 MAC_DEBUG_COUNTER_DEC(&nmacvnodes);
221 }
222
223 void
224 mac_destroy_vnode(struct vnode *vp)
225 {
226
227 mac_vnode_label_free(vp->v_label);
228 vp->v_label = NULL;
229 }
230
231 void
232 mac_copy_vnode_label(struct label *src, struct label *dest)
233 {
234
235 MAC_PERFORM(copy_vnode_label, src, dest);
236 }
237
238 int
239 mac_externalize_vnode_label(struct label *label, char *elements,
240 char *outbuf, size_t outbuflen)
241 {
242 int error;
243
244 MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
245
246 return (error);
247 }
248
249 int
250 mac_internalize_vnode_label(struct label *label, char *string)
251 {
252 int error;
253
254 MAC_INTERNALIZE(vnode, label, string);
255
256 return (error);
257 }
258
259 void
260 mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
261 struct vnode *vp)
262 {
263
264 MAC_PERFORM(update_devfsdirent, mp, de, de->de_label, vp,
265 vp->v_label);
266 }
267
268 void
269 mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
270 struct vnode *vp)
271 {
272
273 MAC_PERFORM(associate_vnode_devfs, mp, mp->mnt_fslabel, de,
274 de->de_label, vp, vp->v_label);
275 }
276
277 int
278 mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
279 {
280 int error;
281
282 ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
283
284 MAC_CHECK(associate_vnode_extattr, mp, mp->mnt_fslabel, vp,
285 vp->v_label);
286
287 return (error);
288 }
289
290 void
291 mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
292 {
293
294 MAC_PERFORM(associate_vnode_singlelabel, mp, mp->mnt_fslabel, vp,
295 vp->v_label);
296 }
297
298 int
299 mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
300 struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
301 {
302 int error;
303
304 ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
305 ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
306
307 error = VOP_OPENEXTATTR(vp, cred, curthread);
308 if (error == EOPNOTSUPP) {
309 /* XXX: Optionally abort if transactions not supported. */
310 if (ea_warn_once == 0) {
311 printf("Warning: transactions not supported "
312 "in EA write.\n");
313 ea_warn_once = 1;
314 }
315 } else if (error)
316 return (error);
317
318 MAC_CHECK(create_vnode_extattr, cred, mp, mp->mnt_fslabel,
319 dvp, dvp->v_label, vp, vp->v_label, cnp);
320
321 if (error) {
322 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
323 return (error);
324 }
325
326 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
327
328 if (error == EOPNOTSUPP)
329 error = 0; /* XXX */
330
331 return (error);
332 }
333
334 static int
335 mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
336 struct label *intlabel)
337 {
338 int error;
339
340 ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
341
342 error = VOP_OPENEXTATTR(vp, cred, curthread);
343 if (error == EOPNOTSUPP) {
344 /* XXX: Optionally abort if transactions not supported. */
345 if (ea_warn_once == 0) {
346 printf("Warning: transactions not supported "
347 "in EA write.\n");
348 ea_warn_once = 1;
349 }
350 } else if (error)
351 return (error);
352
353 MAC_CHECK(setlabel_vnode_extattr, cred, vp, vp->v_label, intlabel);
354
355 if (error) {
356 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
357 return (error);
358 }
359
360 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
361
362 if (error == EOPNOTSUPP)
363 error = 0; /* XXX */
364
365 return (error);
366 }
367
368 void
369 mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
370 struct label *interpvnodelabel, struct image_params *imgp)
371 {
372
373 ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
374
375 if (!mac_enforce_process && !mac_enforce_fs)
376 return;
377
378 MAC_PERFORM(execve_transition, old, new, vp, vp->v_label,
379 interpvnodelabel, imgp, imgp->execlabel);
380 }
381
382 int
383 mac_execve_will_transition(struct ucred *old, struct vnode *vp,
384 struct label *interpvnodelabel, struct image_params *imgp)
385 {
386 int result;
387
388 ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
389
390 if (!mac_enforce_process && !mac_enforce_fs)
391 return (0);
392
393 result = 0;
394 MAC_BOOLEAN(execve_will_transition, ||, old, vp, vp->v_label,
395 interpvnodelabel, imgp, imgp->execlabel);
396
397 return (result);
398 }
399
400 int
401 mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
402 {
403 int error;
404
405 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
406
407 if (!mac_enforce_fs)
408 return (0);
409
410 MAC_CHECK(check_vnode_access, cred, vp, vp->v_label, acc_mode);
411 return (error);
412 }
413
414 int
415 mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
416 {
417 int error;
418
419 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
420
421 if (!mac_enforce_fs)
422 return (0);
423
424 MAC_CHECK(check_vnode_chdir, cred, dvp, dvp->v_label);
425 return (error);
426 }
427
428 int
429 mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
430 {
431 int error;
432
433 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
434
435 if (!mac_enforce_fs)
436 return (0);
437
438 MAC_CHECK(check_vnode_chroot, cred, dvp, dvp->v_label);
439 return (error);
440 }
441
442 int
443 mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
444 struct componentname *cnp, struct vattr *vap)
445 {
446 int error;
447
448 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
449
450 if (!mac_enforce_fs)
451 return (0);
452
453 MAC_CHECK(check_vnode_create, cred, dvp, dvp->v_label, cnp, vap);
454 return (error);
455 }
456
457 int
458 mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
459 struct componentname *cnp)
460 {
461 int error;
462
463 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
464 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
465
466 if (!mac_enforce_fs)
467 return (0);
468
469 MAC_CHECK(check_vnode_delete, cred, dvp, dvp->v_label, vp,
470 vp->v_label, cnp);
471 return (error);
472 }
473
474 int
475 mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
476 acl_type_t type)
477 {
478 int error;
479
480 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
481
482 if (!mac_enforce_fs)
483 return (0);
484
485 MAC_CHECK(check_vnode_deleteacl, cred, vp, vp->v_label, type);
486 return (error);
487 }
488
489 int
490 mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
491 int attrnamespace, const char *name)
492 {
493 int error;
494
495 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr");
496
497 if (!mac_enforce_fs)
498 return (0);
499
500 MAC_CHECK(check_vnode_deleteextattr, cred, vp, vp->v_label,
501 attrnamespace, name);
502 return (error);
503 }
504
505 int
506 mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
507 struct image_params *imgp)
508 {
509 int error;
510
511 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
512
513 if (!mac_enforce_process && !mac_enforce_fs)
514 return (0);
515
516 MAC_CHECK(check_vnode_exec, cred, vp, vp->v_label, imgp,
517 imgp->execlabel);
518
519 return (error);
520 }
521
522 int
523 mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
524 {
525 int error;
526
527 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
528
529 if (!mac_enforce_fs)
530 return (0);
531
532 MAC_CHECK(check_vnode_getacl, cred, vp, vp->v_label, type);
533 return (error);
534 }
535
536 int
537 mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
538 int attrnamespace, const char *name, struct uio *uio)
539 {
540 int error;
541
542 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
543
544 if (!mac_enforce_fs)
545 return (0);
546
547 MAC_CHECK(check_vnode_getextattr, cred, vp, vp->v_label,
548 attrnamespace, name, uio);
549 return (error);
550 }
551
552 int
553 mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
554 struct vnode *vp, struct componentname *cnp)
555 {
556 int error;
557
558 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
559 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
560
561 if (!mac_enforce_fs)
562 return (0);
563
564 MAC_CHECK(check_vnode_link, cred, dvp, dvp->v_label, vp,
565 vp->v_label, cnp);
566 return (error);
567 }
568
569 int
570 mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
571 int attrnamespace)
572 {
573 int error;
574
575 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr");
576
577 if (!mac_enforce_fs)
578 return (0);
579
580 MAC_CHECK(check_vnode_listextattr, cred, vp, vp->v_label,
581 attrnamespace);
582 return (error);
583 }
584
585 int
586 mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
587 struct componentname *cnp)
588 {
589 int error;
590
591 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
592
593 if (!mac_enforce_fs)
594 return (0);
595
596 MAC_CHECK(check_vnode_lookup, cred, dvp, dvp->v_label, cnp);
597 return (error);
598 }
599
600 int
601 mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
602 {
603 int error;
604
605 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
606
607 if (!mac_enforce_fs || !mac_enforce_vm)
608 return (0);
609
610 MAC_CHECK(check_vnode_mmap, cred, vp, vp->v_label, prot);
611 return (error);
612 }
613
614 void
615 mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
616 {
617 int result = *prot;
618
619 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
620
621 if (!mac_enforce_fs || !mac_enforce_vm)
622 return;
623
624 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, vp->v_label,
625 &result);
626
627 *prot = result;
628 }
629
630 int
631 mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
632 {
633 int error;
634
635 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
636
637 if (!mac_enforce_fs || !mac_enforce_vm)
638 return (0);
639
640 MAC_CHECK(check_vnode_mprotect, cred, vp, vp->v_label, prot);
641 return (error);
642 }
643
644 int
645 mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
646 {
647 int error;
648
649 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
650
651 if (!mac_enforce_fs)
652 return (0);
653
654 MAC_CHECK(check_vnode_open, cred, vp, vp->v_label, acc_mode);
655 return (error);
656 }
657
658 int
659 mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
660 struct vnode *vp)
661 {
662 int error;
663
664 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
665
666 if (!mac_enforce_fs)
667 return (0);
668
669 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
670 vp->v_label);
671
672 return (error);
673 }
674
675 int
676 mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
677 struct vnode *vp)
678 {
679 int error;
680
681 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
682
683 if (!mac_enforce_fs)
684 return (0);
685
686 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
687 vp->v_label);
688
689 return (error);
690 }
691
692 int
693 mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
694 {
695 int error;
696
697 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
698
699 if (!mac_enforce_fs)
700 return (0);
701
702 MAC_CHECK(check_vnode_readdir, cred, dvp, dvp->v_label);
703 return (error);
704 }
705
706 int
707 mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
708 {
709 int error;
710
711 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
712
713 if (!mac_enforce_fs)
714 return (0);
715
716 MAC_CHECK(check_vnode_readlink, cred, vp, vp->v_label);
717 return (error);
718 }
719
720 static int
721 mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
722 struct label *newlabel)
723 {
724 int error;
725
726 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
727
728 MAC_CHECK(check_vnode_relabel, cred, vp, vp->v_label, newlabel);
729
730 return (error);
731 }
732
733 int
734 mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
735 struct vnode *vp, struct componentname *cnp)
736 {
737 int error;
738
739 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
740 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
741
742 if (!mac_enforce_fs)
743 return (0);
744
745 MAC_CHECK(check_vnode_rename_from, cred, dvp, dvp->v_label, vp,
746 vp->v_label, cnp);
747 return (error);
748 }
749
750 int
751 mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
752 struct vnode *vp, int samedir, struct componentname *cnp)
753 {
754 int error;
755
756 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
757 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
758
759 if (!mac_enforce_fs)
760 return (0);
761
762 MAC_CHECK(check_vnode_rename_to, cred, dvp, dvp->v_label, vp,
763 vp != NULL ? vp->v_label : NULL, samedir, cnp);
764 return (error);
765 }
766
767 int
768 mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
769 {
770 int error;
771
772 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
773
774 if (!mac_enforce_fs)
775 return (0);
776
777 MAC_CHECK(check_vnode_revoke, cred, vp, vp->v_label);
778 return (error);
779 }
780
781 int
782 mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
783 struct acl *acl)
784 {
785 int error;
786
787 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
788
789 if (!mac_enforce_fs)
790 return (0);
791
792 MAC_CHECK(check_vnode_setacl, cred, vp, vp->v_label, type, acl);
793 return (error);
794 }
795
796 int
797 mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
798 int attrnamespace, const char *name, struct uio *uio)
799 {
800 int error;
801
802 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
803
804 if (!mac_enforce_fs)
805 return (0);
806
807 MAC_CHECK(check_vnode_setextattr, cred, vp, vp->v_label,
808 attrnamespace, name, uio);
809 return (error);
810 }
811
812 int
813 mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
814 {
815 int error;
816
817 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
818
819 if (!mac_enforce_fs)
820 return (0);
821
822 MAC_CHECK(check_vnode_setflags, cred, vp, vp->v_label, flags);
823 return (error);
824 }
825
826 int
827 mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
828 {
829 int error;
830
831 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
832
833 if (!mac_enforce_fs)
834 return (0);
835
836 MAC_CHECK(check_vnode_setmode, cred, vp, vp->v_label, mode);
837 return (error);
838 }
839
840 int
841 mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
842 gid_t gid)
843 {
844 int error;
845
846 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
847
848 if (!mac_enforce_fs)
849 return (0);
850
851 MAC_CHECK(check_vnode_setowner, cred, vp, vp->v_label, uid, gid);
852 return (error);
853 }
854
855 int
856 mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
857 struct timespec atime, struct timespec mtime)
858 {
859 int error;
860
861 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
862
863 if (!mac_enforce_fs)
864 return (0);
865
866 MAC_CHECK(check_vnode_setutimes, cred, vp, vp->v_label, atime,
867 mtime);
868 return (error);
869 }
870
871 int
872 mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
873 struct vnode *vp)
874 {
875 int error;
876
877 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
878
879 if (!mac_enforce_fs)
880 return (0);
881
882 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
883 vp->v_label);
884 return (error);
885 }
886
887 int
888 mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
889 struct vnode *vp)
890 {
891 int error;
892
893 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
894
895 if (!mac_enforce_fs)
896 return (0);
897
898 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
899 vp->v_label);
900
901 return (error);
902 }
903
904 void
905 mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
906 {
907
908 MAC_PERFORM(relabel_vnode, cred, vp, vp->v_label, newlabel);
909 }
910
911 void
912 mac_create_mount(struct ucred *cred, struct mount *mp)
913 {
914
915 MAC_PERFORM(create_mount, cred, mp, mp->mnt_mntlabel,
916 mp->mnt_fslabel);
917 }
918
919 void
920 mac_create_root_mount(struct ucred *cred, struct mount *mp)
921 {
922
923 MAC_PERFORM(create_root_mount, cred, mp, mp->mnt_mntlabel,
924 mp->mnt_fslabel);
925 }
926
927 int
928 mac_check_mount_stat(struct ucred *cred, struct mount *mount)
929 {
930 int error;
931
932 if (!mac_enforce_fs)
933 return (0);
934
935 MAC_CHECK(check_mount_stat, cred, mount, mount->mnt_mntlabel);
936
937 return (error);
938 }
939
940 void
941 mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
942 {
943
944 MAC_PERFORM(create_devfs_device, mp, dev, de, de->de_label);
945 }
946
947 void
948 mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
949 struct devfs_dirent *dd, struct devfs_dirent *de)
950 {
951
952 MAC_PERFORM(create_devfs_symlink, cred, mp, dd, dd->de_label, de,
953 de->de_label);
954 }
955
956 void
957 mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
958 struct devfs_dirent *de)
959 {
960
961 MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
962 de->de_label);
963 }
964
965 /*
966 * Implementation of VOP_SETLABEL() that relies on extended attributes
967 * to store label data. Can be referenced by filesystems supporting
968 * extended attributes.
969 */
970 int
971 vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
972 {
973 struct vnode *vp = ap->a_vp;
974 struct label *intlabel = ap->a_label;
975 int error;
976
977 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
978
979 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
980 return (EOPNOTSUPP);
981
982 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
983 if (error)
984 return (error);
985
986 mac_relabel_vnode(ap->a_cred, vp, intlabel);
987
988 return (0);
989 }
990
991 int
992 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
993 {
994 int error;
995
996 if (vp->v_mount == NULL) {
997 /* printf("vn_setlabel: null v_mount\n"); */
998 if (vp->v_type != VNON)
999 printf("vn_setlabel: null v_mount with non-VNON\n");
1000 return (EBADF);
1001 }
1002
1003 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1004 return (EOPNOTSUPP);
1005
1006 /*
1007 * Multi-phase commit. First check the policies to confirm the
1008 * change is OK. Then commit via the filesystem. Finally,
1009 * update the actual vnode label. Question: maybe the filesystem
1010 * should update the vnode at the end as part of VOP_SETLABEL()?
1011 */
1012 error = mac_check_vnode_relabel(cred, vp, intlabel);
1013 if (error)
1014 return (error);
1015
1016 /*
1017 * VADMIN provides the opportunity for the filesystem to make
1018 * decisions about who is and is not able to modify labels
1019 * and protections on files. This might not be right. We can't
1020 * assume VOP_SETLABEL() will do it, because we might implement
1021 * that as part of vop_stdsetlabel_ea().
1022 */
1023 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
1024 if (error)
1025 return (error);
1026
1027 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
1028 if (error)
1029 return (error);
1030
1031 return (0);
1032 }
Cache object: f463113b303bf72f744bae8480e0ce03
|