1126262Srwatson/*- 2189503Srwatson * Copyright (c) 1999-2002, 2007, 2009 Robert N. M. Watson 3126262Srwatson * Copyright (c) 2001 Ilmar S. Habibulin 4126262Srwatson * Copyright (c) 2001-2004 Networks Associates Technology, Inc. 5172930Srwatson * Copyright (c) 2006 SPARTA, Inc. 6182063Srwatson * Copyright (c) 2008 Apple Inc. 7126262Srwatson * All rights reserved. 8126262Srwatson * 9126262Srwatson * This software was developed by Robert Watson and Ilmar Habibulin for the 10126262Srwatson * TrustedBSD Project. 11126262Srwatson * 12126262Srwatson * This software was developed for the FreeBSD Project in part by Network 13126262Srwatson * Associates Laboratories, the Security Research Division of Network 14126262Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 15126262Srwatson * as part of the DARPA CHATS research program. 16126262Srwatson * 17172930Srwatson * This software was enhanced by SPARTA ISSO under SPAWAR contract 18172930Srwatson * N66001-04-C-6019 ("SEFOS"). 19172930Srwatson * 20189503Srwatson * This software was developed at the University of Cambridge Computer 21189503Srwatson * Laboratory with support from a grant from Google, Inc. 22189503Srwatson * 23126262Srwatson * Redistribution and use in source and binary forms, with or without 24126262Srwatson * modification, are permitted provided that the following conditions 25126262Srwatson * are met: 26126262Srwatson * 1. Redistributions of source code must retain the above copyright 27126262Srwatson * notice, this list of conditions and the following disclaimer. 28126262Srwatson * 2. Redistributions in binary form must reproduce the above copyright 29126262Srwatson * notice, this list of conditions and the following disclaimer in the 30126262Srwatson * documentation and/or other materials provided with the distribution. 31126262Srwatson * 32126262Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 33126262Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34126262Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35126262Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 36126262Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37126262Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38126262Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39126262Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40126262Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41126262Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42126262Srwatson * SUCH DAMAGE. 43126262Srwatson */ 44126262Srwatson 45126262Srwatson#include <sys/cdefs.h> 46126262Srwatson__FBSDID("$FreeBSD$"); 47126262Srwatson 48189503Srwatson#include "opt_kdtrace.h" 49126262Srwatson#include "opt_mac.h" 50126262Srwatson 51126262Srwatson#include <sys/param.h> 52126262Srwatson#include <sys/kernel.h> 53126262Srwatson#include <sys/lock.h> 54126262Srwatson#include <sys/malloc.h> 55126262Srwatson#include <sys/mutex.h> 56126262Srwatson#include <sys/sbuf.h> 57189503Srwatson#include <sys/sdt.h> 58126262Srwatson#include <sys/systm.h> 59126262Srwatson#include <sys/mount.h> 60126262Srwatson#include <sys/file.h> 61126262Srwatson#include <sys/namei.h> 62126262Srwatson#include <sys/protosw.h> 63126262Srwatson#include <sys/socket.h> 64126262Srwatson#include <sys/socketvar.h> 65126262Srwatson#include <sys/sysctl.h> 66126262Srwatson 67126262Srwatson#include <net/if.h> 68126262Srwatson#include <net/if_var.h> 69126262Srwatson 70126262Srwatson#include <netinet/in.h> 71126262Srwatson#include <netinet/in_pcb.h> 72126262Srwatson#include <netinet/ip_var.h> 73126262Srwatson 74163606Srwatson#include <security/mac/mac_framework.h> 75126262Srwatson#include <security/mac/mac_internal.h> 76165469Srwatson#include <security/mac/mac_policy.h> 77126262Srwatson 78126262Srwatsonstatic struct label * 79126262Srwatsonmac_inpcb_label_alloc(int flag) 80126262Srwatson{ 81126262Srwatson struct label *label; 82126262Srwatson int error; 83126262Srwatson 84126262Srwatson label = mac_labelzone_alloc(flag); 85126262Srwatson if (label == NULL) 86126262Srwatson return (NULL); 87189797Srwatson if (flag & M_WAITOK) 88191731Srwatson MAC_POLICY_CHECK(inpcb_init_label, label, flag); 89189797Srwatson else 90191731Srwatson MAC_POLICY_CHECK_NOSLEEP(inpcb_init_label, label, flag); 91126262Srwatson if (error) { 92191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(inpcb_destroy_label, label); 93126262Srwatson mac_labelzone_free(label); 94126262Srwatson return (NULL); 95126262Srwatson } 96126262Srwatson return (label); 97126262Srwatson} 98126262Srwatson 99126262Srwatsonint 100172930Srwatsonmac_inpcb_init(struct inpcb *inp, int flag) 101126262Srwatson{ 102126262Srwatson 103182063Srwatson if (mac_labeled & MPC_OBJECT_INPCB) { 104182063Srwatson inp->inp_label = mac_inpcb_label_alloc(flag); 105182063Srwatson if (inp->inp_label == NULL) 106182063Srwatson return (ENOMEM); 107182063Srwatson } else 108182063Srwatson inp->inp_label = NULL; 109126262Srwatson return (0); 110126262Srwatson} 111126262Srwatson 112126262Srwatsonstatic struct label * 113126262Srwatsonmac_ipq_label_alloc(int flag) 114126262Srwatson{ 115126262Srwatson struct label *label; 116126262Srwatson int error; 117126262Srwatson 118126262Srwatson label = mac_labelzone_alloc(flag); 119126262Srwatson if (label == NULL) 120126262Srwatson return (NULL); 121126262Srwatson 122189797Srwatson if (flag & M_WAITOK) 123191731Srwatson MAC_POLICY_CHECK(ipq_init_label, label, flag); 124189797Srwatson else 125191731Srwatson MAC_POLICY_CHECK_NOSLEEP(ipq_init_label, label, flag); 126126262Srwatson if (error) { 127191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(ipq_destroy_label, label); 128126262Srwatson mac_labelzone_free(label); 129126262Srwatson return (NULL); 130126262Srwatson } 131126262Srwatson return (label); 132126262Srwatson} 133126262Srwatson 134126262Srwatsonint 135179781Srwatsonmac_ipq_init(struct ipq *q, int flag) 136126262Srwatson{ 137126262Srwatson 138182063Srwatson if (mac_labeled & MPC_OBJECT_IPQ) { 139182063Srwatson q->ipq_label = mac_ipq_label_alloc(flag); 140182063Srwatson if (q->ipq_label == NULL) 141182063Srwatson return (ENOMEM); 142182063Srwatson } else 143182063Srwatson q->ipq_label = NULL; 144126262Srwatson return (0); 145126262Srwatson} 146126262Srwatson 147126262Srwatsonstatic void 148126262Srwatsonmac_inpcb_label_free(struct label *label) 149126262Srwatson{ 150126262Srwatson 151191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(inpcb_destroy_label, label); 152126262Srwatson mac_labelzone_free(label); 153126262Srwatson} 154126262Srwatson 155126262Srwatsonvoid 156172930Srwatsonmac_inpcb_destroy(struct inpcb *inp) 157126262Srwatson{ 158126262Srwatson 159182063Srwatson if (inp->inp_label != NULL) { 160182063Srwatson mac_inpcb_label_free(inp->inp_label); 161182063Srwatson inp->inp_label = NULL; 162182063Srwatson } 163126262Srwatson} 164126262Srwatson 165126262Srwatsonstatic void 166126262Srwatsonmac_ipq_label_free(struct label *label) 167126262Srwatson{ 168126262Srwatson 169191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(ipq_destroy_label, label); 170126262Srwatson mac_labelzone_free(label); 171126262Srwatson} 172126262Srwatson 173126262Srwatsonvoid 174179781Srwatsonmac_ipq_destroy(struct ipq *q) 175126262Srwatson{ 176126262Srwatson 177182063Srwatson if (q->ipq_label != NULL) { 178182063Srwatson mac_ipq_label_free(q->ipq_label); 179182063Srwatson q->ipq_label = NULL; 180182063Srwatson } 181126262Srwatson} 182126262Srwatson 183126262Srwatsonvoid 184172930Srwatsonmac_inpcb_create(struct socket *so, struct inpcb *inp) 185126262Srwatson{ 186126262Srwatson 187191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(inpcb_create, so, so->so_label, inp, 188189797Srwatson inp->inp_label); 189126262Srwatson} 190126262Srwatson 191126262Srwatsonvoid 192179781Srwatsonmac_ipq_reassemble(struct ipq *q, struct mbuf *m) 193126262Srwatson{ 194126262Srwatson struct label *label; 195126262Srwatson 196193391Srwatson if (mac_policy_count == 0) 197193391Srwatson return; 198193391Srwatson 199168955Srwatson label = mac_mbuf_to_label(m); 200126262Srwatson 201191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(ipq_reassemble, q, q->ipq_label, m, 202191731Srwatson label); 203126262Srwatson} 204126262Srwatson 205126262Srwatsonvoid 206172930Srwatsonmac_netinet_fragment(struct mbuf *m, struct mbuf *frag) 207126262Srwatson{ 208168955Srwatson struct label *mlabel, *fraglabel; 209126262Srwatson 210193391Srwatson if (mac_policy_count == 0) 211193391Srwatson return; 212193391Srwatson 213168955Srwatson mlabel = mac_mbuf_to_label(m); 214168955Srwatson fraglabel = mac_mbuf_to_label(frag); 215126262Srwatson 216191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(netinet_fragment, m, mlabel, frag, 217191731Srwatson fraglabel); 218126262Srwatson} 219126262Srwatson 220126262Srwatsonvoid 221179781Srwatsonmac_ipq_create(struct mbuf *m, struct ipq *q) 222126262Srwatson{ 223126262Srwatson struct label *label; 224126262Srwatson 225193391Srwatson if (mac_policy_count == 0) 226193391Srwatson return; 227193391Srwatson 228168955Srwatson label = mac_mbuf_to_label(m); 229126262Srwatson 230191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(ipq_create, m, label, q, q->ipq_label); 231126262Srwatson} 232126262Srwatson 233126262Srwatsonvoid 234172930Srwatsonmac_inpcb_create_mbuf(struct inpcb *inp, struct mbuf *m) 235126262Srwatson{ 236126262Srwatson struct label *mlabel; 237126262Srwatson 238178321Srwatson INP_LOCK_ASSERT(inp); 239193391Srwatson 240193391Srwatson if (mac_policy_count == 0) 241193391Srwatson return; 242193391Srwatson 243126262Srwatson mlabel = mac_mbuf_to_label(m); 244126262Srwatson 245191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(inpcb_create_mbuf, inp, inp->inp_label, m, 246189797Srwatson mlabel); 247126262Srwatson} 248126262Srwatson 249126262Srwatsonint 250179781Srwatsonmac_ipq_match(struct mbuf *m, struct ipq *q) 251126262Srwatson{ 252126262Srwatson struct label *label; 253126262Srwatson int result; 254126262Srwatson 255193391Srwatson if (mac_policy_count == 0) 256193391Srwatson return (1); 257193391Srwatson 258168955Srwatson label = mac_mbuf_to_label(m); 259126262Srwatson 260126262Srwatson result = 1; 261191731Srwatson MAC_POLICY_BOOLEAN_NOSLEEP(ipq_match, &&, m, label, q, q->ipq_label); 262126262Srwatson 263126262Srwatson return (result); 264126262Srwatson} 265126262Srwatson 266126262Srwatsonvoid 267173095Srwatsonmac_netinet_arp_send(struct ifnet *ifp, struct mbuf *m) 268173095Srwatson{ 269173095Srwatson struct label *mlabel; 270173095Srwatson 271193391Srwatson if (mac_policy_count == 0) 272193391Srwatson return; 273193391Srwatson 274173095Srwatson mlabel = mac_mbuf_to_label(m); 275173095Srwatson 276173095Srwatson MAC_IFNET_LOCK(ifp); 277191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(netinet_arp_send, ifp, ifp->if_label, m, 278191731Srwatson mlabel); 279173095Srwatson MAC_IFNET_UNLOCK(ifp); 280173095Srwatson} 281173095Srwatson 282173095Srwatsonvoid 283173102Srwatsonmac_netinet_icmp_reply(struct mbuf *mrecv, struct mbuf *msend) 284126262Srwatson{ 285173102Srwatson struct label *mrecvlabel, *msendlabel; 286173102Srwatson 287193391Srwatson if (mac_policy_count == 0) 288193391Srwatson return; 289193391Srwatson 290173102Srwatson mrecvlabel = mac_mbuf_to_label(mrecv); 291173102Srwatson msendlabel = mac_mbuf_to_label(msend); 292173102Srwatson 293191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(netinet_icmp_reply, mrecv, mrecvlabel, 294191731Srwatson msend, msendlabel); 295173102Srwatson} 296173102Srwatson 297173102Srwatsonvoid 298173102Srwatsonmac_netinet_icmp_replyinplace(struct mbuf *m) 299173102Srwatson{ 300126262Srwatson struct label *label; 301126262Srwatson 302193391Srwatson if (mac_policy_count == 0) 303193391Srwatson return; 304193391Srwatson 305126262Srwatson label = mac_mbuf_to_label(m); 306126262Srwatson 307191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(netinet_icmp_replyinplace, m, label); 308126262Srwatson} 309168955Srwatson 310126262Srwatsonvoid 311173095Srwatsonmac_netinet_igmp_send(struct ifnet *ifp, struct mbuf *m) 312173095Srwatson{ 313173095Srwatson struct label *mlabel; 314173095Srwatson 315193391Srwatson if (mac_policy_count == 0) 316193391Srwatson return; 317193391Srwatson 318173095Srwatson mlabel = mac_mbuf_to_label(m); 319173095Srwatson 320173095Srwatson MAC_IFNET_LOCK(ifp); 321191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(netinet_igmp_send, ifp, ifp->if_label, m, 322189797Srwatson mlabel); 323173095Srwatson MAC_IFNET_UNLOCK(ifp); 324173095Srwatson} 325173095Srwatson 326173095Srwatsonvoid 327172930Srwatsonmac_netinet_tcp_reply(struct mbuf *m) 328126262Srwatson{ 329126262Srwatson struct label *label; 330126262Srwatson 331193391Srwatson if (mac_policy_count == 0) 332193391Srwatson return; 333193391Srwatson 334126262Srwatson label = mac_mbuf_to_label(m); 335126262Srwatson 336191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(netinet_tcp_reply, m, label); 337126262Srwatson} 338126262Srwatson 339126262Srwatsonvoid 340179781Srwatsonmac_ipq_update(struct mbuf *m, struct ipq *q) 341126262Srwatson{ 342126262Srwatson struct label *label; 343126262Srwatson 344193391Srwatson if (mac_policy_count == 0) 345193391Srwatson return; 346193391Srwatson 347168955Srwatson label = mac_mbuf_to_label(m); 348126262Srwatson 349191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(ipq_update, m, label, q, q->ipq_label); 350126262Srwatson} 351126262Srwatson 352189503SrwatsonMAC_CHECK_PROBE_DEFINE2(inpcb_check_deliver, "struct inpcb *", 353189503Srwatson "struct mbuf *"); 354189503Srwatson 355126262Srwatsonint 356172930Srwatsonmac_inpcb_check_deliver(struct inpcb *inp, struct mbuf *m) 357126262Srwatson{ 358126262Srwatson struct label *label; 359126262Srwatson int error; 360126262Srwatson 361126262Srwatson M_ASSERTPKTHDR(m); 362126262Srwatson 363193391Srwatson if (mac_policy_count == 0) 364193391Srwatson return (0); 365193391Srwatson 366126262Srwatson label = mac_mbuf_to_label(m); 367126262Srwatson 368191731Srwatson MAC_POLICY_CHECK_NOSLEEP(inpcb_check_deliver, inp, inp->inp_label, m, 369189797Srwatson label); 370189503Srwatson MAC_CHECK_PROBE2(inpcb_check_deliver, error, inp, m); 371126262Srwatson 372126262Srwatson return (error); 373126262Srwatson} 374126262Srwatson 375189503SrwatsonMAC_CHECK_PROBE_DEFINE2(inpcb_check_visible, "struct ucred *", 376189503Srwatson "struct inpcb *"); 377189503Srwatson 378183973Sbzint 379183973Sbzmac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp) 380183973Sbz{ 381183973Sbz int error; 382183973Sbz 383183973Sbz INP_LOCK_ASSERT(inp); 384183973Sbz 385191731Srwatson MAC_POLICY_CHECK_NOSLEEP(inpcb_check_visible, cred, inp, 386191731Srwatson inp->inp_label); 387189503Srwatson MAC_CHECK_PROBE2(inpcb_check_visible, error, cred, inp); 388183973Sbz 389183973Sbz return (error); 390183973Sbz} 391183973Sbz 392126262Srwatsonvoid 393126262Srwatsonmac_inpcb_sosetlabel(struct socket *so, struct inpcb *inp) 394126262Srwatson{ 395126262Srwatson 396178285Srwatson INP_WLOCK_ASSERT(inp); 397165599Srwatson SOCK_LOCK_ASSERT(so); 398189797Srwatson 399191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(inpcb_sosetlabel, so, so->so_label, inp, 400189797Srwatson inp->inp_label); 401126262Srwatson} 402162238Scsjp 403162238Scsjpvoid 404173102Srwatsonmac_netinet_firewall_reply(struct mbuf *mrecv, struct mbuf *msend) 405173102Srwatson{ 406173102Srwatson struct label *mrecvlabel, *msendlabel; 407173102Srwatson 408173102Srwatson M_ASSERTPKTHDR(mrecv); 409173102Srwatson M_ASSERTPKTHDR(msend); 410173102Srwatson 411193391Srwatson if (mac_policy_count == 0) 412193391Srwatson return; 413193391Srwatson 414173102Srwatson mrecvlabel = mac_mbuf_to_label(mrecv); 415173102Srwatson msendlabel = mac_mbuf_to_label(msend); 416173102Srwatson 417191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(netinet_firewall_reply, mrecv, mrecvlabel, 418191731Srwatson msend, msendlabel); 419173102Srwatson} 420173102Srwatson 421173102Srwatsonvoid 422173018Srwatsonmac_netinet_firewall_send(struct mbuf *m) 423162238Scsjp{ 424162238Scsjp struct label *label; 425162238Scsjp 426162238Scsjp M_ASSERTPKTHDR(m); 427189797Srwatson 428193391Srwatson if (mac_policy_count == 0) 429193391Srwatson return; 430193391Srwatson 431162238Scsjp label = mac_mbuf_to_label(m); 432189797Srwatson 433191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(netinet_firewall_send, m, label); 434162238Scsjp} 435165149Scsjp 436165149Scsjp/* 437165420Srwatson * These functions really should be referencing the syncache structure 438165420Srwatson * instead of the label. However, due to some of the complexities associated 439165420Srwatson * with exposing this syncache structure we operate directly on it's label 440165420Srwatson * pointer. This should be OK since we aren't making any access control 441165420Srwatson * decisions within this code directly, we are merely allocating and copying 442165420Srwatson * label storage so we can properly initialize mbuf labels for any packets 443165420Srwatson * the syncache code might create. 444165149Scsjp */ 445165149Scsjpvoid 446172970Srwatsonmac_syncache_destroy(struct label **label) 447165149Scsjp{ 448165149Scsjp 449182063Srwatson if (*label != NULL) { 450191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(syncache_destroy_label, *label); 451182063Srwatson mac_labelzone_free(*label); 452182063Srwatson *label = NULL; 453182063Srwatson } 454165149Scsjp} 455165149Scsjp 456165149Scsjpint 457172970Srwatsonmac_syncache_init(struct label **label) 458165149Scsjp{ 459165149Scsjp int error; 460165149Scsjp 461182063Srwatson if (mac_labeled & MPC_OBJECT_SYNCACHE) { 462182063Srwatson *label = mac_labelzone_alloc(M_NOWAIT); 463182063Srwatson if (*label == NULL) 464182063Srwatson return (ENOMEM); 465182063Srwatson /* 466182063Srwatson * Since we are holding the inpcb locks the policy can not 467182063Srwatson * allocate policy specific label storage using M_WAITOK. So 468182063Srwatson * we need to do a MAC_CHECK instead of the typical 469182063Srwatson * MAC_PERFORM so we can propagate allocation failures back 470182063Srwatson * to the syncache code. 471182063Srwatson */ 472191731Srwatson MAC_POLICY_CHECK_NOSLEEP(syncache_init_label, *label, 473191731Srwatson M_NOWAIT); 474182063Srwatson if (error) { 475191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(syncache_destroy_label, 476191731Srwatson *label); 477182063Srwatson mac_labelzone_free(*label); 478182063Srwatson } 479182063Srwatson return (error); 480182063Srwatson } else 481182063Srwatson *label = NULL; 482182063Srwatson return (0); 483165149Scsjp} 484165149Scsjp 485165149Scsjpvoid 486172970Srwatsonmac_syncache_create(struct label *label, struct inpcb *inp) 487165149Scsjp{ 488165149Scsjp 489178285Srwatson INP_WLOCK_ASSERT(inp); 490189797Srwatson 491191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(syncache_create, label, inp); 492165149Scsjp} 493165149Scsjp 494165149Scsjpvoid 495172970Srwatsonmac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m) 496165149Scsjp{ 497168955Srwatson struct label *mlabel; 498165149Scsjp 499165149Scsjp M_ASSERTPKTHDR(m); 500189797Srwatson 501193391Srwatson if (mac_policy_count == 0) 502193391Srwatson return; 503193391Srwatson 504168955Srwatson mlabel = mac_mbuf_to_label(m); 505189797Srwatson 506191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(syncache_create_mbuf, sc_label, m, 507191731Srwatson mlabel); 508165149Scsjp} 509