]> git.saurik.com Git - apple/xnu.git/blob - security/mac_socket.c
xnu-6153.121.1.tar.gz
[apple/xnu.git] / security / mac_socket.c
1 /*
2 * Copyright (c) 2007-2012 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 /*-
29 * Copyright (c) 1999-2002 Robert N. M. Watson
30 * Copyright (c) 2001 Ilmar S. Habibulin
31 * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
32 * Copyright (c) 2005 SPARTA, Inc.
33 * All rights reserved.
34 *
35 * This software was developed by Robert Watson and Ilmar Habibulin for the
36 * TrustedBSD Project.
37 *
38 * This software was developed for the FreeBSD Project in part by McAfee
39 * Research, the Technology Research Division of Network Associates, Inc.
40 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
41 * DARPA CHATS research program.
42 *
43 * This software was enhanced by SPARTA ISSO under SPAWAR contract
44 * N66001-04-C-6019 ("SEFOS").
45 *
46 * Redistribution and use in source and binary forms, with or without
47 * modification, are permitted provided that the following conditions
48 * are met:
49 * 1. Redistributions of source code must retain the above copyright
50 * notice, this list of conditions and the following disclaimer.
51 * 2. Redistributions in binary form must reproduce the above copyright
52 * notice, this list of conditions and the following disclaimer in the
53 * documentation and/or other materials provided with the distribution.
54 *
55 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
56 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
57 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
58 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
59 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
60 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
61 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
62 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
63 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
64 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
65 * SUCH DAMAGE.
66 */
67
68 #include <sys/cdefs.h>
69
70 #include <sys/param.h>
71 #include <sys/kernel.h>
72 #include <sys/lock.h>
73 #include <sys/malloc.h>
74 #include <sys/sbuf.h>
75 #include <sys/systm.h>
76 #include <sys/mount.h>
77 #include <sys/file.h>
78 #include <sys/namei.h>
79 #include <sys/protosw.h>
80 #include <sys/socket.h>
81 #include <sys/socketvar.h>
82 #include <sys/sysctl.h>
83 #include <sys/kpi_socket.h>
84
85 #include <security/mac_internal.h>
86
87 #if CONFIG_MACF_SOCKET
88 struct label *
89 mac_socket_label_alloc(int flag)
90 {
91 struct label *label;
92 int error;
93
94 label = mac_labelzone_alloc(flag);
95 if (label == NULL) {
96 return NULL;
97 }
98
99 MAC_CHECK(socket_label_init, label, flag);
100 if (error) {
101 MAC_PERFORM(socket_label_destroy, label);
102 mac_labelzone_free(label);
103 return NULL;
104 }
105
106 return label;
107 }
108
109 static struct label *
110 mac_socket_peer_label_alloc(int flag)
111 {
112 struct label *label;
113 int error;
114
115 label = mac_labelzone_alloc(flag);
116 if (label == NULL) {
117 return NULL;
118 }
119
120 MAC_CHECK(socketpeer_label_init, label, flag);
121 if (error) {
122 MAC_PERFORM(socketpeer_label_destroy, label);
123 mac_labelzone_free(label);
124 return NULL;
125 }
126
127 return label;
128 }
129
130 int
131 mac_socket_label_init(struct socket *so, int flag)
132 {
133 so->so_label = mac_socket_label_alloc(flag);
134 if (so->so_label == NULL) {
135 return ENOMEM;
136 }
137 so->so_peerlabel = mac_socket_peer_label_alloc(flag);
138 if (so->so_peerlabel == NULL) {
139 mac_socket_label_free(so->so_label);
140 so->so_label = NULL;
141 return ENOMEM;
142 }
143 return 0;
144 }
145
146 void
147 mac_socket_label_free(struct label *label)
148 {
149 MAC_PERFORM(socket_label_destroy, label);
150 mac_labelzone_free(label);
151 }
152
153 static void
154 mac_socket_peer_label_free(struct label *label)
155 {
156 MAC_PERFORM(socketpeer_label_destroy, label);
157 mac_labelzone_free(label);
158 }
159
160 void
161 mac_socket_label_destroy(struct socket *so)
162 {
163 if (so->so_label != NULL) {
164 mac_socket_label_free(so->so_label);
165 so->so_label = NULL;
166 }
167 if (so->so_peerlabel != NULL) {
168 mac_socket_peer_label_free(so->so_peerlabel);
169 so->so_peerlabel = NULL;
170 }
171 }
172
173 void
174 mac_socket_label_copy(struct label *src, struct label *dest)
175 {
176 MAC_PERFORM(socket_label_copy, src, dest);
177 }
178
179 int
180 mac_socket_label_externalize(struct label *label, char *elements,
181 char *outbuf, size_t outbuflen)
182 {
183 int error;
184
185 error = MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen);
186
187 return error;
188 }
189
190 static int
191 mac_socketpeer_label_externalize(struct label *label, char *elements,
192 char *outbuf, size_t outbuflen)
193 {
194 int error;
195
196 error = MAC_EXTERNALIZE(socketpeer, label, elements, outbuf, outbuflen);
197
198 return error;
199 }
200
201 int
202 mac_socket_label_internalize(struct label *label, char *string)
203 {
204 int error;
205
206 error = MAC_INTERNALIZE(socket, label, string);
207
208 return error;
209 }
210
211 void
212 mac_socket_label_associate(struct ucred *cred, struct socket *so)
213 {
214 #if SECURITY_MAC_CHECK_ENFORCE
215 /* 21167099 - only check if we allow write */
216 if (!mac_socket_enforce) {
217 return;
218 }
219 #endif
220
221 MAC_PERFORM(socket_label_associate, cred,
222 (socket_t)so, so->so_label);
223 }
224
225 void
226 mac_socket_label_associate_accept(struct socket *oldsocket,
227 struct socket *newsocket)
228 {
229 #if SECURITY_MAC_CHECK_ENFORCE
230 /* 21167099 - only check if we allow write */
231 if (!mac_socket_enforce) {
232 return;
233 }
234 #endif
235
236 MAC_PERFORM(socket_label_associate_accept,
237 (socket_t)oldsocket, oldsocket->so_label,
238 (socket_t)newsocket, newsocket->so_label);
239 }
240
241 #if CONFIG_MACF_SOCKET && CONFIG_MACF_NET
242 void
243 mac_socketpeer_label_associate_mbuf(struct mbuf *mbuf, struct socket *so)
244 {
245 struct label *label;
246
247 #if SECURITY_MAC_CHECK_ENFORCE
248 /* 21167099 - only check if we allow write */
249 if (!mac_socket_enforce && !mac_net_enforce) {
250 return;
251 }
252 #endif
253
254 label = mac_mbuf_to_label(mbuf);
255
256 /* Policy must deal with NULL label (unlabeled mbufs) */
257 MAC_PERFORM(socketpeer_label_associate_mbuf, mbuf, label,
258 (socket_t)so, so->so_peerlabel);
259 }
260 #else
261 void
262 mac_socketpeer_label_associate_mbuf(__unused struct mbuf *mbuf,
263 __unused struct socket *so)
264 {
265 return;
266 }
267 #endif
268
269 void
270 mac_socketpeer_label_associate_socket(struct socket *oldsocket,
271 struct socket *newsocket)
272 {
273 #if SECURITY_MAC_CHECK_ENFORCE
274 /* 21167099 - only check if we allow write */
275 if (!mac_socket_enforce) {
276 return;
277 }
278 #endif
279
280 MAC_PERFORM(socketpeer_label_associate_socket,
281 (socket_t)oldsocket, oldsocket->so_label,
282 (socket_t)newsocket, newsocket->so_peerlabel);
283 }
284
285 int
286 mac_socket_check_kqfilter(kauth_cred_t cred, struct knote *kn,
287 struct socket *so)
288 {
289 int error;
290
291 #if SECURITY_MAC_CHECK_ENFORCE
292 /* 21167099 - only check if we allow write */
293 if (!mac_socket_enforce) {
294 return 0;
295 }
296 #endif
297
298 MAC_CHECK(socket_check_kqfilter, cred, kn,
299 (socket_t)so, so->so_label);
300 return error;
301 }
302
303 static int
304 int
305 mac_socket_check_select(kauth_cred_t cred, struct socket *so, int which)
306 {
307 int error;
308
309 #if SECURITY_MAC_CHECK_ENFORCE
310 /* 21167099 - only check if we allow write */
311 if (!mac_socket_enforce) {
312 return 0;
313 }
314 #endif
315
316 MAC_CHECK(socket_check_select, cred,
317 (socket_t)so, so->so_label, which);
318 return error;
319 }
320
321 mac_socket_check_label_update(kauth_cred_t cred, struct socket *so,
322 struct label *newlabel)
323 {
324 int error;
325
326 #if SECURITY_MAC_CHECK_ENFORCE
327 /* 21167099 - only check if we allow write */
328 if (!mac_socket_enforce) {
329 return 0;
330 }
331 #endif
332
333 MAC_CHECK(socket_check_label_update, cred,
334 (socket_t)so, so->so_label,
335 newlabel);
336 return error;
337 }
338
339 int
340 mac_socket_label_update(kauth_cred_t cred, struct socket *so, struct label *label)
341 {
342 int error;
343 #if 0
344 #if SECURITY_MAC_CHECK_ENFORCE
345 /* 21167099 - only check if we allow write */
346 if (!mac_socket_enforce) {
347 return 0;
348 }
349 #endif
350 #endif
351 error = mac_socket_check_label_update(cred, so, label);
352 if (error) {
353 return error;
354 }
355
356 MAC_PERFORM(socket_label_update, cred,
357 (socket_t)so, so->so_label, label);
358
359 #if CONFIG_MACF_NET
360 /*
361 * If the protocol has expressed interest in socket layer changes,
362 * such as if it needs to propagate changes to a cached pcb
363 * label from the socket, notify it of the label change while
364 * holding the socket lock.
365 * XXXMAC - are there cases when we should not do this?
366 */
367 mac_inpcb_label_update(so);
368 #endif
369 return 0;
370 }
371
372 int
373 mac_setsockopt_label(kauth_cred_t cred, struct socket *so, struct mac *mac)
374 {
375 struct label *intlabel;
376 char *buffer;
377 int error;
378 size_t len;
379
380 error = mac_check_structmac_consistent(mac);
381 if (error) {
382 return error;
383 }
384
385 MALLOC(buffer, char *, mac->m_buflen, M_MACTEMP, M_WAITOK);
386 error = copyinstr(CAST_USER_ADDR_T(mac->m_string), buffer,
387 mac->m_buflen, &len);
388 if (error) {
389 FREE(buffer, M_MACTEMP);
390 return error;
391 }
392
393 intlabel = mac_socket_label_alloc(MAC_WAITOK);
394 error = mac_socket_label_internalize(intlabel, buffer);
395 FREE(buffer, M_MACTEMP);
396 if (error) {
397 goto out;
398 }
399
400 error = mac_socket_label_update(cred, so, intlabel);
401 out:
402 mac_socket_label_free(intlabel);
403 return error;
404 }
405
406 int
407 mac_socket_label_get(__unused kauth_cred_t cred, struct socket *so,
408 struct mac *mac)
409 {
410 char *buffer, *elements;
411 struct label *intlabel;
412 int error;
413 size_t len;
414
415 error = mac_check_structmac_consistent(mac);
416 if (error) {
417 return error;
418 }
419
420 MALLOC(elements, char *, mac->m_buflen, M_MACTEMP, M_WAITOK);
421 error = copyinstr(CAST_USER_ADDR_T(mac->m_string), elements,
422 mac->m_buflen, &len);
423 if (error) {
424 FREE(elements, M_MACTEMP);
425 return error;
426 }
427
428 MALLOC(buffer, char *, mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
429 intlabel = mac_socket_label_alloc(MAC_WAITOK);
430 mac_socket_label_copy(so->so_label, intlabel);
431 error = mac_socket_label_externalize(intlabel, elements, buffer,
432 mac->m_buflen);
433 mac_socket_label_free(intlabel);
434 if (error == 0) {
435 error = copyout(buffer, CAST_USER_ADDR_T(mac->m_string),
436 strlen(buffer) + 1);
437 }
438
439 FREE(buffer, M_MACTEMP);
440 FREE(elements, M_MACTEMP);
441
442 return error;
443 }
444
445 int
446 mac_socketpeer_label_get(__unused kauth_cred_t cred, struct socket *so,
447 struct mac *mac)
448 {
449 char *elements, *buffer;
450 struct label *intlabel;
451 int error;
452 size_t len;
453
454 error = mac_check_structmac_consistent(mac);
455 if (error) {
456 return error;
457 }
458
459 MALLOC(elements, char *, mac->m_buflen, M_MACTEMP, M_WAITOK);
460 error = copyinstr(CAST_USER_ADDR_T(mac->m_string), elements,
461 mac->m_buflen, &len);
462 if (error) {
463 FREE(elements, M_MACTEMP);
464 return error;
465 }
466
467 MALLOC(buffer, char *, mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
468 intlabel = mac_socket_label_alloc(MAC_WAITOK);
469 mac_socket_label_copy(so->so_peerlabel, intlabel);
470 error = mac_socketpeer_label_externalize(intlabel, elements, buffer,
471 mac->m_buflen);
472 mac_socket_label_free(intlabel);
473 if (error == 0) {
474 error = copyout(buffer, CAST_USER_ADDR_T(mac->m_string),
475 strlen(buffer) + 1);
476 }
477
478 FREE(buffer, M_MACTEMP);
479 FREE(elements, M_MACTEMP);
480
481 return error;
482 }
483
484 #endif /* MAC_SOCKET */
485
486 int
487 mac_socket_check_accept(kauth_cred_t cred, struct socket *so)
488 {
489 int error;
490
491 #if SECURITY_MAC_CHECK_ENFORCE
492 /* 21167099 - only check if we allow write */
493 if (!mac_socket_enforce) {
494 return 0;
495 }
496 #endif
497
498 MAC_CHECK(socket_check_accept, cred,
499 (socket_t)so, so->so_label);
500 return error;
501 }
502
503 #if CONFIG_MACF_SOCKET_SUBSET
504 int
505 mac_socket_check_accepted(kauth_cred_t cred, struct socket *so)
506 {
507 struct sockaddr *sockaddr;
508 int error;
509
510 #if SECURITY_MAC_CHECK_ENFORCE
511 /* 21167099 - only check if we allow write */
512 if (!mac_socket_enforce) {
513 return 0;
514 }
515 #endif
516
517 if (sock_getaddr((socket_t)so, &sockaddr, 1) != 0) {
518 error = ECONNABORTED;
519 } else {
520 MAC_CHECK(socket_check_accepted, cred,
521 (socket_t)so, so->so_label, sockaddr);
522 sock_freeaddr(sockaddr);
523 }
524 return error;
525 }
526 #endif
527
528 int
529 mac_socket_check_bind(kauth_cred_t ucred, struct socket *so,
530 struct sockaddr *sockaddr)
531 {
532 int error;
533
534 #if SECURITY_MAC_CHECK_ENFORCE
535 /* 21167099 - only check if we allow write */
536 if (!mac_socket_enforce) {
537 return 0;
538 }
539 #endif
540
541 MAC_CHECK(socket_check_bind, ucred,
542 (socket_t)so, so->so_label, sockaddr);
543 return error;
544 }
545
546 int
547 mac_socket_check_connect(kauth_cred_t cred, struct socket *so,
548 struct sockaddr *sockaddr)
549 {
550 int error;
551
552 #if SECURITY_MAC_CHECK_ENFORCE
553 /* 21167099 - only check if we allow write */
554 if (!mac_socket_enforce) {
555 return 0;
556 }
557 #endif
558
559 MAC_CHECK(socket_check_connect, cred,
560 (socket_t)so, so->so_label,
561 sockaddr);
562 return error;
563 }
564
565 int
566 mac_socket_check_create(kauth_cred_t cred, int domain, int type, int protocol)
567 {
568 int error;
569
570 #if SECURITY_MAC_CHECK_ENFORCE
571 /* 21167099 - only check if we allow write */
572 if (!mac_socket_enforce) {
573 return 0;
574 }
575 #endif
576
577 MAC_CHECK(socket_check_create, cred, domain, type, protocol);
578 return error;
579 }
580
581 #if CONFIG_MACF_SOCKET && CONFIG_MACF_NET
582 int
583 mac_socket_check_deliver(struct socket *so, struct mbuf *mbuf)
584 {
585 struct label *label;
586 int error;
587
588 #if SECURITY_MAC_CHECK_ENFORCE
589 /* 21167099 - only check if we allow write */
590 if (!mac_socket_enforce) {
591 return 0;
592 }
593 #endif
594
595 label = mac_mbuf_to_label(mbuf);
596
597 /* Policy must deal with NULL label (unlabeled mbufs) */
598 MAC_CHECK(socket_check_deliver,
599 (socket_t)so, so->so_label, mbuf, label);
600 return error;
601 }
602 #else
603 int
604 mac_socket_check_deliver(__unused struct socket *so, __unused struct mbuf *mbuf)
605 {
606 return 0;
607 }
608 #endif
609
610 int
611 mac_socket_check_ioctl(kauth_cred_t cred, struct socket *so,
612 unsigned int cmd)
613 {
614 int error;
615
616 #if SECURITY_MAC_CHECK_ENFORCE
617 /* 21167099 - only check if we allow write */
618 if (!mac_socket_enforce) {
619 return 0;
620 }
621 #endif
622
623 MAC_CHECK(socket_check_ioctl, cred,
624 (socket_t)so, cmd, so->so_label);
625 return error;
626 }
627
628 int
629 mac_socket_check_stat(kauth_cred_t cred, struct socket *so)
630 {
631 int error;
632
633 #if SECURITY_MAC_CHECK_ENFORCE
634 /* 21167099 - only check if we allow write */
635 if (!mac_socket_enforce) {
636 return 0;
637 }
638 #endif
639
640 MAC_CHECK(socket_check_stat, cred,
641 (socket_t)so, so->so_label);
642 return error;
643 }
644
645 int
646 mac_socket_check_listen(kauth_cred_t cred, struct socket *so)
647 {
648 int error;
649
650 #if SECURITY_MAC_CHECK_ENFORCE
651 /* 21167099 - only check if we allow write */
652 if (!mac_socket_enforce) {
653 return 0;
654 }
655 #endif
656
657 MAC_CHECK(socket_check_listen, cred,
658 (socket_t)so, so->so_label);
659 return error;
660 }
661
662 int
663 mac_socket_check_receive(kauth_cred_t cred, struct socket *so)
664 {
665 int error;
666
667 #if SECURITY_MAC_CHECK_ENFORCE
668 /* 21167099 - only check if we allow write */
669 if (!mac_socket_enforce) {
670 return 0;
671 }
672 #endif
673
674 MAC_CHECK(socket_check_receive, cred,
675 (socket_t)so, so->so_label);
676 return error;
677 }
678
679 int
680 mac_socket_check_received(kauth_cred_t cred, struct socket *so, struct sockaddr *saddr)
681 {
682 int error;
683
684 #if SECURITY_MAC_CHECK_ENFORCE
685 /* 21167099 - only check if we allow write */
686 if (!mac_socket_enforce) {
687 return 0;
688 }
689 #endif
690
691 MAC_CHECK(socket_check_received, cred,
692 so, so->so_label, saddr);
693 return error;
694 }
695
696 int
697 mac_socket_check_send(kauth_cred_t cred, struct socket *so,
698 struct sockaddr *sockaddr)
699 {
700 int error;
701
702 #if SECURITY_MAC_CHECK_ENFORCE
703 /* 21167099 - only check if we allow write */
704 if (!mac_socket_enforce) {
705 return 0;
706 }
707 #endif
708
709 MAC_CHECK(socket_check_send, cred,
710 (socket_t)so, so->so_label, sockaddr);
711 return error;
712 }
713
714 int
715 mac_socket_check_setsockopt(kauth_cred_t cred, struct socket *so,
716 struct sockopt *sopt)
717 {
718 int error;
719
720 #if SECURITY_MAC_CHECK_ENFORCE
721 /* 21167099 - only check if we allow write */
722 if (!mac_socket_enforce) {
723 return 0;
724 }
725 #endif
726
727 MAC_CHECK(socket_check_setsockopt, cred,
728 (socket_t)so, so->so_label, sopt);
729 return error;
730 }
731
732 int
733 mac_socket_check_getsockopt(kauth_cred_t cred, struct socket *so,
734 struct sockopt *sopt)
735 {
736 int error;
737
738 #if SECURITY_MAC_CHECK_ENFORCE
739 /* 21167099 - only check if we allow write */
740 if (!mac_socket_enforce) {
741 return 0;
742 }
743 #endif
744
745 MAC_CHECK(socket_check_getsockopt, cred,
746 (socket_t)so, so->so_label, sopt);
747 return error;
748 }