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