1126262Srwatson/*- 2189503Srwatson * Copyright (c) 1999-2002, 2009 Robert N. M. Watson 3126262Srwatson * Copyright (c) 2001 Ilmar S. Habibulin 4145167Srwatson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 5172930Srwatson * Copyright (c) 2005-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 * 12145167Srwatson * This software was developed for the FreeBSD Project in part by McAfee 13145167Srwatson * Research, the Technology Research Division of Network Associates, Inc. 14145167Srwatson * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 15145167Srwatson * DARPA CHATS research program. 16165426Srwatson * 17147784Srwatson * This software was enhanced by SPARTA ISSO under SPAWAR contract 18147784Srwatson * N66001-04-C-6019 ("SEFOS"). 19126262Srwatson * 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/mac.h> 57126262Srwatson#include <sys/sbuf.h> 58189503Srwatson#include <sys/sdt.h> 59126262Srwatson#include <sys/systm.h> 60126262Srwatson#include <sys/mount.h> 61126262Srwatson#include <sys/file.h> 62126262Srwatson#include <sys/namei.h> 63126262Srwatson#include <sys/protosw.h> 64126262Srwatson#include <sys/socket.h> 65126262Srwatson#include <sys/socketvar.h> 66126262Srwatson#include <sys/sysctl.h> 67126262Srwatson 68126262Srwatson#include <net/bpfdesc.h> 69126262Srwatson#include <net/if.h> 70126262Srwatson#include <net/if_var.h> 71126262Srwatson 72126262Srwatson#include <netinet/in.h> 73126262Srwatson#include <netinet/in_pcb.h> 74126262Srwatson#include <netinet/ip_var.h> 75126262Srwatson 76163606Srwatson#include <security/mac/mac_framework.h> 77126262Srwatson#include <security/mac/mac_internal.h> 78165469Srwatson#include <security/mac/mac_policy.h> 79126262Srwatson 80126262Srwatson/* 81165426Srwatson * Currently, sockets hold two labels: the label of the socket itself, and a 82165426Srwatson * peer label, which may be used by policies to hold a copy of the label of 83165426Srwatson * any remote endpoint. 84165426Srwatson * 85165426Srwatson * Possibly, this peer label should be maintained at the protocol layer 86165426Srwatson * (inpcb, unpcb, etc), as this would allow protocol-aware code to maintain 87165426Srwatson * the label consistently. For example, it might be copied live from a 88165426Srwatson * remote socket for UNIX domain sockets rather than keeping a local copy on 89165426Srwatson * this endpoint, but be cached and updated based on packets received for 90165426Srwatson * TCP/IP. 91193391Srwatson * 92193391Srwatson * Unlike with many other object types, the lock protecting MAC labels on 93193391Srwatson * sockets (the socket lock) is not frequently held at the points in code 94193391Srwatson * where socket-related checks are called. The MAC Framework acquires the 95193391Srwatson * lock over some entry points in order to enforce atomicity (such as label 96193391Srwatson * copies) but in other cases the policy modules will have to acquire the 97193391Srwatson * lock themselves if they use labels. This approach (a) avoids lock 98193391Srwatson * acquisitions when policies don't require labels and (b) solves a number of 99193391Srwatson * potential lock order issues when multiple sockets are used in the same 100193391Srwatson * entry point. 101165426Srwatson */ 102165426Srwatson 103126262Srwatsonstruct label * 104126262Srwatsonmac_socket_label_alloc(int flag) 105126262Srwatson{ 106126262Srwatson struct label *label; 107126262Srwatson int error; 108126262Srwatson 109126262Srwatson label = mac_labelzone_alloc(flag); 110126262Srwatson if (label == NULL) 111126262Srwatson return (NULL); 112126262Srwatson 113189797Srwatson if (flag & M_WAITOK) 114191731Srwatson MAC_POLICY_CHECK(socket_init_label, label, flag); 115189797Srwatson else 116191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_init_label, label, flag); 117126262Srwatson if (error) { 118191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socket_destroy_label, label); 119126262Srwatson mac_labelzone_free(label); 120126262Srwatson return (NULL); 121126262Srwatson } 122126262Srwatson return (label); 123126262Srwatson} 124126262Srwatson 125126262Srwatsonstatic struct label * 126172930Srwatsonmac_socketpeer_label_alloc(int flag) 127126262Srwatson{ 128126262Srwatson struct label *label; 129126262Srwatson int error; 130126262Srwatson 131126262Srwatson label = mac_labelzone_alloc(flag); 132126262Srwatson if (label == NULL) 133126262Srwatson return (NULL); 134126262Srwatson 135189797Srwatson if (flag & M_WAITOK) 136191731Srwatson MAC_POLICY_CHECK(socketpeer_init_label, label, flag); 137189797Srwatson else 138191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socketpeer_init_label, label, flag); 139126262Srwatson if (error) { 140191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socketpeer_destroy_label, label); 141126262Srwatson mac_labelzone_free(label); 142126262Srwatson return (NULL); 143126262Srwatson } 144126262Srwatson return (label); 145126262Srwatson} 146126262Srwatson 147126262Srwatsonint 148172930Srwatsonmac_socket_init(struct socket *so, int flag) 149126262Srwatson{ 150126262Srwatson 151182063Srwatson if (mac_labeled & MPC_OBJECT_SOCKET) { 152182063Srwatson so->so_label = mac_socket_label_alloc(flag); 153182063Srwatson if (so->so_label == NULL) 154182063Srwatson return (ENOMEM); 155182063Srwatson so->so_peerlabel = mac_socketpeer_label_alloc(flag); 156182063Srwatson if (so->so_peerlabel == NULL) { 157182063Srwatson mac_socket_label_free(so->so_label); 158182063Srwatson so->so_label = NULL; 159182063Srwatson return (ENOMEM); 160182063Srwatson } 161182063Srwatson } else { 162126262Srwatson so->so_label = NULL; 163182063Srwatson so->so_peerlabel = NULL; 164126262Srwatson } 165126262Srwatson return (0); 166126262Srwatson} 167126262Srwatson 168126262Srwatsonvoid 169126262Srwatsonmac_socket_label_free(struct label *label) 170126262Srwatson{ 171126262Srwatson 172191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socket_destroy_label, label); 173126262Srwatson mac_labelzone_free(label); 174126262Srwatson} 175126262Srwatson 176126262Srwatsonstatic void 177172930Srwatsonmac_socketpeer_label_free(struct label *label) 178126262Srwatson{ 179126262Srwatson 180191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socketpeer_destroy_label, label); 181126262Srwatson mac_labelzone_free(label); 182126262Srwatson} 183126262Srwatson 184126262Srwatsonvoid 185172930Srwatsonmac_socket_destroy(struct socket *so) 186126262Srwatson{ 187126262Srwatson 188182063Srwatson if (so->so_label != NULL) { 189182063Srwatson mac_socket_label_free(so->so_label); 190182063Srwatson so->so_label = NULL; 191182063Srwatson mac_socketpeer_label_free(so->so_peerlabel); 192182063Srwatson so->so_peerlabel = NULL; 193182063Srwatson } 194126262Srwatson} 195126262Srwatson 196126262Srwatsonvoid 197172930Srwatsonmac_socket_copy_label(struct label *src, struct label *dest) 198126262Srwatson{ 199126262Srwatson 200191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socket_copy_label, src, dest); 201126262Srwatson} 202126262Srwatson 203126262Srwatsonint 204172930Srwatsonmac_socket_externalize_label(struct label *label, char *elements, 205126262Srwatson char *outbuf, size_t outbuflen) 206126262Srwatson{ 207126262Srwatson int error; 208126262Srwatson 209191731Srwatson MAC_POLICY_EXTERNALIZE(socket, label, elements, outbuf, outbuflen); 210126262Srwatson 211126262Srwatson return (error); 212126262Srwatson} 213126262Srwatson 214126262Srwatsonstatic int 215172930Srwatsonmac_socketpeer_externalize_label(struct label *label, char *elements, 216126262Srwatson char *outbuf, size_t outbuflen) 217126262Srwatson{ 218126262Srwatson int error; 219126262Srwatson 220191731Srwatson MAC_POLICY_EXTERNALIZE(socketpeer, label, elements, outbuf, 221191731Srwatson outbuflen); 222126262Srwatson 223126262Srwatson return (error); 224126262Srwatson} 225126262Srwatson 226126262Srwatsonint 227172930Srwatsonmac_socket_internalize_label(struct label *label, char *string) 228126262Srwatson{ 229126262Srwatson int error; 230126262Srwatson 231191731Srwatson MAC_POLICY_INTERNALIZE(socket, label, string); 232126262Srwatson 233126262Srwatson return (error); 234126262Srwatson} 235126262Srwatson 236126262Srwatsonvoid 237172930Srwatsonmac_socket_create(struct ucred *cred, struct socket *so) 238126262Srwatson{ 239126262Srwatson 240191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socket_create, cred, so, so->so_label); 241126262Srwatson} 242126262Srwatson 243126262Srwatsonvoid 244172930Srwatsonmac_socket_newconn(struct socket *oldso, struct socket *newso) 245126262Srwatson{ 246126262Srwatson 247191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socket_newconn, oldso, oldso->so_label, 248191731Srwatson newso, newso->so_label); 249126262Srwatson} 250126262Srwatson 251126262Srwatsonstatic void 252172930Srwatsonmac_socket_relabel(struct ucred *cred, struct socket *so, 253126262Srwatson struct label *newlabel) 254126262Srwatson{ 255126262Srwatson 256168955Srwatson SOCK_LOCK_ASSERT(so); 257168955Srwatson 258191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socket_relabel, cred, so, so->so_label, 259189797Srwatson newlabel); 260126262Srwatson} 261126262Srwatson 262126262Srwatsonvoid 263172930Srwatsonmac_socketpeer_set_from_mbuf(struct mbuf *m, struct socket *so) 264126262Srwatson{ 265126262Srwatson struct label *label; 266126262Srwatson 267193391Srwatson if (mac_policy_count == 0) 268193391Srwatson return; 269193391Srwatson 270168955Srwatson label = mac_mbuf_to_label(m); 271126262Srwatson 272191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socketpeer_set_from_mbuf, m, label, so, 273168955Srwatson so->so_peerlabel); 274126262Srwatson} 275126262Srwatson 276126262Srwatsonvoid 277172930Srwatsonmac_socketpeer_set_from_socket(struct socket *oldso, struct socket *newso) 278126262Srwatson{ 279193332Srwatson 280193332Srwatson if (mac_policy_count == 0) 281193332Srwatson return; 282126262Srwatson 283191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socketpeer_set_from_socket, oldso, 284189797Srwatson oldso->so_label, newso, newso->so_peerlabel); 285126262Srwatson} 286126262Srwatson 287126262Srwatsonvoid 288172930Srwatsonmac_socket_create_mbuf(struct socket *so, struct mbuf *m) 289126262Srwatson{ 290126262Srwatson struct label *label; 291126262Srwatson 292193332Srwatson if (mac_policy_count == 0) 293193332Srwatson return; 294126262Srwatson 295168955Srwatson label = mac_mbuf_to_label(m); 296168955Srwatson 297191731Srwatson MAC_POLICY_PERFORM_NOSLEEP(socket_create_mbuf, so, so->so_label, m, 298191731Srwatson label); 299126262Srwatson} 300126262Srwatson 301189503SrwatsonMAC_CHECK_PROBE_DEFINE2(socket_check_accept, "struct ucred *", 302189503Srwatson "struct socket *"); 303189503Srwatson 304126262Srwatsonint 305172930Srwatsonmac_socket_check_accept(struct ucred *cred, struct socket *so) 306145167Srwatson{ 307145167Srwatson int error; 308145167Srwatson 309191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_accept, cred, so, 310191731Srwatson so->so_label); 311189503Srwatson MAC_CHECK_PROBE2(socket_check_accept, error, cred, so); 312145167Srwatson 313145167Srwatson return (error); 314145167Srwatson} 315145167Srwatson 316189503SrwatsonMAC_CHECK_PROBE_DEFINE3(socket_check_bind, "struct ucred *", 317189503Srwatson "struct socket *", "struct sockaddr *"); 318189503Srwatson 319145167Srwatsonint 320189532Srwatsonmac_socket_check_bind(struct ucred *cred, struct socket *so, 321168955Srwatson struct sockaddr *sa) 322126262Srwatson{ 323126262Srwatson int error; 324126262Srwatson 325191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_bind, cred, so, so->so_label, 326191731Srwatson sa); 327189532Srwatson MAC_CHECK_PROBE3(socket_check_bind, error, cred, so, sa); 328126262Srwatson 329126262Srwatson return (error); 330126262Srwatson} 331126262Srwatson 332189503SrwatsonMAC_CHECK_PROBE_DEFINE3(socket_check_connect, "struct ucred *", 333189503Srwatson "struct socket *", "struct sockaddr *"); 334189503Srwatson 335126262Srwatsonint 336172930Srwatsonmac_socket_check_connect(struct ucred *cred, struct socket *so, 337168955Srwatson struct sockaddr *sa) 338126262Srwatson{ 339126262Srwatson int error; 340126262Srwatson 341191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_connect, cred, so, 342191731Srwatson so->so_label, sa); 343189503Srwatson MAC_CHECK_PROBE3(socket_check_connect, error, cred, so, sa); 344126262Srwatson 345126262Srwatson return (error); 346126262Srwatson} 347126262Srwatson 348189503SrwatsonMAC_CHECK_PROBE_DEFINE4(socket_check_create, "struct ucred *", "int", "int", 349189503Srwatson "int"); 350189503Srwatson 351126262Srwatsonint 352172930Srwatsonmac_socket_check_create(struct ucred *cred, int domain, int type, int proto) 353147784Srwatson{ 354147784Srwatson int error; 355147784Srwatson 356191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_create, cred, domain, type, 357191731Srwatson proto); 358189503Srwatson MAC_CHECK_PROBE4(socket_check_create, error, cred, domain, type, 359189503Srwatson proto); 360147784Srwatson 361147784Srwatson return (error); 362147784Srwatson} 363147784Srwatson 364189503SrwatsonMAC_CHECK_PROBE_DEFINE2(socket_check_deliver, "struct socket *", 365189503Srwatson "struct mbuf *"); 366189503Srwatson 367147784Srwatsonint 368172930Srwatsonmac_socket_check_deliver(struct socket *so, struct mbuf *m) 369126262Srwatson{ 370126262Srwatson struct label *label; 371126262Srwatson int error; 372126262Srwatson 373193332Srwatson if (mac_policy_count == 0) 374193332Srwatson return (0); 375130398Srwatson 376168955Srwatson label = mac_mbuf_to_label(m); 377126262Srwatson 378191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_deliver, so, so->so_label, m, 379191731Srwatson label); 380189503Srwatson MAC_CHECK_PROBE2(socket_check_deliver, error, so, m); 381126262Srwatson 382126262Srwatson return (error); 383126262Srwatson} 384126262Srwatson 385189503SrwatsonMAC_CHECK_PROBE_DEFINE2(socket_check_listen, "struct ucred *", 386189503Srwatson "struct socket *"); 387189503Srwatson 388126262Srwatsonint 389172930Srwatsonmac_socket_check_listen(struct ucred *cred, struct socket *so) 390126262Srwatson{ 391126262Srwatson int error; 392126262Srwatson 393191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_listen, cred, so, 394191731Srwatson so->so_label); 395189503Srwatson MAC_CHECK_PROBE2(socket_check_listen, error, cred, so); 396168955Srwatson 397126262Srwatson return (error); 398126262Srwatson} 399126262Srwatson 400189503SrwatsonMAC_CHECK_PROBE_DEFINE2(socket_check_poll, "struct ucred *", 401189503Srwatson "struct socket *"); 402189503Srwatson 403126262Srwatsonint 404172930Srwatsonmac_socket_check_poll(struct ucred *cred, struct socket *so) 405145167Srwatson{ 406145167Srwatson int error; 407145167Srwatson 408191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_poll, cred, so, so->so_label); 409189503Srwatson MAC_CHECK_PROBE2(socket_check_poll, error, cred, so); 410168955Srwatson 411145167Srwatson return (error); 412145167Srwatson} 413145167Srwatson 414189503SrwatsonMAC_CHECK_PROBE_DEFINE2(socket_check_receive, "struct ucred *", 415189503Srwatson "struct socket *"); 416189503Srwatson 417145167Srwatsonint 418172930Srwatsonmac_socket_check_receive(struct ucred *cred, struct socket *so) 419126262Srwatson{ 420126262Srwatson int error; 421126262Srwatson 422191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_receive, cred, so, 423191731Srwatson so->so_label); 424189503Srwatson MAC_CHECK_PROBE2(socket_check_receive, error, cred, so); 425126262Srwatson 426126262Srwatson return (error); 427126262Srwatson} 428126262Srwatson 429189503SrwatsonMAC_CHECK_PROBE_DEFINE3(socket_check_relabel, "struct ucred *", 430189503Srwatson "struct socket *", "struct label *"); 431189503Srwatson 432126262Srwatsonstatic int 433172930Srwatsonmac_socket_check_relabel(struct ucred *cred, struct socket *so, 434126262Srwatson struct label *newlabel) 435126262Srwatson{ 436126262Srwatson int error; 437126262Srwatson 438168955Srwatson SOCK_LOCK_ASSERT(so); 439130398Srwatson 440191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_relabel, cred, so, 441191731Srwatson so->so_label, newlabel); 442189503Srwatson MAC_CHECK_PROBE3(socket_check_relabel, error, cred, so, newlabel); 443126262Srwatson 444126262Srwatson return (error); 445126262Srwatson} 446126262Srwatson 447189503SrwatsonMAC_CHECK_PROBE_DEFINE2(socket_check_send, "struct ucred *", 448189503Srwatson "struct socket *"); 449189503Srwatson 450126262Srwatsonint 451172930Srwatsonmac_socket_check_send(struct ucred *cred, struct socket *so) 452126262Srwatson{ 453126262Srwatson int error; 454126262Srwatson 455191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_send, cred, so, so->so_label); 456189503Srwatson MAC_CHECK_PROBE2(socket_check_send, error, cred, so); 457126262Srwatson 458126262Srwatson return (error); 459126262Srwatson} 460126262Srwatson 461189503SrwatsonMAC_CHECK_PROBE_DEFINE2(socket_check_stat, "struct ucred *", 462189503Srwatson "struct socket *"); 463189503Srwatson 464126262Srwatsonint 465172930Srwatsonmac_socket_check_stat(struct ucred *cred, struct socket *so) 466145167Srwatson{ 467145167Srwatson int error; 468145167Srwatson 469191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_stat, cred, so, so->so_label); 470189503Srwatson MAC_CHECK_PROBE2(socket_check_stat, error, cred, so); 471145167Srwatson 472145167Srwatson return (error); 473145167Srwatson} 474145167Srwatson 475189503SrwatsonMAC_CHECK_PROBE_DEFINE2(socket_check_visible, "struct ucred *", 476189503Srwatson "struct socket *"); 477189503Srwatson 478145167Srwatsonint 479172930Srwatsonmac_socket_check_visible(struct ucred *cred, struct socket *so) 480126262Srwatson{ 481126262Srwatson int error; 482126262Srwatson 483191731Srwatson MAC_POLICY_CHECK_NOSLEEP(socket_check_visible, cred, so, 484191731Srwatson so->so_label); 485189503Srwatson MAC_CHECK_PROBE2(socket_check_visible, error, cred, so); 486126262Srwatson 487126262Srwatson return (error); 488126262Srwatson} 489126262Srwatson 490126262Srwatsonint 491126262Srwatsonmac_socket_label_set(struct ucred *cred, struct socket *so, 492126262Srwatson struct label *label) 493126262Srwatson{ 494126262Srwatson int error; 495126262Srwatson 496130398Srwatson /* 497165426Srwatson * We acquire the socket lock when we perform the test and set, but 498165426Srwatson * have to release it as the pcb code needs to acquire the pcb lock, 499165426Srwatson * which will precede the socket lock in the lock order. However, 500165426Srwatson * this is fine, as any race will simply result in the inpcb being 501165426Srwatson * refreshed twice, but still consistently, as the inpcb code will 502165426Srwatson * acquire the socket lock before refreshing, holding both locks. 503130398Srwatson */ 504130398Srwatson SOCK_LOCK(so); 505172930Srwatson error = mac_socket_check_relabel(cred, so, label); 506130398Srwatson if (error) { 507130398Srwatson SOCK_UNLOCK(so); 508126262Srwatson return (error); 509130398Srwatson } 510126262Srwatson 511172930Srwatson mac_socket_relabel(cred, so, label); 512130398Srwatson SOCK_UNLOCK(so); 513165426Srwatson 514126262Srwatson /* 515126262Srwatson * If the protocol has expressed interest in socket layer changes, 516165426Srwatson * such as if it needs to propagate changes to a cached pcb label 517165426Srwatson * from the socket, notify it of the label change while holding the 518165426Srwatson * socket lock. 519126262Srwatson */ 520126262Srwatson if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL) 521126262Srwatson (so->so_proto->pr_usrreqs->pru_sosetlabel)(so); 522126262Srwatson 523126262Srwatson return (0); 524126262Srwatson} 525126262Srwatson 526126262Srwatsonint 527126262Srwatsonmac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 528126262Srwatson{ 529126262Srwatson struct label *intlabel; 530126262Srwatson char *buffer; 531126262Srwatson int error; 532126262Srwatson 533182063Srwatson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 534182063Srwatson return (EINVAL); 535182063Srwatson 536126262Srwatson error = mac_check_structmac_consistent(mac); 537126262Srwatson if (error) 538126262Srwatson return (error); 539126262Srwatson 540126262Srwatson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 541126262Srwatson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 542126262Srwatson if (error) { 543126262Srwatson free(buffer, M_MACTEMP); 544126262Srwatson return (error); 545126262Srwatson } 546126262Srwatson 547126262Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 548172930Srwatson error = mac_socket_internalize_label(intlabel, buffer); 549126262Srwatson free(buffer, M_MACTEMP); 550126262Srwatson if (error) 551126262Srwatson goto out; 552126262Srwatson 553126262Srwatson error = mac_socket_label_set(cred, so, intlabel); 554126262Srwatsonout: 555126262Srwatson mac_socket_label_free(intlabel); 556126262Srwatson return (error); 557126262Srwatson} 558126262Srwatson 559126262Srwatsonint 560126262Srwatsonmac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 561126262Srwatson{ 562126262Srwatson char *buffer, *elements; 563130398Srwatson struct label *intlabel; 564126262Srwatson int error; 565126262Srwatson 566182063Srwatson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 567182063Srwatson return (EINVAL); 568182063Srwatson 569126262Srwatson error = mac_check_structmac_consistent(mac); 570126262Srwatson if (error) 571126262Srwatson return (error); 572126262Srwatson 573126262Srwatson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 574126262Srwatson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 575126262Srwatson if (error) { 576126262Srwatson free(elements, M_MACTEMP); 577126262Srwatson return (error); 578126262Srwatson } 579126262Srwatson 580126262Srwatson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 581130398Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 582130398Srwatson SOCK_LOCK(so); 583172930Srwatson mac_socket_copy_label(so->so_label, intlabel); 584130398Srwatson SOCK_UNLOCK(so); 585172930Srwatson error = mac_socket_externalize_label(intlabel, elements, buffer, 586130398Srwatson mac->m_buflen); 587130398Srwatson mac_socket_label_free(intlabel); 588126262Srwatson if (error == 0) 589126262Srwatson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 590126262Srwatson 591126262Srwatson free(buffer, M_MACTEMP); 592126262Srwatson free(elements, M_MACTEMP); 593126262Srwatson 594126262Srwatson return (error); 595126262Srwatson} 596126262Srwatson 597126262Srwatsonint 598126262Srwatsonmac_getsockopt_peerlabel(struct ucred *cred, struct socket *so, 599126262Srwatson struct mac *mac) 600126262Srwatson{ 601126262Srwatson char *elements, *buffer; 602130398Srwatson struct label *intlabel; 603126262Srwatson int error; 604126262Srwatson 605182063Srwatson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 606182063Srwatson return (EINVAL); 607182063Srwatson 608126262Srwatson error = mac_check_structmac_consistent(mac); 609126262Srwatson if (error) 610126262Srwatson return (error); 611126262Srwatson 612126262Srwatson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 613126262Srwatson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 614126262Srwatson if (error) { 615126262Srwatson free(elements, M_MACTEMP); 616126262Srwatson return (error); 617126262Srwatson } 618126262Srwatson 619126262Srwatson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 620130398Srwatson intlabel = mac_socket_label_alloc(M_WAITOK); 621130398Srwatson SOCK_LOCK(so); 622172930Srwatson mac_socket_copy_label(so->so_peerlabel, intlabel); 623130398Srwatson SOCK_UNLOCK(so); 624172930Srwatson error = mac_socketpeer_externalize_label(intlabel, elements, buffer, 625130398Srwatson mac->m_buflen); 626130398Srwatson mac_socket_label_free(intlabel); 627126262Srwatson if (error == 0) 628126262Srwatson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 629126262Srwatson 630126262Srwatson free(buffer, M_MACTEMP); 631126262Srwatson free(elements, M_MACTEMP); 632126262Srwatson 633126262Srwatson return (error); 634126262Srwatson} 635