1c66b4d8dSRobert Watson /*- 22087a58cSRobert Watson * Copyright (c) 1999-2002, 2009 Robert N. M. Watson 3c66b4d8dSRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 47f53207bSRobert Watson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 530d239bcSRobert Watson * Copyright (c) 2005-2006 SPARTA, Inc. 66356dba0SRobert Watson * Copyright (c) 2008 Apple Inc. 7c66b4d8dSRobert Watson * All rights reserved. 8c66b4d8dSRobert Watson * 9c66b4d8dSRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the 10c66b4d8dSRobert Watson * TrustedBSD Project. 11c66b4d8dSRobert Watson * 127f53207bSRobert Watson * This software was developed for the FreeBSD Project in part by McAfee 137f53207bSRobert Watson * Research, the Technology Research Division of Network Associates, Inc. 147f53207bSRobert Watson * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 157f53207bSRobert Watson * DARPA CHATS research program. 16c66b4d8dSRobert Watson * 176758f88eSRobert Watson * This software was enhanced by SPARTA ISSO under SPAWAR contract 186758f88eSRobert Watson * N66001-04-C-6019 ("SEFOS"). 196758f88eSRobert Watson * 202087a58cSRobert Watson * This software was developed at the University of Cambridge Computer 212087a58cSRobert Watson * Laboratory with support from a grant from Google, Inc. 222087a58cSRobert Watson * 23c66b4d8dSRobert Watson * Redistribution and use in source and binary forms, with or without 24c66b4d8dSRobert Watson * modification, are permitted provided that the following conditions 25c66b4d8dSRobert Watson * are met: 26c66b4d8dSRobert Watson * 1. Redistributions of source code must retain the above copyright 27c66b4d8dSRobert Watson * notice, this list of conditions and the following disclaimer. 28c66b4d8dSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 29c66b4d8dSRobert Watson * notice, this list of conditions and the following disclaimer in the 30c66b4d8dSRobert Watson * documentation and/or other materials provided with the distribution. 31c66b4d8dSRobert Watson * 32c66b4d8dSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 33c66b4d8dSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 34c66b4d8dSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 35c66b4d8dSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 36c66b4d8dSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37c66b4d8dSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38c66b4d8dSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39c66b4d8dSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 40c66b4d8dSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 41c66b4d8dSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 42c66b4d8dSRobert Watson * SUCH DAMAGE. 43c66b4d8dSRobert Watson */ 44c66b4d8dSRobert Watson 45c66b4d8dSRobert Watson #include <sys/cdefs.h> 46c66b4d8dSRobert Watson __FBSDID("$FreeBSD$"); 47c66b4d8dSRobert Watson 482087a58cSRobert Watson #include "opt_kdtrace.h" 49c66b4d8dSRobert Watson #include "opt_mac.h" 50c66b4d8dSRobert Watson 51c66b4d8dSRobert Watson #include <sys/param.h> 52c66b4d8dSRobert Watson #include <sys/kernel.h> 53c66b4d8dSRobert Watson #include <sys/lock.h> 54c66b4d8dSRobert Watson #include <sys/malloc.h> 55c66b4d8dSRobert Watson #include <sys/mutex.h> 56c66b4d8dSRobert Watson #include <sys/mac.h> 57c66b4d8dSRobert Watson #include <sys/sbuf.h> 582087a58cSRobert Watson #include <sys/sdt.h> 59c66b4d8dSRobert Watson #include <sys/systm.h> 60c66b4d8dSRobert Watson #include <sys/mount.h> 61c66b4d8dSRobert Watson #include <sys/file.h> 62c66b4d8dSRobert Watson #include <sys/namei.h> 63c66b4d8dSRobert Watson #include <sys/protosw.h> 64c66b4d8dSRobert Watson #include <sys/socket.h> 65c66b4d8dSRobert Watson #include <sys/socketvar.h> 66c66b4d8dSRobert Watson #include <sys/sysctl.h> 67c66b4d8dSRobert Watson 68c66b4d8dSRobert Watson #include <net/bpfdesc.h> 69c66b4d8dSRobert Watson #include <net/if.h> 70c66b4d8dSRobert Watson #include <net/if_var.h> 71c66b4d8dSRobert Watson 72c66b4d8dSRobert Watson #include <netinet/in.h> 73c66b4d8dSRobert Watson #include <netinet/in_pcb.h> 74c66b4d8dSRobert Watson #include <netinet/ip_var.h> 75c66b4d8dSRobert Watson 76aed55708SRobert Watson #include <security/mac/mac_framework.h> 77c66b4d8dSRobert Watson #include <security/mac/mac_internal.h> 780efd6615SRobert Watson #include <security/mac/mac_policy.h> 79c66b4d8dSRobert Watson 80c66b4d8dSRobert Watson /* 81df3c68e4SRobert Watson * Currently, sockets hold two labels: the label of the socket itself, and a 82df3c68e4SRobert Watson * peer label, which may be used by policies to hold a copy of the label of 83df3c68e4SRobert Watson * any remote endpoint. 84df3c68e4SRobert Watson * 85df3c68e4SRobert Watson * Possibly, this peer label should be maintained at the protocol layer 86df3c68e4SRobert Watson * (inpcb, unpcb, etc), as this would allow protocol-aware code to maintain 87df3c68e4SRobert Watson * the label consistently. For example, it might be copied live from a 88df3c68e4SRobert Watson * remote socket for UNIX domain sockets rather than keeping a local copy on 89df3c68e4SRobert Watson * this endpoint, but be cached and updated based on packets received for 90df3c68e4SRobert Watson * TCP/IP. 91df3c68e4SRobert Watson */ 92df3c68e4SRobert Watson 93c66b4d8dSRobert Watson struct label * 94c66b4d8dSRobert Watson mac_socket_label_alloc(int flag) 95c66b4d8dSRobert Watson { 96c66b4d8dSRobert Watson struct label *label; 97c66b4d8dSRobert Watson int error; 98c66b4d8dSRobert Watson 99c66b4d8dSRobert Watson label = mac_labelzone_alloc(flag); 100c66b4d8dSRobert Watson if (label == NULL) 101c66b4d8dSRobert Watson return (NULL); 102c66b4d8dSRobert Watson 10330d239bcSRobert Watson MAC_CHECK(socket_init_label, label, flag); 104c66b4d8dSRobert Watson if (error) { 10530d239bcSRobert Watson MAC_PERFORM(socket_destroy_label, label); 106c66b4d8dSRobert Watson mac_labelzone_free(label); 107c66b4d8dSRobert Watson return (NULL); 108c66b4d8dSRobert Watson } 109c66b4d8dSRobert Watson return (label); 110c66b4d8dSRobert Watson } 111c66b4d8dSRobert Watson 112c66b4d8dSRobert Watson static struct label * 11330d239bcSRobert Watson mac_socketpeer_label_alloc(int flag) 114c66b4d8dSRobert Watson { 115c66b4d8dSRobert Watson struct label *label; 116c66b4d8dSRobert Watson int error; 117c66b4d8dSRobert Watson 118c66b4d8dSRobert Watson label = mac_labelzone_alloc(flag); 119c66b4d8dSRobert Watson if (label == NULL) 120c66b4d8dSRobert Watson return (NULL); 121c66b4d8dSRobert Watson 12230d239bcSRobert Watson MAC_CHECK(socketpeer_init_label, label, flag); 123c66b4d8dSRobert Watson if (error) { 12430d239bcSRobert Watson MAC_PERFORM(socketpeer_destroy_label, label); 125c66b4d8dSRobert Watson mac_labelzone_free(label); 126c66b4d8dSRobert Watson return (NULL); 127c66b4d8dSRobert Watson } 128c66b4d8dSRobert Watson return (label); 129c66b4d8dSRobert Watson } 130c66b4d8dSRobert Watson 131c66b4d8dSRobert Watson int 13230d239bcSRobert Watson mac_socket_init(struct socket *so, int flag) 133c66b4d8dSRobert Watson { 134c66b4d8dSRobert Watson 1356356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_SOCKET) { 136c66b4d8dSRobert Watson so->so_label = mac_socket_label_alloc(flag); 137c66b4d8dSRobert Watson if (so->so_label == NULL) 138c66b4d8dSRobert Watson return (ENOMEM); 13930d239bcSRobert Watson so->so_peerlabel = mac_socketpeer_label_alloc(flag); 140c66b4d8dSRobert Watson if (so->so_peerlabel == NULL) { 141c66b4d8dSRobert Watson mac_socket_label_free(so->so_label); 142c66b4d8dSRobert Watson so->so_label = NULL; 143c66b4d8dSRobert Watson return (ENOMEM); 144c66b4d8dSRobert Watson } 1456356dba0SRobert Watson } else { 1466356dba0SRobert Watson so->so_label = NULL; 1476356dba0SRobert Watson so->so_peerlabel = NULL; 1486356dba0SRobert Watson } 149c66b4d8dSRobert Watson return (0); 150c66b4d8dSRobert Watson } 151c66b4d8dSRobert Watson 152c66b4d8dSRobert Watson void 153c66b4d8dSRobert Watson mac_socket_label_free(struct label *label) 154c66b4d8dSRobert Watson { 155c66b4d8dSRobert Watson 15630d239bcSRobert Watson MAC_PERFORM(socket_destroy_label, label); 157c66b4d8dSRobert Watson mac_labelzone_free(label); 158c66b4d8dSRobert Watson } 159c66b4d8dSRobert Watson 160c66b4d8dSRobert Watson static void 16130d239bcSRobert Watson mac_socketpeer_label_free(struct label *label) 162c66b4d8dSRobert Watson { 163c66b4d8dSRobert Watson 16430d239bcSRobert Watson MAC_PERFORM(socketpeer_destroy_label, label); 165c66b4d8dSRobert Watson mac_labelzone_free(label); 166c66b4d8dSRobert Watson } 167c66b4d8dSRobert Watson 168c66b4d8dSRobert Watson void 16930d239bcSRobert Watson mac_socket_destroy(struct socket *so) 170c66b4d8dSRobert Watson { 171c66b4d8dSRobert Watson 1726356dba0SRobert Watson if (so->so_label != NULL) { 17326ae2b86SRobert Watson mac_socket_label_free(so->so_label); 17426ae2b86SRobert Watson so->so_label = NULL; 17530d239bcSRobert Watson mac_socketpeer_label_free(so->so_peerlabel); 17626ae2b86SRobert Watson so->so_peerlabel = NULL; 177c66b4d8dSRobert Watson } 1786356dba0SRobert Watson } 179c66b4d8dSRobert Watson 180c66b4d8dSRobert Watson void 18130d239bcSRobert Watson mac_socket_copy_label(struct label *src, struct label *dest) 182c66b4d8dSRobert Watson { 183c66b4d8dSRobert Watson 18430d239bcSRobert Watson MAC_PERFORM(socket_copy_label, src, dest); 185c66b4d8dSRobert Watson } 186c66b4d8dSRobert Watson 187c66b4d8dSRobert Watson int 18830d239bcSRobert Watson mac_socket_externalize_label(struct label *label, char *elements, 189c66b4d8dSRobert Watson char *outbuf, size_t outbuflen) 190c66b4d8dSRobert Watson { 191c66b4d8dSRobert Watson int error; 192c66b4d8dSRobert Watson 193c66b4d8dSRobert Watson MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen); 194c66b4d8dSRobert Watson 195c66b4d8dSRobert Watson return (error); 196c66b4d8dSRobert Watson } 197c66b4d8dSRobert Watson 198c66b4d8dSRobert Watson static int 19930d239bcSRobert Watson mac_socketpeer_externalize_label(struct label *label, char *elements, 200c66b4d8dSRobert Watson char *outbuf, size_t outbuflen) 201c66b4d8dSRobert Watson { 202c66b4d8dSRobert Watson int error; 203c66b4d8dSRobert Watson 20430d239bcSRobert Watson MAC_EXTERNALIZE(socketpeer, label, elements, outbuf, outbuflen); 205c66b4d8dSRobert Watson 206c66b4d8dSRobert Watson return (error); 207c66b4d8dSRobert Watson } 208c66b4d8dSRobert Watson 209c66b4d8dSRobert Watson int 21030d239bcSRobert Watson mac_socket_internalize_label(struct label *label, char *string) 211c66b4d8dSRobert Watson { 212c66b4d8dSRobert Watson int error; 213c66b4d8dSRobert Watson 214c66b4d8dSRobert Watson MAC_INTERNALIZE(socket, label, string); 215c66b4d8dSRobert Watson 216c66b4d8dSRobert Watson return (error); 217c66b4d8dSRobert Watson } 218c66b4d8dSRobert Watson 219c66b4d8dSRobert Watson void 22030d239bcSRobert Watson mac_socket_create(struct ucred *cred, struct socket *so) 221c66b4d8dSRobert Watson { 222c66b4d8dSRobert Watson 22330d239bcSRobert Watson MAC_PERFORM(socket_create, cred, so, so->so_label); 224c66b4d8dSRobert Watson } 225c66b4d8dSRobert Watson 226c66b4d8dSRobert Watson void 22730d239bcSRobert Watson mac_socket_newconn(struct socket *oldso, struct socket *newso) 228c66b4d8dSRobert Watson { 229c66b4d8dSRobert Watson 23026ae2b86SRobert Watson SOCK_LOCK_ASSERT(oldso); 23126ae2b86SRobert Watson 23230d239bcSRobert Watson MAC_PERFORM(socket_newconn, oldso, oldso->so_label, newso, 23326ae2b86SRobert Watson newso->so_label); 234c66b4d8dSRobert Watson } 235c66b4d8dSRobert Watson 236c66b4d8dSRobert Watson static void 23730d239bcSRobert Watson mac_socket_relabel(struct ucred *cred, struct socket *so, 238c66b4d8dSRobert Watson struct label *newlabel) 239c66b4d8dSRobert Watson { 240c66b4d8dSRobert Watson 24126ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 24226ae2b86SRobert Watson 24330d239bcSRobert Watson MAC_PERFORM(socket_relabel, cred, so, so->so_label, newlabel); 244c66b4d8dSRobert Watson } 245c66b4d8dSRobert Watson 246c66b4d8dSRobert Watson void 24730d239bcSRobert Watson mac_socketpeer_set_from_mbuf(struct mbuf *m, struct socket *so) 248c66b4d8dSRobert Watson { 249c66b4d8dSRobert Watson struct label *label; 250c66b4d8dSRobert Watson 25126ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 252310e7cebSRobert Watson 25326ae2b86SRobert Watson label = mac_mbuf_to_label(m); 254c66b4d8dSRobert Watson 25530d239bcSRobert Watson MAC_PERFORM(socketpeer_set_from_mbuf, m, label, so, 25626ae2b86SRobert Watson so->so_peerlabel); 257c66b4d8dSRobert Watson } 258c66b4d8dSRobert Watson 259c66b4d8dSRobert Watson void 26030d239bcSRobert Watson mac_socketpeer_set_from_socket(struct socket *oldso, struct socket *newso) 261c66b4d8dSRobert Watson { 262c66b4d8dSRobert Watson 263310e7cebSRobert Watson /* 264df3c68e4SRobert Watson * XXXRW: only hold the socket lock on one at a time, as one socket 265df3c68e4SRobert Watson * is the original, and one is the new. However, it's called in both 266df3c68e4SRobert Watson * directions, so we can't assert the lock here currently. 267310e7cebSRobert Watson */ 26830d239bcSRobert Watson MAC_PERFORM(socketpeer_set_from_socket, oldso, oldso->so_label, 26926ae2b86SRobert Watson newso, newso->so_peerlabel); 270c66b4d8dSRobert Watson } 271c66b4d8dSRobert Watson 272c66b4d8dSRobert Watson void 27330d239bcSRobert Watson mac_socket_create_mbuf(struct socket *so, struct mbuf *m) 274c66b4d8dSRobert Watson { 275c66b4d8dSRobert Watson struct label *label; 276c66b4d8dSRobert Watson 27726ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 278c66b4d8dSRobert Watson 27926ae2b86SRobert Watson label = mac_mbuf_to_label(m); 28026ae2b86SRobert Watson 28130d239bcSRobert Watson MAC_PERFORM(socket_create_mbuf, so, so->so_label, m, label); 282c66b4d8dSRobert Watson } 283c66b4d8dSRobert Watson 2842087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(socket_check_accept, "struct ucred *", 2852087a58cSRobert Watson "struct socket *"); 2862087a58cSRobert Watson 287c66b4d8dSRobert Watson int 28830d239bcSRobert Watson mac_socket_check_accept(struct ucred *cred, struct socket *so) 2897f53207bSRobert Watson { 2907f53207bSRobert Watson int error; 2917f53207bSRobert Watson 29226ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 2937f53207bSRobert Watson 29430d239bcSRobert Watson MAC_CHECK(socket_check_accept, cred, so, so->so_label); 2952087a58cSRobert Watson MAC_CHECK_PROBE2(socket_check_accept, error, cred, so); 2967f53207bSRobert Watson 2977f53207bSRobert Watson return (error); 2987f53207bSRobert Watson } 2997f53207bSRobert Watson 3002087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE3(socket_check_bind, "struct ucred *", 3012087a58cSRobert Watson "struct socket *", "struct sockaddr *"); 3022087a58cSRobert Watson 3037f53207bSRobert Watson int 30430d239bcSRobert Watson mac_socket_check_bind(struct ucred *ucred, struct socket *so, 30526ae2b86SRobert Watson struct sockaddr *sa) 306c66b4d8dSRobert Watson { 307c66b4d8dSRobert Watson int error; 308c66b4d8dSRobert Watson 30926ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 310310e7cebSRobert Watson 31130d239bcSRobert Watson MAC_CHECK(socket_check_bind, ucred, so, so->so_label, sa); 3122087a58cSRobert Watson MAC_CHECK_PROBE3(socket_check_bind, error, ucred, so, sa); 313c66b4d8dSRobert Watson 314c66b4d8dSRobert Watson return (error); 315c66b4d8dSRobert Watson } 316c66b4d8dSRobert Watson 3172087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE3(socket_check_connect, "struct ucred *", 3182087a58cSRobert Watson "struct socket *", "struct sockaddr *"); 3192087a58cSRobert Watson 320c66b4d8dSRobert Watson int 32130d239bcSRobert Watson mac_socket_check_connect(struct ucred *cred, struct socket *so, 32226ae2b86SRobert Watson struct sockaddr *sa) 323c66b4d8dSRobert Watson { 324c66b4d8dSRobert Watson int error; 325c66b4d8dSRobert Watson 32626ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 327310e7cebSRobert Watson 32830d239bcSRobert Watson MAC_CHECK(socket_check_connect, cred, so, so->so_label, sa); 3292087a58cSRobert Watson MAC_CHECK_PROBE3(socket_check_connect, error, cred, so, sa); 330c66b4d8dSRobert Watson 331c66b4d8dSRobert Watson return (error); 332c66b4d8dSRobert Watson } 333c66b4d8dSRobert Watson 3342087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE4(socket_check_create, "struct ucred *", "int", "int", 3352087a58cSRobert Watson "int"); 3362087a58cSRobert Watson 337c66b4d8dSRobert Watson int 33830d239bcSRobert Watson mac_socket_check_create(struct ucred *cred, int domain, int type, int proto) 3396758f88eSRobert Watson { 3406758f88eSRobert Watson int error; 3416758f88eSRobert Watson 34230d239bcSRobert Watson MAC_CHECK(socket_check_create, cred, domain, type, proto); 3432087a58cSRobert Watson MAC_CHECK_PROBE4(socket_check_create, error, cred, domain, type, 3442087a58cSRobert Watson proto); 3456758f88eSRobert Watson 3466758f88eSRobert Watson return (error); 3476758f88eSRobert Watson } 3486758f88eSRobert Watson 3492087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(socket_check_deliver, "struct socket *", 3502087a58cSRobert Watson "struct mbuf *"); 3512087a58cSRobert Watson 3526758f88eSRobert Watson int 35330d239bcSRobert Watson mac_socket_check_deliver(struct socket *so, struct mbuf *m) 354c66b4d8dSRobert Watson { 355c66b4d8dSRobert Watson struct label *label; 356c66b4d8dSRobert Watson int error; 357c66b4d8dSRobert Watson 35826ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 359310e7cebSRobert Watson 36026ae2b86SRobert Watson label = mac_mbuf_to_label(m); 361c66b4d8dSRobert Watson 36230d239bcSRobert Watson MAC_CHECK(socket_check_deliver, so, so->so_label, m, label); 3632087a58cSRobert Watson MAC_CHECK_PROBE2(socket_check_deliver, error, so, m); 364c66b4d8dSRobert Watson 365c66b4d8dSRobert Watson return (error); 366c66b4d8dSRobert Watson } 367c66b4d8dSRobert Watson 3682087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(socket_check_listen, "struct ucred *", 3692087a58cSRobert Watson "struct socket *"); 3702087a58cSRobert Watson 371c66b4d8dSRobert Watson int 37230d239bcSRobert Watson mac_socket_check_listen(struct ucred *cred, struct socket *so) 373c66b4d8dSRobert Watson { 374c66b4d8dSRobert Watson int error; 375c66b4d8dSRobert Watson 37626ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 377310e7cebSRobert Watson 37830d239bcSRobert Watson MAC_CHECK(socket_check_listen, cred, so, so->so_label); 3792087a58cSRobert Watson MAC_CHECK_PROBE2(socket_check_listen, error, cred, so); 38026ae2b86SRobert Watson 381c66b4d8dSRobert Watson return (error); 382c66b4d8dSRobert Watson } 383c66b4d8dSRobert Watson 3842087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(socket_check_poll, "struct ucred *", 3852087a58cSRobert Watson "struct socket *"); 3862087a58cSRobert Watson 387c66b4d8dSRobert Watson int 38830d239bcSRobert Watson mac_socket_check_poll(struct ucred *cred, struct socket *so) 3897f53207bSRobert Watson { 3907f53207bSRobert Watson int error; 3917f53207bSRobert Watson 3927f53207bSRobert Watson SOCK_LOCK_ASSERT(so); 3937f53207bSRobert Watson 39430d239bcSRobert Watson MAC_CHECK(socket_check_poll, cred, so, so->so_label); 3952087a58cSRobert Watson MAC_CHECK_PROBE2(socket_check_poll, error, cred, so); 39626ae2b86SRobert Watson 3977f53207bSRobert Watson return (error); 3987f53207bSRobert Watson } 3997f53207bSRobert Watson 4002087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(socket_check_receive, "struct ucred *", 4012087a58cSRobert Watson "struct socket *"); 4022087a58cSRobert Watson 4037f53207bSRobert Watson int 40430d239bcSRobert Watson mac_socket_check_receive(struct ucred *cred, struct socket *so) 405c66b4d8dSRobert Watson { 406c66b4d8dSRobert Watson int error; 407c66b4d8dSRobert Watson 408310e7cebSRobert Watson SOCK_LOCK_ASSERT(so); 409310e7cebSRobert Watson 41030d239bcSRobert Watson MAC_CHECK(socket_check_receive, cred, so, so->so_label); 4112087a58cSRobert Watson MAC_CHECK_PROBE2(socket_check_receive, error, cred, so); 412c66b4d8dSRobert Watson 413c66b4d8dSRobert Watson return (error); 414c66b4d8dSRobert Watson } 415c66b4d8dSRobert Watson 4162087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE3(socket_check_relabel, "struct ucred *", 4172087a58cSRobert Watson "struct socket *", "struct label *"); 4182087a58cSRobert Watson 419c66b4d8dSRobert Watson static int 42030d239bcSRobert Watson mac_socket_check_relabel(struct ucred *cred, struct socket *so, 421c66b4d8dSRobert Watson struct label *newlabel) 422c66b4d8dSRobert Watson { 423c66b4d8dSRobert Watson int error; 424c66b4d8dSRobert Watson 42526ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 426310e7cebSRobert Watson 42730d239bcSRobert Watson MAC_CHECK(socket_check_relabel, cred, so, so->so_label, newlabel); 4282087a58cSRobert Watson MAC_CHECK_PROBE3(socket_check_relabel, error, cred, so, newlabel); 429c66b4d8dSRobert Watson 430c66b4d8dSRobert Watson return (error); 431c66b4d8dSRobert Watson } 432c66b4d8dSRobert Watson 4332087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(socket_check_send, "struct ucred *", 4342087a58cSRobert Watson "struct socket *"); 4352087a58cSRobert Watson 436c66b4d8dSRobert Watson int 43730d239bcSRobert Watson mac_socket_check_send(struct ucred *cred, struct socket *so) 438c66b4d8dSRobert Watson { 439c66b4d8dSRobert Watson int error; 440c66b4d8dSRobert Watson 441310e7cebSRobert Watson SOCK_LOCK_ASSERT(so); 442310e7cebSRobert Watson 44330d239bcSRobert Watson MAC_CHECK(socket_check_send, cred, so, so->so_label); 4442087a58cSRobert Watson MAC_CHECK_PROBE2(socket_check_send, error, cred, so); 445c66b4d8dSRobert Watson 446c66b4d8dSRobert Watson return (error); 447c66b4d8dSRobert Watson } 448c66b4d8dSRobert Watson 4492087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(socket_check_stat, "struct ucred *", 4502087a58cSRobert Watson "struct socket *"); 4512087a58cSRobert Watson 452c66b4d8dSRobert Watson int 45330d239bcSRobert Watson mac_socket_check_stat(struct ucred *cred, struct socket *so) 4547f53207bSRobert Watson { 4557f53207bSRobert Watson int error; 4567f53207bSRobert Watson 4577f53207bSRobert Watson SOCK_LOCK_ASSERT(so); 4587f53207bSRobert Watson 45930d239bcSRobert Watson MAC_CHECK(socket_check_stat, cred, so, so->so_label); 4602087a58cSRobert Watson MAC_CHECK_PROBE2(socket_check_stat, error, cred, so); 4617f53207bSRobert Watson 4627f53207bSRobert Watson return (error); 4637f53207bSRobert Watson } 4647f53207bSRobert Watson 4652087a58cSRobert Watson MAC_CHECK_PROBE_DEFINE2(socket_check_visible, "struct ucred *", 4662087a58cSRobert Watson "struct socket *"); 4672087a58cSRobert Watson 4687f53207bSRobert Watson int 46930d239bcSRobert Watson mac_socket_check_visible(struct ucred *cred, struct socket *so) 470c66b4d8dSRobert Watson { 471c66b4d8dSRobert Watson int error; 472c66b4d8dSRobert Watson 47326ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 474310e7cebSRobert Watson 47530d239bcSRobert Watson MAC_CHECK(socket_check_visible, cred, so, so->so_label); 4762087a58cSRobert Watson MAC_CHECK_PROBE2(socket_check_visible, error, cred, so); 477c66b4d8dSRobert Watson 478c66b4d8dSRobert Watson return (error); 479c66b4d8dSRobert Watson } 480c66b4d8dSRobert Watson 481c66b4d8dSRobert Watson int 482c66b4d8dSRobert Watson mac_socket_label_set(struct ucred *cred, struct socket *so, 483c66b4d8dSRobert Watson struct label *label) 484c66b4d8dSRobert Watson { 485c66b4d8dSRobert Watson int error; 486c66b4d8dSRobert Watson 487310e7cebSRobert Watson /* 488df3c68e4SRobert Watson * We acquire the socket lock when we perform the test and set, but 489df3c68e4SRobert Watson * have to release it as the pcb code needs to acquire the pcb lock, 490df3c68e4SRobert Watson * which will precede the socket lock in the lock order. However, 491df3c68e4SRobert Watson * this is fine, as any race will simply result in the inpcb being 492df3c68e4SRobert Watson * refreshed twice, but still consistently, as the inpcb code will 493df3c68e4SRobert Watson * acquire the socket lock before refreshing, holding both locks. 494310e7cebSRobert Watson */ 495310e7cebSRobert Watson SOCK_LOCK(so); 49630d239bcSRobert Watson error = mac_socket_check_relabel(cred, so, label); 497310e7cebSRobert Watson if (error) { 498310e7cebSRobert Watson SOCK_UNLOCK(so); 499c66b4d8dSRobert Watson return (error); 500310e7cebSRobert Watson } 501c66b4d8dSRobert Watson 50230d239bcSRobert Watson mac_socket_relabel(cred, so, label); 503310e7cebSRobert Watson SOCK_UNLOCK(so); 504df3c68e4SRobert Watson 505c66b4d8dSRobert Watson /* 506c66b4d8dSRobert Watson * If the protocol has expressed interest in socket layer changes, 507df3c68e4SRobert Watson * such as if it needs to propagate changes to a cached pcb label 508df3c68e4SRobert Watson * from the socket, notify it of the label change while holding the 509df3c68e4SRobert Watson * socket lock. 510c66b4d8dSRobert Watson */ 511c66b4d8dSRobert Watson if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL) 512c66b4d8dSRobert Watson (so->so_proto->pr_usrreqs->pru_sosetlabel)(so); 513c66b4d8dSRobert Watson 514c66b4d8dSRobert Watson return (0); 515c66b4d8dSRobert Watson } 516c66b4d8dSRobert Watson 517c66b4d8dSRobert Watson int 518c66b4d8dSRobert Watson mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 519c66b4d8dSRobert Watson { 520c66b4d8dSRobert Watson struct label *intlabel; 521c66b4d8dSRobert Watson char *buffer; 522c66b4d8dSRobert Watson int error; 523c66b4d8dSRobert Watson 5246356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 5256356dba0SRobert Watson return (EINVAL); 5266356dba0SRobert Watson 527c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 528c66b4d8dSRobert Watson if (error) 529c66b4d8dSRobert Watson return (error); 530c66b4d8dSRobert Watson 531c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 532c66b4d8dSRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 533c66b4d8dSRobert Watson if (error) { 534c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 535c66b4d8dSRobert Watson return (error); 536c66b4d8dSRobert Watson } 537c66b4d8dSRobert Watson 538c66b4d8dSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 53930d239bcSRobert Watson error = mac_socket_internalize_label(intlabel, buffer); 540c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 541c66b4d8dSRobert Watson if (error) 542c66b4d8dSRobert Watson goto out; 543c66b4d8dSRobert Watson 544c66b4d8dSRobert Watson error = mac_socket_label_set(cred, so, intlabel); 545c66b4d8dSRobert Watson out: 546c66b4d8dSRobert Watson mac_socket_label_free(intlabel); 547c66b4d8dSRobert Watson return (error); 548c66b4d8dSRobert Watson } 549c66b4d8dSRobert Watson 550c66b4d8dSRobert Watson int 551c66b4d8dSRobert Watson mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 552c66b4d8dSRobert Watson { 553c66b4d8dSRobert Watson char *buffer, *elements; 554310e7cebSRobert Watson struct label *intlabel; 555c66b4d8dSRobert Watson int error; 556c66b4d8dSRobert Watson 5576356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 5586356dba0SRobert Watson return (EINVAL); 5596356dba0SRobert Watson 560c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 561c66b4d8dSRobert Watson if (error) 562c66b4d8dSRobert Watson return (error); 563c66b4d8dSRobert Watson 564c66b4d8dSRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 565c66b4d8dSRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 566c66b4d8dSRobert Watson if (error) { 567c66b4d8dSRobert Watson free(elements, M_MACTEMP); 568c66b4d8dSRobert Watson return (error); 569c66b4d8dSRobert Watson } 570c66b4d8dSRobert Watson 571c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 572310e7cebSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 573310e7cebSRobert Watson SOCK_LOCK(so); 57430d239bcSRobert Watson mac_socket_copy_label(so->so_label, intlabel); 575310e7cebSRobert Watson SOCK_UNLOCK(so); 57630d239bcSRobert Watson error = mac_socket_externalize_label(intlabel, elements, buffer, 577310e7cebSRobert Watson mac->m_buflen); 578310e7cebSRobert Watson mac_socket_label_free(intlabel); 579c66b4d8dSRobert Watson if (error == 0) 580c66b4d8dSRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 581c66b4d8dSRobert Watson 582c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 583c66b4d8dSRobert Watson free(elements, M_MACTEMP); 584c66b4d8dSRobert Watson 585c66b4d8dSRobert Watson return (error); 586c66b4d8dSRobert Watson } 587c66b4d8dSRobert Watson 588c66b4d8dSRobert Watson int 589c66b4d8dSRobert Watson mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so, 590c66b4d8dSRobert Watson struct mac *mac) 591c66b4d8dSRobert Watson { 592c66b4d8dSRobert Watson char *elements, *buffer; 593310e7cebSRobert Watson struct label *intlabel; 594c66b4d8dSRobert Watson int error; 595c66b4d8dSRobert Watson 5966356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 5976356dba0SRobert Watson return (EINVAL); 5986356dba0SRobert Watson 599c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 600c66b4d8dSRobert Watson if (error) 601c66b4d8dSRobert Watson return (error); 602c66b4d8dSRobert Watson 603c66b4d8dSRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 604c66b4d8dSRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 605c66b4d8dSRobert Watson if (error) { 606c66b4d8dSRobert Watson free(elements, M_MACTEMP); 607c66b4d8dSRobert Watson return (error); 608c66b4d8dSRobert Watson } 609c66b4d8dSRobert Watson 610c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 611310e7cebSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 612310e7cebSRobert Watson SOCK_LOCK(so); 61330d239bcSRobert Watson mac_socket_copy_label(so->so_peerlabel, intlabel); 614310e7cebSRobert Watson SOCK_UNLOCK(so); 61530d239bcSRobert Watson error = mac_socketpeer_externalize_label(intlabel, elements, buffer, 616310e7cebSRobert Watson mac->m_buflen); 617310e7cebSRobert Watson mac_socket_label_free(intlabel); 618c66b4d8dSRobert Watson if (error == 0) 619c66b4d8dSRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 620c66b4d8dSRobert Watson 621c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 622c66b4d8dSRobert Watson free(elements, M_MACTEMP); 623c66b4d8dSRobert Watson 624c66b4d8dSRobert Watson return (error); 625c66b4d8dSRobert Watson } 626