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. 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 * 20c66b4d8dSRobert Watson * Redistribution and use in source and binary forms, with or without 21c66b4d8dSRobert Watson * modification, are permitted provided that the following conditions 22c66b4d8dSRobert Watson * are met: 23c66b4d8dSRobert Watson * 1. Redistributions of source code must retain the above copyright 24c66b4d8dSRobert Watson * notice, this list of conditions and the following disclaimer. 25c66b4d8dSRobert Watson * 2. Redistributions in binary form must reproduce the above copyright 26c66b4d8dSRobert Watson * notice, this list of conditions and the following disclaimer in the 27c66b4d8dSRobert Watson * documentation and/or other materials provided with the distribution. 28c66b4d8dSRobert Watson * 29c66b4d8dSRobert Watson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 30c66b4d8dSRobert Watson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31c66b4d8dSRobert Watson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32c66b4d8dSRobert Watson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 33c66b4d8dSRobert Watson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34c66b4d8dSRobert Watson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35c66b4d8dSRobert Watson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36c66b4d8dSRobert Watson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37c66b4d8dSRobert Watson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38c66b4d8dSRobert Watson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39c66b4d8dSRobert Watson * SUCH DAMAGE. 40c66b4d8dSRobert Watson */ 41c66b4d8dSRobert Watson 42c66b4d8dSRobert Watson #include <sys/cdefs.h> 43c66b4d8dSRobert Watson __FBSDID("$FreeBSD$"); 44c66b4d8dSRobert Watson 45c66b4d8dSRobert Watson #include "opt_mac.h" 46c66b4d8dSRobert Watson 47c66b4d8dSRobert Watson #include <sys/param.h> 48c66b4d8dSRobert Watson #include <sys/kernel.h> 49c66b4d8dSRobert Watson #include <sys/lock.h> 50c66b4d8dSRobert Watson #include <sys/malloc.h> 51c66b4d8dSRobert Watson #include <sys/mutex.h> 52c66b4d8dSRobert Watson #include <sys/mac.h> 53c66b4d8dSRobert Watson #include <sys/sbuf.h> 54c66b4d8dSRobert Watson #include <sys/systm.h> 55c66b4d8dSRobert Watson #include <sys/mount.h> 56c66b4d8dSRobert Watson #include <sys/file.h> 57c66b4d8dSRobert Watson #include <sys/namei.h> 58c66b4d8dSRobert Watson #include <sys/protosw.h> 59c66b4d8dSRobert Watson #include <sys/socket.h> 60c66b4d8dSRobert Watson #include <sys/socketvar.h> 61c66b4d8dSRobert Watson #include <sys/sysctl.h> 62c66b4d8dSRobert Watson 63c66b4d8dSRobert Watson #include <net/bpfdesc.h> 64c66b4d8dSRobert Watson #include <net/if.h> 65c66b4d8dSRobert Watson #include <net/if_var.h> 66c66b4d8dSRobert Watson 67c66b4d8dSRobert Watson #include <netinet/in.h> 68c66b4d8dSRobert Watson #include <netinet/in_pcb.h> 69c66b4d8dSRobert Watson #include <netinet/ip_var.h> 70c66b4d8dSRobert Watson 71aed55708SRobert Watson #include <security/mac/mac_framework.h> 72c66b4d8dSRobert Watson #include <security/mac/mac_internal.h> 730efd6615SRobert Watson #include <security/mac/mac_policy.h> 74c66b4d8dSRobert Watson 75c66b4d8dSRobert Watson /* 76df3c68e4SRobert Watson * Currently, sockets hold two labels: the label of the socket itself, and a 77df3c68e4SRobert Watson * peer label, which may be used by policies to hold a copy of the label of 78df3c68e4SRobert Watson * any remote endpoint. 79df3c68e4SRobert Watson * 80df3c68e4SRobert Watson * Possibly, this peer label should be maintained at the protocol layer 81df3c68e4SRobert Watson * (inpcb, unpcb, etc), as this would allow protocol-aware code to maintain 82df3c68e4SRobert Watson * the label consistently. For example, it might be copied live from a 83df3c68e4SRobert Watson * remote socket for UNIX domain sockets rather than keeping a local copy on 84df3c68e4SRobert Watson * this endpoint, but be cached and updated based on packets received for 85df3c68e4SRobert Watson * TCP/IP. 86df3c68e4SRobert Watson */ 87df3c68e4SRobert Watson 88c66b4d8dSRobert Watson struct label * 89c66b4d8dSRobert Watson mac_socket_label_alloc(int flag) 90c66b4d8dSRobert Watson { 91c66b4d8dSRobert Watson struct label *label; 92c66b4d8dSRobert Watson int error; 93c66b4d8dSRobert Watson 94c66b4d8dSRobert Watson label = mac_labelzone_alloc(flag); 95c66b4d8dSRobert Watson if (label == NULL) 96c66b4d8dSRobert Watson return (NULL); 97c66b4d8dSRobert Watson 9830d239bcSRobert Watson MAC_CHECK(socket_init_label, label, flag); 99c66b4d8dSRobert Watson if (error) { 10030d239bcSRobert Watson MAC_PERFORM(socket_destroy_label, label); 101c66b4d8dSRobert Watson mac_labelzone_free(label); 102c66b4d8dSRobert Watson return (NULL); 103c66b4d8dSRobert Watson } 104c66b4d8dSRobert Watson return (label); 105c66b4d8dSRobert Watson } 106c66b4d8dSRobert Watson 107c66b4d8dSRobert Watson static struct label * 10830d239bcSRobert Watson mac_socketpeer_label_alloc(int flag) 109c66b4d8dSRobert Watson { 110c66b4d8dSRobert Watson struct label *label; 111c66b4d8dSRobert Watson int error; 112c66b4d8dSRobert Watson 113c66b4d8dSRobert Watson label = mac_labelzone_alloc(flag); 114c66b4d8dSRobert Watson if (label == NULL) 115c66b4d8dSRobert Watson return (NULL); 116c66b4d8dSRobert Watson 11730d239bcSRobert Watson MAC_CHECK(socketpeer_init_label, label, flag); 118c66b4d8dSRobert Watson if (error) { 11930d239bcSRobert Watson MAC_PERFORM(socketpeer_destroy_label, label); 120c66b4d8dSRobert Watson mac_labelzone_free(label); 121c66b4d8dSRobert Watson return (NULL); 122c66b4d8dSRobert Watson } 123c66b4d8dSRobert Watson return (label); 124c66b4d8dSRobert Watson } 125c66b4d8dSRobert Watson 126c66b4d8dSRobert Watson int 12730d239bcSRobert Watson mac_socket_init(struct socket *so, int flag) 128c66b4d8dSRobert Watson { 129c66b4d8dSRobert Watson 1306356dba0SRobert Watson if (mac_labeled & MPC_OBJECT_SOCKET) { 131c66b4d8dSRobert Watson so->so_label = mac_socket_label_alloc(flag); 132c66b4d8dSRobert Watson if (so->so_label == NULL) 133c66b4d8dSRobert Watson return (ENOMEM); 13430d239bcSRobert Watson so->so_peerlabel = mac_socketpeer_label_alloc(flag); 135c66b4d8dSRobert Watson if (so->so_peerlabel == NULL) { 136c66b4d8dSRobert Watson mac_socket_label_free(so->so_label); 137c66b4d8dSRobert Watson so->so_label = NULL; 138c66b4d8dSRobert Watson return (ENOMEM); 139c66b4d8dSRobert Watson } 1406356dba0SRobert Watson } else { 1416356dba0SRobert Watson so->so_label = NULL; 1426356dba0SRobert Watson so->so_peerlabel = NULL; 1436356dba0SRobert Watson } 144c66b4d8dSRobert Watson return (0); 145c66b4d8dSRobert Watson } 146c66b4d8dSRobert Watson 147c66b4d8dSRobert Watson void 148c66b4d8dSRobert Watson mac_socket_label_free(struct label *label) 149c66b4d8dSRobert Watson { 150c66b4d8dSRobert Watson 15130d239bcSRobert Watson MAC_PERFORM(socket_destroy_label, label); 152c66b4d8dSRobert Watson mac_labelzone_free(label); 153c66b4d8dSRobert Watson } 154c66b4d8dSRobert Watson 155c66b4d8dSRobert Watson static void 15630d239bcSRobert Watson mac_socketpeer_label_free(struct label *label) 157c66b4d8dSRobert Watson { 158c66b4d8dSRobert Watson 15930d239bcSRobert Watson MAC_PERFORM(socketpeer_destroy_label, label); 160c66b4d8dSRobert Watson mac_labelzone_free(label); 161c66b4d8dSRobert Watson } 162c66b4d8dSRobert Watson 163c66b4d8dSRobert Watson void 16430d239bcSRobert Watson mac_socket_destroy(struct socket *so) 165c66b4d8dSRobert Watson { 166c66b4d8dSRobert Watson 1676356dba0SRobert Watson if (so->so_label != NULL) { 16826ae2b86SRobert Watson mac_socket_label_free(so->so_label); 16926ae2b86SRobert Watson so->so_label = NULL; 17030d239bcSRobert Watson mac_socketpeer_label_free(so->so_peerlabel); 17126ae2b86SRobert Watson so->so_peerlabel = NULL; 172c66b4d8dSRobert Watson } 1736356dba0SRobert Watson } 174c66b4d8dSRobert Watson 175c66b4d8dSRobert Watson void 17630d239bcSRobert Watson mac_socket_copy_label(struct label *src, struct label *dest) 177c66b4d8dSRobert Watson { 178c66b4d8dSRobert Watson 17930d239bcSRobert Watson MAC_PERFORM(socket_copy_label, src, dest); 180c66b4d8dSRobert Watson } 181c66b4d8dSRobert Watson 182c66b4d8dSRobert Watson int 18330d239bcSRobert Watson mac_socket_externalize_label(struct label *label, char *elements, 184c66b4d8dSRobert Watson char *outbuf, size_t outbuflen) 185c66b4d8dSRobert Watson { 186c66b4d8dSRobert Watson int error; 187c66b4d8dSRobert Watson 188c66b4d8dSRobert Watson MAC_EXTERNALIZE(socket, label, elements, outbuf, outbuflen); 189c66b4d8dSRobert Watson 190c66b4d8dSRobert Watson return (error); 191c66b4d8dSRobert Watson } 192c66b4d8dSRobert Watson 193c66b4d8dSRobert Watson static int 19430d239bcSRobert Watson mac_socketpeer_externalize_label(struct label *label, char *elements, 195c66b4d8dSRobert Watson char *outbuf, size_t outbuflen) 196c66b4d8dSRobert Watson { 197c66b4d8dSRobert Watson int error; 198c66b4d8dSRobert Watson 19930d239bcSRobert Watson MAC_EXTERNALIZE(socketpeer, label, elements, outbuf, outbuflen); 200c66b4d8dSRobert Watson 201c66b4d8dSRobert Watson return (error); 202c66b4d8dSRobert Watson } 203c66b4d8dSRobert Watson 204c66b4d8dSRobert Watson int 20530d239bcSRobert Watson mac_socket_internalize_label(struct label *label, char *string) 206c66b4d8dSRobert Watson { 207c66b4d8dSRobert Watson int error; 208c66b4d8dSRobert Watson 209c66b4d8dSRobert Watson MAC_INTERNALIZE(socket, label, string); 210c66b4d8dSRobert Watson 211c66b4d8dSRobert Watson return (error); 212c66b4d8dSRobert Watson } 213c66b4d8dSRobert Watson 214c66b4d8dSRobert Watson void 21530d239bcSRobert Watson mac_socket_create(struct ucred *cred, struct socket *so) 216c66b4d8dSRobert Watson { 217c66b4d8dSRobert Watson 21830d239bcSRobert Watson MAC_PERFORM(socket_create, cred, so, so->so_label); 219c66b4d8dSRobert Watson } 220c66b4d8dSRobert Watson 221c66b4d8dSRobert Watson void 22230d239bcSRobert Watson mac_socket_newconn(struct socket *oldso, struct socket *newso) 223c66b4d8dSRobert Watson { 224c66b4d8dSRobert Watson 22526ae2b86SRobert Watson SOCK_LOCK_ASSERT(oldso); 22626ae2b86SRobert Watson 22730d239bcSRobert Watson MAC_PERFORM(socket_newconn, oldso, oldso->so_label, newso, 22826ae2b86SRobert Watson newso->so_label); 229c66b4d8dSRobert Watson } 230c66b4d8dSRobert Watson 231c66b4d8dSRobert Watson static void 23230d239bcSRobert Watson mac_socket_relabel(struct ucred *cred, struct socket *so, 233c66b4d8dSRobert Watson struct label *newlabel) 234c66b4d8dSRobert Watson { 235c66b4d8dSRobert Watson 23626ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 23726ae2b86SRobert Watson 23830d239bcSRobert Watson MAC_PERFORM(socket_relabel, cred, so, so->so_label, newlabel); 239c66b4d8dSRobert Watson } 240c66b4d8dSRobert Watson 241c66b4d8dSRobert Watson void 24230d239bcSRobert Watson mac_socketpeer_set_from_mbuf(struct mbuf *m, struct socket *so) 243c66b4d8dSRobert Watson { 244c66b4d8dSRobert Watson struct label *label; 245c66b4d8dSRobert Watson 24626ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 247310e7cebSRobert Watson 24826ae2b86SRobert Watson label = mac_mbuf_to_label(m); 249c66b4d8dSRobert Watson 25030d239bcSRobert Watson MAC_PERFORM(socketpeer_set_from_mbuf, m, label, so, 25126ae2b86SRobert Watson so->so_peerlabel); 252c66b4d8dSRobert Watson } 253c66b4d8dSRobert Watson 254c66b4d8dSRobert Watson void 25530d239bcSRobert Watson mac_socketpeer_set_from_socket(struct socket *oldso, struct socket *newso) 256c66b4d8dSRobert Watson { 257c66b4d8dSRobert Watson 258310e7cebSRobert Watson /* 259df3c68e4SRobert Watson * XXXRW: only hold the socket lock on one at a time, as one socket 260df3c68e4SRobert Watson * is the original, and one is the new. However, it's called in both 261df3c68e4SRobert Watson * directions, so we can't assert the lock here currently. 262310e7cebSRobert Watson */ 26330d239bcSRobert Watson MAC_PERFORM(socketpeer_set_from_socket, oldso, oldso->so_label, 26426ae2b86SRobert Watson newso, newso->so_peerlabel); 265c66b4d8dSRobert Watson } 266c66b4d8dSRobert Watson 267c66b4d8dSRobert Watson void 26830d239bcSRobert Watson mac_socket_create_mbuf(struct socket *so, struct mbuf *m) 269c66b4d8dSRobert Watson { 270c66b4d8dSRobert Watson struct label *label; 271c66b4d8dSRobert Watson 27226ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 273c66b4d8dSRobert Watson 27426ae2b86SRobert Watson label = mac_mbuf_to_label(m); 27526ae2b86SRobert Watson 27630d239bcSRobert Watson MAC_PERFORM(socket_create_mbuf, so, so->so_label, m, label); 277c66b4d8dSRobert Watson } 278c66b4d8dSRobert Watson 279c66b4d8dSRobert Watson int 28030d239bcSRobert Watson mac_socket_check_accept(struct ucred *cred, struct socket *so) 2817f53207bSRobert Watson { 2827f53207bSRobert Watson int error; 2837f53207bSRobert Watson 28426ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 2857f53207bSRobert Watson 28630d239bcSRobert Watson MAC_CHECK(socket_check_accept, cred, so, so->so_label); 2877f53207bSRobert Watson 2887f53207bSRobert Watson return (error); 2897f53207bSRobert Watson } 2907f53207bSRobert Watson 2917f53207bSRobert Watson int 29230d239bcSRobert Watson mac_socket_check_bind(struct ucred *ucred, struct socket *so, 29326ae2b86SRobert Watson struct sockaddr *sa) 294c66b4d8dSRobert Watson { 295c66b4d8dSRobert Watson int error; 296c66b4d8dSRobert Watson 29726ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 298310e7cebSRobert Watson 29930d239bcSRobert Watson MAC_CHECK(socket_check_bind, ucred, so, so->so_label, sa); 300c66b4d8dSRobert Watson 301c66b4d8dSRobert Watson return (error); 302c66b4d8dSRobert Watson } 303c66b4d8dSRobert Watson 304c66b4d8dSRobert Watson int 30530d239bcSRobert Watson mac_socket_check_connect(struct ucred *cred, struct socket *so, 30626ae2b86SRobert Watson struct sockaddr *sa) 307c66b4d8dSRobert Watson { 308c66b4d8dSRobert Watson int error; 309c66b4d8dSRobert Watson 31026ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 311310e7cebSRobert Watson 31230d239bcSRobert Watson MAC_CHECK(socket_check_connect, cred, so, so->so_label, sa); 313c66b4d8dSRobert Watson 314c66b4d8dSRobert Watson return (error); 315c66b4d8dSRobert Watson } 316c66b4d8dSRobert Watson 317c66b4d8dSRobert Watson int 31830d239bcSRobert Watson mac_socket_check_create(struct ucred *cred, int domain, int type, int proto) 3196758f88eSRobert Watson { 3206758f88eSRobert Watson int error; 3216758f88eSRobert Watson 32230d239bcSRobert Watson MAC_CHECK(socket_check_create, cred, domain, type, proto); 3236758f88eSRobert Watson 3246758f88eSRobert Watson return (error); 3256758f88eSRobert Watson } 3266758f88eSRobert Watson 3276758f88eSRobert Watson int 32830d239bcSRobert Watson mac_socket_check_deliver(struct socket *so, struct mbuf *m) 329c66b4d8dSRobert Watson { 330c66b4d8dSRobert Watson struct label *label; 331c66b4d8dSRobert Watson int error; 332c66b4d8dSRobert Watson 33326ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 334310e7cebSRobert Watson 33526ae2b86SRobert Watson label = mac_mbuf_to_label(m); 336c66b4d8dSRobert Watson 33730d239bcSRobert Watson MAC_CHECK(socket_check_deliver, so, so->so_label, m, label); 338c66b4d8dSRobert Watson 339c66b4d8dSRobert Watson return (error); 340c66b4d8dSRobert Watson } 341c66b4d8dSRobert Watson 342c66b4d8dSRobert Watson int 34330d239bcSRobert Watson mac_socket_check_listen(struct ucred *cred, struct socket *so) 344c66b4d8dSRobert Watson { 345c66b4d8dSRobert Watson int error; 346c66b4d8dSRobert Watson 34726ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 348310e7cebSRobert Watson 34930d239bcSRobert Watson MAC_CHECK(socket_check_listen, cred, so, so->so_label); 35026ae2b86SRobert Watson 351c66b4d8dSRobert Watson return (error); 352c66b4d8dSRobert Watson } 353c66b4d8dSRobert Watson 354c66b4d8dSRobert Watson int 35530d239bcSRobert Watson mac_socket_check_poll(struct ucred *cred, struct socket *so) 3567f53207bSRobert Watson { 3577f53207bSRobert Watson int error; 3587f53207bSRobert Watson 3597f53207bSRobert Watson SOCK_LOCK_ASSERT(so); 3607f53207bSRobert Watson 36130d239bcSRobert Watson MAC_CHECK(socket_check_poll, cred, so, so->so_label); 36226ae2b86SRobert Watson 3637f53207bSRobert Watson return (error); 3647f53207bSRobert Watson } 3657f53207bSRobert Watson 3667f53207bSRobert Watson int 36730d239bcSRobert Watson mac_socket_check_receive(struct ucred *cred, struct socket *so) 368c66b4d8dSRobert Watson { 369c66b4d8dSRobert Watson int error; 370c66b4d8dSRobert Watson 371310e7cebSRobert Watson SOCK_LOCK_ASSERT(so); 372310e7cebSRobert Watson 37330d239bcSRobert Watson MAC_CHECK(socket_check_receive, cred, so, so->so_label); 374c66b4d8dSRobert Watson 375c66b4d8dSRobert Watson return (error); 376c66b4d8dSRobert Watson } 377c66b4d8dSRobert Watson 378c66b4d8dSRobert Watson static int 37930d239bcSRobert Watson mac_socket_check_relabel(struct ucred *cred, struct socket *so, 380c66b4d8dSRobert Watson struct label *newlabel) 381c66b4d8dSRobert Watson { 382c66b4d8dSRobert Watson int error; 383c66b4d8dSRobert Watson 38426ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 385310e7cebSRobert Watson 38630d239bcSRobert Watson MAC_CHECK(socket_check_relabel, cred, so, so->so_label, newlabel); 387c66b4d8dSRobert Watson 388c66b4d8dSRobert Watson return (error); 389c66b4d8dSRobert Watson } 390c66b4d8dSRobert Watson 391c66b4d8dSRobert Watson int 39230d239bcSRobert Watson mac_socket_check_send(struct ucred *cred, struct socket *so) 393c66b4d8dSRobert Watson { 394c66b4d8dSRobert Watson int error; 395c66b4d8dSRobert Watson 396310e7cebSRobert Watson SOCK_LOCK_ASSERT(so); 397310e7cebSRobert Watson 39830d239bcSRobert Watson MAC_CHECK(socket_check_send, cred, so, so->so_label); 399c66b4d8dSRobert Watson 400c66b4d8dSRobert Watson return (error); 401c66b4d8dSRobert Watson } 402c66b4d8dSRobert Watson 403c66b4d8dSRobert Watson int 40430d239bcSRobert Watson mac_socket_check_stat(struct ucred *cred, struct socket *so) 4057f53207bSRobert Watson { 4067f53207bSRobert Watson int error; 4077f53207bSRobert Watson 4087f53207bSRobert Watson SOCK_LOCK_ASSERT(so); 4097f53207bSRobert Watson 41030d239bcSRobert Watson MAC_CHECK(socket_check_stat, cred, so, so->so_label); 4117f53207bSRobert Watson 4127f53207bSRobert Watson return (error); 4137f53207bSRobert Watson } 4147f53207bSRobert Watson 4157f53207bSRobert Watson int 41630d239bcSRobert Watson mac_socket_check_visible(struct ucred *cred, struct socket *so) 417c66b4d8dSRobert Watson { 418c66b4d8dSRobert Watson int error; 419c66b4d8dSRobert Watson 42026ae2b86SRobert Watson SOCK_LOCK_ASSERT(so); 421310e7cebSRobert Watson 42230d239bcSRobert Watson MAC_CHECK(socket_check_visible, cred, so, so->so_label); 423c66b4d8dSRobert Watson 424c66b4d8dSRobert Watson return (error); 425c66b4d8dSRobert Watson } 426c66b4d8dSRobert Watson 427c66b4d8dSRobert Watson int 428c66b4d8dSRobert Watson mac_socket_label_set(struct ucred *cred, struct socket *so, 429c66b4d8dSRobert Watson struct label *label) 430c66b4d8dSRobert Watson { 431c66b4d8dSRobert Watson int error; 432c66b4d8dSRobert Watson 433310e7cebSRobert Watson /* 434df3c68e4SRobert Watson * We acquire the socket lock when we perform the test and set, but 435df3c68e4SRobert Watson * have to release it as the pcb code needs to acquire the pcb lock, 436df3c68e4SRobert Watson * which will precede the socket lock in the lock order. However, 437df3c68e4SRobert Watson * this is fine, as any race will simply result in the inpcb being 438df3c68e4SRobert Watson * refreshed twice, but still consistently, as the inpcb code will 439df3c68e4SRobert Watson * acquire the socket lock before refreshing, holding both locks. 440310e7cebSRobert Watson */ 441310e7cebSRobert Watson SOCK_LOCK(so); 44230d239bcSRobert Watson error = mac_socket_check_relabel(cred, so, label); 443310e7cebSRobert Watson if (error) { 444310e7cebSRobert Watson SOCK_UNLOCK(so); 445c66b4d8dSRobert Watson return (error); 446310e7cebSRobert Watson } 447c66b4d8dSRobert Watson 44830d239bcSRobert Watson mac_socket_relabel(cred, so, label); 449310e7cebSRobert Watson SOCK_UNLOCK(so); 450df3c68e4SRobert Watson 451c66b4d8dSRobert Watson /* 452c66b4d8dSRobert Watson * If the protocol has expressed interest in socket layer changes, 453df3c68e4SRobert Watson * such as if it needs to propagate changes to a cached pcb label 454df3c68e4SRobert Watson * from the socket, notify it of the label change while holding the 455df3c68e4SRobert Watson * socket lock. 456c66b4d8dSRobert Watson */ 457c66b4d8dSRobert Watson if (so->so_proto->pr_usrreqs->pru_sosetlabel != NULL) 458c66b4d8dSRobert Watson (so->so_proto->pr_usrreqs->pru_sosetlabel)(so); 459c66b4d8dSRobert Watson 460c66b4d8dSRobert Watson return (0); 461c66b4d8dSRobert Watson } 462c66b4d8dSRobert Watson 463c66b4d8dSRobert Watson int 464c66b4d8dSRobert Watson mac_setsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 465c66b4d8dSRobert Watson { 466c66b4d8dSRobert Watson struct label *intlabel; 467c66b4d8dSRobert Watson char *buffer; 468c66b4d8dSRobert Watson int error; 469c66b4d8dSRobert Watson 4706356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 4716356dba0SRobert Watson return (EINVAL); 4726356dba0SRobert Watson 473c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 474c66b4d8dSRobert Watson if (error) 475c66b4d8dSRobert Watson return (error); 476c66b4d8dSRobert Watson 477c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 478c66b4d8dSRobert Watson error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL); 479c66b4d8dSRobert Watson if (error) { 480c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 481c66b4d8dSRobert Watson return (error); 482c66b4d8dSRobert Watson } 483c66b4d8dSRobert Watson 484c66b4d8dSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 48530d239bcSRobert Watson error = mac_socket_internalize_label(intlabel, buffer); 486c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 487c66b4d8dSRobert Watson if (error) 488c66b4d8dSRobert Watson goto out; 489c66b4d8dSRobert Watson 490c66b4d8dSRobert Watson error = mac_socket_label_set(cred, so, intlabel); 491c66b4d8dSRobert Watson out: 492c66b4d8dSRobert Watson mac_socket_label_free(intlabel); 493c66b4d8dSRobert Watson return (error); 494c66b4d8dSRobert Watson } 495c66b4d8dSRobert Watson 496c66b4d8dSRobert Watson int 497c66b4d8dSRobert Watson mac_getsockopt_label(struct ucred *cred, struct socket *so, struct mac *mac) 498c66b4d8dSRobert Watson { 499c66b4d8dSRobert Watson char *buffer, *elements; 500310e7cebSRobert Watson struct label *intlabel; 501c66b4d8dSRobert Watson int error; 502c66b4d8dSRobert Watson 5036356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 5046356dba0SRobert Watson return (EINVAL); 5056356dba0SRobert Watson 506c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 507c66b4d8dSRobert Watson if (error) 508c66b4d8dSRobert Watson return (error); 509c66b4d8dSRobert Watson 510c66b4d8dSRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 511c66b4d8dSRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 512c66b4d8dSRobert Watson if (error) { 513c66b4d8dSRobert Watson free(elements, M_MACTEMP); 514c66b4d8dSRobert Watson return (error); 515c66b4d8dSRobert Watson } 516c66b4d8dSRobert Watson 517c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 518310e7cebSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 519310e7cebSRobert Watson SOCK_LOCK(so); 52030d239bcSRobert Watson mac_socket_copy_label(so->so_label, intlabel); 521310e7cebSRobert Watson SOCK_UNLOCK(so); 52230d239bcSRobert Watson error = mac_socket_externalize_label(intlabel, elements, buffer, 523310e7cebSRobert Watson mac->m_buflen); 524310e7cebSRobert Watson mac_socket_label_free(intlabel); 525c66b4d8dSRobert Watson if (error == 0) 526c66b4d8dSRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 527c66b4d8dSRobert Watson 528c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 529c66b4d8dSRobert Watson free(elements, M_MACTEMP); 530c66b4d8dSRobert Watson 531c66b4d8dSRobert Watson return (error); 532c66b4d8dSRobert Watson } 533c66b4d8dSRobert Watson 534c66b4d8dSRobert Watson int 535c66b4d8dSRobert Watson mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so, 536c66b4d8dSRobert Watson struct mac *mac) 537c66b4d8dSRobert Watson { 538c66b4d8dSRobert Watson char *elements, *buffer; 539310e7cebSRobert Watson struct label *intlabel; 540c66b4d8dSRobert Watson int error; 541c66b4d8dSRobert Watson 5426356dba0SRobert Watson if (!(mac_labeled & MPC_OBJECT_SOCKET)) 5436356dba0SRobert Watson return (EINVAL); 5446356dba0SRobert Watson 545c66b4d8dSRobert Watson error = mac_check_structmac_consistent(mac); 546c66b4d8dSRobert Watson if (error) 547c66b4d8dSRobert Watson return (error); 548c66b4d8dSRobert Watson 549c66b4d8dSRobert Watson elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK); 550c66b4d8dSRobert Watson error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL); 551c66b4d8dSRobert Watson if (error) { 552c66b4d8dSRobert Watson free(elements, M_MACTEMP); 553c66b4d8dSRobert Watson return (error); 554c66b4d8dSRobert Watson } 555c66b4d8dSRobert Watson 556c66b4d8dSRobert Watson buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO); 557310e7cebSRobert Watson intlabel = mac_socket_label_alloc(M_WAITOK); 558310e7cebSRobert Watson SOCK_LOCK(so); 55930d239bcSRobert Watson mac_socket_copy_label(so->so_peerlabel, intlabel); 560310e7cebSRobert Watson SOCK_UNLOCK(so); 56130d239bcSRobert Watson error = mac_socketpeer_externalize_label(intlabel, elements, buffer, 562310e7cebSRobert Watson mac->m_buflen); 563310e7cebSRobert Watson mac_socket_label_free(intlabel); 564c66b4d8dSRobert Watson if (error == 0) 565c66b4d8dSRobert Watson error = copyout(buffer, mac->m_string, strlen(buffer)+1); 566c66b4d8dSRobert Watson 567c66b4d8dSRobert Watson free(buffer, M_MACTEMP); 568c66b4d8dSRobert Watson free(elements, M_MACTEMP); 569c66b4d8dSRobert Watson 570c66b4d8dSRobert Watson return (error); 571c66b4d8dSRobert Watson } 572