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_net.c 122875 2003-11-18 00:39:07Z rwatson $");
39
40 #include "opt_mac.h"
41
42 #include <sys/param.h>
43 #include <sys/kernel.h>
44 #include <sys/lock.h>
45 #include <sys/malloc.h>
46 #include <sys/mutex.h>
47 #include <sys/mac.h>
48 #include <sys/sbuf.h>
49 #include <sys/systm.h>
50 #include <sys/mount.h>
51 #include <sys/file.h>
52 #include <sys/namei.h>
53 #include <sys/protosw.h>
54 #include <sys/socket.h>
55 #include <sys/socketvar.h>
56 #include <sys/sysctl.h>
57
58 #include <sys/mac_policy.h>
59
60 #include <net/bpfdesc.h>
61 #include <net/if.h>
62 #include <net/if_var.h>
63
64 #include <netinet/in.h>
65 #include <netinet/in_pcb.h>
66 #include <netinet/ip_var.h>
67
68 #include <security/mac/mac_internal.h>
69
70 static int mac_enforce_network = 1;
71 SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
72 &mac_enforce_network, 0, "Enforce MAC policy on network packets");
73 TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
74
75 static int mac_enforce_socket = 1;
76 SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
77 &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
78 TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
79
80 #ifdef MAC_DEBUG
81 static unsigned int nmacmbufs, nmacifnets, nmacbpfdescs, nmacsockets,
82 nmacinpcbs, nmacipqs;
83
84 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
85 &nmacmbufs, 0, "number of mbufs in use");
86 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
87 &nmacifnets, 0, "number of ifnets in use");
88 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, inpcbs, CTLFLAG_RD,
89 &nmacinpcbs, 0, "number of inpcbs in use");
90 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
91 &nmacipqs, 0, "number of ipqs in use");
92 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
93 &nmacbpfdescs, 0, "number of bpfdescs in use");
94 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
95 &nmacsockets, 0, "number of sockets in use");
96 #endif
97
98 static struct label *
99 mbuf_to_label(struct mbuf *mbuf)
100 {
101 struct m_tag *tag;
102 struct label *label;
103
104 tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
105 label = (struct label *)(tag+1);
106
107 return (label);
108 }
109
110 static struct label *
111 mac_bpfdesc_label_alloc(void)
112 {
113 struct label *label;
114
115 label = mac_labelzone_alloc(M_WAITOK);
116 MAC_PERFORM(init_bpfdesc_label, label);
117 MAC_DEBUG_COUNTER_INC(&nmacbpfdescs);
118 return (label);
119 }
120
121 void
122 mac_init_bpfdesc(struct bpf_d *bpf_d)
123 {
124
125 bpf_d->bd_label = mac_bpfdesc_label_alloc();
126 }
127
128 static struct label *
129 mac_ifnet_label_alloc(void)
130 {
131 struct label *label;
132
133 label = mac_labelzone_alloc(M_WAITOK);
134 MAC_PERFORM(init_ifnet_label, label);
135 MAC_DEBUG_COUNTER_INC(&nmacifnets);
136 return (label);
137 }
138
139 void
140 mac_init_ifnet(struct ifnet *ifp)
141 {
142
143 ifp->if_label = mac_ifnet_label_alloc();
144 }
145
146 static struct label *
147 mac_inpcb_label_alloc(int flag)
148 {
149 struct label *label;
150 int error;
151
152 label = mac_labelzone_alloc(flag);
153 if (label == NULL)
154 return (NULL);
155 MAC_CHECK(init_inpcb_label, label, flag);
156 if (error) {
157 MAC_PERFORM(destroy_inpcb_label, label);
158 mac_labelzone_free(label);
159 return (NULL);
160 }
161 MAC_DEBUG_COUNTER_INC(&nmacinpcbs);
162 return (label);
163 }
164
165 int
166 mac_init_inpcb(struct inpcb *inp, int flag)
167 {
168
169 inp->inp_label = mac_inpcb_label_alloc(flag);
170 if (inp->inp_label == NULL)
171 return (ENOMEM);
172 return (0);
173 }
174
175 static struct label *
176 mac_ipq_label_alloc(int flag)
177 {
178 struct label *label;
179 int error;
180
181 label = mac_labelzone_alloc(flag);
182 if (label == NULL)
183 return (NULL);
184
185 MAC_CHECK(init_ipq_label, label, flag);
186 if (error) {
187 MAC_PERFORM(destroy_ipq_label, label);
188 mac_labelzone_free(label);
189 return (NULL);
190 }
191 MAC_DEBUG_COUNTER_INC(&nmacipqs);
192 return (label);
193 }
194
195 int
196 mac_init_ipq(struct ipq *ipq, int flag)
197 {
198
199 ipq->ipq_label = mac_ipq_label_alloc(flag);
200 if (ipq->ipq_label == NULL)
201 return (ENOMEM);
202 return (0);
203 }
204
205 int
206 mac_init_mbuf_tag(struct m_tag *tag, int flag)
207 {
208 struct label *label;
209 int error;
210
211 label = (struct label *) (tag + 1);
212 mac_init_label(label);
213
214 MAC_CHECK(init_mbuf_label, label, flag);
215 if (error) {
216 MAC_PERFORM(destroy_mbuf_label, label);
217 mac_destroy_label(label);
218 } else {
219 MAC_DEBUG_COUNTER_INC(&nmacmbufs);
220 }
221 return (error);
222 }
223
224 int
225 mac_init_mbuf(struct mbuf *m, int flag)
226 {
227 struct m_tag *tag;
228 int error;
229
230 M_ASSERTPKTHDR(m);
231
232 #ifndef MAC_ALWAYS_LABEL_MBUF
233 /*
234 * If conditionally allocating mbuf labels, don't allocate unless
235 * they are required.
236 */
237 if (!mac_labelmbufs)
238 return (0);
239 #endif
240 tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
241 flag);
242 if (tag == NULL)
243 return (ENOMEM);
244 error = mac_init_mbuf_tag(tag, flag);
245 if (error) {
246 m_tag_free(tag);
247 return (error);
248 }
249 m_tag_prepend(m, tag);
250 return (0);
251 }
252
253 struct label *
254 mac_socket_label_alloc(int flag)
255 {
256 struct label *label;
257 int error;
258
259 label = mac_labelzone_alloc(flag);
260 if (label == NULL)
261 return (NULL);
262
263 MAC_CHECK(init_socket_label, label, flag);
264 if (error) {
265 MAC_PERFORM(destroy_socket_label, label);
266 mac_labelzone_free(label);
267 return (NULL);
268 }
269 MAC_DEBUG_COUNTER_INC(&nmacsockets);
270 return (label);
271 }
272
273 static struct label *
274 mac_socket_peer_label_alloc(int flag)
275 {
276 struct label *label;
277 int error;
278
279 label = mac_labelzone_alloc(flag);
280 if (label == NULL)
281 return (NULL);
282
283 MAC_CHECK(init_socket_peer_label, label, flag);
284 if (error) {
285 MAC_PERFORM(destroy_socket_peer_label, label);
286 mac_labelzone_free(label);
287 return (NULL);
288 }
289 MAC_DEBUG_COUNTER_INC(&nmacsockets);
290 return (label);
291 }
292
293 int
294 mac_init_socket(struct socket *so, int flag)
295 {
296
297 so->so_label = mac_socket_label_alloc(flag);
298 if (so->so_label == NULL)
299 return (ENOMEM);
300 so->so_peerlabel = mac_socket_peer_label_alloc(flag);
301 if (so->so_peerlabel == NULL) {
302 mac_socket_label_free(so->so_label);
303 so->so_label = NULL;
304 return (ENOMEM);
305 }
306 return (0);
307 }
308
309 static void
310 mac_bpfdesc_label_free(struct label *label)
311 {
312
313 MAC_PERFORM(destroy_bpfdesc_label, label);
314 mac_labelzone_free(label);
315 MAC_DEBUG_COUNTER_DEC(&nmacbpfdescs);
316 }
317
318 void
319 mac_destroy_bpfdesc(struct bpf_d *bpf_d)
320 {
321
322 mac_bpfdesc_label_free(bpf_d->bd_label);
323 bpf_d->bd_label = NULL;
324 }
325
326 static void
327 mac_ifnet_label_free(struct label *label)
328 {
329
330 MAC_PERFORM(destroy_ifnet_label, label);
331 mac_labelzone_free(label);
332 MAC_DEBUG_COUNTER_DEC(&nmacifnets);
333 }
334
335 void
336 mac_destroy_ifnet(struct ifnet *ifp)
337 {
338
339 mac_ifnet_label_free(ifp->if_label);
340 ifp->if_label = NULL;
341 }
342
343 static void
344 mac_inpcb_label_free(struct label *label)
345 {
346
347 MAC_PERFORM(destroy_inpcb_label, label);
348 mac_labelzone_free(label);
349 MAC_DEBUG_COUNTER_DEC(&nmacinpcbs);
350 }
351
352 void
353 mac_destroy_inpcb(struct inpcb *inp)
354 {
355
356 mac_inpcb_label_free(inp->inp_label);
357 inp->inp_label = NULL;
358 }
359
360 static void
361 mac_ipq_label_free(struct label *label)
362 {
363
364 MAC_PERFORM(destroy_ipq_label, label);
365 mac_labelzone_free(label);
366 MAC_DEBUG_COUNTER_DEC(&nmacipqs);
367 }
368
369 void
370 mac_destroy_ipq(struct ipq *ipq)
371 {
372
373 mac_ipq_label_free(ipq->ipq_label);
374 ipq->ipq_label = NULL;
375 }
376
377 void
378 mac_destroy_mbuf_tag(struct m_tag *tag)
379 {
380 struct label *label;
381
382 label = (struct label *)(tag+1);
383
384 MAC_PERFORM(destroy_mbuf_label, label);
385 mac_destroy_label(label);
386 MAC_DEBUG_COUNTER_DEC(&nmacmbufs);
387 }
388
389 void
390 mac_socket_label_free(struct label *label)
391 {
392
393 MAC_PERFORM(destroy_socket_label, label);
394 mac_labelzone_free(label);
395 MAC_DEBUG_COUNTER_DEC(&nmacsockets);
396 }
397
398 static void
399 mac_socket_peer_label_free(struct label *label)
400 {
401
402 MAC_PERFORM(destroy_socket_peer_label, label);
403 mac_labelzone_free(label);
404 MAC_DEBUG_COUNTER_DEC(&nmacsockets);
405 }
406
407 void
408 mac_destroy_socket(struct socket *socket)
409 {
410
411 mac_socket_label_free(socket->so_label);
412 socket->so_label = NULL;
413 mac_socket_peer_label_free(socket->so_peerlabel);
414 socket->so_peerlabel = NULL;
415 }
416
417 void
418 mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
419 {
420 struct label *src_label, *dest_label;
421
422 src_label = (struct label *)(src+1);
423 dest_label = (struct label *)(dest+1);
424
425 /*
426 * mac_init_mbuf_tag() is called on the target tag in
427 * m_tag_copy(), so we don't need to call it here.
428 */
429 MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
430 }
431
432 void
433 mac_copy_socket_label(struct label *src, struct label *dest)
434 {
435
436 MAC_PERFORM(copy_socket_label, src, dest);
437 }
438
439 static int
440 mac_externalize_ifnet_label(struct label *label, char *elements,
441 char *outbuf, size_t outbuflen)
442 {
443 int error;
444
445 MAC_EXTERNALIZE(ifnet, label, elements, outbuf, outbuflen);
446
447 return (error);
448 }
449
450 int
451 mac_externalize_socket_label(struct label *label, char *elements,
452 char *outbuf, size_t outbuflen)
453 {
454 int error;
455
456 MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
457
458 return (error);
459 }
460
461 static int
462 mac_externalize_socket_peer_label(struct label *label, char *elements,
463 char *outbuf, size_t outbuflen)
464 {
465 int error;
466
467 MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen);
468
469 return (error);
470 }
471
472 static int
473 mac_internalize_ifnet_label(struct label *label, char *string)
474 {
475 int error;
476
477 MAC_INTERNALIZE(ifnet, label, string);
478
479 return (error);
480 }
481
482 int
483 mac_internalize_socket_label(struct label *label, char *string)
484 {
485 int error;
486
487 MAC_INTERNALIZE(socket, label, string);
488
489 return (error);
490 }
491
492 void
493 mac_create_ifnet(struct ifnet *ifnet)
494 {
495
496 MAC_PERFORM(create_ifnet, ifnet, ifnet->if_label);
497 }
498
499 void
500 mac_create_inpcb_from_socket(struct socket *so, struct inpcb *inp)
501 {
502
503 MAC_PERFORM(create_inpcb_from_socket, so, so->so_label, inp,
504 inp->inp_label);
505 }
506
507 void
508 mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
509 {
510
511 MAC_PERFORM(create_bpfdesc, cred, bpf_d, bpf_d->bd_label);
512 }
513
514 void
515 mac_create_socket(struct ucred *cred, struct socket *socket)
516 {
517
518 MAC_PERFORM(create_socket, cred, socket, socket->so_label);
519 }
520
521 void
522 mac_create_socket_from_socket(struct socket *oldsocket,
523 struct socket *newsocket)
524 {
525
526 MAC_PERFORM(create_socket_from_socket, oldsocket, oldsocket->so_label,
527 newsocket, newsocket->so_label);
528 }
529
530 static void
531 mac_relabel_socket(struct ucred *cred, struct socket *socket,
532 struct label *newlabel)
533 {
534
535 MAC_PERFORM(relabel_socket, cred, socket, socket->so_label, newlabel);
536 }
537
538 void
539 mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
540 {
541 struct label *label;
542
543 label = mbuf_to_label(mbuf);
544
545 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
546 socket->so_peerlabel);
547 }
548
549 void
550 mac_set_socket_peer_from_socket(struct socket *oldsocket,
551 struct socket *newsocket)
552 {
553
554 MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
555 oldsocket->so_label, newsocket, newsocket->so_peerlabel);
556 }
557
558 void
559 mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
560 {
561 struct label *label;
562
563 label = mbuf_to_label(datagram);
564
565 MAC_PERFORM(create_datagram_from_ipq, ipq, ipq->ipq_label,
566 datagram, label);
567 }
568
569 void
570 mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
571 {
572 struct label *datagramlabel, *fragmentlabel;
573
574 datagramlabel = mbuf_to_label(datagram);
575 fragmentlabel = mbuf_to_label(fragment);
576
577 MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
578 fragmentlabel);
579 }
580
581 void
582 mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
583 {
584 struct label *label;
585
586 label = mbuf_to_label(fragment);
587
588 MAC_PERFORM(create_ipq, fragment, label, ipq, ipq->ipq_label);
589 }
590
591 void
592 mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
593 {
594 struct label *oldmbuflabel, *newmbuflabel;
595
596 oldmbuflabel = mbuf_to_label(oldmbuf);
597 newmbuflabel = mbuf_to_label(newmbuf);
598
599 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
600 newmbuflabel);
601 }
602
603 void
604 mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
605 {
606 struct label *label;
607
608 label = mbuf_to_label(mbuf);
609
610 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, bpf_d->bd_label, mbuf,
611 label);
612 }
613
614 void
615 mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
616 {
617 struct label *label;
618
619 label = mbuf_to_label(mbuf);
620
621 MAC_PERFORM(create_mbuf_linklayer, ifnet, ifnet->if_label, mbuf,
622 label);
623 }
624
625 void
626 mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
627 {
628 struct label *label;
629
630 label = mbuf_to_label(mbuf);
631
632 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, ifnet->if_label, mbuf,
633 label);
634 }
635
636 void
637 mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
638 struct mbuf *newmbuf)
639 {
640 struct label *oldmbuflabel, *newmbuflabel;
641
642 oldmbuflabel = mbuf_to_label(oldmbuf);
643 newmbuflabel = mbuf_to_label(newmbuf);
644
645 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
646 ifnet, ifnet->if_label, newmbuf, newmbuflabel);
647 }
648
649 void
650 mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
651 {
652 struct label *oldmbuflabel, *newmbuflabel;
653
654 oldmbuflabel = mbuf_to_label(oldmbuf);
655 newmbuflabel = mbuf_to_label(newmbuf);
656
657 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
658 newmbuflabel);
659 }
660
661 int
662 mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
663 {
664 struct label *label;
665 int result;
666
667 label = mbuf_to_label(fragment);
668
669 result = 1;
670 MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
671 ipq->ipq_label);
672
673 return (result);
674 }
675
676 void
677 mac_reflect_mbuf_icmp(struct mbuf *m)
678 {
679 struct label *label;
680
681 label = mbuf_to_label(m);
682
683 MAC_PERFORM(reflect_mbuf_icmp, m, label);
684 }
685 void
686 mac_reflect_mbuf_tcp(struct mbuf *m)
687 {
688 struct label *label;
689
690 label = mbuf_to_label(m);
691
692 MAC_PERFORM(reflect_mbuf_tcp, m, label);
693 }
694
695 void
696 mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
697 {
698 struct label *label;
699
700 label = mbuf_to_label(fragment);
701
702 MAC_PERFORM(update_ipq, fragment, label, ipq, ipq->ipq_label);
703 }
704
705 void
706 mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
707 {
708 struct label *label;
709
710 label = mbuf_to_label(mbuf);
711
712 MAC_PERFORM(create_mbuf_from_socket, socket, socket->so_label, mbuf,
713 label);
714 }
715
716 int
717 mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
718 {
719 int error;
720
721 if (!mac_enforce_network)
722 return (0);
723
724 MAC_CHECK(check_bpfdesc_receive, bpf_d, bpf_d->bd_label, ifnet,
725 ifnet->if_label);
726
727 return (error);
728 }
729
730 int
731 mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
732 {
733 struct label *label;
734 int error;
735
736 M_ASSERTPKTHDR(mbuf);
737
738 if (!mac_enforce_network)
739 return (0);
740
741 label = mbuf_to_label(mbuf);
742
743 MAC_CHECK(check_ifnet_transmit, ifnet, ifnet->if_label, mbuf,
744 label);
745
746 return (error);
747 }
748
749 int
750 mac_check_inpcb_deliver(struct inpcb *inp, struct mbuf *m)
751 {
752 struct label *label;
753 int error;
754
755 M_ASSERTPKTHDR(m);
756
757 if (!mac_enforce_socket)
758 return (0);
759
760 label = mbuf_to_label(m);
761
762 MAC_CHECK(check_inpcb_deliver, inp, inp->inp_label, m, label);
763
764 return (error);
765 }
766
767 int
768 mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
769 struct sockaddr *sockaddr)
770 {
771 int error;
772
773 if (!mac_enforce_socket)
774 return (0);
775
776 MAC_CHECK(check_socket_bind, ucred, socket, socket->so_label,
777 sockaddr);
778
779 return (error);
780 }
781
782 int
783 mac_check_socket_connect(struct ucred *cred, struct socket *socket,
784 struct sockaddr *sockaddr)
785 {
786 int error;
787
788 if (!mac_enforce_socket)
789 return (0);
790
791 MAC_CHECK(check_socket_connect, cred, socket, socket->so_label,
792 sockaddr);
793
794 return (error);
795 }
796
797 int
798 mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
799 {
800 struct label *label;
801 int error;
802
803 if (!mac_enforce_socket)
804 return (0);
805
806 label = mbuf_to_label(mbuf);
807
808 MAC_CHECK(check_socket_deliver, socket, socket->so_label, mbuf,
809 label);
810
811 return (error);
812 }
813
814 int
815 mac_check_socket_listen(struct ucred *cred, struct socket *socket)
816 {
817 int error;
818
819 if (!mac_enforce_socket)
820 return (0);
821
822 MAC_CHECK(check_socket_listen, cred, socket, socket->so_label);
823 return (error);
824 }
825
826 int
827 mac_check_socket_receive(struct ucred *cred, struct socket *so)
828 {
829 int error;
830
831 if (!mac_enforce_socket)
832 return (0);
833
834 MAC_CHECK(check_socket_receive, cred, so, so->so_label);
835
836 return (error);
837 }
838
839 static int
840 mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
841 struct label *newlabel)
842 {
843 int error;
844
845 MAC_CHECK(check_socket_relabel, cred, socket, socket->so_label,
846 newlabel);
847
848 return (error);
849 }
850
851 int
852 mac_check_socket_send(struct ucred *cred, struct socket *so)
853 {
854 int error;
855
856 if (!mac_enforce_socket)
857 return (0);
858
859 MAC_CHECK(check_socket_send, cred, so, so->so_label);
860
861 return (error);
862 }
863
864 int
865 mac_check_socket_visible(struct ucred *cred, struct socket *socket)
866 {
867 int error;
868
869 if (!mac_enforce_socket)
870 return (0);
871
872 MAC_CHECK(check_socket_visible, cred, socket, socket->so_label);
873
874 return (error);
875 }
876
877 int
878 mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
879 struct ifnet *ifnet)
880 {
881 char *elements, *buffer;
882 struct mac mac;
883 int error;
884
885 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
886 if (error)
887 return (error);
888
889 error = mac_check_structmac_consistent(&mac);
890 if (error)
891 return (error);
892
893 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
894 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
895 if (error) {
896 free(elements, M_MACTEMP);
897 return (error);
898 }
899
900 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
901 error = mac_externalize_ifnet_label(ifnet->if_label, elements,
902 buffer, mac.m_buflen);
903 if (error == 0)
904 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
905
906 free(buffer, M_MACTEMP);
907 free(elements, M_MACTEMP);
908
909 return (error);
910 }
911
912 int
913 mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
914 struct ifnet *ifnet)
915 {
916 struct label *intlabel;
917 struct mac mac;
918 char *buffer;
919 int error;
920
921 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
922 if (error)
923 return (error);
924
925 error = mac_check_structmac_consistent(&mac);
926 if (error)
927 return (error);
928
929 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
930 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
931 if (error) {
932 free(buffer, M_MACTEMP);
933 return (error);
934 }
935
936 intlabel = mac_ifnet_label_alloc();
937 error = mac_internalize_ifnet_label(intlabel, buffer);
938 free(buffer, M_MACTEMP);
939 if (error) {
940 mac_ifnet_label_free(intlabel);
941 return (error);
942 }
943
944 /*
945 * XXX: Note that this is a redundant privilege check, since
946 * policies impose this check themselves if required by the
947 * policy. Eventually, this should go away.
948 */
949 error = suser_cred(cred, 0);
950 if (error) {
951 mac_ifnet_label_free(intlabel);
952 return (error);
953 }
954
955 MAC_CHECK(check_ifnet_relabel, cred, ifnet, ifnet->if_label,
956 intlabel);
957 if (error) {
958 mac_ifnet_label_free(intlabel);
959 return (error);
960 }
961
962 MAC_PERFORM(relabel_ifnet, cred, ifnet, ifnet->if_label, intlabel);
963
964 mac_ifnet_label_free(intlabel);
965 return (0);
966 }
967
968 void
969 mac_inpcb_sosetlabel(struct socket *so, struct inpcb *inp)
970 {
971
972 /* XXX: assert socket lock. */
973 INP_LOCK_ASSERT(inp);
974 MAC_PERFORM(inpcb_sosetlabel, so, so->so_label, inp, inp->inp_label);
975 }
976
977 int
978 mac_socket_label_set(struct ucred *cred, struct socket *so,
979 struct label *label)
980 {
981 int error;
982
983 error = mac_check_socket_relabel(cred, so, label);
984 if (error)
985 return (error);
986
987 mac_relabel_socket(cred, so, label);
988
989 /*
990 * If the protocol has expressed interest in socket layer changes,
991 * such as if it needs to propagate changes to a cached pcb
992 * label from the socket, notify it of the label change while
993 * holding the socket lock.
994 */
995 if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL)
996 (so->so_proto->pr_usrreqs->pru_sosetlabel)(so);
997
998 return (0);
999 }
1000
1001 int
1002 mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
1003 {
1004 struct label *intlabel;
1005 char *buffer;
1006 int error;
1007
1008 error = mac_check_structmac_consistent(mac);
1009 if (error)
1010 return (error);
1011
1012 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
1013 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
1014 if (error) {
1015 free(buffer, M_MACTEMP);
1016 return (error);
1017 }
1018
1019 intlabel = mac_socket_label_alloc(M_WAITOK);
1020 error = mac_internalize_socket_label(intlabel, buffer);
1021 free(buffer, M_MACTEMP);
1022 if (error)
1023 goto out;
1024
1025 /* XXX: Socket lock here. */
1026 error = mac_socket_label_set(cred, so, intlabel);
1027 /* XXX: Socket unlock here. */
1028 out:
1029 mac_socket_label_free(intlabel);
1030 return (error);
1031 }
1032
1033 int
1034 mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac)
1035 {
1036 char *buffer, *elements;
1037 int error;
1038
1039 error = mac_check_structmac_consistent(mac);
1040 if (error)
1041 return (error);
1042
1043 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
1044 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
1045 if (error) {
1046 free(elements, M_MACTEMP);
1047 return (error);
1048 }
1049
1050 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1051 error = mac_externalize_socket_label(so->so_label, elements,
1052 buffer, mac->m_buflen);
1053 if (error == 0)
1054 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
1055
1056 free(buffer, M_MACTEMP);
1057 free(elements, M_MACTEMP);
1058
1059 return (error);
1060 }
1061
1062 int
1063 mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so,
1064 struct mac *mac)
1065 {
1066 char *elements, *buffer;
1067 int error;
1068
1069 error = mac_check_structmac_consistent(mac);
1070 if (error)
1071 return (error);
1072
1073 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
1074 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
1075 if (error) {
1076 free(elements, M_MACTEMP);
1077 return (error);
1078 }
1079
1080 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
1081 error = mac_externalize_socket_peer_label(so->so_peerlabel,
1082 elements, buffer, mac->m_buflen);
1083 if (error == 0)
1084 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
1085
1086 free(buffer, M_MACTEMP);
1087 free(elements, M_MACTEMP);
1088
1089 return (error);
1090 }
Cache object: 881c84f0195e0bac1074d5fcacb770c6
|