1c66b4d8dSRobert Watson /*- 2c66b4d8dSRobert Watson * Copyright (c) 1999-2002 Robert N. M. Watson 3c66b4d8dSRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 47f53207bSRobert Watson * Copyright (c) 2001-2005 Networks Associates Technology, Inc. 56758f88eSRobert Watson * Copyright (c) 2005 SPARTA, Inc. 6c66b4d8dSRobert Watson * All rights reserved. 7c66b4d8dSRobert Watson * 8c66b4d8dSRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the 9c66b4d8dSRobert Watson * TrustedBSD Project. 10c66b4d8dSRobert Watson * 117f53207bSRobert Watson * This software was developed for the FreeBSD Project in part by McAfee 127f53207bSRobert Watson * Research, the Technology Research Division of Network Associates, Inc. 137f53207bSRobert Watson * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the 147f53207bSRobert Watson * DARPA CHATS research program. 15c66b4d8dSRobert Watson * 166758f88eSRobert Watson * This software was enhanced by SPARTA ISSO under SPAWAR contract 176758f88eSRobert Watson * N66001-04-C-6019 ("SEFOS"). 186758f88eSRobert Watson * 19c66b4d8dSRobert Watson * Redistribution and use in source and binary forms, with or without 20c66b4d8dSRobert Watson * modification, are permitted provided that the following conditions 21c66b4d8dSRobert Watson * are met: 22c66b4d8dSRobert Watson * 1. Redistributions of source code must retain the above copyright 23c66b4d8dSRobert Watson * notice, this list of conditions and the following disclaimer. 24c66b4d8dSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 25c66b4d8dSRobert Watson * notice, this list of conditions and the following disclaimer in the 26c66b4d8dSRobert Watson * documentation and/or other materials provided with the distribution. 27c66b4d8dSRobert Watson * 28c66b4d8dSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 29c66b4d8dSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30c66b4d8dSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31c66b4d8dSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 32c66b4d8dSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33c66b4d8dSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34c66b4d8dSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35c66b4d8dSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36c66b4d8dSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37c66b4d8dSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38c66b4d8dSRobert Watson * SUCH DAMAGE. 39c66b4d8dSRobert Watson */ 40c66b4d8dSRobert Watson 41c66b4d8dSRobert Watson #include <sys/cdefs.h> 42c66b4d8dSRobert Watson __FBSDID("$FreeBSD$"); 43c66b4d8dSRobert Watson 44c66b4d8dSRobert Watson #include "opt_mac.h" 45c66b4d8dSRobert Watson 46c66b4d8dSRobert Watson #include <sys/param.h> 47c66b4d8dSRobert Watson #include <sys/kernel.h> 48c66b4d8dSRobert Watson #include <sys/lock.h> 49c66b4d8dSRobert Watson #include <sys/malloc.h> 50c66b4d8dSRobert Watson #include <sys/mutex.h> 51c66b4d8dSRobert Watson #include <sys/mac.h> 52c66b4d8dSRobert Watson #include <sys/sbuf.h> 53c66b4d8dSRobert Watson #include <sys/systm.h> 54c66b4d8dSRobert Watson #include <sys/mount.h> 55c66b4d8dSRobert Watson #include <sys/file.h> 56c66b4d8dSRobert Watson #include <sys/namei.h> 57c66b4d8dSRobert Watson #include <sys/protosw.h> 58c66b4d8dSRobert Watson #include <sys/socket.h> 59c66b4d8dSRobert Watson #include <sys/socketvar.h> 60c66b4d8dSRobert Watson #include <sys/sysctl.h> 61c66b4d8dSRobert Watson 62c66b4d8dSRobert Watson #include <sys/mac_policy.h> 63c66b4d8dSRobert Watson 64c66b4d8dSRobert Watson #include <net/bpfdesc.h> 65c66b4d8dSRobert Watson #include <net/if.h> 66c66b4d8dSRobert Watson #include <net/if_var.h> 67c66b4d8dSRobert Watson 68c66b4d8dSRobert Watson #include <netinet/in.h> 69c66b4d8dSRobert Watson #include <netinet/in_pcb.h> 70c66b4d8dSRobert Watson #include <netinet/ip_var.h> 71c66b4d8dSRobert Watson 72c66b4d8dSRobert Watson #include <security/mac/mac_internal.h> 73c66b4d8dSRobert Watson 74c66b4d8dSRobert Watson /* 75c66b4d8dSRobert Watson * mac_enforce_socket is used by the inet code when delivering to an inpcb 76c66b4d8dSRobert Watson * without hitting the socket layer, and has to be non-static for now. 77c66b4d8dSRobert Watson */ 78c66b4d8dSRobert Watson int mac_enforce_socket = 1; 79c66b4d8dSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 80c66b4d8dSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 81c66b4d8dSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 82c66b4d8dSRobert Watson 83c66b4d8dSRobert Watson #ifdef MAC_DEBUG 84c66b4d8dSRobert Watson static unsigned int nmacsockets; 85c66b4d8dSRobert Watson 86c66b4d8dSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 87c66b4d8dSRobert Watson &nmacsockets, 0, "number of sockets in use"); 88c66b4d8dSRobert Watson #endif 89c66b4d8dSRobert Watson 90c66b4d8dSRobert Watson struct label * 91c66b4d8dSRobert Watson mac_socket_label_alloc(int flag) 92c66b4d8dSRobert Watson { 93c66b4d8dSRobert Watson struct label *label; 94c66b4d8dSRobert Watson int error; 95c66b4d8dSRobert Watson 96c66b4d8dSRobert Watson label = mac_labelzone_alloc(flag); 97c66b4d8dSRobert Watson if (label == NULL) 98c66b4d8dSRobert Watson return (NULL); 99c66b4d8dSRobert Watson 100c66b4d8dSRobert Watson MAC_CHECK(init_socket_label, label, flag); 101c66b4d8dSRobert Watson if (error) { 102c66b4d8dSRobert Watson MAC_PERFORM(destroy_socket_label, label); 103c66b4d8dSRobert Watson mac_labelzone_free(label); 104c66b4d8dSRobert Watson return (NULL); 105c66b4d8dSRobert Watson } 106c66b4d8dSRobert Watson MAC_DEBUG_COUNTER_INC(&nmacsockets); 107c66b4d8dSRobert Watson return (label); 108c66b4d8dSRobert Watson } 109c66b4d8dSRobert Watson 110c66b4d8dSRobert Watson static struct label * 111c66b4d8dSRobert Watson mac_socket_peer_label_alloc(int flag) 112c66b4d8dSRobert Watson { 113c66b4d8dSRobert Watson struct label *label; 114c66b4d8dSRobert Watson int error; 115c66b4d8dSRobert Watson 116c66b4d8dSRobert Watson label = mac_labelzone_alloc(flag); 117c66b4d8dSRobert Watson if (label == NULL) 118c66b4d8dSRobert Watson return (NULL); 119c66b4d8dSRobert Watson 120c66b4d8dSRobert Watson MAC_CHECK(init_socket_peer_label, label, flag); 121c66b4d8dSRobert Watson if (error) { 122c66b4d8dSRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 123c66b4d8dSRobert Watson mac_labelzone_free(label); 124c66b4d8dSRobert Watson return (NULL); 125c66b4d8dSRobert Watson } 126c66b4d8dSRobert Watson MAC_DEBUG_COUNTER_INC(&nmacsockets); 127c66b4d8dSRobert Watson return (label); 128c66b4d8dSRobert Watson } 129c66b4d8dSRobert Watson 130c66b4d8dSRobert Watson int 131c66b4d8dSRobert Watson mac_init_socket(struct socket *so, int flag) 132c66b4d8dSRobert Watson { 133c66b4d8dSRobert Watson 134c66b4d8dSRobert Watson so->so_label = mac_socket_label_alloc(flag); 135c66b4d8dSRobert Watson if (so->so_label == NULL) 136c66b4d8dSRobert Watson return (ENOMEM); 137c66b4d8dSRobert Watson so->so_peerlabel = mac_socket_peer_label_alloc(flag); 138c66b4d8dSRobert Watson if (so->so_peerlabel == NULL) { 139c66b4d8dSRobert Watson mac_socket_label_free(so->so_label); 140c66b4d8dSRobert Watson so->so_label = NULL; 141c66b4d8dSRobert Watson return (ENOMEM); 142c66b4d8dSRobert Watson } 143c66b4d8dSRobert Watson return (0); 144c66b4d8dSRobert Watson } 145c66b4d8dSRobert Watson 146c66b4d8dSRobert Watson void 147c66b4d8dSRobert Watson mac_socket_label_free(struct label *label) 148c66b4d8dSRobert Watson { 149c66b4d8dSRobert Watson 150c66b4d8dSRobert Watson MAC_PERFORM(destroy_socket_label, label); 151c66b4d8dSRobert Watson mac_labelzone_free(label); 152c66b4d8dSRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacsockets); 153c66b4d8dSRobert Watson } 154c66b4d8dSRobert Watson 155c66b4d8dSRobert Watson static void 156c66b4d8dSRobert Watson mac_socket_peer_label_free(struct label *label) 157c66b4d8dSRobert Watson { 158c66b4d8dSRobert Watson 159c66b4d8dSRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 160c66b4d8dSRobert Watson mac_labelzone_free(label); 161c66b4d8dSRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacsockets); 162c66b4d8dSRobert Watson } 163c66b4d8dSRobert Watson 164c66b4d8dSRobert Watson void 165c66b4d8dSRobert Watson mac_destroy_socket(struct socket *socket) 166c66b4d8dSRobert Watson { 167c66b4d8dSRobert Watson 168c66b4d8dSRobert Watson mac_socket_label_free(socket->so_label); 169c66b4d8dSRobert Watson socket->so_label = NULL; 170c66b4d8dSRobert Watson mac_socket_peer_label_free(socket->so_peerlabel); 171c66b4d8dSRobert Watson socket->so_peerlabel = NULL; 172c66b4d8dSRobert Watson } 173c66b4d8dSRobert Watson 174c66b4d8dSRobert Watson void 175c66b4d8dSRobert Watson mac_copy_socket_label(struct label *src, struct label *dest) 176c66b4d8dSRobert Watson { 177c66b4d8dSRobert Watson 178c66b4d8dSRobert Watson MAC_PERFORM(copy_socket_label, src, dest); 179c66b4d8dSRobert Watson } 180c66b4d8dSRobert Watson 181c66b4d8dSRobert Watson int 182c66b4d8dSRobert Watson mac_externalize_socket_label(struct label *label, char *elements, 183c66b4d8dSRobert Watson char *outbuf, size_t outbuflen) 184c66b4d8dSRobert Watson { 185c66b4d8dSRobert Watson int error; 186c66b4d8dSRobert Watson 187c66b4d8dSRobert Watson MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen); 188c66b4d8dSRobert Watson 189c66b4d8dSRobert Watson return (error); 190c66b4d8dSRobert Watson } 191c66b4d8dSRobert Watson 192c66b4d8dSRobert Watson static int 193c66b4d8dSRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements, 194c66b4d8dSRobert Watson char *outbuf, size_t outbuflen) 195c66b4d8dSRobert Watson { 196c66b4d8dSRobert Watson int error; 197c66b4d8dSRobert Watson 198c66b4d8dSRobert Watson MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen); 199c66b4d8dSRobert Watson 200c66b4d8dSRobert Watson return (error); 201c66b4d8dSRobert Watson } 202c66b4d8dSRobert Watson 203c66b4d8dSRobert Watson int 204c66b4d8dSRobert Watson mac_internalize_socket_label(struct label *label, char *string) 205c66b4d8dSRobert Watson { 206c66b4d8dSRobert Watson int error; 207c66b4d8dSRobert Watson 208c66b4d8dSRobert Watson MAC_INTERNALIZE(socket, label, string); 209c66b4d8dSRobert Watson 210c66b4d8dSRobert Watson return (error); 211c66b4d8dSRobert Watson } 212c66b4d8dSRobert Watson 213c66b4d8dSRobert Watson void 214c66b4d8dSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 215c66b4d8dSRobert Watson { 216c66b4d8dSRobert Watson 217c66b4d8dSRobert Watson MAC_PERFORM(create_socket, cred, socket, socket->so_label); 218c66b4d8dSRobert Watson } 219c66b4d8dSRobert Watson 220c66b4d8dSRobert Watson void 221c66b4d8dSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 222c66b4d8dSRobert Watson struct socket *newsocket) 223c66b4d8dSRobert Watson { 224c66b4d8dSRobert Watson 225310e7cebSRobert Watson SOCK_LOCK_ASSERT(oldsocket); 226c66b4d8dSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, oldsocket->so_label, 227c66b4d8dSRobert Watson newsocket, newsocket->so_label); 228c66b4d8dSRobert Watson } 229c66b4d8dSRobert Watson 230c66b4d8dSRobert Watson static void 231c66b4d8dSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 232c66b4d8dSRobert Watson struct label *newlabel) 233c66b4d8dSRobert Watson { 234c66b4d8dSRobert Watson 235310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 236c66b4d8dSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, socket->so_label, newlabel); 237c66b4d8dSRobert Watson } 238c66b4d8dSRobert Watson 239c66b4d8dSRobert Watson void 240c66b4d8dSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 241c66b4d8dSRobert Watson { 242c66b4d8dSRobert Watson struct label *label; 243c66b4d8dSRobert Watson 244310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 245310e7cebSRobert Watson 246c66b4d8dSRobert Watson label = mac_mbuf_to_label(mbuf); 247c66b4d8dSRobert Watson 248c66b4d8dSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket, 249c66b4d8dSRobert Watson socket->so_peerlabel); 250c66b4d8dSRobert Watson } 251c66b4d8dSRobert Watson 252c66b4d8dSRobert Watson void 253c66b4d8dSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 254c66b4d8dSRobert Watson struct socket *newsocket) 255c66b4d8dSRobert Watson { 256c66b4d8dSRobert Watson 257310e7cebSRobert Watson /* 258310e7cebSRobert Watson * XXXRW: only hold the socket lock on one at a time, as one 259310e7cebSRobert Watson * socket is the original, and one is the new. However, it's 260310e7cebSRobert Watson * called in both directions, so we can't assert the lock 261310e7cebSRobert Watson * here currently. 262310e7cebSRobert Watson */ 263c66b4d8dSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 264c66b4d8dSRobert Watson oldsocket->so_label, newsocket, newsocket->so_peerlabel); 265c66b4d8dSRobert Watson } 266c66b4d8dSRobert Watson 267c66b4d8dSRobert Watson void 268c66b4d8dSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 269c66b4d8dSRobert Watson { 270c66b4d8dSRobert Watson struct label *label; 271c66b4d8dSRobert Watson 272c66b4d8dSRobert Watson label = mac_mbuf_to_label(mbuf); 273c66b4d8dSRobert Watson 274310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 275c66b4d8dSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, socket->so_label, mbuf, 276c66b4d8dSRobert Watson label); 277c66b4d8dSRobert Watson } 278c66b4d8dSRobert Watson 279c66b4d8dSRobert Watson int 2807f53207bSRobert Watson mac_check_socket_accept(struct ucred *cred, struct socket *socket) 2817f53207bSRobert Watson { 2827f53207bSRobert Watson int error; 2837f53207bSRobert Watson 2847f53207bSRobert Watson SOCK_LOCK_ASSERT(socket); 2857f53207bSRobert Watson 2867f53207bSRobert Watson if (!mac_enforce_socket) 2877f53207bSRobert Watson return (0); 2887f53207bSRobert Watson 2897f53207bSRobert Watson MAC_CHECK(check_socket_accept, cred, socket, socket->so_label); 2907f53207bSRobert Watson 2917f53207bSRobert Watson return (error); 2927f53207bSRobert Watson } 2937f53207bSRobert Watson 2947f53207bSRobert Watson int 295c66b4d8dSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 296c66b4d8dSRobert Watson struct sockaddr *sockaddr) 297c66b4d8dSRobert Watson { 298c66b4d8dSRobert Watson int error; 299c66b4d8dSRobert Watson 300310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 301310e7cebSRobert Watson 302c66b4d8dSRobert Watson if (!mac_enforce_socket) 303c66b4d8dSRobert Watson return (0); 304c66b4d8dSRobert Watson 305c66b4d8dSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, socket->so_label, 306c66b4d8dSRobert Watson sockaddr); 307c66b4d8dSRobert Watson 308c66b4d8dSRobert Watson return (error); 309c66b4d8dSRobert Watson } 310c66b4d8dSRobert Watson 311c66b4d8dSRobert Watson int 312c66b4d8dSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 313c66b4d8dSRobert Watson struct sockaddr *sockaddr) 314c66b4d8dSRobert Watson { 315c66b4d8dSRobert Watson int error; 316c66b4d8dSRobert Watson 317310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 318310e7cebSRobert Watson 319c66b4d8dSRobert Watson if (!mac_enforce_socket) 320c66b4d8dSRobert Watson return (0); 321c66b4d8dSRobert Watson 322c66b4d8dSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, socket->so_label, 323c66b4d8dSRobert Watson sockaddr); 324c66b4d8dSRobert Watson 325c66b4d8dSRobert Watson return (error); 326c66b4d8dSRobert Watson } 327c66b4d8dSRobert Watson 328c66b4d8dSRobert Watson int 3296758f88eSRobert Watson mac_check_socket_create(struct ucred *cred, int domain, int type, 3306758f88eSRobert Watson int protocol) 3316758f88eSRobert Watson { 3326758f88eSRobert Watson int error; 3336758f88eSRobert Watson 3346758f88eSRobert Watson if (!mac_enforce_socket) 3356758f88eSRobert Watson return (0); 3366758f88eSRobert Watson 3376758f88eSRobert Watson MAC_CHECK(check_socket_create, cred, domain, type, protocol); 3386758f88eSRobert Watson 3396758f88eSRobert Watson return (error); 3406758f88eSRobert Watson } 3416758f88eSRobert Watson 3426758f88eSRobert Watson int 343c66b4d8dSRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 344c66b4d8dSRobert Watson { 345c66b4d8dSRobert Watson struct label *label; 346c66b4d8dSRobert Watson int error; 347c66b4d8dSRobert Watson 348310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 349310e7cebSRobert Watson 350c66b4d8dSRobert Watson if (!mac_enforce_socket) 351c66b4d8dSRobert Watson return (0); 352c66b4d8dSRobert Watson 353c66b4d8dSRobert Watson label = mac_mbuf_to_label(mbuf); 354c66b4d8dSRobert Watson 355c66b4d8dSRobert Watson MAC_CHECK(check_socket_deliver, socket, socket->so_label, mbuf, 356c66b4d8dSRobert Watson label); 357c66b4d8dSRobert Watson 358c66b4d8dSRobert Watson return (error); 359c66b4d8dSRobert Watson } 360c66b4d8dSRobert Watson 361c66b4d8dSRobert Watson int 362c66b4d8dSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 363c66b4d8dSRobert Watson { 364c66b4d8dSRobert Watson int error; 365c66b4d8dSRobert Watson 366310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 367310e7cebSRobert Watson 368c66b4d8dSRobert Watson if (!mac_enforce_socket) 369c66b4d8dSRobert Watson return (0); 370c66b4d8dSRobert Watson 371c66b4d8dSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, socket->so_label); 372c66b4d8dSRobert Watson return (error); 373c66b4d8dSRobert Watson } 374c66b4d8dSRobert Watson 375c66b4d8dSRobert Watson int 3767f53207bSRobert Watson mac_check_socket_poll(struct ucred *cred, struct socket *so) 3777f53207bSRobert Watson { 3787f53207bSRobert Watson int error; 3797f53207bSRobert Watson 3807f53207bSRobert Watson SOCK_LOCK_ASSERT(so); 3817f53207bSRobert Watson 3827f53207bSRobert Watson if (!mac_enforce_socket) 3837f53207bSRobert Watson return (0); 3847f53207bSRobert Watson 3857f53207bSRobert Watson MAC_CHECK(check_socket_poll, cred, so, so->so_label); 3867f53207bSRobert Watson return (error); 3877f53207bSRobert Watson } 3887f53207bSRobert Watson 3897f53207bSRobert Watson int 390c66b4d8dSRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so) 391c66b4d8dSRobert Watson { 392c66b4d8dSRobert Watson int error; 393c66b4d8dSRobert Watson 394310e7cebSRobert Watson SOCK_LOCK_ASSERT(so); 395310e7cebSRobert Watson 396c66b4d8dSRobert Watson if (!mac_enforce_socket) 397c66b4d8dSRobert Watson return (0); 398c66b4d8dSRobert Watson 399c66b4d8dSRobert Watson MAC_CHECK(check_socket_receive, cred, so, so->so_label); 400c66b4d8dSRobert Watson 401c66b4d8dSRobert Watson return (error); 402c66b4d8dSRobert Watson } 403c66b4d8dSRobert Watson 404c66b4d8dSRobert Watson static int 405c66b4d8dSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 406c66b4d8dSRobert Watson struct label *newlabel) 407c66b4d8dSRobert Watson { 408c66b4d8dSRobert Watson int error; 409c66b4d8dSRobert Watson 410310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 411310e7cebSRobert Watson 412c66b4d8dSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, socket->so_label, 413c66b4d8dSRobert Watson newlabel); 414c66b4d8dSRobert Watson 415c66b4d8dSRobert Watson return (error); 416c66b4d8dSRobert Watson } 417c66b4d8dSRobert Watson 418c66b4d8dSRobert Watson int 419c66b4d8dSRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so) 420c66b4d8dSRobert Watson { 421c66b4d8dSRobert Watson int error; 422c66b4d8dSRobert Watson 423310e7cebSRobert Watson SOCK_LOCK_ASSERT(so); 424310e7cebSRobert Watson 425c66b4d8dSRobert Watson if (!mac_enforce_socket) 426c66b4d8dSRobert Watson return (0); 427c66b4d8dSRobert Watson 428c66b4d8dSRobert Watson MAC_CHECK(check_socket_send, cred, so, so->so_label); 429c66b4d8dSRobert Watson 430c66b4d8dSRobert Watson return (error); 431c66b4d8dSRobert Watson } 432c66b4d8dSRobert Watson 433c66b4d8dSRobert Watson int 4347f53207bSRobert Watson mac_check_socket_stat(struct ucred *cred, struct socket *so) 4357f53207bSRobert Watson { 4367f53207bSRobert Watson int error; 4377f53207bSRobert Watson 4387f53207bSRobert Watson SOCK_LOCK_ASSERT(so); 4397f53207bSRobert Watson 4407f53207bSRobert Watson if (!mac_enforce_socket) 4417f53207bSRobert Watson return (0); 4427f53207bSRobert Watson 4437f53207bSRobert Watson MAC_CHECK(check_socket_stat, cred, so, so->so_label); 4447f53207bSRobert Watson 4457f53207bSRobert Watson return (error); 4467f53207bSRobert Watson } 4477f53207bSRobert Watson 4487f53207bSRobert Watson int 449c66b4d8dSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 450c66b4d8dSRobert Watson { 451c66b4d8dSRobert Watson int error; 452c66b4d8dSRobert Watson 453310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 454310e7cebSRobert Watson 455c66b4d8dSRobert Watson if (!mac_enforce_socket) 456c66b4d8dSRobert Watson return (0); 457c66b4d8dSRobert Watson 458c66b4d8dSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, socket->so_label); 459c66b4d8dSRobert Watson 460c66b4d8dSRobert Watson return (error); 461c66b4d8dSRobert Watson } 462c66b4d8dSRobert Watson 463c66b4d8dSRobert Watson int 464c66b4d8dSRobert Watson mac_socket_label_set(struct ucred *cred, struct socket *so, 465c66b4d8dSRobert Watson struct label *label) 466c66b4d8dSRobert Watson { 467c66b4d8dSRobert Watson int error; 468c66b4d8dSRobert Watson 469310e7cebSRobert Watson /* 470310e7cebSRobert Watson * We acquire the socket lock when we perform the test and set, 471310e7cebSRobert Watson * but have to release it as the pcb code needs to acquire the 472310e7cebSRobert Watson * pcb lock, which will precede the socket lock in the lock 473310e7cebSRobert Watson * order. However, this is fine, as any race will simply 474310e7cebSRobert Watson * result in the inpcb being refreshed twice, but still 475310e7cebSRobert Watson * consistently, as the inpcb code will acquire the socket lock 476310e7cebSRobert Watson * before refreshing, holding both locks. 477310e7cebSRobert Watson */ 478310e7cebSRobert Watson SOCK_LOCK(so); 479c66b4d8dSRobert Watson error = mac_check_socket_relabel(cred, so, label); 480310e7cebSRobert Watson if (error) { 481310e7cebSRobert Watson SOCK_UNLOCK(so); 482c66b4d8dSRobert Watson return (error); 483310e7cebSRobert Watson } 484c66b4d8dSRobert Watson 485c66b4d8dSRobert Watson mac_relabel_socket(cred, so, label); 486310e7cebSRobert Watson SOCK_UNLOCK(so); 487c66b4d8dSRobert Watson /* 488c66b4d8dSRobert Watson * If the protocol has expressed interest in socket layer changes, 489c66b4d8dSRobert Watson * such as if it needs to propagate changes to a cached pcb 490c66b4d8dSRobert Watson * label from the socket, notify it of the label change while 491c66b4d8dSRobert Watson * holding the socket lock. 492c66b4d8dSRobert Watson */ 493c66b4d8dSRobert Watson if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL) 494c66b4d8dSRobert Watson (so->so_proto->pr_usrreqs->pru_sosetlabel)(so); 495c66b4d8dSRobert Watson 496c66b4d8dSRobert Watson return (0); 497c66b4d8dSRobert Watson } 498c66b4d8dSRobert Watson 499c66b4d8dSRobert Watson int 500c66b4d8dSRobert Watson mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 501c66b4d8dSRobert Watson { 502c66b4d8dSRobert Watson struct label *intlabel; 503c66b4d8dSRobert Watson char *buffer; 504c66b4d8dSRobert Watson int error; 505c66b4d8dSRobert Watson 506c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 507c66b4d8dSRobert Watson if (error) 508c66b4d8dSRobert Watson return (error); 509c66b4d8dSRobert Watson 510c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 511c66b4d8dSRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 512c66b4d8dSRobert Watson if (error) { 513c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 514c66b4d8dSRobert Watson return (error); 515c66b4d8dSRobert Watson } 516c66b4d8dSRobert Watson 517c66b4d8dSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 518c66b4d8dSRobert Watson error = mac_internalize_socket_label(intlabel, buffer); 519c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 520c66b4d8dSRobert Watson if (error) 521c66b4d8dSRobert Watson goto out; 522c66b4d8dSRobert Watson 523c66b4d8dSRobert Watson error = mac_socket_label_set(cred, so, intlabel); 524c66b4d8dSRobert Watson out: 525c66b4d8dSRobert Watson mac_socket_label_free(intlabel); 526c66b4d8dSRobert Watson return (error); 527c66b4d8dSRobert Watson } 528c66b4d8dSRobert Watson 529c66b4d8dSRobert Watson int 530c66b4d8dSRobert Watson mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 531c66b4d8dSRobert Watson { 532c66b4d8dSRobert Watson char *buffer, *elements; 533310e7cebSRobert Watson struct label *intlabel; 534c66b4d8dSRobert Watson int error; 535c66b4d8dSRobert Watson 536c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 537c66b4d8dSRobert Watson if (error) 538c66b4d8dSRobert Watson return (error); 539c66b4d8dSRobert Watson 540c66b4d8dSRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 541c66b4d8dSRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 542c66b4d8dSRobert Watson if (error) { 543c66b4d8dSRobert Watson free(elements, M_MACTEMP); 544c66b4d8dSRobert Watson return (error); 545c66b4d8dSRobert Watson } 546c66b4d8dSRobert Watson 547c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 548310e7cebSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 549310e7cebSRobert Watson SOCK_LOCK(so); 550310e7cebSRobert Watson mac_copy_socket_label(so->so_label, intlabel); 551310e7cebSRobert Watson SOCK_UNLOCK(so); 552310e7cebSRobert Watson error = mac_externalize_socket_label(intlabel, elements, buffer, 553310e7cebSRobert Watson mac->m_buflen); 554310e7cebSRobert Watson mac_socket_label_free(intlabel); 555c66b4d8dSRobert Watson if (error == 0) 556c66b4d8dSRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 557c66b4d8dSRobert Watson 558c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 559c66b4d8dSRobert Watson free(elements, M_MACTEMP); 560c66b4d8dSRobert Watson 561c66b4d8dSRobert Watson return (error); 562c66b4d8dSRobert Watson } 563c66b4d8dSRobert Watson 564c66b4d8dSRobert Watson int 565c66b4d8dSRobert Watson mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so, 566c66b4d8dSRobert Watson struct mac *mac) 567c66b4d8dSRobert Watson { 568c66b4d8dSRobert Watson char *elements, *buffer; 569310e7cebSRobert Watson struct label *intlabel; 570c66b4d8dSRobert Watson int error; 571c66b4d8dSRobert Watson 572c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 573c66b4d8dSRobert Watson if (error) 574c66b4d8dSRobert Watson return (error); 575c66b4d8dSRobert Watson 576c66b4d8dSRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 577c66b4d8dSRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 578c66b4d8dSRobert Watson if (error) { 579c66b4d8dSRobert Watson free(elements, M_MACTEMP); 580c66b4d8dSRobert Watson return (error); 581c66b4d8dSRobert Watson } 582c66b4d8dSRobert Watson 583c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 584310e7cebSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 585310e7cebSRobert Watson SOCK_LOCK(so); 586310e7cebSRobert Watson mac_copy_socket_label(so->so_peerlabel, intlabel); 587310e7cebSRobert Watson SOCK_UNLOCK(so); 588310e7cebSRobert Watson error = mac_externalize_socket_peer_label(intlabel, elements, buffer, 589310e7cebSRobert Watson mac->m_buflen); 590310e7cebSRobert Watson mac_socket_label_free(intlabel); 591c66b4d8dSRobert Watson if (error == 0) 592c66b4d8dSRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 593c66b4d8dSRobert Watson 594c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 595c66b4d8dSRobert Watson free(elements, M_MACTEMP); 596c66b4d8dSRobert Watson 597c66b4d8dSRobert Watson return (error); 598c66b4d8dSRobert Watson } 599