1c66b4d8dSRobert Watson /*- 2c66b4d8dSRobert Watson * Copyright (c) 1999-2002 Robert N. M. Watson 3c66b4d8dSRobert Watson * Copyright (c) 2001 Ilmar S. Habibulin 4c66b4d8dSRobert Watson * Copyright (c) 2001-2004 Networks Associates Technology, Inc. 5c66b4d8dSRobert Watson * All rights reserved. 6c66b4d8dSRobert Watson * 7c66b4d8dSRobert Watson * This software was developed by Robert Watson and Ilmar Habibulin for the 8c66b4d8dSRobert Watson * TrustedBSD Project. 9c66b4d8dSRobert Watson * 10c66b4d8dSRobert Watson * This software was developed for the FreeBSD Project in part by Network 11c66b4d8dSRobert Watson * Associates Laboratories, the Security Research Division of Network 12c66b4d8dSRobert Watson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), 13c66b4d8dSRobert Watson * as part of the DARPA CHATS research program. 14c66b4d8dSRobert Watson * 15c66b4d8dSRobert Watson * Redistribution and use in source and binary forms, with or without 16c66b4d8dSRobert Watson * modification, are permitted provided that the following conditions 17c66b4d8dSRobert Watson * are met: 18c66b4d8dSRobert Watson * 1. Redistributions of source code must retain the above copyright 19c66b4d8dSRobert Watson * notice, this list of conditions and the following disclaimer. 20c66b4d8dSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 21c66b4d8dSRobert Watson * notice, this list of conditions and the following disclaimer in the 22c66b4d8dSRobert Watson * documentation and/or other materials provided with the distribution. 23c66b4d8dSRobert Watson * 24c66b4d8dSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25c66b4d8dSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26c66b4d8dSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27c66b4d8dSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28c66b4d8dSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29c66b4d8dSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30c66b4d8dSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31c66b4d8dSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32c66b4d8dSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33c66b4d8dSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34c66b4d8dSRobert Watson * SUCH DAMAGE. 35c66b4d8dSRobert Watson */ 36c66b4d8dSRobert Watson 37c66b4d8dSRobert Watson #include <sys/cdefs.h> 38c66b4d8dSRobert Watson __FBSDID("$FreeBSD$"); 39c66b4d8dSRobert Watson 40c66b4d8dSRobert Watson #include "opt_mac.h" 41c66b4d8dSRobert Watson 42c66b4d8dSRobert Watson #include <sys/param.h> 43c66b4d8dSRobert Watson #include <sys/kernel.h> 44c66b4d8dSRobert Watson #include <sys/lock.h> 45c66b4d8dSRobert Watson #include <sys/malloc.h> 46c66b4d8dSRobert Watson #include <sys/mutex.h> 47c66b4d8dSRobert Watson #include <sys/mac.h> 48c66b4d8dSRobert Watson #include <sys/sbuf.h> 49c66b4d8dSRobert Watson #include <sys/systm.h> 50c66b4d8dSRobert Watson #include <sys/mount.h> 51c66b4d8dSRobert Watson #include <sys/file.h> 52c66b4d8dSRobert Watson #include <sys/namei.h> 53c66b4d8dSRobert Watson #include <sys/protosw.h> 54c66b4d8dSRobert Watson #include <sys/socket.h> 55c66b4d8dSRobert Watson #include <sys/socketvar.h> 56c66b4d8dSRobert Watson #include <sys/sysctl.h> 57c66b4d8dSRobert Watson 58c66b4d8dSRobert Watson #include <sys/mac_policy.h> 59c66b4d8dSRobert Watson 60c66b4d8dSRobert Watson #include <net/bpfdesc.h> 61c66b4d8dSRobert Watson #include <net/if.h> 62c66b4d8dSRobert Watson #include <net/if_var.h> 63c66b4d8dSRobert Watson 64c66b4d8dSRobert Watson #include <netinet/in.h> 65c66b4d8dSRobert Watson #include <netinet/in_pcb.h> 66c66b4d8dSRobert Watson #include <netinet/ip_var.h> 67c66b4d8dSRobert Watson 68c66b4d8dSRobert Watson #include <security/mac/mac_internal.h> 69c66b4d8dSRobert Watson 70c66b4d8dSRobert Watson /* 71c66b4d8dSRobert Watson * mac_enforce_socket is used by the inet code when delivering to an inpcb 72c66b4d8dSRobert Watson * without hitting the socket layer, and has to be non-static for now. 73c66b4d8dSRobert Watson */ 74c66b4d8dSRobert Watson int mac_enforce_socket = 1; 75c66b4d8dSRobert Watson SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW, 76c66b4d8dSRobert Watson &mac_enforce_socket, 0, "Enforce MAC policy on socket operations"); 77c66b4d8dSRobert Watson TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket); 78c66b4d8dSRobert Watson 79c66b4d8dSRobert Watson #ifdef MAC_DEBUG 80c66b4d8dSRobert Watson static unsigned int nmacsockets; 81c66b4d8dSRobert Watson 82c66b4d8dSRobert Watson SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD, 83c66b4d8dSRobert Watson &nmacsockets, 0, "number of sockets in use"); 84c66b4d8dSRobert Watson #endif 85c66b4d8dSRobert Watson 86c66b4d8dSRobert Watson struct label * 87c66b4d8dSRobert Watson mac_socket_label_alloc(int flag) 88c66b4d8dSRobert Watson { 89c66b4d8dSRobert Watson struct label *label; 90c66b4d8dSRobert Watson int error; 91c66b4d8dSRobert Watson 92c66b4d8dSRobert Watson label = mac_labelzone_alloc(flag); 93c66b4d8dSRobert Watson if (label == NULL) 94c66b4d8dSRobert Watson return (NULL); 95c66b4d8dSRobert Watson 96c66b4d8dSRobert Watson MAC_CHECK(init_socket_label, label, flag); 97c66b4d8dSRobert Watson if (error) { 98c66b4d8dSRobert Watson MAC_PERFORM(destroy_socket_label, label); 99c66b4d8dSRobert Watson mac_labelzone_free(label); 100c66b4d8dSRobert Watson return (NULL); 101c66b4d8dSRobert Watson } 102c66b4d8dSRobert Watson MAC_DEBUG_COUNTER_INC(&nmacsockets); 103c66b4d8dSRobert Watson return (label); 104c66b4d8dSRobert Watson } 105c66b4d8dSRobert Watson 106c66b4d8dSRobert Watson static struct label * 107c66b4d8dSRobert Watson mac_socket_peer_label_alloc(int flag) 108c66b4d8dSRobert Watson { 109c66b4d8dSRobert Watson struct label *label; 110c66b4d8dSRobert Watson int error; 111c66b4d8dSRobert Watson 112c66b4d8dSRobert Watson label = mac_labelzone_alloc(flag); 113c66b4d8dSRobert Watson if (label == NULL) 114c66b4d8dSRobert Watson return (NULL); 115c66b4d8dSRobert Watson 116c66b4d8dSRobert Watson MAC_CHECK(init_socket_peer_label, label, flag); 117c66b4d8dSRobert Watson if (error) { 118c66b4d8dSRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 119c66b4d8dSRobert Watson mac_labelzone_free(label); 120c66b4d8dSRobert Watson return (NULL); 121c66b4d8dSRobert Watson } 122c66b4d8dSRobert Watson MAC_DEBUG_COUNTER_INC(&nmacsockets); 123c66b4d8dSRobert Watson return (label); 124c66b4d8dSRobert Watson } 125c66b4d8dSRobert Watson 126c66b4d8dSRobert Watson int 127c66b4d8dSRobert Watson mac_init_socket(struct socket *so, int flag) 128c66b4d8dSRobert Watson { 129c66b4d8dSRobert Watson 130c66b4d8dSRobert Watson so->so_label = mac_socket_label_alloc(flag); 131c66b4d8dSRobert Watson if (so->so_label == NULL) 132c66b4d8dSRobert Watson return (ENOMEM); 133c66b4d8dSRobert Watson so->so_peerlabel = mac_socket_peer_label_alloc(flag); 134c66b4d8dSRobert Watson if (so->so_peerlabel == NULL) { 135c66b4d8dSRobert Watson mac_socket_label_free(so->so_label); 136c66b4d8dSRobert Watson so->so_label = NULL; 137c66b4d8dSRobert Watson return (ENOMEM); 138c66b4d8dSRobert Watson } 139c66b4d8dSRobert Watson return (0); 140c66b4d8dSRobert Watson } 141c66b4d8dSRobert Watson 142c66b4d8dSRobert Watson void 143c66b4d8dSRobert Watson mac_socket_label_free(struct label *label) 144c66b4d8dSRobert Watson { 145c66b4d8dSRobert Watson 146c66b4d8dSRobert Watson MAC_PERFORM(destroy_socket_label, label); 147c66b4d8dSRobert Watson mac_labelzone_free(label); 148c66b4d8dSRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacsockets); 149c66b4d8dSRobert Watson } 150c66b4d8dSRobert Watson 151c66b4d8dSRobert Watson static void 152c66b4d8dSRobert Watson mac_socket_peer_label_free(struct label *label) 153c66b4d8dSRobert Watson { 154c66b4d8dSRobert Watson 155c66b4d8dSRobert Watson MAC_PERFORM(destroy_socket_peer_label, label); 156c66b4d8dSRobert Watson mac_labelzone_free(label); 157c66b4d8dSRobert Watson MAC_DEBUG_COUNTER_DEC(&nmacsockets); 158c66b4d8dSRobert Watson } 159c66b4d8dSRobert Watson 160c66b4d8dSRobert Watson void 161c66b4d8dSRobert Watson mac_destroy_socket(struct socket *socket) 162c66b4d8dSRobert Watson { 163c66b4d8dSRobert Watson 164c66b4d8dSRobert Watson mac_socket_label_free(socket->so_label); 165c66b4d8dSRobert Watson socket->so_label = NULL; 166c66b4d8dSRobert Watson mac_socket_peer_label_free(socket->so_peerlabel); 167c66b4d8dSRobert Watson socket->so_peerlabel = NULL; 168c66b4d8dSRobert Watson } 169c66b4d8dSRobert Watson 170c66b4d8dSRobert Watson void 171c66b4d8dSRobert Watson mac_copy_socket_label(struct label *src, struct label *dest) 172c66b4d8dSRobert Watson { 173c66b4d8dSRobert Watson 174c66b4d8dSRobert Watson MAC_PERFORM(copy_socket_label, src, dest); 175c66b4d8dSRobert Watson } 176c66b4d8dSRobert Watson 177c66b4d8dSRobert Watson int 178c66b4d8dSRobert Watson mac_externalize_socket_label(struct label *label, char *elements, 179c66b4d8dSRobert Watson char *outbuf, size_t outbuflen) 180c66b4d8dSRobert Watson { 181c66b4d8dSRobert Watson int error; 182c66b4d8dSRobert Watson 183c66b4d8dSRobert Watson MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen); 184c66b4d8dSRobert Watson 185c66b4d8dSRobert Watson return (error); 186c66b4d8dSRobert Watson } 187c66b4d8dSRobert Watson 188c66b4d8dSRobert Watson static int 189c66b4d8dSRobert Watson mac_externalize_socket_peer_label(struct label *label, char *elements, 190c66b4d8dSRobert Watson char *outbuf, size_t outbuflen) 191c66b4d8dSRobert Watson { 192c66b4d8dSRobert Watson int error; 193c66b4d8dSRobert Watson 194c66b4d8dSRobert Watson MAC_EXTERNALIZE(socket_peer, label, elements, outbuf, outbuflen); 195c66b4d8dSRobert Watson 196c66b4d8dSRobert Watson return (error); 197c66b4d8dSRobert Watson } 198c66b4d8dSRobert Watson 199c66b4d8dSRobert Watson int 200c66b4d8dSRobert Watson mac_internalize_socket_label(struct label *label, char *string) 201c66b4d8dSRobert Watson { 202c66b4d8dSRobert Watson int error; 203c66b4d8dSRobert Watson 204c66b4d8dSRobert Watson MAC_INTERNALIZE(socket, label, string); 205c66b4d8dSRobert Watson 206c66b4d8dSRobert Watson return (error); 207c66b4d8dSRobert Watson } 208c66b4d8dSRobert Watson 209c66b4d8dSRobert Watson void 210c66b4d8dSRobert Watson mac_create_socket(struct ucred *cred, struct socket *socket) 211c66b4d8dSRobert Watson { 212c66b4d8dSRobert Watson 213c66b4d8dSRobert Watson MAC_PERFORM(create_socket, cred, socket, socket->so_label); 214c66b4d8dSRobert Watson } 215c66b4d8dSRobert Watson 216c66b4d8dSRobert Watson void 217c66b4d8dSRobert Watson mac_create_socket_from_socket(struct socket *oldsocket, 218c66b4d8dSRobert Watson struct socket *newsocket) 219c66b4d8dSRobert Watson { 220c66b4d8dSRobert Watson 221310e7cebSRobert Watson SOCK_LOCK_ASSERT(oldsocket); 222c66b4d8dSRobert Watson MAC_PERFORM(create_socket_from_socket, oldsocket, oldsocket->so_label, 223c66b4d8dSRobert Watson newsocket, newsocket->so_label); 224c66b4d8dSRobert Watson } 225c66b4d8dSRobert Watson 226c66b4d8dSRobert Watson static void 227c66b4d8dSRobert Watson mac_relabel_socket(struct ucred *cred, struct socket *socket, 228c66b4d8dSRobert Watson struct label *newlabel) 229c66b4d8dSRobert Watson { 230c66b4d8dSRobert Watson 231310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 232c66b4d8dSRobert Watson MAC_PERFORM(relabel_socket, cred, socket, socket->so_label, newlabel); 233c66b4d8dSRobert Watson } 234c66b4d8dSRobert Watson 235c66b4d8dSRobert Watson void 236c66b4d8dSRobert Watson mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket) 237c66b4d8dSRobert Watson { 238c66b4d8dSRobert Watson struct label *label; 239c66b4d8dSRobert Watson 240310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 241310e7cebSRobert Watson 242c66b4d8dSRobert Watson label = mac_mbuf_to_label(mbuf); 243c66b4d8dSRobert Watson 244c66b4d8dSRobert Watson MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket, 245c66b4d8dSRobert Watson socket->so_peerlabel); 246c66b4d8dSRobert Watson } 247c66b4d8dSRobert Watson 248c66b4d8dSRobert Watson void 249c66b4d8dSRobert Watson mac_set_socket_peer_from_socket(struct socket *oldsocket, 250c66b4d8dSRobert Watson struct socket *newsocket) 251c66b4d8dSRobert Watson { 252c66b4d8dSRobert Watson 253310e7cebSRobert Watson /* 254310e7cebSRobert Watson * XXXRW: only hold the socket lock on one at a time, as one 255310e7cebSRobert Watson * socket is the original, and one is the new. However, it's 256310e7cebSRobert Watson * called in both directions, so we can't assert the lock 257310e7cebSRobert Watson * here currently. 258310e7cebSRobert Watson */ 259c66b4d8dSRobert Watson MAC_PERFORM(set_socket_peer_from_socket, oldsocket, 260c66b4d8dSRobert Watson oldsocket->so_label, newsocket, newsocket->so_peerlabel); 261c66b4d8dSRobert Watson } 262c66b4d8dSRobert Watson 263c66b4d8dSRobert Watson void 264c66b4d8dSRobert Watson mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf) 265c66b4d8dSRobert Watson { 266c66b4d8dSRobert Watson struct label *label; 267c66b4d8dSRobert Watson 268c66b4d8dSRobert Watson label = mac_mbuf_to_label(mbuf); 269c66b4d8dSRobert Watson 270310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 271c66b4d8dSRobert Watson MAC_PERFORM(create_mbuf_from_socket, socket, socket->so_label, mbuf, 272c66b4d8dSRobert Watson label); 273c66b4d8dSRobert Watson } 274c66b4d8dSRobert Watson 275c66b4d8dSRobert Watson int 276c66b4d8dSRobert Watson mac_check_socket_bind(struct ucred *ucred, struct socket *socket, 277c66b4d8dSRobert Watson struct sockaddr *sockaddr) 278c66b4d8dSRobert Watson { 279c66b4d8dSRobert Watson int error; 280c66b4d8dSRobert Watson 281310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 282310e7cebSRobert Watson 283c66b4d8dSRobert Watson if (!mac_enforce_socket) 284c66b4d8dSRobert Watson return (0); 285c66b4d8dSRobert Watson 286c66b4d8dSRobert Watson MAC_CHECK(check_socket_bind, ucred, socket, socket->so_label, 287c66b4d8dSRobert Watson sockaddr); 288c66b4d8dSRobert Watson 289c66b4d8dSRobert Watson return (error); 290c66b4d8dSRobert Watson } 291c66b4d8dSRobert Watson 292c66b4d8dSRobert Watson int 293c66b4d8dSRobert Watson mac_check_socket_connect(struct ucred *cred, struct socket *socket, 294c66b4d8dSRobert Watson struct sockaddr *sockaddr) 295c66b4d8dSRobert Watson { 296c66b4d8dSRobert Watson int error; 297c66b4d8dSRobert Watson 298310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 299310e7cebSRobert Watson 300c66b4d8dSRobert Watson if (!mac_enforce_socket) 301c66b4d8dSRobert Watson return (0); 302c66b4d8dSRobert Watson 303c66b4d8dSRobert Watson MAC_CHECK(check_socket_connect, cred, socket, socket->so_label, 304c66b4d8dSRobert Watson sockaddr); 305c66b4d8dSRobert Watson 306c66b4d8dSRobert Watson return (error); 307c66b4d8dSRobert Watson } 308c66b4d8dSRobert Watson 309c66b4d8dSRobert Watson int 310c66b4d8dSRobert Watson mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf) 311c66b4d8dSRobert Watson { 312c66b4d8dSRobert Watson struct label *label; 313c66b4d8dSRobert Watson int error; 314c66b4d8dSRobert Watson 315310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 316310e7cebSRobert Watson 317c66b4d8dSRobert Watson if (!mac_enforce_socket) 318c66b4d8dSRobert Watson return (0); 319c66b4d8dSRobert Watson 320c66b4d8dSRobert Watson label = mac_mbuf_to_label(mbuf); 321c66b4d8dSRobert Watson 322c66b4d8dSRobert Watson MAC_CHECK(check_socket_deliver, socket, socket->so_label, mbuf, 323c66b4d8dSRobert Watson label); 324c66b4d8dSRobert Watson 325c66b4d8dSRobert Watson return (error); 326c66b4d8dSRobert Watson } 327c66b4d8dSRobert Watson 328c66b4d8dSRobert Watson int 329c66b4d8dSRobert Watson mac_check_socket_listen(struct ucred *cred, struct socket *socket) 330c66b4d8dSRobert Watson { 331c66b4d8dSRobert Watson int error; 332c66b4d8dSRobert Watson 333310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 334310e7cebSRobert Watson 335c66b4d8dSRobert Watson if (!mac_enforce_socket) 336c66b4d8dSRobert Watson return (0); 337c66b4d8dSRobert Watson 338c66b4d8dSRobert Watson MAC_CHECK(check_socket_listen, cred, socket, socket->so_label); 339c66b4d8dSRobert Watson return (error); 340c66b4d8dSRobert Watson } 341c66b4d8dSRobert Watson 342c66b4d8dSRobert Watson int 343c66b4d8dSRobert Watson mac_check_socket_receive(struct ucred *cred, struct socket *so) 344c66b4d8dSRobert Watson { 345c66b4d8dSRobert Watson int error; 346c66b4d8dSRobert Watson 347310e7cebSRobert Watson SOCK_LOCK_ASSERT(so); 348310e7cebSRobert Watson 349c66b4d8dSRobert Watson if (!mac_enforce_socket) 350c66b4d8dSRobert Watson return (0); 351c66b4d8dSRobert Watson 352c66b4d8dSRobert Watson MAC_CHECK(check_socket_receive, cred, so, so->so_label); 353c66b4d8dSRobert Watson 354c66b4d8dSRobert Watson return (error); 355c66b4d8dSRobert Watson } 356c66b4d8dSRobert Watson 357c66b4d8dSRobert Watson static int 358c66b4d8dSRobert Watson mac_check_socket_relabel(struct ucred *cred, struct socket *socket, 359c66b4d8dSRobert Watson struct label *newlabel) 360c66b4d8dSRobert Watson { 361c66b4d8dSRobert Watson int error; 362c66b4d8dSRobert Watson 363310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 364310e7cebSRobert Watson 365c66b4d8dSRobert Watson MAC_CHECK(check_socket_relabel, cred, socket, socket->so_label, 366c66b4d8dSRobert Watson newlabel); 367c66b4d8dSRobert Watson 368c66b4d8dSRobert Watson return (error); 369c66b4d8dSRobert Watson } 370c66b4d8dSRobert Watson 371c66b4d8dSRobert Watson int 372c66b4d8dSRobert Watson mac_check_socket_send(struct ucred *cred, struct socket *so) 373c66b4d8dSRobert Watson { 374c66b4d8dSRobert Watson int error; 375c66b4d8dSRobert Watson 376310e7cebSRobert Watson SOCK_LOCK_ASSERT(so); 377310e7cebSRobert Watson 378c66b4d8dSRobert Watson if (!mac_enforce_socket) 379c66b4d8dSRobert Watson return (0); 380c66b4d8dSRobert Watson 381c66b4d8dSRobert Watson MAC_CHECK(check_socket_send, cred, so, so->so_label); 382c66b4d8dSRobert Watson 383c66b4d8dSRobert Watson return (error); 384c66b4d8dSRobert Watson } 385c66b4d8dSRobert Watson 386c66b4d8dSRobert Watson int 387c66b4d8dSRobert Watson mac_check_socket_visible(struct ucred *cred, struct socket *socket) 388c66b4d8dSRobert Watson { 389c66b4d8dSRobert Watson int error; 390c66b4d8dSRobert Watson 391310e7cebSRobert Watson SOCK_LOCK_ASSERT(socket); 392310e7cebSRobert Watson 393c66b4d8dSRobert Watson if (!mac_enforce_socket) 394c66b4d8dSRobert Watson return (0); 395c66b4d8dSRobert Watson 396c66b4d8dSRobert Watson MAC_CHECK(check_socket_visible, cred, socket, socket->so_label); 397c66b4d8dSRobert Watson 398c66b4d8dSRobert Watson return (error); 399c66b4d8dSRobert Watson } 400c66b4d8dSRobert Watson 401c66b4d8dSRobert Watson int 402c66b4d8dSRobert Watson mac_socket_label_set(struct ucred *cred, struct socket *so, 403c66b4d8dSRobert Watson struct label *label) 404c66b4d8dSRobert Watson { 405c66b4d8dSRobert Watson int error; 406c66b4d8dSRobert Watson 407310e7cebSRobert Watson /* 408310e7cebSRobert Watson * We acquire the socket lock when we perform the test and set, 409310e7cebSRobert Watson * but have to release it as the pcb code needs to acquire the 410310e7cebSRobert Watson * pcb lock, which will precede the socket lock in the lock 411310e7cebSRobert Watson * order. However, this is fine, as any race will simply 412310e7cebSRobert Watson * result in the inpcb being refreshed twice, but still 413310e7cebSRobert Watson * consistently, as the inpcb code will acquire the socket lock 414310e7cebSRobert Watson * before refreshing, holding both locks. 415310e7cebSRobert Watson */ 416310e7cebSRobert Watson SOCK_LOCK(so); 417c66b4d8dSRobert Watson error = mac_check_socket_relabel(cred, so, label); 418310e7cebSRobert Watson if (error) { 419310e7cebSRobert Watson SOCK_UNLOCK(so); 420c66b4d8dSRobert Watson return (error); 421310e7cebSRobert Watson } 422c66b4d8dSRobert Watson 423c66b4d8dSRobert Watson mac_relabel_socket(cred, so, label); 424310e7cebSRobert Watson SOCK_UNLOCK(so); 425c66b4d8dSRobert Watson /* 426c66b4d8dSRobert Watson * If the protocol has expressed interest in socket layer changes, 427c66b4d8dSRobert Watson * such as if it needs to propagate changes to a cached pcb 428c66b4d8dSRobert Watson * label from the socket, notify it of the label change while 429c66b4d8dSRobert Watson * holding the socket lock. 430c66b4d8dSRobert Watson */ 431c66b4d8dSRobert Watson if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL) 432c66b4d8dSRobert Watson (so->so_proto->pr_usrreqs->pru_sosetlabel)(so); 433c66b4d8dSRobert Watson 434c66b4d8dSRobert Watson return (0); 435c66b4d8dSRobert Watson } 436c66b4d8dSRobert Watson 437c66b4d8dSRobert Watson int 438c66b4d8dSRobert Watson mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 439c66b4d8dSRobert Watson { 440c66b4d8dSRobert Watson struct label *intlabel; 441c66b4d8dSRobert Watson char *buffer; 442c66b4d8dSRobert Watson int error; 443c66b4d8dSRobert Watson 444c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 445c66b4d8dSRobert Watson if (error) 446c66b4d8dSRobert Watson return (error); 447c66b4d8dSRobert Watson 448c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 449c66b4d8dSRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 450c66b4d8dSRobert Watson if (error) { 451c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 452c66b4d8dSRobert Watson return (error); 453c66b4d8dSRobert Watson } 454c66b4d8dSRobert Watson 455c66b4d8dSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 456c66b4d8dSRobert Watson error = mac_internalize_socket_label(intlabel, buffer); 457c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 458c66b4d8dSRobert Watson if (error) 459c66b4d8dSRobert Watson goto out; 460c66b4d8dSRobert Watson 461c66b4d8dSRobert Watson error = mac_socket_label_set(cred, so, intlabel); 462c66b4d8dSRobert Watson out: 463c66b4d8dSRobert Watson mac_socket_label_free(intlabel); 464c66b4d8dSRobert Watson return (error); 465c66b4d8dSRobert Watson } 466c66b4d8dSRobert Watson 467c66b4d8dSRobert Watson int 468c66b4d8dSRobert Watson mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 469c66b4d8dSRobert Watson { 470c66b4d8dSRobert Watson char *buffer, *elements; 471310e7cebSRobert Watson struct label *intlabel; 472c66b4d8dSRobert Watson int error; 473c66b4d8dSRobert Watson 474c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 475c66b4d8dSRobert Watson if (error) 476c66b4d8dSRobert Watson return (error); 477c66b4d8dSRobert Watson 478c66b4d8dSRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 479c66b4d8dSRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 480c66b4d8dSRobert Watson if (error) { 481c66b4d8dSRobert Watson free(elements, M_MACTEMP); 482c66b4d8dSRobert Watson return (error); 483c66b4d8dSRobert Watson } 484c66b4d8dSRobert Watson 485c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 486310e7cebSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 487310e7cebSRobert Watson SOCK_LOCK(so); 488310e7cebSRobert Watson mac_copy_socket_label(so->so_label, intlabel); 489310e7cebSRobert Watson SOCK_UNLOCK(so); 490310e7cebSRobert Watson error = mac_externalize_socket_label(intlabel, elements, buffer, 491310e7cebSRobert Watson mac->m_buflen); 492310e7cebSRobert Watson mac_socket_label_free(intlabel); 493c66b4d8dSRobert Watson if (error == 0) 494c66b4d8dSRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 495c66b4d8dSRobert Watson 496c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 497c66b4d8dSRobert Watson free(elements, M_MACTEMP); 498c66b4d8dSRobert Watson 499c66b4d8dSRobert Watson return (error); 500c66b4d8dSRobert Watson } 501c66b4d8dSRobert Watson 502c66b4d8dSRobert Watson int 503c66b4d8dSRobert Watson mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so, 504c66b4d8dSRobert Watson struct mac *mac) 505c66b4d8dSRobert Watson { 506c66b4d8dSRobert Watson char *elements, *buffer; 507310e7cebSRobert Watson struct label *intlabel; 508c66b4d8dSRobert Watson int error; 509c66b4d8dSRobert Watson 510c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 511c66b4d8dSRobert Watson if (error) 512c66b4d8dSRobert Watson return (error); 513c66b4d8dSRobert Watson 514c66b4d8dSRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 515c66b4d8dSRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 516c66b4d8dSRobert Watson if (error) { 517c66b4d8dSRobert Watson free(elements, M_MACTEMP); 518c66b4d8dSRobert Watson return (error); 519c66b4d8dSRobert Watson } 520c66b4d8dSRobert Watson 521c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 522310e7cebSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 523310e7cebSRobert Watson SOCK_LOCK(so); 524310e7cebSRobert Watson mac_copy_socket_label(so->so_peerlabel, intlabel); 525310e7cebSRobert Watson SOCK_UNLOCK(so); 526310e7cebSRobert Watson error = mac_externalize_socket_peer_label(intlabel, elements, buffer, 527310e7cebSRobert Watson mac->m_buflen); 528310e7cebSRobert Watson mac_socket_label_free(intlabel); 529c66b4d8dSRobert Watson if (error == 0) 530c66b4d8dSRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 531c66b4d8dSRobert Watson 532c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 533c66b4d8dSRobert Watson free(elements, M_MACTEMP); 534c66b4d8dSRobert Watson 535c66b4d8dSRobert Watson return (error); 536c66b4d8dSRobert Watson } 537