1/* 2 * Copyright (c) 2007 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-2004 Networks Associates Technology, Inc. 32 * Copyright (c) 2006-2007 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 Network 39 * Associates Laboratories, the Security Research Division of Network 40 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 41 * as part of the 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/param.h> 69#include <sys/kernel.h> 70#include <sys/mbuf.h> 71#include <sys/socket.h> 72#include <sys/socketvar.h> 73 74#include <net/if.h> 75#include <net/if_var.h> 76#include <net/route.h> 77 78#include <netinet/in.h> 79#include <netinet/in_pcb.h> 80#include <netinet/ip_var.h> 81 82#include <security/mac_internal.h> 83 84static struct label * 85mac_inpcb_label_alloc(int flag) 86{ 87 struct label *label; 88 int error; 89 90 label = mac_labelzone_alloc(flag); 91 if (label == NULL) 92 return (NULL); 93 MAC_CHECK(inpcb_label_init, label, flag); 94 if (error) { 95 MAC_PERFORM(inpcb_label_destroy, label); 96 mac_labelzone_free(label); 97 return (NULL); 98 } 99 return (label); 100} 101 102int 103mac_inpcb_label_init(struct inpcb *inp, int flag) 104{ 105 106 inp->inp_label = mac_inpcb_label_alloc(flag); 107 if (inp->inp_label == NULL) 108 return (ENOMEM); 109 return (0); 110} 111 112static struct label * 113mac_ipq_label_alloc(int flag) 114{ 115 struct label *label; 116 int error; 117 118 label = mac_labelzone_alloc(flag); 119 if (label == NULL) 120 return (NULL); 121 122 MAC_CHECK(ipq_label_init, label, flag); 123 if (error) { 124 MAC_PERFORM(ipq_label_destroy, label); 125 mac_labelzone_free(label); 126 return (NULL); 127 } 128 return (label); 129} 130 131int 132mac_ipq_label_init(struct ipq *ipq, int flag) 133{ 134 135 ipq->ipq_label = mac_ipq_label_alloc(flag); 136 if (ipq->ipq_label == NULL) 137 return (ENOMEM); 138 return (0); 139} 140 141static void 142mac_inpcb_label_free(struct label *label) 143{ 144 145 MAC_PERFORM(inpcb_label_destroy, label); 146 mac_labelzone_free(label); 147} 148 149void 150mac_inpcb_label_destroy(struct inpcb *inp) 151{ 152 153 mac_inpcb_label_free(inp->inp_label); 154 inp->inp_label = NULL; 155} 156 157void 158mac_inpcb_label_recycle(struct inpcb *inp) 159{ 160 161 MAC_PERFORM(inpcb_label_recycle, inp->inp_label); 162} 163 164static void 165mac_ipq_label_free(struct label *label) 166{ 167 168 MAC_PERFORM(ipq_label_destroy, label); 169 mac_labelzone_free(label); 170} 171 172void 173mac_ipq_label_destroy(struct ipq *ipq) 174{ 175 176 mac_ipq_label_free(ipq->ipq_label); 177 ipq->ipq_label = NULL; 178} 179 180void 181mac_inpcb_label_associate(struct socket *so, struct inpcb *inp) 182{ 183 184 MAC_PERFORM(inpcb_label_associate, so, so->so_label, inp, 185 inp->inp_label); 186} 187 188void 189mac_mbuf_label_associate_ipq(struct ipq *ipq, struct mbuf *m) 190{ 191 struct label *label; 192 193 label = mac_mbuf_to_label(m); 194 195 MAC_PERFORM(mbuf_label_associate_ipq, ipq, ipq->ipq_label, m, label); 196} 197 198void 199mac_netinet_fragment(struct mbuf *datagram, struct mbuf *fragment) 200{ 201 struct label *datagramlabel, *fragmentlabel; 202 203 datagramlabel = mac_mbuf_to_label(datagram); 204 fragmentlabel = mac_mbuf_to_label(fragment); 205 206 MAC_PERFORM(netinet_fragment, datagram, datagramlabel, fragment, 207 fragmentlabel); 208} 209 210void 211mac_ipq_label_associate(struct mbuf *fragment, struct ipq *ipq) 212{ 213 struct label *label; 214 215 label = mac_mbuf_to_label(fragment); 216 217 MAC_PERFORM(ipq_label_associate, fragment, label, ipq, ipq->ipq_label); 218} 219 220void 221mac_mbuf_label_associate_inpcb(struct inpcb *inp, struct mbuf *m) 222{ 223 struct label *mlabel; 224 225 /* INP_LOCK_ASSERT(inp); */ 226 mlabel = mac_mbuf_to_label(m); 227 228 MAC_PERFORM(mbuf_label_associate_inpcb, inp, inp->inp_label, m, mlabel); 229} 230 231int 232mac_ipq_label_compare(struct mbuf *fragment, struct ipq *ipq) 233{ 234 struct label *label; 235 int result; 236 237 label = mac_mbuf_to_label(fragment); 238 239 result = 1; 240 MAC_BOOLEAN(ipq_label_compare, &&, fragment, label, ipq, ipq->ipq_label); 241 242 return (result); 243} 244 245void 246mac_netinet_icmp_reply(struct mbuf *m) 247{ 248 struct label *label; 249 250 label = mac_mbuf_to_label(m); 251 252 MAC_PERFORM(netinet_icmp_reply, m, label); 253} 254 255void 256mac_netinet_tcp_reply(struct mbuf *m) 257{ 258 struct label *label; 259 260 label = mac_mbuf_to_label(m); 261 262 MAC_PERFORM(netinet_tcp_reply, m, label); 263} 264 265void 266mac_ipq_label_update(struct mbuf *fragment, struct ipq *ipq) 267{ 268 struct label *label; 269 270 label = mac_mbuf_to_label(fragment); 271 272 MAC_PERFORM(ipq_label_update, fragment, label, ipq, ipq->ipq_label); 273} 274 275int 276mac_inpcb_check_deliver(struct inpcb *inp, struct mbuf *m, int family, int type) 277{ 278 struct label *label; 279 int error; 280 281 if ((m->m_flags & M_PKTHDR) == 0) 282 panic("%s: no mbuf packet header!", __func__); 283 284 label = mac_mbuf_to_label(m); 285 286 MAC_CHECK(inpcb_check_deliver, inp, inp->inp_label, m, label, 287 family, type); 288 289 return (error); 290} 291 292/* 293 * Propagate a change in the socket label to the inpcb label. 294 */ 295void 296mac_inpcb_label_update(struct socket *so) 297{ 298 struct inpcb *inp; 299 300 /* XXX: assert socket lock. */ 301 inp = sotoinpcb(so); /* XXX: inp locking */ 302 303 if (inp != NULL) { 304 /* INP_LOCK_ASSERT(inp); */ 305 MAC_PERFORM(inpcb_label_update, so, so->so_label, inp, 306 inp->inp_label); 307 } 308} 309